I have SAM Lambda written in Python, i'm using Cloudfront and API Gateway to expose an endpoint to trigger the lambda, and I have a security issue to fix about:
CloudFront distributions should have a default root object configured
So I want to add a default root object to the cloudfront, and I need some help to configure it.
I've tried to add the default root object to s3 bucket, and also tried to add it to the root in the project but it's not working for me.
This is my template:
AWSTemplateFormatVersion: "2010-09-09"
Transform:
- AWS::Serverless-2016-10-31
Parameters:
EnvironmentName:
Description: An environment name that will be prefixed to resource names e.g. dev,test for feature branch use dev1,dev2...
Type: String
Stage:
Type: String
Description: The name for a project pipeline stage, such as Staging or Prod, for which resources are provisioned and deployed.
Default: Stage
AllowedValues:
- Prod
- Stage
ApiKey:
Description: A unique key that you can distribute to clients such as CloudFront who are executing API Gateway
Type: String
Default: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
NoEcho: true
ServiceName:
Description: Service name
Type: String
Default: work-item-creation
LambdaFunc:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${EnvironmentName}-cw-${ServiceName}-lambda"
Description: Work Item Creation Lambda
Handler: app.lambda_handler
Runtime: python3.9
MemorySize: 128
Timeout: 30
CodeUri: lambda_func/
Role: !GetAtt
- LambdaExecutionRole
- Arn
Environment:
Variables:
PAT: "{{resolve:secretsmanager:secrets:SecretString:AZURE_PAT}}"
Events:
CreateWorkItem:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /create-work-item
Method: post
Stage: !Ref Stage
Auth:
ApiKeyRequired: true
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub "${EnvironmentName}-cw-${ServiceName}-lambda-execution-role"
Description: Creating service role in IAM for AWS Lambda
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /service-role/
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Policies:
- PolicyName: "s3-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- s3:ListBucket
Resource:
- !Sub 'arn:aws:s3:::artifacts-us-east-1'
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Service
Value: !Ref ServiceName
ApiGatewayKey:
Type: "AWS::ApiGateway::ApiKey"
DependsOn:
- LambdaFunc
Properties:
Name: !Sub "${EnvironmentName}-cw-${ServiceName}-api-gateway-key"
Description: Work Item Creation API Key
Enabled: true
StageKeys:
- RestApiId: !Ref ServerlessRestApi
StageName: !Ref Stage
Value: !Ref ApiKey
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Service
Value: !Ref ServiceName
ApiKeyUsagePlan:
Type: "AWS::ApiGateway::UsagePlan"
DependsOn:
- LambdaFunc
- ApiGatewayKey
Properties:
UsagePlanName: !Sub "${EnvironmentName}-cw-${ServiceName}-api-key-usage-plan"
Description: Work Item Creation API Key usage plan
ApiStages:
- ApiId: !Ref ServerlessRestApi
Stage: !Ref Stage
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Service
Value: !Ref ServiceName
LinkUsagePlanApiKey:
Type: "AWS::ApiGateway::UsagePlanKey"
Properties:
KeyId: !Ref ApiGatewayKey
KeyType: API_KEY
UsagePlanId: !Ref ApiKeyUsagePlan
CloudFront:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
IPV6Enabled: true
HttpVersion: http2
Comment: !Sub "Work Item Creation CloudFront, Environment: ${EnvironmentName}"
Aliases:
- !Join [
".",
[
!Ref ServiceName,
!Sub "{{resolve:ssm:/${EnvironmentName}/aws/route53/domain-name:1}}",
],
]
ViewerCertificate:
AcmCertificateArn: !Sub "{{resolve:ssm:/${EnvironmentName}/aws/acm/ssl-certificate-id:1}}"
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021
Origins:
- Id: APIGOrigin
DomainName: !Sub ${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com
OriginPath: !Sub /${Stage}
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: x-api-key
HeaderValue: !Ref ApiKey
- Id: S3Origin
DomainName: artifacts-us-east-1.s3.amazonaws.com
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
DefaultRootObject: default.html
DefaultCacheBehavior:
AllowedMethods:
["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
CachedMethods: ["GET", "HEAD", "OPTIONS"]
ForwardedValues:
Headers:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
- Authorization
# - Host APIG needs to use SNI
QueryString: true
TargetOriginId: APIGOrigin
ViewerProtocolPolicy: https-only
Compress: true
DefaultTTL: 0
CustomErrorResponses:
- ErrorCachingMinTTL: 0
ErrorCode: 400
- ErrorCachingMinTTL: 1
ErrorCode: 403
- ErrorCachingMinTTL: 5
ErrorCode: 500
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Service
Value: !Ref ServiceName
RecordSetGroup:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneId: !Sub "{{resolve:ssm:/${EnvironmentName}/aws/route53/internal-public-hosted-zone-id:1}}"
RecordSets:
- Name:
!Join [
".",
[
!Ref ServiceName,
!Sub "{{resolve:ssm:/${EnvironmentName}/aws/route53/domain-name:1}}",
],
]
Type: A
AliasTarget:
HostedZoneId: XXXXXXXXX # hosted zone ID of CloudFront
DNSName: !GetAtt CloudFront.DomainName
Outputs:
WorkItemCreationEndPoint:
Description: Work Item Creation Rest API endpoint
Value: !Ref RecordSetGroup
Where and how do I need to configure the default root object? I have tried to set up the html in the bucket called artifact-us-east-1
but it doesn't seem to be working.
Also, I have tried to add it to the project in the root location.
I have fugured it out and it's easier than I thoght. You need to return the html from your lambda using api gateway resposne definition. For example:
html_response = {
"statusCode": "404",
"body": {},
"headers": {
'Content-Type': 'text/html',
}
}
Then add to the template.yaml file another path /index.html and enable default root object. Actualy, when setting default root object, and routing to the root / aws routing in by default to /index.html.