diff --git a/postcode_lookup/lambda_basic_auth.py b/postcode_lookup/lambda_basic_auth.py new file mode 100644 index 0000000..2bd5051 --- /dev/null +++ b/postcode_lookup/lambda_basic_auth.py @@ -0,0 +1,21 @@ +def lambda_handler(event, context): + headers = event.get("headers", {}) + auth = headers.get("Authorization") + dc_auth = "Basic ZGM6ZGM=" # dc:dc in base64 + + if auth == dc_auth: + return { + "principalId": "dc", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "execute-api:Invoke", + "Effect": "Allow", + "Resource": "*", + } + ], + }, + } + + raise Exception("Unauthorized") diff --git a/template.yaml b/template.yaml index 2121234..4adcc49 100644 --- a/template.yaml +++ b/template.yaml @@ -1,5 +1,7 @@ AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 +Transform: + - AWS::LanguageExtensions + - AWS::Serverless-2016-10-31 Description: "EC Postcode Lookup app: Lambda, API Gateway" Globals: @@ -40,6 +42,11 @@ Parameters: Description: "The DC_ENVIRONMENT environment variable passed to the app." Type: AWS::SSM::Parameter::Value +Conditions: + UseBasicAuth: !Or + - !Equals [ !Ref DCEnvironment, development ] + - !Equals [ !Ref DCEnvironment, staging ] + Resources: ECDeployerRole: Type: AWS::IAM::Role @@ -55,7 +62,6 @@ Resources: - 'sts:AssumeRole' RoleName: ECDeployer - ECPostcodeLookupFunction: Type: AWS::Serverless::Function Properties: @@ -75,11 +81,13 @@ Resources: HTTPRequests: Type: Api Properties: + RestApiId: !Ref ECPostcodeLookupFunctionApiGateway Path: /{proxy+} Method: ANY HTTPRequestRoots: Type: Api Properties: + RestApiId: !Ref ECPostcodeLookupFunctionApiGateway Path: / Method: ANY @@ -90,6 +98,43 @@ Resources: LogGroupName: !Sub /aws/lambda/${ECPostcodeLookupFunction} RetentionInDays: 60 + ECPostcodeLookupFunctionApiGateway: + Type: AWS::Serverless::Api + Properties: + AlwaysDeploy: True + StageName: Prod + Cors: + AllowMethods: "'GET'" + AllowOrigin: "'*'" + MaxAge: "'600'" + Auth: + DefaultAuthorizer: !If [ UseBasicAuth, "BasicAuthFunction", !Ref AWS::NoValue] + Authorizers: + BasicAuthFunction: + FunctionArn: !GetAtt BasicAuthFunction.Arn + FunctionPayloadType: REQUEST + Identity: + Headers: + - Authorization + ReauthorizeEvery: 3600 + + BasicAuthGatewayResponse: + Condition: UseBasicAuth + Type: AWS::ApiGateway::GatewayResponse + Properties: + ResponseParameters: + gatewayresponse.header.www-authenticate: "'Basic realm=\"Restricted\"'" + ResponseType: UNAUTHORIZED + RestApiId: !Ref ECPostcodeLookupFunctionApiGateway + StatusCode: '401' + + BasicAuthFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: ./postcode_lookup/ + Handler: lambda_basic_auth.lambda_handler + Runtime: python3.12 + FailOver: Type: AWS::S3::Bucket Properties: @@ -143,7 +188,7 @@ Resources: Comment: 'Cloudfront Distribution pointing to Lambda origin' Origins: - Id: Dynamic - DomainName: !Sub "${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com" + DomainName: !Sub "${ECPostcodeLookupFunctionApiGateway}.execute-api.${AWS::Region}.amazonaws.com" OriginPath: "/Prod" CustomOriginConfig: OriginProtocolPolicy: "https-only" @@ -281,6 +326,6 @@ Resources: Outputs: ECPostcodeLookupFqdn: Description: "API Gateway endpoint FQDN for EC Postcode Lookup function" - Value: !Sub "${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com" + Value: !Sub "${ECPostcodeLookupFunctionApiGateway}.execute-api.${AWS::Region}.amazonaws.com" Export: Name: !Join [ ":", [ !Ref "AWS::StackName", "ECPostcodeLookupFqdn" ] ]