def add_bucket_policy(self, bucket: s3.Bucket) -> s3.BucketPolicy: """Add a policy to the bucket if CloudFront is disabled. Ensure PublicRead. Args: bucket: The bucket resource to place the policy. Returns: The Bucket Policy Resource. """ return self.template.add_resource( s3.BucketPolicy( "BucketPolicy", Bucket=bucket.ref(), PolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement( Effect=Allow, Principal=Principal("*"), Action=[Action("s3", "getObject")], Resource=[Join("", [bucket.get_att("Arn"), "/*"])], ) ], ), ))
def _get_cloudfront_bucket_policy_statements( self, bucket: s3.Bucket, oai: cloudfront.CloudFrontOriginAccessIdentity) -> List[Statement]: return [ Statement( Action=[awacs.s3.GetObject], Effect=Allow, Principal=Principal("CanonicalUser", oai.get_att("S3CanonicalUserId")), Resource=[Join("", [bucket.get_att("Arn"), "/*"])], ), Statement( Action=[awacs.s3.ListBucket], Effect=Allow, Principal=Principal("CanonicalUser", oai.get_att("S3CanonicalUserId")), Resource=[bucket.get_att("Arn")], ), ]
def _get_cloudfront_bucket_policy_statements( bucket: s3.Bucket, oai: cloudfront.CloudFrontOriginAccessIdentity) -> List[Statement]: return [ Statement( Action=[awacs.s3.GetObject], Effect=Allow, # S3CanonicalUserId is translated to the ARN when AWS renders this Principal=Principal("CanonicalUser", oai.get_att("S3CanonicalUserId")), Resource=[Join("", [bucket.get_att("Arn"), "/*"])], ) ]
def add_cloudfront_bucket_policy( self, bucket: s3.Bucket, oai: cloudfront.CloudFrontOriginAccessIdentity) -> s3.BucketPolicy: """Given a bucket and oai resource add cloudfront access to the bucket. Keyword Args: bucket: A bucket resource. oai: An Origin Access Identity resource. Return: The CloudFront Bucket access resource. """ return self.template.add_resource( s3.BucketPolicy( "AllowCFAccess", Bucket=bucket.ref(), PolicyDocument=PolicyDocument( Version="2012-10-17", Statement=self._get_cloudfront_bucket_policy_statements( bucket, oai), ), ))
def get_cloudfront_distribution_options( self, bucket: s3.Bucket, oai: cloudfront.CloudFrontOriginAccessIdentity, lambda_function_associations: List[ cloudfront.LambdaFunctionAssociation], ) -> Dict[str, Any]: """Retrieve the options for our CloudFront distribution. Args: bucket: The bucket resource oai: The origin access identity resource. lambda_function_associations: List of Lambda Function associations. Return: The CloudFront Distribution Options. """ if os.getenv("AWS_REGION") == "us-east-1": # use global endpoint for us-east-1 origin = Join(".", [bucket.ref(), "s3.amazonaws.com"]) else: # use reginal endpoint to avoid "temporary" redirect that can last over an hour # https://forums.aws.amazon.com/message.jspa?messageID=677452 origin = Join(".", [bucket.ref(), "s3", Region, "amazonaws.com"]) return { "Aliases": self.add_aliases(), "Origins": [ cloudfront.Origin( DomainName=origin, S3OriginConfig=cloudfront. S3OriginConfig(OriginAccessIdentity=Join( "", ["origin-access-identity/cloudfront/", oai.ref()])), Id="S3Origin", ) ], "DefaultCacheBehavior": cloudfront.DefaultCacheBehavior( AllowedMethods=["GET", "HEAD"], Compress=False, DefaultTTL="86400", ForwardedValues=cloudfront.ForwardedValues( Cookies=cloudfront.Cookies(Forward="none"), QueryString=False), LambdaFunctionAssociations=lambda_function_associations, TargetOriginId="S3Origin", ViewerProtocolPolicy="redirect-to-https", ), "DefaultRootObject": "index.html", "Logging": self.add_logging_bucket(), "PriceClass": self.variables["PriceClass"], "CustomErrorResponses": [ cloudfront.CustomErrorResponse( ErrorCode=response["ErrorCode"], ResponseCode=response["ResponseCode"], ResponsePagePath=response["ResponsePagePath"], ) for response in self.variables["custom_error_responses"] ], "Enabled": True, "WebACLId": self.add_web_acl(), "ViewerCertificate": self.add_acm_cert(), }
def get_distribution_options( self, bucket: s3.Bucket, oai: cloudfront.CloudFrontOriginAccessIdentity, lambda_funcs: List[cloudfront.LambdaFunctionAssociation], check_auth_lambda_version: awslambda.Version, http_headers_lambda_version: awslambda.Version, parse_auth_lambda_version: awslambda.Version, refresh_auth_lambda_version: awslambda.Version, sign_out_lambda_version: awslambda.Version, ) -> Dict[str, Any]: """Retrieve the options for our CloudFront distribution. Keyword Args: bucket: The bucket resource. oai: The origin access identity resource. lambda_funcs: List of Lambda Function associations. check_auth_lambda_version: Lambda Function Version to use. http_headers_lambda_version: Lambda Function Version to use. parse_auth_lambda_version: Lambda Function Version to use. refresh_auth_lambda_version: Lambda Function Version to use. sign_out_lambda_version: Lambda Function Version to use. Return: The CloudFront Distribution Options. """ default_cache_behavior_lambdas = lambda_funcs default_cache_behavior_lambdas.append( cloudfront.LambdaFunctionAssociation( EventType="viewer-request", LambdaFunctionARN=check_auth_lambda_version.ref(), )) default_cache_behavior_lambdas.append( cloudfront.LambdaFunctionAssociation( EventType="origin-response", LambdaFunctionARN=http_headers_lambda_version.ref(), )) return { "Aliases": self.add_aliases(), "Origins": [ cloudfront.Origin( DomainName=Join(".", [bucket.ref(), "s3.amazonaws.com"]), S3OriginConfig=cloudfront. S3OriginConfig(OriginAccessIdentity=Join( "", ["origin-access-identity/cloudfront/", oai.ref()])), Id="protected-bucket", ) ], "CacheBehaviors": [ cloudfront.CacheBehavior( PathPattern=self.variables["RedirectPathSignIn"], Compress=True, ForwardedValues=cloudfront.ForwardedValues( QueryString=True), LambdaFunctionAssociations=[ cloudfront.LambdaFunctionAssociation( EventType="viewer-request", LambdaFunctionARN=parse_auth_lambda_version.ref(), ) ], TargetOriginId="protected-bucket", ViewerProtocolPolicy="redirect-to-https", ), cloudfront.CacheBehavior( PathPattern=self.variables["RedirectPathAuthRefresh"], Compress=True, ForwardedValues=cloudfront.ForwardedValues( QueryString=True), LambdaFunctionAssociations=[ cloudfront.LambdaFunctionAssociation( EventType="viewer-request", LambdaFunctionARN=refresh_auth_lambda_version.ref( ), ) ], TargetOriginId="protected-bucket", ViewerProtocolPolicy="redirect-to-https", ), cloudfront.CacheBehavior( PathPattern=self.variables["SignOutUrl"], Compress=True, ForwardedValues=cloudfront.ForwardedValues( QueryString=True), LambdaFunctionAssociations=[ cloudfront.LambdaFunctionAssociation( EventType="viewer-request", LambdaFunctionARN=sign_out_lambda_version.ref(), ) ], TargetOriginId="protected-bucket", ViewerProtocolPolicy="redirect-to-https", ), ], "DefaultCacheBehavior": cloudfront.DefaultCacheBehavior( AllowedMethods=["GET", "HEAD"], Compress=True, DefaultTTL="86400", ForwardedValues=cloudfront.ForwardedValues(QueryString=True), LambdaFunctionAssociations=default_cache_behavior_lambdas, TargetOriginId="protected-bucket", ViewerProtocolPolicy="redirect-to-https", ), "DefaultRootObject": "index.html", "Logging": self.add_logging_bucket(), "PriceClass": self.variables["PriceClass"], "Enabled": True, "WebACLId": self.add_web_acl(), "CustomErrorResponses": self._get_error_responses(), "ViewerCertificate": self.add_acm_cert(), }