diff --git a/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json b/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json index 45de5e173..684fdc1ef 100644 --- a/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json +++ b/source/use_cases/aws-custom-glue-etl/test/integ.gluejob.expected.json @@ -1,28 +1,17 @@ { "Description": "Integration Test for sample application that uses aws-kineisstream-glue-job construct", - "Parameters": { - "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3Bucket96760533": { - "Type": "String", - "Description": "S3 bucket for asset \"d4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4\"" - }, - "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9": { - "Type": "String", - "Description": "S3 key for asset version \"d4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4\"" - }, - "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4ArtifactHashC026BAAB": { - "Type": "String", - "Description": "Artifact hash for asset \"d4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4\"" - } - }, "Resources": { "CustomETLKinesisStreamB4F1869F": { "Type": "AWS::Kinesis::Stream", "Properties": { - "ShardCount": 1, "RetentionPeriodHours": 24, + "ShardCount": 1, "StreamEncryption": { "EncryptionType": "KMS", "KeyId": "alias/aws/kinesis" + }, + "StreamModeDetails": { + "StreamMode": "PROVISIONED" } } }, @@ -135,7 +124,11 @@ "s3:GetBucket*", "s3:List*", "s3:DeleteObject*", - "s3:PutObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", "s3:Abort*" ], "Effect": "Allow", @@ -180,34 +173,7 @@ }, ":s3:::", { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3Bucket96760533" - }, - "/", - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" } ] ] @@ -222,34 +188,7 @@ }, ":s3:::", { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3Bucket96760533" - }, - "/", - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, "/*" ] @@ -286,6 +225,9 @@ "BlockPublicPolicy": true, "IgnorePublicAcls": true, "RestrictPublicBuckets": true + }, + "VersioningConfiguration": { + "Status": "Enabled" } }, "UpdateReplacePolicy": "Retain", @@ -310,7 +252,7 @@ "PolicyDocument": { "Statement": [ { - "Action": "*", + "Action": "s3:*", "Condition": { "Bool": { "aws:SecureTransport": "false" @@ -320,21 +262,28 @@ "Principal": { "AWS": "*" }, - "Resource": { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "CustomETLS3LoggingBucketBBDD45CB", - "Arn" - ] - }, - "/*" + "Resource": [ + { + "Fn::GetAtt": [ + "CustomETLS3LoggingBucketBBDD45CB", + "Arn" ] - ] - }, - "Sid": "HttpsOnly" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CustomETLS3LoggingBucketBBDD45CB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] } ], "Version": "2012-10-17" @@ -393,7 +342,7 @@ "PolicyDocument": { "Statement": [ { - "Action": "*", + "Action": "s3:*", "Condition": { "Bool": { "aws:SecureTransport": "false" @@ -403,21 +352,28 @@ "Principal": { "AWS": "*" }, - "Resource": { - "Fn::Join": [ - "", - [ - { - "Fn::GetAtt": [ - "CustomETLS3Bucket3EE58725", - "Arn" - ] - }, - "/*" + "Resource": [ + { + "Fn::GetAtt": [ + "CustomETLS3Bucket3EE58725", + "Arn" ] - ] - }, - "Sid": "HttpsOnly" + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CustomETLS3Bucket3EE58725", + "Arn" + ] + }, + "/*" + ] + ] + } + ] } ], "Version": "2012-10-17" @@ -431,42 +387,7 @@ "Name": "gluestreaming", "PythonVersion": "3", "ScriptLocation": { - "Fn::Join": [ - "", - [ - "s3://", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3Bucket96760533" - }, - "/", - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParametersd4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4S3VersionKey856519B9" - } - ] - } - ] - } - ] - ] + "Fn::Sub": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d4dd6643ee852c9578ae2d36cf2dc8a48630fd2219a15e74502c7ea75bff70c4.py" } }, "Role": { @@ -488,7 +409,7 @@ "Fn::Join": [ "", [ - "s3://", + "s3a://", { "Ref": "CustomETLS3Bucket3EE58725" }, @@ -498,7 +419,35 @@ } }, "GlueVersion": "2.0", - "SecurityConfiguration": "ETLJobSecurityConfig" + "NumberOfWorkers": 2, + "SecurityConfiguration": "ETLJobSecurityConfig", + "WorkerType": "G.1X" + } + }, + "CustomETLKinesisStreamGetRecordsIteratorAgeAlarmCD7F4E34": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "EvaluationPeriods": 1, + "AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.", + "MetricName": "GetRecords.IteratorAgeMilliseconds", + "Namespace": "AWS/Kinesis", + "Period": 300, + "Statistic": "Maximum", + "Threshold": 43200 + } + }, + "CustomETLKinesisStreamReadProvisionedThroughputExceededAlarm6AB32664": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "ComparisonOperator": "GreaterThanThreshold", + "EvaluationPeriods": 1, + "AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.", + "MetricName": "ReadProvisionedThroughputExceeded", + "Namespace": "AWS/Kinesis", + "Period": 300, + "Statistic": "Average", + "Threshold": 0 } }, "GlueDatabase": { @@ -523,7 +472,7 @@ }, "TableInput": { "Parameters": { - "classication": "json" + "classification": "json" }, "StorageDescriptor": { "Columns": [ @@ -599,7 +548,7 @@ } } }, - "GlueJobPolicyAEA4B94E": { + "CustomETLGlueJobPolicy0AE5B5CB": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { @@ -745,7 +694,7 @@ ], "Version": "2012-10-17" }, - "PolicyName": "GlueJobPolicyAEA4B94E", + "PolicyName": "CustomETLGlueJobPolicy0AE5B5CB", "Roles": [ { "Ref": "CustomETLJobRole53A1671F" @@ -783,5 +732,39 @@ ] } } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } } } \ No newline at end of file diff --git a/source/use_cases/aws-restaurant-management-demo/.eslintignore b/source/use_cases/aws-restaurant-management-demo/.eslintignore index 8773c034a..56378a21b 100644 --- a/source/use_cases/aws-restaurant-management-demo/.eslintignore +++ b/source/use_cases/aws-restaurant-management-demo/.eslintignore @@ -3,4 +3,5 @@ test/*.js bin/*.js *.d.ts coverage -test/lambda/index.js \ No newline at end of file +test/lambda/index.js +*/lambda/**/*.js diff --git a/source/use_cases/aws-restaurant-management-demo/bin/restaurant-management-system-demo.ts b/source/use_cases/aws-restaurant-management-demo/bin/restaurant-management-system-demo.ts index 911bc80ff..8b0719fa2 100644 --- a/source/use_cases/aws-restaurant-management-demo/bin/restaurant-management-system-demo.ts +++ b/source/use_cases/aws-restaurant-management-demo/bin/restaurant-management-system-demo.ts @@ -1,4 +1,5 @@ #!/usr/bin/env node + /** * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * diff --git a/source/use_cases/aws-restaurant-management-demo/package.json b/source/use_cases/aws-restaurant-management-demo/package.json index e491915aa..005d56c74 100644 --- a/source/use_cases/aws-restaurant-management-demo/package.json +++ b/source/use_cases/aws-restaurant-management-demo/package.json @@ -44,6 +44,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/aws-ssm": "0.0.0", "@aws-cdk/aws-redshift": "0.0.0", @@ -55,7 +56,7 @@ "@aws-solutions-constructs/aws-lambda-dynamodb": "0.0.0", "@aws-solutions-constructs/aws-lambda-s3": "0.0.0", "@aws-solutions-constructs/aws-lambda-sns": "0.0.0", - "@aws-solutions-constructs/aws-lambda-step-function": "0.0.0", + "@aws-solutions-constructs/aws-lambda-stepfunctions": "0.0.0", "source-map-support": "^0.5.16", "typescript": "^4.2.4" } diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/existingResourcesStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/existingResourcesStack.test.js.snap new file mode 100644 index 000000000..045ea91a1 --- /dev/null +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/existingResourcesStack.test.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ExistingResourcesStack 1`] = ` +Object { + "Resources": Object { + "existingorderarchivebucket95AB7C99": Object { + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + }, + }, +} +`; diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap new file mode 100644 index 000000000..b7fbe604c --- /dev/null +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/kitchenStaffStack.test.js.snap @@ -0,0 +1,1028 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test-kitchen-staff-stack 1`] = ` +Object { + "Outputs": Object { + "kitchenstaffapiLambdaRestApiEndpoint79E1D2E0": Object { + "Value": Object { + "Fn::Join": Array [ + "", + Array [ + "https://", + Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + ".execute-api.", + Object { + "Ref": "AWS::Region", + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "kitchenstaffapiLambdaRestApiDeploymentStageprodB9D4F4B3", + }, + "/", + ], + ], + }, + }, + }, + "Parameters": Object { + "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aArtifactHashF06EE331": Object { + "Description": "Artifact hash for asset \\"70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08a\\"", + "Type": "String", + }, + "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aS3Bucket757BF55F": Object { + "Description": "S3 bucket for asset \\"70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08a\\"", + "Type": "String", + }, + "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aS3VersionKey35483A87": Object { + "Description": "S3 key for asset version \\"70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08a\\"", + "Type": "String", + }, + "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6ArtifactHash19177DB6": Object { + "Description": "Artifact hash for asset \\"e2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6\\"", + "Type": "String", + }, + "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6S3Bucket387AC028": Object { + "Description": "S3 bucket for asset \\"e2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6\\"", + "Type": "String", + }, + "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6S3VersionKeyAE03533F": Object { + "Description": "S3 key for asset version \\"e2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6\\"", + "Type": "String", + }, + }, + "Resources": Object { + "completeorderLambdaFunction1B59DF2A": Object { + "DependsOn": Array [ + "completeorderLambdaFunctionServiceRoleDefaultPolicyB81B4D1C", + "completeorderLambdaFunctionServiceRoleFDF8F85D", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aS3Bucket757BF55F", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aS3VersionKey35483A87", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters70bd4fd4308c840ccf8c83659645c3bdca4d50fd6103f8c37f9a1eac8781c08aS3VersionKey35483A87", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "completeorderLambdaFunctionServiceRoleFDF8F85D", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "completeorderLambdaFunctionServiceRoleDefaultPolicyB81B4D1C": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "completeorderLambdaFunctionServiceRoleDefaultPolicyB81B4D1C", + "Roles": Array [ + Object { + "Ref": "completeorderLambdaFunctionServiceRoleFDF8F85D", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "completeorderLambdaFunctionServiceRoleFDF8F85D": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "getopenordersLambdaFunctionCAD5B34A": Object { + "DependsOn": Array [ + "getopenordersLambdaFunctionServiceRoleDefaultPolicy2BBF8B21", + "getopenordersLambdaFunctionServiceRoleFA20DF64", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6S3Bucket387AC028", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6S3VersionKeyAE03533F", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameterse2a5b561be3a843c8fd1113f472938bb46cece6597ae4222db21547cb0bf48d6S3VersionKeyAE03533F", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "getopenordersLambdaFunctionServiceRoleFA20DF64", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "getopenordersLambdaFunctionServiceRoleDefaultPolicy2BBF8B21": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "getopenordersLambdaFunctionServiceRoleDefaultPolicy2BBF8B21", + "Roles": Array [ + Object { + "Ref": "getopenordersLambdaFunctionServiceRoleFA20DF64", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "getopenordersLambdaFunctionServiceRoleFA20DF64": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "kitchenstaffapiApiAccessLogGroup30DB1160": Object { + "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + }, + "kitchenstaffapiCognitoAuthorizerA7F33D82": Object { + "Properties": Object { + "IdentitySource": "method.request.header.Authorization", + "Name": "authorizer", + "ProviderARNs": Array [ + Object { + "Fn::GetAtt": Array [ + "kitchenstaffapiCognitoUserPool21035423", + "Arn", + ], + }, + ], + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "Type": "COGNITO_USER_POOLS", + }, + "Type": "AWS::ApiGateway::Authorizer", + }, + "kitchenstaffapiCognitoUserPool21035423": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "AccountRecoverySetting": Object { + "RecoveryMechanisms": Array [ + Object { + "Name": "verified_phone_number", + "Priority": 1, + }, + Object { + "Name": "verified_email", + "Priority": 2, + }, + ], + }, + "AdminCreateUserConfig": Object { + "AllowAdminCreateUserOnly": true, + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "UserPoolAddOns": Object { + "AdvancedSecurityMode": "ENFORCED", + }, + "VerificationMessageTemplate": Object { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}", + }, + }, + "Type": "AWS::Cognito::UserPool", + "UpdateReplacePolicy": "Retain", + }, + "kitchenstaffapiCognitoUserPoolClient064BFF69": Object { + "Properties": Object { + "AllowedOAuthFlows": Array [ + "implicit", + "code", + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": Array [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin", + ], + "CallbackURLs": Array [ + "https://example.com", + ], + "SupportedIdentityProviders": Array [ + "COGNITO", + ], + "UserPoolId": Object { + "Ref": "kitchenstaffapiCognitoUserPool21035423", + }, + }, + "Type": "AWS::Cognito::UserPoolClient", + }, + "kitchenstaffapiLambdaRestApiAccount3F0B8F7C": Object { + "DependsOn": Array [ + "kitchenstaffapiLambdaRestApiF3F7D4FC", + ], + "Properties": Object { + "CloudWatchRoleArn": Object { + "Fn::GetAtt": Array [ + "kitchenstaffapiLambdaRestApiCloudWatchRole0A152CE6", + "Arn", + ], + }, + }, + "Type": "AWS::ApiGateway::Account", + }, + "kitchenstaffapiLambdaRestApiCloudWatchRole0A152CE6": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "apigateway.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:GetLogEvents", + "logs:FilterLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaRestApiCloudWatchRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "kitchenstaffapiLambdaRestApiDeployment832EAD6B983d9ce6284ee8e6f3c6844bc18ebcc3": Object { + "DependsOn": Array [ + "kitchenstaffapiLambdaRestApicompleteorderproxyANYAA8E4C52", + "kitchenstaffapiLambdaRestApicompleteorderproxyF9BF19EB", + "kitchenstaffapiLambdaRestApicompleteorder8E72FD84", + "kitchenstaffapiLambdaRestApigetopenordersproxyANY7A3BF144", + "kitchenstaffapiLambdaRestApigetopenordersproxyFF3E7DFD", + "kitchenstaffapiLambdaRestApigetopenorders25EC2468", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W45", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + }, + ], + }, + }, + "Properties": Object { + "Description": "Automatically created by the RestApi construct", + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Deployment", + }, + "kitchenstaffapiLambdaRestApiDeploymentStageprodB9D4F4B3": Object { + "Properties": Object { + "AccessLogSetting": Object { + "DestinationArn": Object { + "Fn::GetAtt": Array [ + "kitchenstaffapiApiAccessLogGroup30DB1160", + "Arn", + ], + }, + "Format": "{\\"requestId\\":\\"$context.requestId\\",\\"ip\\":\\"$context.identity.sourceIp\\",\\"user\\":\\"$context.identity.user\\",\\"caller\\":\\"$context.identity.caller\\",\\"requestTime\\":\\"$context.requestTime\\",\\"httpMethod\\":\\"$context.httpMethod\\",\\"resourcePath\\":\\"$context.resourcePath\\",\\"status\\":\\"$context.status\\",\\"protocol\\":\\"$context.protocol\\",\\"responseLength\\":\\"$context.responseLength\\"}", + }, + "DeploymentId": Object { + "Ref": "kitchenstaffapiLambdaRestApiDeployment832EAD6B983d9ce6284ee8e6f3c6844bc18ebcc3", + }, + "MethodSettings": Array [ + Object { + "DataTraceEnabled": false, + "HttpMethod": "*", + "LoggingLevel": "INFO", + "ResourcePath": "/*", + }, + ], + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "StageName": "prod", + "TracingEnabled": true, + }, + "Type": "AWS::ApiGateway::Stage", + }, + "kitchenstaffapiLambdaRestApiF3F7D4FC": Object { + "Properties": Object { + "Description": "Demo: Kitchen staff API", + "EndpointConfiguration": Object { + "Types": Array [ + "EDGE", + ], + }, + "Name": "LambdaRestApi", + }, + "Type": "AWS::ApiGateway::RestApi", + }, + "kitchenstaffapiLambdaRestApiUsagePlan1249F8F9": Object { + "Properties": Object { + "ApiStages": Array [ + Object { + "ApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "Stage": Object { + "Ref": "kitchenstaffapiLambdaRestApiDeploymentStageprodB9D4F4B3", + }, + "Throttle": Object {}, + }, + ], + }, + "Type": "AWS::ApiGateway::UsagePlan", + }, + "kitchenstaffapiLambdaRestApicompleteorder8E72FD84": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "kitchenstaffapiLambdaRestApiF3F7D4FC", + "RootResourceId", + ], + }, + "PathPart": "complete-order", + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "kitchenstaffapiLambdaRestApicompleteorderproxyANYAA8E4C52": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "kitchenstaffapiCognitoAuthorizerA7F33D82", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "completeorderLambdaFunction1B59DF2A", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "kitchenstaffapiLambdaRestApicompleteorderproxyF9BF19EB", + }, + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "kitchenstaffapiLambdaRestApicompleteorderproxyANYApiPermissionKitchenStaffStackkitchenstaffapiLambdaRestApi652BB0C4ANYcompleteorderproxyD7DDAD90": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "completeorderLambdaFunction1B59DF2A", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "/", + Object { + "Ref": "kitchenstaffapiLambdaRestApiDeploymentStageprodB9D4F4B3", + }, + "/*/complete-order/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "kitchenstaffapiLambdaRestApicompleteorderproxyANYApiPermissionTestKitchenStaffStackkitchenstaffapiLambdaRestApi652BB0C4ANYcompleteorderproxy3F69EF93": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "completeorderLambdaFunction1B59DF2A", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "/test-invoke-stage/*/complete-order/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "kitchenstaffapiLambdaRestApicompleteorderproxyF9BF19EB": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "kitchenstaffapiLambdaRestApicompleteorder8E72FD84", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "kitchenstaffapiLambdaRestApigetopenorders25EC2468": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "kitchenstaffapiLambdaRestApiF3F7D4FC", + "RootResourceId", + ], + }, + "PathPart": "get-open-orders", + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "kitchenstaffapiLambdaRestApigetopenordersproxyANY7A3BF144": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "kitchenstaffapiCognitoAuthorizerA7F33D82", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "getopenordersLambdaFunctionCAD5B34A", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "kitchenstaffapiLambdaRestApigetopenordersproxyFF3E7DFD", + }, + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "kitchenstaffapiLambdaRestApigetopenordersproxyANYApiPermissionKitchenStaffStackkitchenstaffapiLambdaRestApi652BB0C4ANYgetopenordersproxy897FB53F": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getopenordersLambdaFunctionCAD5B34A", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "/", + Object { + "Ref": "kitchenstaffapiLambdaRestApiDeploymentStageprodB9D4F4B3", + }, + "/*/get-open-orders/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "kitchenstaffapiLambdaRestApigetopenordersproxyANYApiPermissionTestKitchenStaffStackkitchenstaffapiLambdaRestApi652BB0C4ANYgetopenordersproxy966B02A6": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getopenordersLambdaFunctionCAD5B34A", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + "/test-invoke-stage/*/get-open-orders/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "kitchenstaffapiLambdaRestApigetopenordersproxyFF3E7DFD": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "kitchenstaffapiLambdaRestApigetopenorders25EC2468", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "kitchenstaffapiLambdaRestApiF3F7D4FC", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + }, +} +`; diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/managerStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/managerStack.test.js.snap new file mode 100644 index 000000000..e9196af84 --- /dev/null +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/managerStack.test.js.snap @@ -0,0 +1,3201 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test-manager-stack 1`] = ` +Object { + "Mappings": Object { + "ServiceprincipalMap": Object { + "af-south-1": Object { + "states": "states.af-south-1.amazonaws.com", + }, + "ap-east-1": Object { + "states": "states.ap-east-1.amazonaws.com", + }, + "ap-northeast-1": Object { + "states": "states.ap-northeast-1.amazonaws.com", + }, + "ap-northeast-2": Object { + "states": "states.ap-northeast-2.amazonaws.com", + }, + "ap-northeast-3": Object { + "states": "states.ap-northeast-3.amazonaws.com", + }, + "ap-south-1": Object { + "states": "states.ap-south-1.amazonaws.com", + }, + "ap-southeast-1": Object { + "states": "states.ap-southeast-1.amazonaws.com", + }, + "ap-southeast-2": Object { + "states": "states.ap-southeast-2.amazonaws.com", + }, + "ap-southeast-3": Object { + "states": "states.ap-southeast-3.amazonaws.com", + }, + "ca-central-1": Object { + "states": "states.ca-central-1.amazonaws.com", + }, + "cn-north-1": Object { + "states": "states.cn-north-1.amazonaws.com", + }, + "cn-northwest-1": Object { + "states": "states.cn-northwest-1.amazonaws.com", + }, + "eu-central-1": Object { + "states": "states.eu-central-1.amazonaws.com", + }, + "eu-north-1": Object { + "states": "states.eu-north-1.amazonaws.com", + }, + "eu-south-1": Object { + "states": "states.eu-south-1.amazonaws.com", + }, + "eu-south-2": Object { + "states": "states.eu-south-2.amazonaws.com", + }, + "eu-west-1": Object { + "states": "states.eu-west-1.amazonaws.com", + }, + "eu-west-2": Object { + "states": "states.eu-west-2.amazonaws.com", + }, + "eu-west-3": Object { + "states": "states.eu-west-3.amazonaws.com", + }, + "me-south-1": Object { + "states": "states.me-south-1.amazonaws.com", + }, + "sa-east-1": Object { + "states": "states.sa-east-1.amazonaws.com", + }, + "us-east-1": Object { + "states": "states.us-east-1.amazonaws.com", + }, + "us-east-2": Object { + "states": "states.us-east-2.amazonaws.com", + }, + "us-gov-east-1": Object { + "states": "states.us-gov-east-1.amazonaws.com", + }, + "us-gov-west-1": Object { + "states": "states.us-gov-west-1.amazonaws.com", + }, + "us-iso-east-1": Object { + "states": "states.amazonaws.com", + }, + "us-iso-west-1": Object { + "states": "states.amazonaws.com", + }, + "us-isob-east-1": Object { + "states": "states.amazonaws.com", + }, + "us-west-1": Object { + "states": "states.us-west-1.amazonaws.com", + }, + "us-west-2": Object { + "states": "states.us-west-2.amazonaws.com", + }, + }, + }, + "Outputs": Object { + "managerapiLambdaRestApiEndpointD1A41897": Object { + "Value": Object { + "Fn::Join": Array [ + "", + Array [ + "https://", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + ".execute-api.", + Object { + "Ref": "AWS::Region", + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "managerapiLambdaRestApiDeploymentStageprod59C4A8D4", + }, + "/", + ], + ], + }, + }, + }, + "Parameters": Object { + "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13ArtifactHashD2A2C2EB": Object { + "Description": "Artifact hash for asset \\"3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13\\"", + "Type": "String", + }, + "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13S3Bucket6D0E979D": Object { + "Description": "S3 bucket for asset \\"3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13\\"", + "Type": "String", + }, + "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13S3VersionKeyF08F3926": Object { + "Description": "S3 key for asset version \\"3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13\\"", + "Type": "String", + }, + "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aArtifactHash06F9F843": Object { + "Description": "Artifact hash for asset \\"417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729a\\"", + "Type": "String", + }, + "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aS3BucketEFF1BA01": Object { + "Description": "S3 bucket for asset \\"417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729a\\"", + "Type": "String", + }, + "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aS3VersionKey9BBF88A7": Object { + "Description": "S3 key for asset version \\"417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729a\\"", + "Type": "String", + }, + "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194ArtifactHash049C6120": Object { + "Description": "Artifact hash for asset \\"4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194\\"", + "Type": "String", + }, + "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194S3Bucket6E9AF9DD": Object { + "Description": "S3 bucket for asset \\"4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194\\"", + "Type": "String", + }, + "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194S3VersionKey00C1823E": Object { + "Description": "S3 key for asset version \\"4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194\\"", + "Type": "String", + }, + "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0ArtifactHashF35F1FB9": Object { + "Description": "Artifact hash for asset \\"83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0\\"", + "Type": "String", + }, + "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0S3Bucket0FECA056": Object { + "Description": "S3 bucket for asset \\"83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0\\"", + "Type": "String", + }, + "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0S3VersionKeyA5DB7D1B": Object { + "Description": "S3 key for asset version \\"83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0\\"", + "Type": "String", + }, + "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2ArtifactHashF4AAF0F9": Object { + "Description": "Artifact hash for asset \\"99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2\\"", + "Type": "String", + }, + "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2S3Bucket75F8025A": Object { + "Description": "S3 bucket for asset \\"99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2\\"", + "Type": "String", + }, + "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2S3VersionKey0BAC175C": Object { + "Description": "S3 key for asset version \\"99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2\\"", + "Type": "String", + }, + "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393ArtifactHashEA0663AC": Object { + "Description": "Artifact hash for asset \\"bee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393\\"", + "Type": "String", + }, + "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393S3Bucket514B0A32": Object { + "Description": "S3 bucket for asset \\"bee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393\\"", + "Type": "String", + }, + "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393S3VersionKey0D96EFA5": Object { + "Description": "S3 key for asset version \\"bee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393\\"", + "Type": "String", + }, + "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baArtifactHashE5FF10CC": Object { + "Description": "Artifact hash for asset \\"e247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967ba\\"", + "Type": "String", + }, + "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baS3Bucket0B99817B": Object { + "Description": "S3 bucket for asset \\"e247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967ba\\"", + "Type": "String", + }, + "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baS3VersionKey6F469E09": Object { + "Description": "S3 key for asset version \\"e247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967ba\\"", + "Type": "String", + }, + }, + "Resources": Object { + "archiveordersLambdaFunction66659E04": Object { + "DependsOn": Array [ + "archiveordersLambdaFunctionServiceRoleDefaultPolicyDB67FB52", + "archiveordersLambdaFunctionServiceRoleE513ACF7", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2S3Bucket75F8025A", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2S3VersionKey0BAC175C", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters99da7fc0497f7d8697128700d73d1010c153a6af5446b3f86452c62b633be3e2S3VersionKey0BAC175C", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + "S3_BUCKET_NAME": Object { + "Fn::ImportValue": "ExistingResourcesStack:ExportsOutputRefexistingorderarchivebucket95AB7C994BD2255B", + }, + }, + }, + "Handler": "index.handler", + "Layers": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefshareddbfunctionslayerA9CFEC5A89EBE406", + }, + ], + "Role": Object { + "Fn::GetAtt": Array [ + "archiveordersLambdaFunctionServiceRoleE513ACF7", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "archiveordersLambdaFunctionServiceRoleDefaultPolicyDB67FB52": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject*", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "ExistingResourcesStack:ExportsOutputFnGetAttexistingorderarchivebucket95AB7C99Arn7A4BF717", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "ExistingResourcesStack:ExportsOutputFnGetAttexistingorderarchivebucket95AB7C99Arn7A4BF717", + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "archiveordersLambdaFunctionServiceRoleDefaultPolicyDB67FB52", + "Roles": Array [ + Object { + "Ref": "archiveordersLambdaFunctionServiceRoleE513ACF7", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "archiveordersLambdaFunctionServiceRoleE513ACF7": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "calculatetipsLambdaFunction9F2FE033": Object { + "DependsOn": Array [ + "calculatetipsLambdaFunctionServiceRoleDefaultPolicyED27C928", + "calculatetipsLambdaFunctionServiceRoleDE97A87F", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aS3BucketEFF1BA01", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aS3VersionKey9BBF88A7", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters417a2e0a2352189e861a2cadf25a3b8a7ccbc22a6d8e3d4466f611d46fdd729aS3VersionKey9BBF88A7", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + "SNS_TOPIC_ARN": Object { + "Ref": "calculatetipstopicSnsTopicD7FACC9C", + }, + "SNS_TOPIC_NAME": Object { + "Fn::GetAtt": Array [ + "calculatetipstopicSnsTopicD7FACC9C", + "TopicName", + ], + }, + }, + }, + "Handler": "index.handler", + "Layers": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefshareddbfunctionslayerA9CFEC5A89EBE406", + }, + ], + "Role": Object { + "Fn::GetAtt": Array [ + "calculatetipsLambdaFunctionServiceRoleDE97A87F", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "calculatetipsLambdaFunctionServiceRoleDE97A87F": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "calculatetipsLambdaFunctionServiceRoleDefaultPolicyED27C928": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + Object { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": Object { + "Ref": "calculatetipstopicSnsTopicD7FACC9C", + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "calculatetipsLambdaFunctionServiceRoleDefaultPolicyED27C928", + "Roles": Array [ + Object { + "Ref": "calculatetipsLambdaFunctionServiceRoleDE97A87F", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "calculatetipstopicSnsTopicD7FACC9C": Object { + "Properties": Object { + "KmsMasterKeyId": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":kms:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":alias/aws/sns", + ], + ], + }, + }, + "Type": "AWS::SNS::Topic", + }, + "calculatetipstopicSnsTopicPolicy529CD9C3": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "SNS:Publish", + "SNS:RemovePermission", + "SNS:SetTopicAttributes", + "SNS:DeleteTopic", + "SNS:ListSubscriptionsByTopic", + "SNS:GetTopicAttributes", + "SNS:Receive", + "SNS:AddPermission", + "SNS:Subscribe", + ], + "Condition": Object { + "StringEquals": Object { + "AWS:SourceOwner": Object { + "Ref": "AWS::AccountId", + }, + }, + }, + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + "Resource": Object { + "Ref": "calculatetipstopicSnsTopicD7FACC9C", + }, + "Sid": "TopicOwnerOnlyAccess", + }, + Object { + "Action": Array [ + "SNS:Publish", + "SNS:RemovePermission", + "SNS:SetTopicAttributes", + "SNS:DeleteTopic", + "SNS:ListSubscriptionsByTopic", + "SNS:GetTopicAttributes", + "SNS:Receive", + "SNS:AddPermission", + "SNS:Subscribe", + ], + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Object { + "Ref": "calculatetipstopicSnsTopicD7FACC9C", + }, + "Sid": "HttpsOnly", + }, + ], + "Version": "2012-10-17", + }, + "Topics": Array [ + Object { + "Ref": "calculatetipstopicSnsTopicD7FACC9C", + }, + ], + }, + "Type": "AWS::SNS::TopicPolicy", + }, + "checklateordersLambdaFunctionAwsEventsLambdaInvokePermission124C4D337": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "checklateordersLambdaFunctionB46EDA7D", + "Arn", + ], + }, + "Principal": "events.amazonaws.com", + "SourceArn": Object { + "Fn::GetAtt": Array [ + "checklateordersschedulerchecklateordersschedulerWEventsRule15B31DCC", + "Arn", + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "checklateordersLambdaFunctionB46EDA7D": Object { + "DependsOn": Array [ + "checklateordersLambdaFunctionServiceRoleDefaultPolicy4DABEECE", + "checklateordersLambdaFunctionServiceRoleA8F250A0", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baS3Bucket0B99817B", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baS3VersionKey6F469E09", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameterse247a6949734ab1a72f6679bdeb6de1bd7e6c8714508986e7cfe184ad2b967baS3VersionKey6F469E09", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + "LATE_ORDER_THRESHOLD": "30", + "SNS_TOPIC_ARN": Object { + "Ref": "checklateordersnotifierSnsTopic2055CAD8", + }, + "SNS_TOPIC_NAME": Object { + "Fn::GetAtt": Array [ + "checklateordersnotifierSnsTopic2055CAD8", + "TopicName", + ], + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "checklateordersLambdaFunctionServiceRoleA8F250A0", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "checklateordersLambdaFunctionServiceRoleA8F250A0": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "checklateordersLambdaFunctionServiceRoleDefaultPolicy4DABEECE": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + Object { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": Object { + "Ref": "checklateordersnotifierSnsTopic2055CAD8", + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "checklateordersLambdaFunctionServiceRoleDefaultPolicy4DABEECE", + "Roles": Array [ + Object { + "Ref": "checklateordersLambdaFunctionServiceRoleA8F250A0", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "checklateordersnotifierSnsTopic2055CAD8": Object { + "Properties": Object { + "KmsMasterKeyId": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":kms:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":alias/aws/sns", + ], + ], + }, + }, + "Type": "AWS::SNS::Topic", + }, + "checklateordersnotifierSnsTopicPolicyCF0A65E0": Object { + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "SNS:Publish", + "SNS:RemovePermission", + "SNS:SetTopicAttributes", + "SNS:DeleteTopic", + "SNS:ListSubscriptionsByTopic", + "SNS:GetTopicAttributes", + "SNS:Receive", + "SNS:AddPermission", + "SNS:Subscribe", + ], + "Condition": Object { + "StringEquals": Object { + "AWS:SourceOwner": Object { + "Ref": "AWS::AccountId", + }, + }, + }, + "Effect": "Allow", + "Principal": Object { + "AWS": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::", + Object { + "Ref": "AWS::AccountId", + }, + ":root", + ], + ], + }, + }, + "Resource": Object { + "Ref": "checklateordersnotifierSnsTopic2055CAD8", + }, + "Sid": "TopicOwnerOnlyAccess", + }, + Object { + "Action": Array [ + "SNS:Publish", + "SNS:RemovePermission", + "SNS:SetTopicAttributes", + "SNS:DeleteTopic", + "SNS:ListSubscriptionsByTopic", + "SNS:GetTopicAttributes", + "SNS:Receive", + "SNS:AddPermission", + "SNS:Subscribe", + ], + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Object { + "Ref": "checklateordersnotifierSnsTopic2055CAD8", + }, + "Sid": "HttpsOnly", + }, + ], + "Version": "2012-10-17", + }, + "Topics": Array [ + Object { + "Ref": "checklateordersnotifierSnsTopic2055CAD8", + }, + ], + }, + "Type": "AWS::SNS::TopicPolicy", + }, + "checklateordersschedulerchecklateordersschedulerWEventsRule15B31DCC": Object { + "Properties": Object { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": Array [ + Object { + "Arn": Object { + "Fn::GetAtt": Array [ + "checklateordersLambdaFunctionB46EDA7D", + "Arn", + ], + }, + "Id": "Target0", + }, + ], + }, + "Type": "AWS::Events::Rule", + }, + "closeoutserviceExecutionAbortedAlarm861B143E": Object { + "Properties": Object { + "AlarmDescription": "Alarm for the number of executions that aborted exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "Dimensions": Array [ + Object { + "Name": "StateMachineArn", + "Value": Object { + "Ref": "closeoutserviceStateMachineC9DD68A8", + }, + }, + ], + "EvaluationPeriods": 1, + "MetricName": "ExecutionsAborted", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Maximum", + "Threshold": 1, + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "closeoutserviceExecutionFailedAlarm7495D8BE": Object { + "Properties": Object { + "AlarmDescription": "Alarm for the number of executions that failed exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "Dimensions": Array [ + Object { + "Name": "StateMachineArn", + "Value": Object { + "Ref": "closeoutserviceStateMachineC9DD68A8", + }, + }, + ], + "EvaluationPeriods": 1, + "MetricName": "ExecutionsFailed", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Sum", + "Threshold": 1, + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "closeoutserviceExecutionThrottledAlarmC5A6E612": Object { + "Properties": Object { + "AlarmDescription": "Alarm for the number of executions that throttled exceeded the threshold of 1. ", + "ComparisonOperator": "GreaterThanOrEqualToThreshold", + "Dimensions": Array [ + Object { + "Name": "StateMachineArn", + "Value": Object { + "Ref": "closeoutserviceStateMachineC9DD68A8", + }, + }, + ], + "EvaluationPeriods": 1, + "MetricName": "ExecutionThrottled", + "Namespace": "AWS/States", + "Period": 300, + "Statistic": "Sum", + "Threshold": 1, + }, + "Type": "AWS::CloudWatch::Alarm", + }, + "closeoutserviceLambdaFunction684B26D3": Object { + "DependsOn": Array [ + "closeoutserviceLambdaFunctionServiceRoleDefaultPolicy95A79CC3", + "closeoutserviceLambdaFunctionServiceRoleB49E9696", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393S3Bucket514B0A32", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393S3VersionKey0D96EFA5", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParametersbee7a88e44057a981dee36ffd34a5dfeebd59c93fc6b10b697156d547aca9393S3VersionKey0D96EFA5", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "STATE_MACHINE_ARN": Object { + "Ref": "closeoutserviceStateMachineC9DD68A8", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "closeoutserviceLambdaFunctionServiceRoleB49E9696", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "closeoutserviceLambdaFunctionServiceRoleB49E9696": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "closeoutserviceLambdaFunctionServiceRoleDefaultPolicy95A79CC3": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "states:StartExecution", + "Effect": "Allow", + "Resource": Object { + "Ref": "closeoutserviceStateMachineC9DD68A8", + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "closeoutserviceLambdaFunctionServiceRoleDefaultPolicy95A79CC3", + "Roles": Array [ + Object { + "Ref": "closeoutserviceLambdaFunctionServiceRoleB49E9696", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "closeoutserviceStateMachineC9DD68A8": Object { + "DependsOn": Array [ + "closeoutserviceStateMachineRoleDefaultPolicy5F05BEB8", + "closeoutserviceStateMachineRoleCA7F9A09", + ], + "Properties": Object { + "DefinitionString": Object { + "Fn::Join": Array [ + "", + Array [ + "{\\"StartAt\\":\\"create-reports-task\\",\\"States\\":{\\"create-reports-task\\":{\\"Next\\":\\"calculate-tips-task\\",\\"Type\\":\\"Task\\",\\"Resource\\":\\"", + Object { + "Fn::GetAtt": Array [ + "createreportLambdaFunctionB37EBE52", + "Arn", + ], + }, + "\\"},\\"calculate-tips-task\\":{\\"Next\\":\\"archive-orders-task\\",\\"Type\\":\\"Task\\",\\"Resource\\":\\"", + Object { + "Fn::GetAtt": Array [ + "calculatetipsLambdaFunction9F2FE033", + "Arn", + ], + }, + "\\"},\\"archive-orders-task\\":{\\"End\\":true,\\"Type\\":\\"Task\\",\\"Resource\\":\\"", + Object { + "Fn::GetAtt": Array [ + "archiveordersLambdaFunction66659E04", + "Arn", + ], + }, + "\\"}}}", + ], + ], + }, + "LoggingConfiguration": Object { + "Destinations": Array [ + Object { + "CloudWatchLogsLogGroup": Object { + "LogGroupArn": Object { + "Fn::GetAtt": Array [ + "closeoutserviceStateMachineLogGroup56CA2C8F", + "Arn", + ], + }, + }, + }, + ], + "Level": "ERROR", + }, + "RoleArn": Object { + "Fn::GetAtt": Array [ + "closeoutserviceStateMachineRoleCA7F9A09", + "Arn", + ], + }, + }, + "Type": "AWS::StepFunctions::StateMachine", + }, + "closeoutserviceStateMachineLogGroup56CA2C8F": Object { + "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, + "Properties": Object { + "LogGroupName": "/aws/vendedlogs/states/managerstackcloseoutservicestatemachinelog5da3d5b2d585", + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + }, + "closeoutserviceStateMachineRoleCA7F9A09": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": Object { + "Fn::FindInMap": Array [ + "ServiceprincipalMap", + Object { + "Ref": "AWS::Region", + }, + "states", + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "closeoutserviceStateMachineRoleDefaultPolicy5F05BEB8": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "The 'LogDelivery' actions do not support resource-level authorizations", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogDelivery", + "logs:GetLogDelivery", + "logs:UpdateLogDelivery", + "logs:DeleteLogDelivery", + "logs:ListLogDeliveries", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "createreportLambdaFunctionB37EBE52", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "createreportLambdaFunctionB37EBE52", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + Object { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "calculatetipsLambdaFunction9F2FE033", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "calculatetipsLambdaFunction9F2FE033", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + Object { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "archiveordersLambdaFunction66659E04", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "archiveordersLambdaFunction66659E04", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "logs:PutResourcePolicy", + "logs:DescribeResourcePolicies", + "logs:DescribeLogGroups", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "closeoutserviceStateMachineRoleDefaultPolicy5F05BEB8", + "Roles": Array [ + Object { + "Ref": "closeoutserviceStateMachineRoleCA7F9A09", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "createreportLambdaFunctionB37EBE52": Object { + "DependsOn": Array [ + "createreportLambdaFunctionServiceRoleDefaultPolicy5A317B6C", + "createreportLambdaFunctionServiceRole33C78256", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194S3Bucket6E9AF9DD", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194S3VersionKey00C1823E", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters4f63f3314eba5199f6a3a67bcc61daa0b5818e6d1fd850453035e9897c9ea194S3VersionKey00C1823E", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + "S3_BUCKET_NAME": Object { + "Ref": "reportsbucketS3BucketCC334898", + }, + }, + }, + "Handler": "index.handler", + "Layers": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefshareddbfunctionslayerA9CFEC5A89EBE406", + }, + ], + "Role": Object { + "Fn::GetAtt": Array [ + "createreportLambdaFunctionServiceRole33C78256", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "createreportLambdaFunctionServiceRole33C78256": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "createreportLambdaFunctionServiceRoleDefaultPolicy5A317B6C": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject*", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "createreportLambdaFunctionServiceRoleDefaultPolicy5A317B6C", + "Roles": Array [ + Object { + "Ref": "createreportLambdaFunctionServiceRole33C78256", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "getallordersLambdaFunctionFEF65B05": Object { + "DependsOn": Array [ + "getallordersLambdaFunctionServiceRoleDefaultPolicy705A0D9A", + "getallordersLambdaFunctionServiceRole8AF6EF71", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13S3Bucket6D0E979D", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13S3VersionKeyF08F3926", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters3a83da329865c0ce17a9871113042571872da858fb0911bab4526333986b2e13S3VersionKeyF08F3926", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + }, + }, + "Handler": "index.handler", + "Layers": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefshareddbfunctionslayerA9CFEC5A89EBE406", + }, + ], + "Role": Object { + "Fn::GetAtt": Array [ + "getallordersLambdaFunctionServiceRole8AF6EF71", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "getallordersLambdaFunctionServiceRole8AF6EF71": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "getallordersLambdaFunctionServiceRoleDefaultPolicy705A0D9A": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "getallordersLambdaFunctionServiceRoleDefaultPolicy705A0D9A", + "Roles": Array [ + Object { + "Ref": "getallordersLambdaFunctionServiceRole8AF6EF71", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "getreportLambdaFunction2A26EACE": Object { + "DependsOn": Array [ + "getreportLambdaFunctionServiceRoleDefaultPolicy0A75937B", + "getreportLambdaFunctionServiceRole39064368", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0S3Bucket0FECA056", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0S3VersionKeyA5DB7D1B", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters83ada50af307c970f7adc20c9db53c485f8a494eb3f1f5c79964c30a6fc739c0S3VersionKeyA5DB7D1B", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "S3_BUCKET_NAME": Object { + "Ref": "reportsbucketS3BucketCC334898", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "getreportLambdaFunctionServiceRole39064368", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "getreportLambdaFunctionServiceRole39064368": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "getreportLambdaFunctionServiceRoleDefaultPolicy0A75937B": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject*", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "getreportLambdaFunctionServiceRoleDefaultPolicy0A75937B", + "Roles": Array [ + Object { + "Ref": "getreportLambdaFunctionServiceRole39064368", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "managerapiApiAccessLogGroup35F9537B": Object { + "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + }, + "managerapiCognitoAuthorizer5745AF8D": Object { + "Properties": Object { + "IdentitySource": "method.request.header.Authorization", + "Name": "authorizer", + "ProviderARNs": Array [ + Object { + "Fn::GetAtt": Array [ + "managerapiCognitoUserPool03946196", + "Arn", + ], + }, + ], + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "Type": "COGNITO_USER_POOLS", + }, + "Type": "AWS::ApiGateway::Authorizer", + }, + "managerapiCognitoUserPool03946196": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "AccountRecoverySetting": Object { + "RecoveryMechanisms": Array [ + Object { + "Name": "verified_phone_number", + "Priority": 1, + }, + Object { + "Name": "verified_email", + "Priority": 2, + }, + ], + }, + "AdminCreateUserConfig": Object { + "AllowAdminCreateUserOnly": true, + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "UserPoolAddOns": Object { + "AdvancedSecurityMode": "ENFORCED", + }, + "VerificationMessageTemplate": Object { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}", + }, + }, + "Type": "AWS::Cognito::UserPool", + "UpdateReplacePolicy": "Retain", + }, + "managerapiCognitoUserPoolClientB3BC933D": Object { + "Properties": Object { + "AllowedOAuthFlows": Array [ + "implicit", + "code", + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": Array [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin", + ], + "CallbackURLs": Array [ + "https://example.com", + ], + "SupportedIdentityProviders": Array [ + "COGNITO", + ], + "UserPoolId": Object { + "Ref": "managerapiCognitoUserPool03946196", + }, + }, + "Type": "AWS::Cognito::UserPoolClient", + }, + "managerapiLambdaRestApi62BEEAC7": Object { + "Properties": Object { + "Description": "Demo: Manager API", + "EndpointConfiguration": Object { + "Types": Array [ + "EDGE", + ], + }, + "Name": "LambdaRestApi", + }, + "Type": "AWS::ApiGateway::RestApi", + }, + "managerapiLambdaRestApiAccount350A78F5": Object { + "DependsOn": Array [ + "managerapiLambdaRestApi62BEEAC7", + ], + "Properties": Object { + "CloudWatchRoleArn": Object { + "Fn::GetAtt": Array [ + "managerapiLambdaRestApiCloudWatchRole43F48235", + "Arn", + ], + }, + }, + "Type": "AWS::ApiGateway::Account", + }, + "managerapiLambdaRestApiCloudWatchRole43F48235": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "apigateway.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:GetLogEvents", + "logs:FilterLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaRestApiCloudWatchRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "managerapiLambdaRestApiDeployment719D102Abf8fc62f0a59aea37747b68fec60f4a4": Object { + "DependsOn": Array [ + "managerapiLambdaRestApicloseoutserviceproxyANY182BEB46", + "managerapiLambdaRestApicloseoutserviceproxyECAF0FA1", + "managerapiLambdaRestApicloseoutservice2D3987E6", + "managerapiLambdaRestApigetallordersproxyANYEAB740ED", + "managerapiLambdaRestApigetallordersproxyEE336136", + "managerapiLambdaRestApigetallorders29C83FB0", + "managerapiLambdaRestApigetreportproxyANY93C7142D", + "managerapiLambdaRestApigetreportproxy2FB66C91", + "managerapiLambdaRestApigetreportDB310438", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W45", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + }, + ], + }, + }, + "Properties": Object { + "Description": "Automatically created by the RestApi construct", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Deployment", + }, + "managerapiLambdaRestApiDeploymentStageprod59C4A8D4": Object { + "Properties": Object { + "AccessLogSetting": Object { + "DestinationArn": Object { + "Fn::GetAtt": Array [ + "managerapiApiAccessLogGroup35F9537B", + "Arn", + ], + }, + "Format": "{\\"requestId\\":\\"$context.requestId\\",\\"ip\\":\\"$context.identity.sourceIp\\",\\"user\\":\\"$context.identity.user\\",\\"caller\\":\\"$context.identity.caller\\",\\"requestTime\\":\\"$context.requestTime\\",\\"httpMethod\\":\\"$context.httpMethod\\",\\"resourcePath\\":\\"$context.resourcePath\\",\\"status\\":\\"$context.status\\",\\"protocol\\":\\"$context.protocol\\",\\"responseLength\\":\\"$context.responseLength\\"}", + }, + "DeploymentId": Object { + "Ref": "managerapiLambdaRestApiDeployment719D102Abf8fc62f0a59aea37747b68fec60f4a4", + }, + "MethodSettings": Array [ + Object { + "DataTraceEnabled": false, + "HttpMethod": "*", + "LoggingLevel": "INFO", + "ResourcePath": "/*", + }, + ], + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "StageName": "prod", + "TracingEnabled": true, + }, + "Type": "AWS::ApiGateway::Stage", + }, + "managerapiLambdaRestApiUsagePlanF10CE619": Object { + "Properties": Object { + "ApiStages": Array [ + Object { + "ApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "Stage": Object { + "Ref": "managerapiLambdaRestApiDeploymentStageprod59C4A8D4", + }, + "Throttle": Object {}, + }, + ], + }, + "Type": "AWS::ApiGateway::UsagePlan", + }, + "managerapiLambdaRestApicloseoutservice2D3987E6": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "managerapiLambdaRestApi62BEEAC7", + "RootResourceId", + ], + }, + "PathPart": "close-out-service", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApicloseoutserviceproxyANY182BEB46": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "managerapiCognitoAuthorizer5745AF8D", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "closeoutserviceLambdaFunction684B26D3", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "managerapiLambdaRestApicloseoutserviceproxyECAF0FA1", + }, + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "managerapiLambdaRestApicloseoutserviceproxyANYApiPermissionManagerStackmanagerapiLambdaRestApi386CA826ANYcloseoutserviceproxy132F7E1D": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "closeoutserviceLambdaFunction684B26D3", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/", + Object { + "Ref": "managerapiLambdaRestApiDeploymentStageprod59C4A8D4", + }, + "/*/close-out-service/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "managerapiLambdaRestApicloseoutserviceproxyANYApiPermissionTestManagerStackmanagerapiLambdaRestApi386CA826ANYcloseoutserviceproxy8A25C882": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "closeoutserviceLambdaFunction684B26D3", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/test-invoke-stage/*/close-out-service/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "managerapiLambdaRestApicloseoutserviceproxyECAF0FA1": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "managerapiLambdaRestApicloseoutservice2D3987E6", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApigetallorders29C83FB0": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "managerapiLambdaRestApi62BEEAC7", + "RootResourceId", + ], + }, + "PathPart": "get-all-orders", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApigetallordersproxyANYApiPermissionManagerStackmanagerapiLambdaRestApi386CA826ANYgetallordersproxy57374F7E": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getallordersLambdaFunctionFEF65B05", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/", + Object { + "Ref": "managerapiLambdaRestApiDeploymentStageprod59C4A8D4", + }, + "/*/get-all-orders/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "managerapiLambdaRestApigetallordersproxyANYApiPermissionTestManagerStackmanagerapiLambdaRestApi386CA826ANYgetallordersproxy45104276": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getallordersLambdaFunctionFEF65B05", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/test-invoke-stage/*/get-all-orders/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "managerapiLambdaRestApigetallordersproxyANYEAB740ED": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "managerapiCognitoAuthorizer5745AF8D", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "getallordersLambdaFunctionFEF65B05", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "managerapiLambdaRestApigetallordersproxyEE336136", + }, + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "managerapiLambdaRestApigetallordersproxyEE336136": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "managerapiLambdaRestApigetallorders29C83FB0", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApigetreportDB310438": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "managerapiLambdaRestApi62BEEAC7", + "RootResourceId", + ], + }, + "PathPart": "get-report", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApigetreportproxy2FB66C91": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "managerapiLambdaRestApigetreportDB310438", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "managerapiLambdaRestApigetreportproxyANY93C7142D": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "managerapiCognitoAuthorizer5745AF8D", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "getreportLambdaFunction2A26EACE", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "managerapiLambdaRestApigetreportproxy2FB66C91", + }, + "RestApiId": Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "managerapiLambdaRestApigetreportproxyANYApiPermissionManagerStackmanagerapiLambdaRestApi386CA826ANYgetreportproxy80B2B901": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getreportLambdaFunction2A26EACE", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/", + Object { + "Ref": "managerapiLambdaRestApiDeploymentStageprod59C4A8D4", + }, + "/*/get-report/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "managerapiLambdaRestApigetreportproxyANYApiPermissionTestManagerStackmanagerapiLambdaRestApi386CA826ANYgetreportproxy7868B7DA": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "getreportLambdaFunction2A26EACE", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "managerapiLambdaRestApi62BEEAC7", + }, + "/test-invoke-stage/*/get-report/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "reportsbucketS3BucketCC334898": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "BucketEncryption": Object { + "ServerSideEncryptionConfiguration": Array [ + Object { + "ServerSideEncryptionByDefault": Object { + "SSEAlgorithm": "AES256", + }, + }, + ], + }, + "LifecycleConfiguration": Object { + "Rules": Array [ + Object { + "NoncurrentVersionTransitions": Array [ + Object { + "StorageClass": "GLACIER", + "TransitionInDays": 90, + }, + ], + "Status": "Enabled", + }, + ], + }, + "LoggingConfiguration": Object { + "DestinationBucketName": Object { + "Ref": "reportsbucketS3LoggingBucket088F7E0E", + }, + }, + "PublicAccessBlockConfiguration": Object { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true, + }, + "VersioningConfiguration": Object { + "Status": "Enabled", + }, + }, + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + }, + "reportsbucketS3BucketPolicyCF9C1527": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "reportsbucketS3BucketCC334898", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3BucketCC334898", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, + "reportsbucketS3LoggingBucket088F7E0E": Object { + "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W35", + "reason": "This S3 bucket is used as the access logging bucket for another bucket", + }, + ], + }, + }, + "Properties": Object { + "AccessControl": "LogDeliveryWrite", + "BucketEncryption": Object { + "ServerSideEncryptionConfiguration": Array [ + Object { + "ServerSideEncryptionByDefault": Object { + "SSEAlgorithm": "AES256", + }, + }, + ], + }, + "PublicAccessBlockConfiguration": Object { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true, + }, + "VersioningConfiguration": Object { + "Status": "Enabled", + }, + }, + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + }, + "reportsbucketS3LoggingBucketPolicy82A7D267": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "reportsbucketS3LoggingBucket088F7E0E", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3LoggingBucket088F7E0E", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "reportsbucketS3LoggingBucket088F7E0E", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, + }, +} +`; diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap new file mode 100644 index 000000000..b47c344a9 --- /dev/null +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/serviceStaffStack.test.js.snap @@ -0,0 +1,1028 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test-service-staff-stack 1`] = ` +Object { + "Outputs": Object { + "servicestaffapiLambdaRestApiEndpointF8896A96": Object { + "Value": Object { + "Fn::Join": Array [ + "", + Array [ + "https://", + Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + ".execute-api.", + Object { + "Ref": "AWS::Region", + }, + ".", + Object { + "Ref": "AWS::URLSuffix", + }, + "/", + Object { + "Ref": "servicestaffapiLambdaRestApiDeploymentStageprod2DCA6394", + }, + "/", + ], + ], + }, + }, + }, + "Parameters": Object { + "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8ArtifactHash025BE40D": Object { + "Description": "Artifact hash for asset \\"8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8\\"", + "Type": "String", + }, + "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8S3BucketC4EDB090": Object { + "Description": "S3 bucket for asset \\"8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8\\"", + "Type": "String", + }, + "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8S3VersionKey5D4A7E1B": Object { + "Description": "S3 key for asset version \\"8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8\\"", + "Type": "String", + }, + "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080ArtifactHash28E831DC": Object { + "Description": "Artifact hash for asset \\"f340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080\\"", + "Type": "String", + }, + "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080S3Bucket40BD61E4": Object { + "Description": "S3 bucket for asset \\"f340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080\\"", + "Type": "String", + }, + "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080S3VersionKey661F3160": Object { + "Description": "S3 key for asset version \\"f340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080\\"", + "Type": "String", + }, + }, + "Resources": Object { + "createorderLambdaFunction24B8D5B1": Object { + "DependsOn": Array [ + "createorderLambdaFunctionServiceRoleDefaultPolicyA4FD773D", + "createorderLambdaFunctionServiceRole407C1F58", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8S3BucketC4EDB090", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8S3VersionKey5D4A7E1B", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters8a8cc7536577c2b18b202c3f2d96d2e6ef38d6cd26b3cbcc4547ba11759adff8S3VersionKey5D4A7E1B", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "createorderLambdaFunctionServiceRole407C1F58", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "createorderLambdaFunctionServiceRole407C1F58": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "createorderLambdaFunctionServiceRoleDefaultPolicyA4FD773D": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "createorderLambdaFunctionServiceRoleDefaultPolicyA4FD773D", + "Roles": Array [ + Object { + "Ref": "createorderLambdaFunctionServiceRole407C1F58", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "processpaymentLambdaFunction2BB176F5": Object { + "DependsOn": Array [ + "processpaymentLambdaFunctionServiceRoleDefaultPolicy3675D629", + "processpaymentLambdaFunctionServiceRole04F88DC8", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W58", + "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", + }, + Object { + "id": "W89", + "reason": "This is not a rule for the general case, just for specific use cases/industries", + }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, + ], + }, + }, + "Properties": Object { + "Code": Object { + "S3Bucket": Object { + "Ref": "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080S3Bucket40BD61E4", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080S3VersionKey661F3160", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParametersf340dbb5bff487818e0bfbfcd1dcdb62fb8068b86b63fd5e15c68b4d9686a080S3VersionKey661F3160", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Environment": Object { + "Variables": Object { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", + "DDB_TABLE_NAME": Object { + "Fn::ImportValue": "SharedStack:ExportsOutputRefordertable80C5609084F626AD", + }, + }, + }, + "Handler": "index.handler", + "Role": Object { + "Fn::GetAtt": Array [ + "processpaymentLambdaFunctionServiceRole04F88DC8", + "Arn", + ], + }, + "Runtime": "nodejs14.x", + "Timeout": 15, + "TracingConfig": Object { + "Mode": "Active", + }, + }, + "Type": "AWS::Lambda::Function", + }, + "processpaymentLambdaFunctionServiceRole04F88DC8": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":log-group:/aws/lambda/*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaFunctionServiceRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "processpaymentLambdaFunctionServiceRoleDefaultPolicy3675D629": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, + "Properties": Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, + Object { + "Action": Array [ + "dynamodb:BatchGetItem", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:Query", + "dynamodb:GetItem", + "dynamodb:Scan", + "dynamodb:ConditionCheckItem", + "dynamodb:BatchWriteItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + ], + "Effect": "Allow", + "Resource": Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::ImportValue": "SharedStack:ExportsOutputFnGetAttordertable80C56090ArnFF5A50B5", + }, + "/index/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "processpaymentLambdaFunctionServiceRoleDefaultPolicy3675D629", + "Roles": Array [ + Object { + "Ref": "processpaymentLambdaFunctionServiceRole04F88DC8", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "servicestaffapiApiAccessLogGroupF2EF9693": Object { + "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + }, + "servicestaffapiCognitoAuthorizerAD8B40CD": Object { + "Properties": Object { + "IdentitySource": "method.request.header.Authorization", + "Name": "authorizer", + "ProviderARNs": Array [ + Object { + "Fn::GetAtt": Array [ + "servicestaffapiCognitoUserPool3DD3B0E0", + "Arn", + ], + }, + ], + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "Type": "COGNITO_USER_POOLS", + }, + "Type": "AWS::ApiGateway::Authorizer", + }, + "servicestaffapiCognitoUserPool3DD3B0E0": Object { + "DeletionPolicy": "Retain", + "Properties": Object { + "AccountRecoverySetting": Object { + "RecoveryMechanisms": Array [ + Object { + "Name": "verified_phone_number", + "Priority": 1, + }, + Object { + "Name": "verified_email", + "Priority": 2, + }, + ], + }, + "AdminCreateUserConfig": Object { + "AllowAdminCreateUserOnly": true, + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "UserPoolAddOns": Object { + "AdvancedSecurityMode": "ENFORCED", + }, + "VerificationMessageTemplate": Object { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}", + }, + }, + "Type": "AWS::Cognito::UserPool", + "UpdateReplacePolicy": "Retain", + }, + "servicestaffapiCognitoUserPoolClientB6DED78F": Object { + "Properties": Object { + "AllowedOAuthFlows": Array [ + "implicit", + "code", + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": Array [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin", + ], + "CallbackURLs": Array [ + "https://example.com", + ], + "SupportedIdentityProviders": Array [ + "COGNITO", + ], + "UserPoolId": Object { + "Ref": "servicestaffapiCognitoUserPool3DD3B0E0", + }, + }, + "Type": "AWS::Cognito::UserPoolClient", + }, + "servicestaffapiLambdaRestApi81C353A0": Object { + "Properties": Object { + "Description": "Demo: Service staff API", + "EndpointConfiguration": Object { + "Types": Array [ + "EDGE", + ], + }, + "Name": "LambdaRestApi", + }, + "Type": "AWS::ApiGateway::RestApi", + }, + "servicestaffapiLambdaRestApiAccount03DEB06F": Object { + "DependsOn": Array [ + "servicestaffapiLambdaRestApi81C353A0", + ], + "Properties": Object { + "CloudWatchRoleArn": Object { + "Fn::GetAtt": Array [ + "servicestaffapiLambdaRestApiCloudWatchRoleCE0F0BA2", + "Arn", + ], + }, + }, + "Type": "AWS::ApiGateway::Account", + }, + "servicestaffapiLambdaRestApiCloudWatchRoleCE0F0BA2": Object { + "Properties": Object { + "AssumeRolePolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": Object { + "Service": "apigateway.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Policies": Array [ + Object { + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": Array [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:GetLogEvents", + "logs:FilterLogEvents", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":*", + ], + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LambdaRestApiCloudWatchRolePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "servicestaffapiLambdaRestApiDeployment344E0BF0f02c858dd7350b71af50ff6d8f77f6c2": Object { + "DependsOn": Array [ + "servicestaffapiLambdaRestApicreateorderproxyANY3B15F9EA", + "servicestaffapiLambdaRestApicreateorderproxy0E60FED5", + "servicestaffapiLambdaRestApicreateorder06D2A86B", + "servicestaffapiLambdaRestApiprocesspaymentproxyANYE502AA7B", + "servicestaffapiLambdaRestApiprocesspaymentproxy8CA5C2E5", + "servicestaffapiLambdaRestApiprocesspayment6A5A2B17", + ], + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W45", + "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checkes for it in AWS::ApiGateway::Deployment resource", + }, + ], + }, + }, + "Properties": Object { + "Description": "Automatically created by the RestApi construct", + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Deployment", + }, + "servicestaffapiLambdaRestApiDeploymentStageprod2DCA6394": Object { + "Properties": Object { + "AccessLogSetting": Object { + "DestinationArn": Object { + "Fn::GetAtt": Array [ + "servicestaffapiApiAccessLogGroupF2EF9693", + "Arn", + ], + }, + "Format": "{\\"requestId\\":\\"$context.requestId\\",\\"ip\\":\\"$context.identity.sourceIp\\",\\"user\\":\\"$context.identity.user\\",\\"caller\\":\\"$context.identity.caller\\",\\"requestTime\\":\\"$context.requestTime\\",\\"httpMethod\\":\\"$context.httpMethod\\",\\"resourcePath\\":\\"$context.resourcePath\\",\\"status\\":\\"$context.status\\",\\"protocol\\":\\"$context.protocol\\",\\"responseLength\\":\\"$context.responseLength\\"}", + }, + "DeploymentId": Object { + "Ref": "servicestaffapiLambdaRestApiDeployment344E0BF0f02c858dd7350b71af50ff6d8f77f6c2", + }, + "MethodSettings": Array [ + Object { + "DataTraceEnabled": false, + "HttpMethod": "*", + "LoggingLevel": "INFO", + "ResourcePath": "/*", + }, + ], + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "StageName": "prod", + "TracingEnabled": true, + }, + "Type": "AWS::ApiGateway::Stage", + }, + "servicestaffapiLambdaRestApiUsagePlanCCBD3C60": Object { + "Properties": Object { + "ApiStages": Array [ + Object { + "ApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "Stage": Object { + "Ref": "servicestaffapiLambdaRestApiDeploymentStageprod2DCA6394", + }, + "Throttle": Object {}, + }, + ], + }, + "Type": "AWS::ApiGateway::UsagePlan", + }, + "servicestaffapiLambdaRestApicreateorder06D2A86B": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "servicestaffapiLambdaRestApi81C353A0", + "RootResourceId", + ], + }, + "PathPart": "create-order", + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "servicestaffapiLambdaRestApicreateorderproxy0E60FED5": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "servicestaffapiLambdaRestApicreateorder06D2A86B", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "servicestaffapiLambdaRestApicreateorderproxyANY3B15F9EA": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "servicestaffapiCognitoAuthorizerAD8B40CD", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "createorderLambdaFunction24B8D5B1", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "servicestaffapiLambdaRestApicreateorderproxy0E60FED5", + }, + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + "servicestaffapiLambdaRestApicreateorderproxyANYApiPermissionServiceStaffStackservicestaffapiLambdaRestApiA743D41DANYcreateorderproxyB767FAB2": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "createorderLambdaFunction24B8D5B1", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "/", + Object { + "Ref": "servicestaffapiLambdaRestApiDeploymentStageprod2DCA6394", + }, + "/*/create-order/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "servicestaffapiLambdaRestApicreateorderproxyANYApiPermissionTestServiceStaffStackservicestaffapiLambdaRestApiA743D41DANYcreateorderproxy5FF339BE": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "createorderLambdaFunction24B8D5B1", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "/test-invoke-stage/*/create-order/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "servicestaffapiLambdaRestApiprocesspayment6A5A2B17": Object { + "Properties": Object { + "ParentId": Object { + "Fn::GetAtt": Array [ + "servicestaffapiLambdaRestApi81C353A0", + "RootResourceId", + ], + }, + "PathPart": "process-payment", + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "servicestaffapiLambdaRestApiprocesspaymentproxy8CA5C2E5": Object { + "Properties": Object { + "ParentId": Object { + "Ref": "servicestaffapiLambdaRestApiprocesspayment6A5A2B17", + }, + "PathPart": "{proxy+}", + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Resource", + }, + "servicestaffapiLambdaRestApiprocesspaymentproxyANYApiPermissionServiceStaffStackservicestaffapiLambdaRestApiA743D41DANYprocesspaymentproxyD72A3BE0": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "processpaymentLambdaFunction2BB176F5", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "/", + Object { + "Ref": "servicestaffapiLambdaRestApiDeploymentStageprod2DCA6394", + }, + "/*/process-payment/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "servicestaffapiLambdaRestApiprocesspaymentproxyANYApiPermissionTestServiceStaffStackservicestaffapiLambdaRestApiA743D41DANYprocesspaymentproxyFC2482DA": Object { + "Properties": Object { + "Action": "lambda:InvokeFunction", + "FunctionName": Object { + "Fn::GetAtt": Array [ + "processpaymentLambdaFunction2BB176F5", + "Arn", + ], + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":execute-api:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":", + Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + "/test-invoke-stage/*/process-payment/*", + ], + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "servicestaffapiLambdaRestApiprocesspaymentproxyANYE502AA7B": Object { + "Properties": Object { + "AuthorizationType": "COGNITO_USER_POOLS", + "AuthorizerId": Object { + "Ref": "servicestaffapiCognitoAuthorizerAD8B40CD", + }, + "HttpMethod": "ANY", + "Integration": Object { + "IntegrationHttpMethod": "POST", + "Type": "AWS_PROXY", + "Uri": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":apigateway:", + Object { + "Ref": "AWS::Region", + }, + ":lambda:path/2015-03-31/functions/", + Object { + "Fn::GetAtt": Array [ + "processpaymentLambdaFunction2BB176F5", + "Arn", + ], + }, + "/invocations", + ], + ], + }, + }, + "ResourceId": Object { + "Ref": "servicestaffapiLambdaRestApiprocesspaymentproxy8CA5C2E5", + }, + "RestApiId": Object { + "Ref": "servicestaffapiLambdaRestApi81C353A0", + }, + }, + "Type": "AWS::ApiGateway::Method", + }, + }, +} +`; diff --git a/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/sharedStack.test.js.snap b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/sharedStack.test.js.snap new file mode 100644 index 000000000..6b8288345 --- /dev/null +++ b/source/use_cases/aws-restaurant-management-demo/test/__snapshots__/sharedStack.test.js.snap @@ -0,0 +1,171 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test-shared-stack 1`] = ` +Object { + "Parameters": Object { + "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9ArtifactHash1A6D75D8": Object { + "Description": "Artifact hash for asset \\"2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9\\"", + "Type": "String", + }, + "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9S3Bucket7C16E5DF": Object { + "Description": "S3 bucket for asset \\"2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9\\"", + "Type": "String", + }, + "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9S3VersionKeyEA7A0324": Object { + "Description": "S3 key for asset version \\"2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9\\"", + "Type": "String", + }, + }, + "Resources": Object { + "ordertable80C56090": Object { + "DeletionPolicy": "Delete", + "Properties": Object { + "AttributeDefinitions": Array [ + Object { + "AttributeName": "id", + "AttributeType": "S", + }, + Object { + "AttributeName": "gsi1pk", + "AttributeType": "S", + }, + Object { + "AttributeName": "gsi1sk", + "AttributeType": "S", + }, + ], + "GlobalSecondaryIndexes": Array [ + Object { + "IndexName": "gsi1pk-gsi1sk-index", + "KeySchema": Array [ + Object { + "AttributeName": "gsi1pk", + "KeyType": "HASH", + }, + Object { + "AttributeName": "gsi1sk", + "KeyType": "RANGE", + }, + ], + "Projection": Object { + "ProjectionType": "ALL", + }, + "ProvisionedThroughput": Object { + "ReadCapacityUnits": 5, + "WriteCapacityUnits": 5, + }, + }, + ], + "KeySchema": Array [ + Object { + "AttributeName": "id", + "KeyType": "HASH", + }, + ], + "ProvisionedThroughput": Object { + "ReadCapacityUnits": 5, + "WriteCapacityUnits": 5, + }, + }, + "Type": "AWS::DynamoDB::Table", + "UpdateReplacePolicy": "Delete", + }, + "ordertableReadScalingTarget145F706F": Object { + "Properties": Object { + "MaxCapacity": 50, + "MinCapacity": 1, + "ResourceId": Object { + "Fn::Join": Array [ + "", + Array [ + "table/", + Object { + "Ref": "ordertable80C56090", + }, + ], + ], + }, + "RoleARN": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":iam::ACCOUNT_NUMBER_HERE:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable", + ], + ], + }, + "ScalableDimension": "dynamodb:table:ReadCapacityUnits", + "ServiceNamespace": "dynamodb", + }, + "Type": "AWS::ApplicationAutoScaling::ScalableTarget", + }, + "ordertableReadScalingTargetTracking6E5FE6D6": Object { + "Properties": Object { + "PolicyName": "SharedStackordertableReadScalingTargetTracking5EEE9186", + "PolicyType": "TargetTrackingScaling", + "ScalingTargetId": Object { + "Ref": "ordertableReadScalingTarget145F706F", + }, + "TargetTrackingScalingPolicyConfiguration": Object { + "PredefinedMetricSpecification": Object { + "PredefinedMetricType": "DynamoDBReadCapacityUtilization", + }, + "TargetValue": 50, + }, + }, + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + }, + "shareddbfunctionslayerA9CFEC5A": Object { + "Properties": Object { + "CompatibleRuntimes": Array [ + "nodejs14.x", + ], + "Content": Object { + "S3Bucket": Object { + "Ref": "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9S3Bucket7C16E5DF", + }, + "S3Key": Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::Select": Array [ + 0, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9S3VersionKeyEA7A0324", + }, + ], + }, + ], + }, + Object { + "Fn::Select": Array [ + 1, + Object { + "Fn::Split": Array [ + "||", + Object { + "Ref": "AssetParameters2cde1830f2ad369a1330b9dd603fe0b939ec6d81fbe00f66ffb45945750d9da9S3VersionKeyEA7A0324", + }, + ], + }, + ], + }, + ], + ], + }, + }, + "Description": "Layer for common database access functions", + "LicenseInfo": "Apache-2.0", + }, + "Type": "AWS::Lambda::LayerVersion", + }, + }, +} +`; diff --git a/source/use_cases/aws-s3-static-website/test/__snapshots__/s3-static-site-stack.test.js.snap b/source/use_cases/aws-s3-static-website/test/__snapshots__/s3-static-site-stack.test.js.snap index f175f7992..e452686f5 100644 --- a/source/use_cases/aws-s3-static-website/test/__snapshots__/s3-static-site-stack.test.js.snap +++ b/source/use_cases/aws-s3-static-website/test/__snapshots__/s3-static-site-stack.test.js.snap @@ -11,8 +11,8 @@ Object { "https://", Object { "Fn::GetAtt": Array [ - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E", - "RegionalDomainName", + "CloudFrontToS3CloudFrontDistribution241D9866", + "DomainName", ], }, ], @@ -33,21 +33,21 @@ Object { "Description": "S3 key for asset version \\"2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503deb\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": Object { - "Description": "Artifact hash for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916ArtifactHashB448546A": Object { + "Description": "Artifact hash for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": Object { - "Description": "S3 bucket for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF": Object { + "Description": "S3 bucket for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": Object { - "Description": "S3 key for asset version \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD": Object { + "Description": "S3 key for asset version \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, }, "Resources": Object { - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E": Object { + "CloudFrontToS3CloudFrontDistribution241D9866": Object { "Metadata": Object { "cfn_nag": Object { "rules_to_suppress": Array [ @@ -61,30 +61,20 @@ Object { "Properties": Object { "DistributionConfig": Object { "DefaultCacheBehavior": Object { - "AllowedMethods": Array [ - "GET", - "HEAD", - ], - "CachedMethods": Array [ - "GET", - "HEAD", - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": Object { - "Cookies": Object { - "Forward": "none", - }, - "QueryString": false, - }, - "LambdaFunctionAssociations": Array [ + "FunctionAssociations": Array [ Object { - "EventType": "origin-response", - "LambdaFunctionARN": Object { - "Ref": "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE", + "EventType": "viewer-response", + "FunctionARN": Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3SetHttpSecurityHeaders9E6088E2", + "FunctionARN", + ], }, }, ], - "TargetOriginId": "origin1", + "TargetOriginId": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "ViewerProtocolPolicy": "redirect-to-https", }, "DefaultRootObject": "index.html", @@ -98,7 +88,6 @@ Object { "RegionalDomainName", ], }, - "IncludeCookies": false, }, "Origins": Array [ Object { @@ -108,7 +97,7 @@ Object { "RegionalDomainName", ], }, - "Id": "origin1", + "Id": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "S3OriginConfig": Object { "OriginAccessIdentity": Object { "Fn::Join": Array [ @@ -116,7 +105,7 @@ Object { Array [ "origin-access-identity/cloudfront/", Object { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "Ref": "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", }, ], ], @@ -124,18 +113,14 @@ Object { }, }, ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": Object { - "CloudFrontDefaultCertificate": true, - }, }, }, "Type": "AWS::CloudFront::Distribution", }, - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91": Object { + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F": Object { "Properties": Object { "CloudFrontOriginAccessIdentityConfig": Object { - "Comment": "Access S3 bucket content only through CloudFront", + "Comment": "Identity for S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", }, }, "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", @@ -149,10 +134,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", }, - Object { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", - }, ], }, }, @@ -180,6 +161,53 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, + "CloudFrontToS3CloudfrontLoggingBucketPolicy416B82D9": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, "CloudFrontToS3S3Bucket9CE6AB04": Object { "DeletionPolicy": "Retain", "Properties": Object { @@ -192,6 +220,19 @@ Object { }, ], }, + "LifecycleConfiguration": Object { + "Rules": Array [ + Object { + "NoncurrentVersionTransitions": Array [ + Object { + "StorageClass": "GLACIER", + "TransitionInDays": 90, + }, + ], + "Status": "Enabled", + }, + ], + }, "LoggingConfiguration": Object { "DestinationBucketName": Object { "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2", @@ -228,29 +269,16 @@ Object { "PolicyDocument": Object { "Statement": Array [ Object { - "Action": Array [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - ], - "Effect": "Allow", - "Principal": Object { - "AWS": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":iam::cloudfront:user/CloudFront Origin Access Identity ", - Object { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", - }, - ], - ], + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", }, }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, "Resource": Array [ Object { "Fn::GetAtt": Array [ @@ -280,7 +308,7 @@ Object { "Principal": Object { "CanonicalUser": Object { "Fn::GetAtt": Array [ - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", "S3CanonicalUserId", ], }, @@ -315,10 +343,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket", }, - Object { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy", - }, ], }, }, @@ -346,104 +370,64 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, - "CloudFrontToS3SetHttpSecurityHeaders9E6088E2": Object { - "DependsOn": Array [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - ], - "Metadata": Object { - "cfn_nag": Object { - "rules_to_suppress": Array [ - Object { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", - }, - Object { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries", - }, - ], - }, - }, + "CloudFrontToS3S3LoggingBucketPolicy360F3875": Object { "Properties": Object { - "Code": Object { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \\"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\\" } ]; callback(null, response); };", - }, - "Handler": "index.handler", - "Role": Object { - "Fn::GetAtt": Array [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - "Arn", - ], + "Bucket": Object { + "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2", }, - "Runtime": "nodejs14.x", - }, - "Type": "AWS::Lambda::Function", - }, - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10": Object { - "Properties": Object { - "AssumeRolePolicyDocument": Object { + "PolicyDocument": Object { "Statement": Array [ Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": Object { - "Service": "lambda.amazonaws.com", + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, }, - }, - Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", + "Effect": "Deny", "Principal": Object { - "Service": "edgelambda.amazonaws.com", + "AWS": "*", }, - }, - ], - "Version": "2012-10-17", - }, - "Policies": Array [ - Object { - "PolicyDocument": Object { - "Statement": Array [ + "Resource": Array [ Object { - "Action": Array [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", + "Fn::GetAtt": Array [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn", ], - "Effect": "Allow", - "Resource": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:aws:logs:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":log-group:/aws/lambda/*", - ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn", + ], + }, + "/*", ], - }, + ], }, ], - "Version": "2012-10-17", }, - "PolicyName": "LambdaFunctionServiceRolePolicy", - }, - ], + ], + "Version": "2012-10-17", + }, }, - "Type": "AWS::IAM::Role", + "Type": "AWS::S3::BucketPolicy", }, - "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE": Object { + "CloudFrontToS3SetHttpSecurityHeaders9E6088E2": Object { "Properties": Object { - "FunctionName": Object { - "Ref": "CloudFrontToS3SetHttpSecurityHeaders9E6088E2", + "AutoPublish": true, + "FunctionCode": "function handler(event) { var response = event.response; var headers = response.headers; headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; headers['content-security-policy'] = { value: \\"default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'\\"}; headers['x-content-type-options'] = { value: 'nosniff'}; headers['x-frame-options'] = {value: 'DENY'}; headers['x-xss-protection'] = {value: '1; mode=block'}; return response; }", + "FunctionConfig": Object { + "Comment": "SetHttpSecurityHeadersc876981af0ddffc7454da8dcf76a116580471cc611", + "Runtime": "cloudfront-js-1.0", }, + "Name": "SetHttpSecurityHeadersc876981af0ddffc7454da8dcf76a116580471cc611", }, - "Type": "AWS::Lambda::Version", + "Type": "AWS::CloudFront::Function", }, "CustomResource": Object { "DeletionPolicy": "Delete", @@ -471,7 +455,7 @@ Object { "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF", }, "S3Key": Object { "Fn::Join": Array [ @@ -484,7 +468,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -497,7 +481,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -507,6 +491,7 @@ Object { ], }, }, + "Description": "AWS CDK resource provider framework - onEvent (S3StaticWebsiteStack/CustomResourceProvider)", "Environment": Object { "Variables": Object { "USER_ON_EVENT_FUNCTION_ARN": Object { @@ -524,7 +509,7 @@ Object { "Arn", ], }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -567,12 +552,28 @@ Object { Object { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": Object { - "Fn::GetAtt": Array [ - "copyObjHandlerDA1C4669", - "Arn", - ], - }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "copyObjHandlerDA1C4669", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "copyObjHandlerDA1C4669", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], }, ], "Version": "2012-10-17", @@ -684,7 +685,18 @@ Object { ], "Effect": "Allow", "Resource": Array [ - "arn:aws:s3:::wildrydes-us-east-1", + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":s3:::wildrydes-us-east-1", + ], + ], + }, "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*", ], }, @@ -705,7 +717,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:s3:::", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":s3:::", Object { "Ref": "CloudFrontToS3S3Bucket9CE6AB04", }, diff --git a/source/use_cases/aws-s3-static-website/test/integ.basic-deployment.expected.json b/source/use_cases/aws-s3-static-website/test/integ.basic-deployment.expected.json index af4358c12..50924503d 100644 --- a/source/use_cases/aws-s3-static-website/test/integ.basic-deployment.expected.json +++ b/source/use_cases/aws-s3-static-website/test/integ.basic-deployment.expected.json @@ -31,15 +31,58 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket" - }, - { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy" } ] } } }, + "CloudFrontToS3S3LoggingBucketPolicy360F3875": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, "CloudFrontToS3S3Bucket9CE6AB04": { "Type": "AWS::S3::Bucket", "Properties": { @@ -52,6 +95,19 @@ } ] }, + "LifecycleConfiguration": { + "Rules": [ + { + "NoncurrentVersionTransitions": [ + { + "StorageClass": "GLACIER", + "TransitionInDays": 90 + } + ], + "Status": "Enabled" + } + ] + }, "LoggingConfiguration": { "DestinationBucketName": { "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2" @@ -79,29 +135,16 @@ "PolicyDocument": { "Statement": [ { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::cloudfront:user/CloudFront Origin Access Identity ", - { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91" - } - ] - ] + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" } }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, "Resource": [ { "Fn::GetAtt": [ @@ -131,7 +174,7 @@ "Principal": { "CanonicalUser": { "Fn::GetAtt": [ - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", "S3CanonicalUserId" ] } @@ -166,110 +209,15 @@ } } }, - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91": { - "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", - "Properties": { - "CloudFrontOriginAccessIdentityConfig": { - "Comment": "Access S3 bucket content only through CloudFront" - } - } - }, - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "edgelambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Policies": [ - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:logs:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":log-group:/aws/lambda/*" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "LambdaFunctionServiceRolePolicy" - } - ] - } - }, "CloudFrontToS3SetHttpSecurityHeaders9E6088E2": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\" } ]; callback(null, response); };" - }, - "Handler": "index.handler", - "Role": { - "Fn::GetAtt": [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - "Arn" - ] - }, - "Runtime": "nodejs14.x" - }, - "DependsOn": [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10" - ], - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ - { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions." - }, - { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries" - } - ] - } - } - }, - "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE": { - "Type": "AWS::Lambda::Version", + "Type": "AWS::CloudFront::Function", "Properties": { - "FunctionName": { - "Ref": "CloudFrontToS3SetHttpSecurityHeaders9E6088E2" + "Name": "SetHttpSecurityHeadersc89bf7cb13bc7f7194252ea024cb8eeb4e31b4fd0e", + "AutoPublish": true, + "FunctionCode": "function handler(event) { var response = event.response; var headers = response.headers; headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; headers['content-security-policy'] = { value: \"default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'\"}; headers['x-content-type-options'] = { value: 'nosniff'}; headers['x-frame-options'] = {value: 'DENY'}; headers['x-xss-protection'] = {value: '1; mode=block'}; return response; }", + "FunctionConfig": { + "Comment": "SetHttpSecurityHeadersc89bf7cb13bc7f7194252ea024cb8eeb4e31b4fd0e", + "Runtime": "cloudfront-js-1.0" } } }, @@ -304,44 +252,85 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" - }, - { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" } ] } } }, - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E": { + "CloudFrontToS3CloudfrontLoggingBucketPolicy416B82D9": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "CloudFrontToS3CloudfrontLoggingBucket8350BE9B" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F": { + "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "Properties": { + "CloudFrontOriginAccessIdentityConfig": { + "Comment": "Identity for StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1EFE54F66" + } + } + }, + "CloudFrontToS3CloudFrontDistribution241D9866": { "Type": "AWS::CloudFront::Distribution", "Properties": { "DistributionConfig": { "DefaultCacheBehavior": { - "AllowedMethods": [ - "GET", - "HEAD" - ], - "CachedMethods": [ - "GET", - "HEAD" - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": { - "Cookies": { - "Forward": "none" - }, - "QueryString": false - }, - "LambdaFunctionAssociations": [ + "FunctionAssociations": [ { - "EventType": "origin-response", - "LambdaFunctionARN": { - "Ref": "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE" + "EventType": "viewer-response", + "FunctionARN": { + "Fn::GetAtt": [ + "CloudFrontToS3SetHttpSecurityHeaders9E6088E2", + "FunctionARN" + ] } } ], - "TargetOriginId": "origin1", + "TargetOriginId": "StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1EFE54F66", "ViewerProtocolPolicy": "redirect-to-https" }, "DefaultRootObject": "index.html", @@ -354,8 +343,7 @@ "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", "RegionalDomainName" ] - }, - "IncludeCookies": false + } }, "Origins": [ { @@ -365,7 +353,7 @@ "RegionalDomainName" ] }, - "Id": "origin1", + "Id": "StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1EFE54F66", "S3OriginConfig": { "OriginAccessIdentity": { "Fn::Join": [ @@ -373,18 +361,14 @@ [ "origin-access-identity/cloudfront/", { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91" + "Ref": "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F" } ] ] } } } - ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": { - "CloudFrontDefaultCertificate": true - } + ] } }, "Metadata": { @@ -441,7 +425,18 @@ ], "Effect": "Allow", "Resource": [ - "arn:aws:s3:::wildrydes-us-east-1", + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::wildrydes-us-east-1" + ] + ] + }, "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" ] }, @@ -462,7 +457,11 @@ "Fn::Join": [ "", [ - "arn:aws:s3:::", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", { "Ref": "CloudFrontToS3S3Bucket9CE6AB04" } @@ -499,49 +498,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debS3BucketC3836BD9" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debS3VersionKeyEDA18BF9" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debS3VersionKeyEDA18BF9" - } - ] - } - ] - } - ] - ] - } + "S3Key": "2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503deb.zip" }, - "Handler": "copy_s3_objects.on_event", "Role": { "Fn::GetAtt": [ "copyObjHandlerServiceRoleA0ECE649", "Arn" ] }, + "Handler": "copy_s3_objects.on_event", "Runtime": "python3.8", "Timeout": 300 }, @@ -589,12 +556,28 @@ { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "copyObjHandlerDA1C4669", - "Arn" - ] - } + "Resource": [ + { + "Fn::GetAtt": [ + "copyObjHandlerDA1C4669", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "copyObjHandlerDA1C4669", + "Arn" + ] + }, + ":*" + ] + ] + } + ] } ], "Version": "2012-10-17" @@ -612,50 +595,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - } - ] - ] - } + "S3Key": "543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916.zip" }, - "Handler": "framework.onEvent", "Role": { "Fn::GetAtt": [ "CustomResourceProviderframeworkonEventServiceRole7EBC5835", "Arn" ] }, - "Runtime": "nodejs14.x", + "Description": "AWS CDK resource provider framework - onEvent (StaticWebsiteStack/CustomResourceProvider)", "Environment": { "Variables": { "USER_ON_EVENT_FUNCTION_ARN": { @@ -666,6 +616,8 @@ } } }, + "Handler": "framework.onEvent", + "Runtime": "nodejs12.x", "Timeout": 900 }, "DependsOn": [ @@ -692,32 +644,6 @@ "DeletionPolicy": "Delete" } }, - "Parameters": { - "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debS3BucketC3836BD9": { - "Type": "String", - "Description": "S3 bucket for asset \"2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503deb\"" - }, - "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debS3VersionKeyEDA18BF9": { - "Type": "String", - "Description": "S3 key for asset version \"2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503deb\"" - }, - "AssetParameters2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503debArtifactHashA2BE913F": { - "Type": "String", - "Description": "Artifact hash for asset \"2a96a41ef8e6db639865e8dc7826848e60ba75ebdb553c6c9bf2f961ef503deb\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": { - "Type": "String", - "Description": "S3 bucket for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": { - "Type": "String", - "Description": "S3 key for asset version \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": { - "Type": "String", - "Description": "Artifact hash for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - } - }, "Outputs": { "websiteURL": { "Value": { @@ -727,13 +653,47 @@ "https://", { "Fn::GetAtt": [ - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E", - "RegionalDomainName" + "CloudFrontToS3CloudFrontDistribution241D9866", + "DomainName" ] } ] ] } } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } } } \ No newline at end of file diff --git a/source/use_cases/aws-s3-static-website/test/s3-static-site-stack.test.ts b/source/use_cases/aws-s3-static-website/test/s3-static-site-stack.test.ts index e46ce063c..cfd5d269d 100644 --- a/source/use_cases/aws-s3-static-website/test/s3-static-site-stack.test.ts +++ b/source/use_cases/aws-s3-static-website/test/s3-static-site-stack.test.ts @@ -54,60 +54,74 @@ test('check s3 bucket public access setting', () => { test('check CR lambda function permissions', () => { const app = new cdk.App(); const stack = new S3StaticWebsiteStack(app, 'S3StaticWebsiteStack'); - expect(stack).toHaveResource("AWS::IAM::Policy", { - PolicyDocument: { - Statement: [ - { - Action: [ - "s3:GetObject", - "s3:ListBucket" - ], - Effect: "Allow", - Resource: [ - "arn:aws:s3:::wildrydes-us-east-1", - "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" - ] - }, - { - Action: [ - "s3:ListBucket", - "s3:GetObject", - "s3:PutObject", - "s3:PutObjectAcl", - "s3:PutObjectVersionAcl", - "s3:DeleteObject", - "s3:DeleteObjectVersion", - "s3:CopyObject" - ], - Effect: "Allow", - Resource: [ - { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - Ref: "CloudFrontToS3S3Bucket9CE6AB04" - } + expect(stack).toHaveResourceLike("AWS::IAM::Policy",{ + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::wildrydes-us-east-1" + ] ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - Ref: "CloudFrontToS3S3Bucket9CE6AB04" - }, - "/*" + }, + "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" + ] + }, + { + "Action": [ + "s3:ListBucket", + "s3:GetObject", + "s3:PutObject", + "s3:PutObjectAcl", + "s3:PutObjectVersionAcl", + "s3:DeleteObject", + "s3:DeleteObjectVersion", + "s3:CopyObject" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + } + ] ] - ] - } - ] - } - ], - Version: "2012-10-17" + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + }, + "/*" + ] + ] + } + ] + } +] }, PolicyName: "copyObjHandlerServiceRoleDefaultPolicyFCA51C18", Roles: [ @@ -116,4 +130,5 @@ test('check CR lambda function permissions', () => { } ] }); -}); \ No newline at end of file +}); + diff --git a/source/use_cases/aws-serverless-image-handler/lib/index.ts b/source/use_cases/aws-serverless-image-handler/lib/index.ts index bae358422..550d2be51 100644 --- a/source/use_cases/aws-serverless-image-handler/lib/index.ts +++ b/source/use_cases/aws-serverless-image-handler/lib/index.ts @@ -74,7 +74,7 @@ export interface ServerlessImageHandlerCustomProps { * * @default - false. */ - readonly cloudFrontDistributionProps?: cloudfront.DistributionProps | any, + readonly cloudFrontDistributionProps?: cloudFront.DistributionProps | any, /** * Optional user provided props to override the default props for the API Gateway REST API. * @@ -195,18 +195,18 @@ export class ServerlessImageHandler extends Construct { // Add the SOURCE_BUCKETS environment variable to the Lambda function const bucketsArr = (props.sourceBuckets !== "") ? props.sourceBuckets.split(',') : []; - bucketsArr.push(this.lambdaS3.s3Bucket.bucketName); + bucketsArr.push(this.safeGetBucketProperty().bucketName); const bucketsStr = bucketsArr.toString().replace(/\s+/g, ''); this.cloudFrontApiGatewayLambda.lambdaFunction.addEnvironment("SOURCE_BUCKETS", bucketsStr); } /** * @summary Returns an instance of cloudFront.CloudFrontWebDistribution created by the construct. - * @returns { cloudFront.CloudFrontWebDistribution } Instance of CloudFrontWebDistribution created by the construct. + * @returns { cloudFront.Distribution } Instance of CloudFrontWebDistribution created by the construct. * @since 0.8.0 * @access public */ - public cloudFrontDistribution(): cloudFront.CloudFrontWebDistribution { + public cloudFrontDistribution(): cloudFront.Distribution { return this.cloudFrontApiGatewayLambda.cloudFrontWebDistribution; } @@ -237,6 +237,17 @@ export class ServerlessImageHandler extends Construct { * @access public */ public s3Bucket(): s3.Bucket { - return this.lambdaS3.s3Bucket; + return this.safeGetBucketProperty(); + } + + private safeGetBucketProperty(): s3.Bucket { + // When LambdaToS3 was altered to accept IBucket, the + // s3Bucket property became optional. This app always + // has LambdaToS3 create a new bucket, so if the S3Bucket property + // is undefined, then an invalid situation has arisen. + if (!this.lambdaS3.s3Bucket) { + throw Error('s3Bucket is not set - this should never occur'); + } + return this.lambdaS3.s3Bucket; } } \ No newline at end of file diff --git a/source/use_cases/aws-serverless-image-handler/test/__snapshots__/test.serverless-image-handler.test.js.snap b/source/use_cases/aws-serverless-image-handler/test/__snapshots__/test.serverless-image-handler.test.js.snap index cd74d7d04..c47014469 100644 --- a/source/use_cases/aws-serverless-image-handler/test/__snapshots__/test.serverless-image-handler.test.js.snap +++ b/source/use_cases/aws-serverless-image-handler/test/__snapshots__/test.serverless-image-handler.test.js.snap @@ -31,26 +31,40 @@ Object { }, }, "Parameters": Object { - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96ArtifactHash7AE27721": Object { - "Description": "Artifact hash for asset \\"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\\"", + "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1ArtifactHash1C81AD0D": Object { + "Description": "Artifact hash for asset \\"cd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1\\"", "Type": "String", }, - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3Bucket65CDB50E": Object { - "Description": "S3 bucket for asset \\"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\\"", + "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1S3Bucket55C0D3E0": Object { + "Description": "S3 bucket for asset \\"cd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1\\"", "Type": "String", }, - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1": Object { - "Description": "S3 key for asset version \\"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\\"", + "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1S3VersionKeyE00C37AD": Object { + "Description": "S3 key for asset version \\"cd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1\\"", "Type": "String", }, }, "Resources": Object { "testserverlessimagehandlerCloudFrontApiGatewayLambdaApiAccessLogGroup75A8AB40": Object { "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, "Type": "AWS::Logs::LogGroup", "UpdateReplacePolicy": "Retain", }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionCFDistribution5DCC756A": Object { + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution73757325": Object { "Metadata": Object { "cfn_nag": Object { "rules_to_suppress": Array [ @@ -64,33 +78,22 @@ Object { "Properties": Object { "DistributionConfig": Object { "DefaultCacheBehavior": Object { - "AllowedMethods": Array [ - "GET", - "HEAD", - ], - "CachedMethods": Array [ - "GET", - "HEAD", - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": Object { - "Cookies": Object { - "Forward": "none", - }, - "QueryString": false, - }, - "LambdaFunctionAssociations": Array [ + "FunctionAssociations": Array [ Object { - "EventType": "origin-response", - "LambdaFunctionARN": Object { - "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersVersion5920FF7F", + "EventType": "viewer-response", + "FunctionARN": Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59", + "FunctionARN", + ], }, }, ], - "TargetOriginId": "origin1", + "TargetOriginId": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin161738C6A", "ViewerProtocolPolicy": "redirect-to-https", }, - "DefaultRootObject": "index.html", "Enabled": true, "HttpVersion": "http2", "IPV6Enabled": true, @@ -101,16 +104,11 @@ Object { "RegionalDomainName", ], }, - "IncludeCookies": false, }, "Origins": Array [ Object { "CustomOriginConfig": Object { - "HTTPPort": 80, - "HTTPSPort": 443, - "OriginKeepaliveTimeout": 5, "OriginProtocolPolicy": "https-only", - "OriginReadTimeout": 30, "OriginSSLProtocols": Array [ "TLSv1.2", ], @@ -159,13 +157,20 @@ Object { }, ], }, - "Id": "origin1", + "Id": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin161738C6A", + "OriginPath": Object { + "Fn::Join": Array [ + "", + Array [ + "/", + Object { + "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageprodBD57762D", + }, + ], + ], + }, }, ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": Object { - "CloudFrontDefaultCertificate": true, - }, }, }, "Type": "AWS::CloudFront::Distribution", @@ -179,10 +184,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", }, - Object { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", - }, ], }, }, @@ -210,104 +211,64 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59": Object { - "DependsOn": Array [ - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325", - ], - "Metadata": Object { - "cfn_nag": Object { - "rules_to_suppress": Array [ - Object { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", - }, - Object { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries", - }, - ], - }, - }, + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucketPolicy966FBA77": Object { "Properties": Object { - "Code": Object { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \\"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\\" } ]; callback(null, response); };", - }, - "Handler": "index.handler", - "Role": Object { - "Fn::GetAtt": Array [ - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325", - "Arn", - ], + "Bucket": Object { + "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", }, - "Runtime": "nodejs14.x", - }, - "Type": "AWS::Lambda::Function", - }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325": Object { - "Properties": Object { - "AssumeRolePolicyDocument": Object { + "PolicyDocument": Object { "Statement": Array [ Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": Object { - "Service": "lambda.amazonaws.com", + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, }, - }, - Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", + "Effect": "Deny", "Principal": Object { - "Service": "edgelambda.amazonaws.com", + "AWS": "*", }, - }, - ], - "Version": "2012-10-17", - }, - "Policies": Array [ - Object { - "PolicyDocument": Object { - "Statement": Array [ + "Resource": Array [ Object { - "Action": Array [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", + "Fn::GetAtt": Array [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", + "Arn", ], - "Effect": "Allow", - "Resource": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:aws:logs:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":log-group:/aws/lambda/*", - ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", + "Arn", + ], + }, + "/*", ], - }, + ], }, ], - "Version": "2012-10-17", }, - "PolicyName": "LambdaFunctionServiceRolePolicy", - }, - ], + ], + "Version": "2012-10-17", + }, }, - "Type": "AWS::IAM::Role", + "Type": "AWS::S3::BucketPolicy", }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersVersion5920FF7F": Object { + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59": Object { "Properties": Object { - "FunctionName": Object { - "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59", + "AutoPublish": true, + "FunctionCode": "function handler(event) { var response = event.response; var headers = response.headers; headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; headers['content-security-policy'] = { value: \\"default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'\\"}; headers['x-content-type-options'] = { value: 'nosniff'}; headers['x-frame-options'] = {value: 'DENY'}; headers['x-xss-protection'] = {value: '1; mode=block'}; return response; }", + "FunctionConfig": Object { + "Comment": "SetHttpSecurityHeadersc892743f1cbff1695f678386f5b532b064c85bbbbd", + "Runtime": "cloudfront-js-1.0", }, + "Name": "SetHttpSecurityHeadersc892743f1cbff1695f678386f5b532b064c85bbbbd", }, - "Type": "AWS::Lambda::Version", + "Type": "AWS::CloudFront::Function", }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaFunctionF12AF5FC": Object { "DependsOn": Array [ @@ -325,13 +286,17 @@ Object { "id": "W89", "reason": "This is not a rule for the general case, just for specific use cases/industries", }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, ], }, }, "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3Bucket65CDB50E", + "Ref": "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1S3Bucket55C0D3E0", }, "S3Key": Object { "Fn::Join": Array [ @@ -344,7 +309,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1", + "Ref": "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1S3VersionKeyE00C37AD", }, ], }, @@ -357,7 +322,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1", + "Ref": "AssetParameterscd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1S3VersionKeyE00C37AD", }, ], }, @@ -397,6 +362,9 @@ Object { ], }, "Runtime": "nodejs14.x", + "TracingConfig": Object { + "Mode": "Active", + }, }, "Type": "AWS::Lambda::Function", }, @@ -429,7 +397,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:logs:", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", Object { "Ref": "AWS::Region", }, @@ -452,9 +424,27 @@ Object { "Type": "AWS::IAM::Role", }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaFunctionServiceRoleDefaultPolicy9E8AAE29": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, "Properties": Object { "PolicyDocument": Object { "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, Object { "Action": Array [ "s3:GetObject*", @@ -593,8 +583,18 @@ Object { "Type": "AWS::Lambda::Permission", }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiANYBB77827B": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W59", + "reason": "AWS::ApiGateway::Method AuthorizationType is set to 'NONE' because API Gateway behind CloudFront does not support AWS_IAM authentication", + }, + ], + }, + }, "Properties": Object { - "AuthorizationType": "AWS_IAM", + "AuthorizationType": "NONE", "HttpMethod": "ANY", "Integration": Object { "IntegrationHttpMethod": "POST", @@ -682,7 +682,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:logs:", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", Object { "Ref": "AWS::Region", }, @@ -744,7 +748,7 @@ Object { }, "MethodSettings": Array [ Object { - "DataTraceEnabled": true, + "DataTraceEnabled": false, "HttpMethod": "*", "LoggingLevel": "INFO", "ResourcePath": "/*", @@ -754,6 +758,7 @@ Object { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA", }, "StageName": "prod", + "TracingEnabled": true, }, "Type": "AWS::ApiGateway::Stage", }, @@ -818,7 +823,7 @@ Object { Object { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA", }, - "/test-invoke-stage/*/{proxy+}", + "/test-invoke-stage/*/*", ], ], }, @@ -859,7 +864,7 @@ Object { Object { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageprodBD57762D", }, - "/*/{proxy+}", + "/*/*", ], ], }, @@ -867,8 +872,18 @@ Object { "Type": "AWS::Lambda::Permission", }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyANYF4D41A65": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W59", + "reason": "AWS::ApiGateway::Method AuthorizationType is set to 'NONE' because API Gateway behind CloudFront does not support AWS_IAM authentication", + }, + ], + }, + }, "Properties": Object { - "AuthorizationType": "AWS_IAM", + "AuthorizationType": "NONE", "HttpMethod": "ANY", "Integration": Object { "IntegrationHttpMethod": "POST", @@ -908,16 +923,6 @@ Object { }, "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662": Object { "DeletionPolicy": "Retain", - "Metadata": Object { - "cfn_nag": Object { - "rules_to_suppress": Array [ - Object { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy", - }, - ], - }, - }, "Properties": Object { "BucketEncryption": Object { "ServerSideEncryptionConfiguration": Array [ @@ -928,6 +933,19 @@ Object { }, ], }, + "LifecycleConfiguration": Object { + "Rules": Array [ + Object { + "NoncurrentVersionTransitions": Array [ + Object { + "StorageClass": "GLACIER", + "TransitionInDays": 90, + }, + ], + "Status": "Enabled", + }, + ], + }, "LoggingConfiguration": Object { "DestinationBucketName": Object { "Ref": "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", @@ -946,6 +964,53 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, + "testserverlessimagehandlerExistingLambdaS3S3BucketPolicy4313A384": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181": Object { "DeletionPolicy": "Retain", "Metadata": Object { @@ -955,10 +1020,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket", }, - Object { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy", - }, ], }, }, @@ -986,6 +1047,53 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucketPolicy1D599FE4": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, "testserverlessimagehandlerLambdaS3AccessPolicyD6DC56B2": Object { "Metadata": Object { "cfn_nag": Object { diff --git a/source/use_cases/aws-serverless-image-handler/test/integ.basic-deployment.expected.json b/source/use_cases/aws-serverless-image-handler/test/integ.basic-deployment.expected.json index ee3b6ef51..e210f84f4 100644 --- a/source/use_cases/aws-serverless-image-handler/test/integ.basic-deployment.expected.json +++ b/source/use_cases/aws-serverless-image-handler/test/integ.basic-deployment.expected.json @@ -31,7 +31,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -57,13 +61,25 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords" + ], + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "s3:GetObject*", "s3:GetBucket*", "s3:List*", "s3:DeleteObject*", - "s3:PutObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", "s3:Abort*" ], "Effect": "Allow", @@ -99,6 +115,16 @@ "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaFunctionServiceRole110B3FC6" } ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC." + } + ] + } } }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaFunctionF12AF5FC": { @@ -106,56 +132,22 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3Bucket65CDB50E" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1" - } - ] - } - ] - } - ] - ] - } + "S3Key": "cd62adae72264cea63bda88de1b14cf6c4cec29557ae44e526714470d2e2f1f1.zip" }, - "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaFunctionServiceRole110B3FC6", "Arn" ] }, - "Runtime": "nodejs14.x", "Environment": { "Variables": { - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", "AUTO_WEBP": "No", "CORS_ENABLED": "Yes", "CORS_ORIGIN": "*", + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", "S3_BUCKET_NAME": { "Ref": "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662" }, @@ -171,6 +163,11 @@ ] } } + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x", + "TracingConfig": { + "Mode": "Active" } }, "DependsOn": [ @@ -187,6 +184,10 @@ { "id": "W89", "reason": "This is not a rule for the general case, just for specific use cases/industries" + }, + { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients" } ] } @@ -195,7 +196,21 @@ "testserverlessimagehandlerCloudFrontApiGatewayLambdaApiAccessLogGroup75A8AB40": { "Type": "AWS::Logs::LogGroup", "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely" + }, + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA": { "Type": "AWS::ApiGateway::RestApi", @@ -255,13 +270,14 @@ }, "MethodSettings": [ { - "DataTraceEnabled": true, + "DataTraceEnabled": false, "HttpMethod": "*", "LoggingLevel": "INFO", "ResourcePath": "/*" } ], - "StageName": "prod" + "StageName": "prod", + "TracingEnabled": true } }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiproxy4612A938": { @@ -314,7 +330,7 @@ { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageprodBD57762D" }, - "/*/{proxy+}" + "/*/*" ] ] } @@ -351,7 +367,7 @@ { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA" }, - "/test-invoke-stage/*/{proxy+}" + "/test-invoke-stage/*/*" ] ] } @@ -367,7 +383,7 @@ "RestApiId": { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA" }, - "AuthorizationType": "AWS_IAM", + "AuthorizationType": "NONE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -395,6 +411,16 @@ ] } } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W59", + "reason": "AWS::ApiGateway::Method AuthorizationType is set to 'NONE' because API Gateway behind CloudFront does not support AWS_IAM authentication" + } + ] + } } }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiANYApiPermissiontestserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi39D5B0E8ANYE42619BB": { @@ -488,7 +514,7 @@ "RestApiId": { "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA" }, - "AuthorizationType": "AWS_IAM", + "AuthorizationType": "NONE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", @@ -516,6 +542,16 @@ ] } } + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W59", + "reason": "AWS::ApiGateway::Method AuthorizationType is set to 'NONE' because API Gateway behind CloudFront does not support AWS_IAM authentication" + } + ] + } } }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiUsagePlan24615316": { @@ -568,7 +604,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -603,102 +643,15 @@ "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApi7B1E91FA" ] }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "edgelambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Policies": [ - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:logs:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":log-group:/aws/lambda/*" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "LambdaFunctionServiceRolePolicy" - } - ] - } - }, "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59": { - "Type": "AWS::Lambda::Function", + "Type": "AWS::CloudFront::Function", "Properties": { - "Code": { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\" } ]; callback(null, response); };" - }, - "Handler": "index.handler", - "Role": { - "Fn::GetAtt": [ - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325", - "Arn" - ] - }, - "Runtime": "nodejs14.x" - }, - "DependsOn": [ - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersServiceRole6A96B325" - ], - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ - { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions." - }, - { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries" - } - ] - } - } - }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersVersion5920FF7F": { - "Type": "AWS::Lambda::Version", - "Properties": { - "FunctionName": { - "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59" + "Name": "SetHttpSecurityHeadersc837763a6a3a9a67e25b11f161390c447daaa927a0", + "AutoPublish": true, + "FunctionCode": "function handler(event) { var response = event.response; var headers = response.headers; headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; headers['content-security-policy'] = { value: \"default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'\"}; headers['x-content-type-options'] = { value: 'nosniff'}; headers['x-frame-options'] = {value: 'DENY'}; headers['x-xss-protection'] = {value: '1; mode=block'}; return response; }", + "FunctionConfig": { + "Comment": "SetHttpSecurityHeadersc837763a6a3a9a67e25b11f161390c447daaa927a0", + "Runtime": "cloudfront-js-1.0" } } }, @@ -733,47 +686,79 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" - }, - { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" } ] } } }, - "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionCFDistribution5DCC756A": { + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucketPolicy966FBA77": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution73757325": { "Type": "AWS::CloudFront::Distribution", "Properties": { "DistributionConfig": { "DefaultCacheBehavior": { - "AllowedMethods": [ - "GET", - "HEAD" - ], - "CachedMethods": [ - "GET", - "HEAD" - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": { - "Cookies": { - "Forward": "none" - }, - "QueryString": false - }, - "LambdaFunctionAssociations": [ + "FunctionAssociations": [ { - "EventType": "origin-response", - "LambdaFunctionARN": { - "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersVersion5920FF7F" + "EventType": "viewer-response", + "FunctionARN": { + "Fn::GetAtt": [ + "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewaySetHttpSecurityHeadersC49E7B59", + "FunctionARN" + ] } } ], - "TargetOriginId": "origin1", + "TargetOriginId": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin1C13C667A", "ViewerProtocolPolicy": "redirect-to-https" }, - "DefaultRootObject": "index.html", "Enabled": true, "HttpVersion": "http2", "IPV6Enabled": true, @@ -783,17 +768,12 @@ "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudfrontLoggingBucket58AA7378", "RegionalDomainName" ] - }, - "IncludeCookies": false + } }, "Origins": [ { "CustomOriginConfig": { - "HTTPPort": 80, - "HTTPSPort": 443, - "OriginKeepaliveTimeout": 5, "OriginProtocolPolicy": "https-only", - "OriginReadTimeout": 30, "OriginSSLProtocols": [ "TLSv1.2" ] @@ -842,13 +822,20 @@ } ] }, - "Id": "origin1" + "Id": "testserverlessimagehandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin1C13C667A", + "OriginPath": { + "Fn::Join": [ + "", + [ + "/", + { + "Ref": "testserverlessimagehandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageprodBD57762D" + } + ] + ] + } } - ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": { - "CloudFrontDefaultCertificate": true - } + ] } }, "Metadata": { @@ -893,15 +880,58 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket" - }, - { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy" } ] } } }, + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucketPolicy1D599FE4": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662": { "Type": "AWS::S3::Bucket", "Properties": { @@ -914,6 +944,19 @@ } ] }, + "LifecycleConfiguration": { + "Rules": [ + { + "NoncurrentVersionTransitions": [ + { + "StorageClass": "GLACIER", + "TransitionInDays": 90 + } + ], + "Status": "Enabled" + } + ] + }, "LoggingConfiguration": { "DestinationBucketName": { "Ref": "testserverlessimagehandlerExistingLambdaS3S3LoggingBucket406E2181" @@ -930,15 +973,52 @@ } }, "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain", - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ + "DeletionPolicy": "Retain" + }, + "testserverlessimagehandlerExistingLambdaS3S3BucketPolicy4313A384": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662" + }, + "PolicyDocument": { + "Statement": [ { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy" + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "testserverlessimagehandlerExistingLambdaS3S3Bucket9203E662", + "Arn" + ] + }, + "/*" + ] + ] + } + ] } - ] + ], + "Version": "2012-10-17" } } }, @@ -1012,17 +1092,37 @@ } }, "Parameters": { - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3Bucket65CDB50E": { - "Type": "String", - "Description": "S3 bucket for asset \"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\"" - }, - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96S3VersionKeyCF89D2F1": { - "Type": "String", - "Description": "S3 key for asset version \"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\"" - }, - "AssetParameters5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96ArtifactHash7AE27721": { - "Type": "String", - "Description": "Artifact hash for asset \"5f752add658f79e0005d882c0bc5a08dc38a14dc55135d974ea1d2226cb28b96\"" + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] } } } \ No newline at end of file diff --git a/source/use_cases/aws-serverless-image-handler/test/test.serverless-image-handler.test.ts b/source/use_cases/aws-serverless-image-handler/test/test.serverless-image-handler.test.ts index 63840d2c3..41cffc19a 100644 --- a/source/use_cases/aws-serverless-image-handler/test/test.serverless-image-handler.test.ts +++ b/source/use_cases/aws-serverless-image-handler/test/test.serverless-image-handler.test.ts @@ -70,5 +70,5 @@ test('Custom deployment unit testing', () => { // Assertion 4 expect(sih.cloudFrontDistribution()).toBeDefined(); // Assertion 5 - expect(sih.lambdaFunction()).toHaveProperty('environment.TEST_KEY', 'TEST_VALUE'); + expect(sih.lambdaFunction()).toHaveProperty('environment.TEST_KEY', {"value": "TEST_VALUE"}); }); \ No newline at end of file diff --git a/source/use_cases/aws-serverless-image-handler/tsconfig.json b/source/use_cases/aws-serverless-image-handler/tsconfig.json index 07afb1f64..7ca946aa3 100644 --- a/source/use_cases/aws-serverless-image-handler/tsconfig.json +++ b/source/use_cases/aws-serverless-image-handler/tsconfig.json @@ -4,12 +4,14 @@ "charset": "utf8", "declaration": true, "experimentalDecorators": true, + "incremental": true, "inlineSourceMap": true, "inlineSources": true, "lib": [ - "es2018" + "es2019" ], "module": "CommonJS", + "newLine": "lf", "noEmitOnError": true, "noFallthroughCasesInSwitch": true, "noImplicitAny": true, @@ -21,8 +23,10 @@ "strict": true, "strictNullChecks": true, "strictPropertyInitialization": true, - "stripInternal": true, - "target": "ES2018" + "stripInternal": false, + "target": "ES2019", + "composite": false, + "tsBuildInfoFile": "tsconfig.tsbuildinfo" }, "include": [ "**/*.ts" diff --git a/source/use_cases/aws-serverless-web-app/test/__snapshots__/s3-static-site-stack.test.js.snap b/source/use_cases/aws-serverless-web-app/test/__snapshots__/s3-static-site-stack.test.js.snap index 87c900291..c4ba423ce 100644 --- a/source/use_cases/aws-serverless-web-app/test/__snapshots__/s3-static-site-stack.test.js.snap +++ b/source/use_cases/aws-serverless-web-app/test/__snapshots__/s3-static-site-stack.test.js.snap @@ -19,8 +19,8 @@ Object { "https://", Object { "Fn::GetAtt": Array [ - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E", - "RegionalDomainName", + "CloudFrontToS3CloudFrontDistribution241D9866", + "DomainName", ], }, ], @@ -41,21 +41,21 @@ Object { "Description": "S3 key for asset version \\"1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": Object { - "Description": "Artifact hash for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916ArtifactHashB448546A": Object { + "Description": "Artifact hash for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": Object { - "Description": "S3 bucket for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF": Object { + "Description": "S3 bucket for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": Object { - "Description": "S3 key for asset version \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD": Object { + "Description": "S3 key for asset version \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, }, "Resources": Object { - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E": Object { + "CloudFrontToS3CloudFrontDistribution241D9866": Object { "Metadata": Object { "cfn_nag": Object { "rules_to_suppress": Array [ @@ -69,30 +69,9 @@ Object { "Properties": Object { "DistributionConfig": Object { "DefaultCacheBehavior": Object { - "AllowedMethods": Array [ - "GET", - "HEAD", - ], - "CachedMethods": Array [ - "GET", - "HEAD", - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": Object { - "Cookies": Object { - "Forward": "none", - }, - "QueryString": false, - }, - "LambdaFunctionAssociations": Array [ - Object { - "EventType": "origin-response", - "LambdaFunctionARN": Object { - "Ref": "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE", - }, - }, - ], - "TargetOriginId": "origin1", + "TargetOriginId": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "ViewerProtocolPolicy": "redirect-to-https", }, "DefaultRootObject": "index.html", @@ -106,7 +85,6 @@ Object { "RegionalDomainName", ], }, - "IncludeCookies": false, }, "Origins": Array [ Object { @@ -116,7 +94,7 @@ Object { "RegionalDomainName", ], }, - "Id": "origin1", + "Id": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "S3OriginConfig": Object { "OriginAccessIdentity": Object { "Fn::Join": Array [ @@ -124,7 +102,7 @@ Object { Array [ "origin-access-identity/cloudfront/", Object { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "Ref": "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", }, ], ], @@ -132,18 +110,14 @@ Object { }, }, ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": Object { - "CloudFrontDefaultCertificate": true, - }, }, }, "Type": "AWS::CloudFront::Distribution", }, - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91": Object { + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F": Object { "Properties": Object { "CloudFrontOriginAccessIdentityConfig": Object { - "Comment": "Access S3 bucket content only through CloudFront", + "Comment": "Identity for S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", }, }, "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", @@ -157,10 +131,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", }, - Object { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution", - }, ], }, }, @@ -188,6 +158,53 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, + "CloudFrontToS3CloudfrontLoggingBucketPolicy416B82D9": Object { + "Properties": Object { + "Bucket": Object { + "Ref": "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + }, + "PolicyDocument": Object { + "Statement": Array [ + Object { + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, + }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn", + ], + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::S3::BucketPolicy", + }, "CloudFrontToS3S3Bucket9CE6AB04": Object { "DeletionPolicy": "Retain", "Properties": Object { @@ -200,6 +217,19 @@ Object { }, ], }, + "LifecycleConfiguration": Object { + "Rules": Array [ + Object { + "NoncurrentVersionTransitions": Array [ + Object { + "StorageClass": "GLACIER", + "TransitionInDays": 90, + }, + ], + "Status": "Enabled", + }, + ], + }, "LoggingConfiguration": Object { "DestinationBucketName": Object { "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2", @@ -236,29 +266,16 @@ Object { "PolicyDocument": Object { "Statement": Array [ Object { - "Action": Array [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - ], - "Effect": "Allow", - "Principal": Object { - "AWS": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:", - Object { - "Ref": "AWS::Partition", - }, - ":iam::cloudfront:user/CloudFront Origin Access Identity ", - Object { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", - }, - ], - ], + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", }, }, + "Effect": "Deny", + "Principal": Object { + "AWS": "*", + }, "Resource": Array [ Object { "Fn::GetAtt": Array [ @@ -288,7 +305,7 @@ Object { "Principal": Object { "CanonicalUser": Object { "Fn::GetAtt": Array [ - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", "S3CanonicalUserId", ], }, @@ -323,10 +340,6 @@ Object { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket", }, - Object { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy", - }, ], }, }, @@ -354,104 +367,52 @@ Object { "Type": "AWS::S3::Bucket", "UpdateReplacePolicy": "Retain", }, - "CloudFrontToS3SetHttpSecurityHeaders9E6088E2": Object { - "DependsOn": Array [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - ], - "Metadata": Object { - "cfn_nag": Object { - "rules_to_suppress": Array [ - Object { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions.", - }, - Object { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries", - }, - ], - }, - }, + "CloudFrontToS3S3LoggingBucketPolicy360F3875": Object { "Properties": Object { - "Code": Object { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \\"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\\" } ]; callback(null, response); };", - }, - "Handler": "index.handler", - "Role": Object { - "Fn::GetAtt": Array [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - "Arn", - ], + "Bucket": Object { + "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2", }, - "Runtime": "nodejs14.x", - }, - "Type": "AWS::Lambda::Function", - }, - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10": Object { - "Properties": Object { - "AssumeRolePolicyDocument": Object { + "PolicyDocument": Object { "Statement": Array [ Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": Object { - "Service": "lambda.amazonaws.com", + "Action": "s3:*", + "Condition": Object { + "Bool": Object { + "aws:SecureTransport": "false", + }, }, - }, - Object { - "Action": "sts:AssumeRole", - "Effect": "Allow", + "Effect": "Deny", "Principal": Object { - "Service": "edgelambda.amazonaws.com", + "AWS": "*", }, - }, - ], - "Version": "2012-10-17", - }, - "Policies": Array [ - Object { - "PolicyDocument": Object { - "Statement": Array [ + "Resource": Array [ Object { - "Action": Array [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", + "Fn::GetAtt": Array [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn", ], - "Effect": "Allow", - "Resource": Object { - "Fn::Join": Array [ - "", - Array [ - "arn:aws:logs:", - Object { - "Ref": "AWS::Region", - }, - ":", - Object { - "Ref": "AWS::AccountId", - }, - ":log-group:/aws/lambda/*", - ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn", + ], + }, + "/*", ], - }, + ], }, ], - "Version": "2012-10-17", }, - "PolicyName": "LambdaFunctionServiceRolePolicy", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE": Object { - "Properties": Object { - "FunctionName": Object { - "Ref": "CloudFrontToS3SetHttpSecurityHeaders9E6088E2", + ], + "Version": "2012-10-17", }, }, - "Type": "AWS::Lambda::Version", + "Type": "AWS::S3::BucketPolicy", }, "CustomResource": Object { "DeletionPolicy": "Delete", @@ -479,7 +440,7 @@ Object { "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF", }, "S3Key": Object { "Fn::Join": Array [ @@ -492,7 +453,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -505,7 +466,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -515,6 +476,7 @@ Object { ], }, }, + "Description": "AWS CDK resource provider framework - onEvent (S3StaticWebsiteStack/CustomResourceProvider)", "Environment": Object { "Variables": Object { "USER_ON_EVENT_FUNCTION_ARN": Object { @@ -532,7 +494,7 @@ Object { "Arn", ], }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -575,12 +537,28 @@ Object { Object { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": Object { - "Fn::GetAtt": Array [ - "staticContentHandlerC21DFC88", - "Arn", - ], - }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "staticContentHandlerC21DFC88", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "staticContentHandlerC21DFC88", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], }, ], "Version": "2012-10-17", @@ -692,7 +670,18 @@ Object { ], "Effect": "Allow", "Resource": Array [ - "arn:aws:s3:::wildrydes-us-east-1", + Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":s3:::wildrydes-us-east-1", + ], + ], + }, "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*", ], }, @@ -713,7 +702,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:s3:::", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":s3:::", Object { "Ref": "CloudFrontToS3S3Bucket9CE6AB04", }, diff --git a/source/use_cases/aws-serverless-web-app/test/__snapshots__/serverless-backend-stack.test.js.snap b/source/use_cases/aws-serverless-web-app/test/__snapshots__/serverless-backend-stack.test.js.snap index 986ec2f36..625e47ca9 100644 --- a/source/use_cases/aws-serverless-web-app/test/__snapshots__/serverless-backend-stack.test.js.snap +++ b/source/use_cases/aws-serverless-web-app/test/__snapshots__/serverless-backend-stack.test.js.snap @@ -43,16 +43,16 @@ Object { "Description": "S3 key for asset version \\"3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": Object { - "Description": "Artifact hash for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916ArtifactHashB448546A": Object { + "Description": "Artifact hash for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": Object { - "Description": "S3 bucket for asset \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF": Object { + "Description": "S3 bucket for asset \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": Object { - "Description": "S3 key for asset version \\"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\\"", + "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD": Object { + "Description": "S3 key for asset version \\"543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916\\"", "Type": "String", }, "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360ArtifactHash5ED5576F": Object { @@ -71,6 +71,20 @@ Object { "Resources": Object { "CognitoToApiGatewayToLambdaApiAccessLogGroup43A4A269": Object { "DeletionPolicy": "Retain", + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely", + }, + Object { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)", + }, + ], + }, + }, "Type": "AWS::Logs::LogGroup", "UpdateReplacePolicy": "Retain", }, @@ -94,21 +108,28 @@ Object { "Type": "AWS::ApiGateway::Authorizer", }, "CognitoToApiGatewayToLambdaCognitoUserPool6EE989F1": Object { + "DeletionPolicy": "Retain", "Properties": Object { + "AccountRecoverySetting": Object { + "RecoveryMechanisms": Array [ + Object { + "Name": "verified_phone_number", + "Priority": 1, + }, + Object { + "Name": "verified_email", + "Priority": 2, + }, + ], + }, "AdminCreateUserConfig": Object { - "AllowAdminCreateUserOnly": true, + "AllowAdminCreateUserOnly": false, }, + "AutoVerifiedAttributes": Array [ + "email", + ], "EmailVerificationMessage": "The verification code to your new account is {####}", "EmailVerificationSubject": "Verify your new account", - "SmsConfiguration": Object { - "ExternalId": "ServerlessBackendStackCognitoToApiGatewayToLambdaCognitoUserPool0C465C62", - "SnsCallerArn": Object { - "Fn::GetAtt": Array [ - "CognitoToApiGatewayToLambdaCognitoUserPoolsmsRole62C22F60", - "Arn", - ], - }, - }, "SmsVerificationMessage": "The verification code to your new account is {####}", "UserPoolAddOns": Object { "AdvancedSecurityMode": "ENFORCED", @@ -122,62 +143,34 @@ Object { }, }, "Type": "AWS::Cognito::UserPool", + "UpdateReplacePolicy": "Retain", }, "CognitoToApiGatewayToLambdaCognitoUserPoolClientC6919938": Object { "Properties": Object { + "AllowedOAuthFlows": Array [ + "implicit", + "code", + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": Array [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin", + ], + "CallbackURLs": Array [ + "https://example.com", + ], + "SupportedIdentityProviders": Array [ + "COGNITO", + ], "UserPoolId": Object { "Ref": "CognitoToApiGatewayToLambdaCognitoUserPool6EE989F1", }, }, "Type": "AWS::Cognito::UserPoolClient", }, - "CognitoToApiGatewayToLambdaCognitoUserPoolsmsRole62C22F60": Object { - "Metadata": Object { - "cfn_nag": Object { - "rules_to_suppress": Array [ - Object { - "id": "W11", - "reason": "Allowing * resource on permissions policy since its used by Cognito to send SMS messages via sns:Publish", - }, - ], - }, - }, - "Properties": Object { - "AssumeRolePolicyDocument": Object { - "Statement": Array [ - Object { - "Action": "sts:AssumeRole", - "Condition": Object { - "StringEquals": Object { - "sts:ExternalId": "ServerlessBackendStackCognitoToApiGatewayToLambdaCognitoUserPool0C465C62", - }, - }, - "Effect": "Allow", - "Principal": Object { - "Service": "cognito-idp.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "Policies": Array [ - Object { - "PolicyDocument": Object { - "Statement": Array [ - Object { - "Action": "sns:Publish", - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "sns-publish", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, "CognitoToApiGatewayToLambdaLambdaFunction555D0B9C": Object { "DependsOn": Array [ "CognitoToApiGatewayToLambdaLambdaFunctionServiceRoleDefaultPolicyCC3D84AE", @@ -194,6 +187,10 @@ Object { "id": "W89", "reason": "This is not a rule for the general case, just for specific use cases/industries", }, + Object { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients", + }, ], }, }, @@ -252,6 +249,9 @@ Object { ], }, "Runtime": "nodejs14.x", + "TracingConfig": Object { + "Mode": "Active", + }, }, "Type": "AWS::Lambda::Function", }, @@ -284,7 +284,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:logs:", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", Object { "Ref": "AWS::Region", }, @@ -307,9 +311,27 @@ Object { "Type": "AWS::IAM::Role", }, "CognitoToApiGatewayToLambdaLambdaFunctionServiceRoleDefaultPolicyCC3D84AE": Object { + "Metadata": Object { + "cfn_nag": Object { + "rules_to_suppress": Array [ + Object { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC.", + }, + ], + }, + }, "Properties": Object { "PolicyDocument": Object { "Statement": Array [ + Object { + "Action": Array [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + ], + "Effect": "Allow", + "Resource": "*", + }, Object { "Action": Array [ "dynamodb:BatchGetItem", @@ -323,6 +345,7 @@ Object { "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", + "dynamodb:DescribeTable", ], "Effect": "Allow", "Resource": Array [ @@ -531,7 +554,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:logs:", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":logs:", Object { "Ref": "AWS::Region", }, @@ -553,7 +580,7 @@ Object { }, "Type": "AWS::IAM::Role", }, - "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E6682fe19d2bcf96aadbe65fec49213c15c": Object { + "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E66be3a2e657ed1037e23e62faacc9671b0": Object { "DependsOn": Array [ "CognitoToApiGatewayToLambdaLambdaRestApiproxyANY2839789B", "CognitoToApiGatewayToLambdaLambdaRestApiproxyOPTIONS63FED6E8", @@ -591,11 +618,11 @@ Object { "Format": "{\\"requestId\\":\\"$context.requestId\\",\\"ip\\":\\"$context.identity.sourceIp\\",\\"user\\":\\"$context.identity.user\\",\\"caller\\":\\"$context.identity.caller\\",\\"requestTime\\":\\"$context.requestTime\\",\\"httpMethod\\":\\"$context.httpMethod\\",\\"resourcePath\\":\\"$context.resourcePath\\",\\"status\\":\\"$context.status\\",\\"protocol\\":\\"$context.protocol\\",\\"responseLength\\":\\"$context.responseLength\\"}", }, "DeploymentId": Object { - "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E6682fe19d2bcf96aadbe65fec49213c15c", + "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E66be3a2e657ed1037e23e62faacc9671b0", }, "MethodSettings": Array [ Object { - "DataTraceEnabled": true, + "DataTraceEnabled": false, "HttpMethod": "*", "LoggingLevel": "INFO", "ResourcePath": "/*", @@ -605,6 +632,7 @@ Object { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0", }, "StageName": "prod", + "TracingEnabled": true, }, "Type": "AWS::ApiGateway::Stage", }, @@ -758,7 +786,7 @@ Object { Object { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeploymentStageprod743A20E1", }, - "/*/{proxy+}", + "/*/*", ], ], }, @@ -795,7 +823,7 @@ Object { Object { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0", }, - "/test-invoke-stage/*/{proxy+}", + "/test-invoke-stage/*/*", ], ], }, @@ -898,7 +926,7 @@ Object { "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3BucketC05003CF", }, "S3Key": Object { "Fn::Join": Array [ @@ -911,7 +939,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -924,7 +952,7 @@ Object { "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC", + "Ref": "AssetParameters543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916S3VersionKeyA2C7BFCD", }, ], }, @@ -934,6 +962,7 @@ Object { ], }, }, + "Description": "AWS CDK resource provider framework - onEvent (ServerlessBackendStack/CustomResourceProvider)", "Environment": Object { "Variables": Object { "USER_ON_EVENT_FUNCTION_ARN": Object { @@ -951,7 +980,7 @@ Object { "Arn", ], }, - "Runtime": "nodejs14.x", + "Runtime": "nodejs12.x", "Timeout": 900, }, "Type": "AWS::Lambda::Function", @@ -994,12 +1023,28 @@ Object { Object { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": Object { - "Fn::GetAtt": Array [ - "updateConfigHandler59840941", - "Arn", - ], - }, + "Resource": Array [ + Object { + "Fn::GetAtt": Array [ + "updateConfigHandler59840941", + "Arn", + ], + }, + Object { + "Fn::Join": Array [ + "", + Array [ + Object { + "Fn::GetAtt": Array [ + "updateConfigHandler59840941", + "Arn", + ], + }, + ":*", + ], + ], + }, + ], }, ], "Version": "2012-10-17", @@ -1029,6 +1074,9 @@ Object { "KeyType": "HASH", }, ], + "PointInTimeRecoverySpecification": Object { + "PointInTimeRecoveryEnabled": true, + }, "SSESpecification": Object { "SSEEnabled": true, }, @@ -1139,7 +1187,11 @@ Object { "Fn::Join": Array [ "", Array [ - "arn:aws:s3:::", + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":s3:::", Object { "Fn::ImportValue": "websiteBucket", }, diff --git a/source/use_cases/aws-serverless-web-app/test/integ.001-s3-static-website-deployment.expected.json b/source/use_cases/aws-serverless-web-app/test/integ.001-s3-static-website-deployment.expected.json index 670b0856a..58ca7d0d3 100644 --- a/source/use_cases/aws-serverless-web-app/test/integ.001-s3-static-website-deployment.expected.json +++ b/source/use_cases/aws-serverless-web-app/test/integ.001-s3-static-website-deployment.expected.json @@ -31,15 +31,58 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for another bucket" - }, - { - "id": "W51", - "reason": "This S3 bucket Bucket does not need a bucket policy" } ] } } }, + "CloudFrontToS3S3LoggingBucketPolicy360F3875": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CloudFrontToS3S3LoggingBucketEF5CD8B2", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, "CloudFrontToS3S3Bucket9CE6AB04": { "Type": "AWS::S3::Bucket", "Properties": { @@ -52,6 +95,19 @@ } ] }, + "LifecycleConfiguration": { + "Rules": [ + { + "NoncurrentVersionTransitions": [ + { + "StorageClass": "GLACIER", + "TransitionInDays": 90 + } + ], + "Status": "Enabled" + } + ] + }, "LoggingConfiguration": { "DestinationBucketName": { "Ref": "CloudFrontToS3S3LoggingBucketEF5CD8B2" @@ -79,29 +135,16 @@ "PolicyDocument": { "Statement": [ { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::cloudfront:user/CloudFront Origin Access Identity ", - { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91" - } - ] - ] + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" } }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, "Resource": [ { "Fn::GetAtt": [ @@ -131,7 +174,7 @@ "Principal": { "CanonicalUser": { "Fn::GetAtt": [ - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91", + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F", "S3CanonicalUserId" ] } @@ -166,113 +209,6 @@ } } }, - "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91": { - "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", - "Properties": { - "CloudFrontOriginAccessIdentityConfig": { - "Comment": "Access S3 bucket content only through CloudFront" - } - } - }, - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - } - }, - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "edgelambda.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Policies": [ - { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:logs:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":log-group:/aws/lambda/*" - ] - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "LambdaFunctionServiceRolePolicy" - } - ] - } - }, - "CloudFrontToS3SetHttpSecurityHeaders9E6088E2": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "ZipFile": "exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; headers['x-xss-protection'] = [ { key: 'X-XSS-Protection', value: '1; mode=block' } ]; headers['x-frame-options'] = [ { key: 'X-Frame-Options', value: 'DENY' } ]; headers['x-content-type-options'] = [ { key: 'X-Content-Type-Options', value: 'nosniff' } ]; headers['strict-transport-security'] = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload' } ]; headers['referrer-policy'] = [ { key: 'Referrer-Policy', value: 'same-origin' } ]; headers['content-security-policy'] = [ { key: 'Content-Security-Policy', value: \"default-src 'none'; base-uri 'self'; img-src 'self'; script-src 'self'; style-src 'self' https:; object-src 'none'; frame-ancestors 'none'; font-src 'self' https:; form-action 'self'; manifest-src 'self'; connect-src 'self'\" } ]; callback(null, response); };" - }, - "Handler": "index.handler", - "Role": { - "Fn::GetAtt": [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10", - "Arn" - ] - }, - "Runtime": "nodejs14.x" - }, - "DependsOn": [ - "CloudFrontToS3SetHttpSecurityHeadersServiceRole6BABDE10" - ], - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ - { - "id": "W58", - "reason": "Lambda functions has the required permission to write CloudWatch Logs. It uses custom policy instead of arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole with tighter permissions." - }, - { - "id": "W89", - "reason": "This is not a rule for the general case, just for specific use cases/industries" - } - ] - } - } - }, - "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE": { - "Type": "AWS::Lambda::Version", - "Properties": { - "FunctionName": { - "Ref": "CloudFrontToS3SetHttpSecurityHeaders9E6088E2" - } - } - }, "CloudFrontToS3CloudfrontLoggingBucket8350BE9B": { "Type": "AWS::S3::Bucket", "Properties": { @@ -304,44 +240,74 @@ { "id": "W35", "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" - }, - { - "id": "W51", - "reason": "This S3 bucket is used as the access logging bucket for CloudFront Distribution" } ] } } }, - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E": { + "CloudFrontToS3CloudfrontLoggingBucketPolicy416B82D9": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "CloudFrontToS3CloudfrontLoggingBucket8350BE9B" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F": { + "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "Properties": { + "CloudFrontOriginAccessIdentityConfig": { + "Comment": "Identity for S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507" + } + } + }, + "CloudFrontToS3CloudFrontDistribution241D9866": { "Type": "AWS::CloudFront::Distribution", "Properties": { "DistributionConfig": { "DefaultCacheBehavior": { - "AllowedMethods": [ - "GET", - "HEAD" - ], - "CachedMethods": [ - "GET", - "HEAD" - ], + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", "Compress": true, - "ForwardedValues": { - "Cookies": { - "Forward": "none" - }, - "QueryString": false - }, - "LambdaFunctionAssociations": [ - { - "EventType": "origin-response", - "LambdaFunctionARN": { - "Ref": "CloudFrontToS3SetHttpSecurityHeadersVersion699208AE" - } - } - ], - "TargetOriginId": "origin1", + "TargetOriginId": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "ViewerProtocolPolicy": "redirect-to-https" }, "DefaultRootObject": "index.html", @@ -354,8 +320,7 @@ "CloudFrontToS3CloudfrontLoggingBucket8350BE9B", "RegionalDomainName" ] - }, - "IncludeCookies": false + } }, "Origins": [ { @@ -365,7 +330,7 @@ "RegionalDomainName" ] }, - "Id": "origin1", + "Id": "S3StaticWebsiteStackCloudFrontToS3CloudFrontDistributionOrigin1F7C9B507", "S3OriginConfig": { "OriginAccessIdentity": { "Fn::Join": [ @@ -373,18 +338,14 @@ [ "origin-access-identity/cloudfront/", { - "Ref": "CloudFrontToS3CloudFrontOriginAccessIdentity34CC1F91" + "Ref": "CloudFrontToS3CloudFrontDistributionOrigin1S3OriginB0637B8F" } ] ] } } } - ], - "PriceClass": "PriceClass_100", - "ViewerCertificate": { - "CloudFrontDefaultCertificate": true - } + ] } }, "Metadata": { @@ -441,7 +402,18 @@ ], "Effect": "Allow", "Resource": [ - "arn:aws:s3:::wildrydes-us-east-1", + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::wildrydes-us-east-1" + ] + ] + }, "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" ] }, @@ -462,7 +434,11 @@ "Fn::Join": [ "", [ - "arn:aws:s3:::", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", { "Ref": "CloudFrontToS3S3Bucket9CE6AB04" } @@ -499,49 +475,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36S3BucketE560DEC2" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36S3VersionKeyA9698665" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36S3VersionKeyA9698665" - } - ] - } - ] - } - ] - ] - } + "S3Key": "1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36.zip" }, - "Handler": "copy_s3_objects.on_event", "Role": { "Fn::GetAtt": [ "staticContentHandlerServiceRole3B648F21", "Arn" ] }, + "Handler": "copy_s3_objects.on_event", "Runtime": "python3.8", "Timeout": 300 }, @@ -589,12 +533,28 @@ { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "staticContentHandlerC21DFC88", - "Arn" - ] - } + "Resource": [ + { + "Fn::GetAtt": [ + "staticContentHandlerC21DFC88", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "staticContentHandlerC21DFC88", + "Arn" + ] + }, + ":*" + ] + ] + } + ] } ], "Version": "2012-10-17" @@ -612,50 +572,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - } - ] - ] - } + "S3Key": "543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916.zip" }, - "Handler": "framework.onEvent", "Role": { "Fn::GetAtt": [ "CustomResourceProviderframeworkonEventServiceRole7EBC5835", "Arn" ] }, - "Runtime": "nodejs14.x", + "Description": "AWS CDK resource provider framework - onEvent (S3StaticWebsiteStack/CustomResourceProvider)", "Environment": { "Variables": { "USER_ON_EVENT_FUNCTION_ARN": { @@ -666,6 +593,8 @@ } } }, + "Handler": "framework.onEvent", + "Runtime": "nodejs12.x", "Timeout": 900 }, "DependsOn": [ @@ -692,32 +621,6 @@ "DeletionPolicy": "Delete" } }, - "Parameters": { - "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36S3BucketE560DEC2": { - "Type": "String", - "Description": "S3 bucket for asset \"1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36\"" - }, - "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36S3VersionKeyA9698665": { - "Type": "String", - "Description": "S3 key for asset version \"1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36\"" - }, - "AssetParameters1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36ArtifactHash171A5ECB": { - "Type": "String", - "Description": "Artifact hash for asset \"1726e5810ad30312b951166bf153fa8cbc793db9019a7fa8f3440a20d21f3d36\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": { - "Type": "String", - "Description": "S3 bucket for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": { - "Type": "String", - "Description": "S3 key for asset version \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": { - "Type": "String", - "Description": "Artifact hash for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - } - }, "Outputs": { "websiteURL": { "Value": { @@ -727,8 +630,8 @@ "https://", { "Fn::GetAtt": [ - "CloudFrontToS3CloudFrontDistributionCFDistribution7EEEEF4E", - "RegionalDomainName" + "CloudFrontToS3CloudFrontDistribution241D9866", + "DomainName" ] } ] @@ -743,5 +646,39 @@ "Name": "websiteBucket" } } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } } } \ No newline at end of file diff --git a/source/use_cases/aws-serverless-web-app/test/integ.002-backend-deployment.expected.json b/source/use_cases/aws-serverless-web-app/test/integ.002-backend-deployment.expected.json index 3d68e6e39..ee678a169 100644 --- a/source/use_cases/aws-serverless-web-app/test/integ.002-backend-deployment.expected.json +++ b/source/use_cases/aws-serverless-web-app/test/integ.002-backend-deployment.expected.json @@ -30,7 +30,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -56,6 +60,14 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords" + ], + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "dynamodb:BatchGetItem", @@ -68,7 +80,8 @@ "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", - "dynamodb:DeleteItem" + "dynamodb:DeleteItem", + "dynamodb:DescribeTable" ], "Effect": "Allow", "Resource": [ @@ -92,6 +105,16 @@ "Ref": "CognitoToApiGatewayToLambdaLambdaFunctionServiceRole921AB2D6" } ] + }, + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W12", + "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray and access ENIs in a VPC." + } + ] + } } }, "CognitoToApiGatewayToLambdaLambdaFunction555D0B9C": { @@ -99,50 +122,16 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360S3Bucket20EEB389" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360S3VersionKeyC46EC577" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360S3VersionKeyC46EC577" - } - ] - } - ] - } - ] - ] - } + "S3Key": "9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360.zip" }, - "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "CognitoToApiGatewayToLambdaLambdaFunctionServiceRole921AB2D6", "Arn" ] }, - "Runtime": "nodejs14.x", "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", @@ -150,6 +139,11 @@ "Ref": "LambdaToDynamoDBDynamoTable53C1442D" } } + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x", + "TracingConfig": { + "Mode": "Active" } }, "DependsOn": [ @@ -166,6 +160,10 @@ { "id": "W89", "reason": "This is not a rule for the general case, just for specific use cases/industries" + }, + { + "id": "W92", + "reason": "Impossible for us to define the correct concurrency for clients" } ] } @@ -174,7 +172,21 @@ "CognitoToApiGatewayToLambdaApiAccessLogGroup43A4A269": { "Type": "AWS::Logs::LogGroup", "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" + "DeletionPolicy": "Retain", + "Metadata": { + "cfn_nag": { + "rules_to_suppress": [ + { + "id": "W86", + "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely" + }, + { + "id": "W84", + "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)" + } + ] + } + } }, "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0": { "Type": "AWS::ApiGateway::RestApi", @@ -187,7 +199,7 @@ "Name": "LambdaRestApi" } }, - "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E6682fe19d2bcf96aadbe65fec49213c15c": { + "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E66be3a2e657ed1037e23e62faacc9671b0": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -229,17 +241,18 @@ "Format": "{\"requestId\":\"$context.requestId\",\"ip\":\"$context.identity.sourceIp\",\"user\":\"$context.identity.user\",\"caller\":\"$context.identity.caller\",\"requestTime\":\"$context.requestTime\",\"httpMethod\":\"$context.httpMethod\",\"resourcePath\":\"$context.resourcePath\",\"status\":\"$context.status\",\"protocol\":\"$context.protocol\",\"responseLength\":\"$context.responseLength\"}" }, "DeploymentId": { - "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E6682fe19d2bcf96aadbe65fec49213c15c" + "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeployment1E6D5E66be3a2e657ed1037e23e62faacc9671b0" }, "MethodSettings": [ { - "DataTraceEnabled": true, + "DataTraceEnabled": false, "HttpMethod": "*", "LoggingLevel": "INFO", "ResourcePath": "/*" } ], - "StageName": "prod" + "StageName": "prod", + "TracingEnabled": true } }, "CognitoToApiGatewayToLambdaLambdaRestApiOPTIONS84242119": { @@ -373,7 +386,7 @@ { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApiDeploymentStageprod743A20E1" }, - "/*/{proxy+}" + "/*/*" ] ] } @@ -410,7 +423,7 @@ { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0" }, - "/test-invoke-stage/*/{proxy+}" + "/test-invoke-stage/*/*" ] ] } @@ -633,7 +646,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -668,70 +685,29 @@ "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0" ] }, - "CognitoToApiGatewayToLambdaCognitoUserPoolsmsRole62C22F60": { - "Type": "AWS::IAM::Role", + "CognitoToApiGatewayToLambdaCognitoUserPool6EE989F1": { + "Type": "AWS::Cognito::UserPool", "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ + "AccountRecoverySetting": { + "RecoveryMechanisms": [ { - "Action": "sts:AssumeRole", - "Condition": { - "StringEquals": { - "sts:ExternalId": "ServerlessBackendStackCognitoToApiGatewayToLambdaCognitoUserPool0C465C62" - } - }, - "Effect": "Allow", - "Principal": { - "Service": "cognito-idp.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Policies": [ - { - "PolicyDocument": { - "Statement": [ - { - "Action": "sns:Publish", - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" + "Name": "verified_phone_number", + "Priority": 1 }, - "PolicyName": "sns-publish" - } - ] - }, - "Metadata": { - "cfn_nag": { - "rules_to_suppress": [ { - "id": "W11", - "reason": "Allowing * resource on permissions policy since its used by Cognito to send SMS messages via sns:Publish" + "Name": "verified_email", + "Priority": 2 } ] - } - } - }, - "CognitoToApiGatewayToLambdaCognitoUserPool6EE989F1": { - "Type": "AWS::Cognito::UserPool", - "Properties": { + }, "AdminCreateUserConfig": { - "AllowAdminCreateUserOnly": true + "AllowAdminCreateUserOnly": false }, + "AutoVerifiedAttributes": [ + "email" + ], "EmailVerificationMessage": "The verification code to your new account is {####}", "EmailVerificationSubject": "Verify your new account", - "SmsConfiguration": { - "ExternalId": "ServerlessBackendStackCognitoToApiGatewayToLambdaCognitoUserPool0C465C62", - "SnsCallerArn": { - "Fn::GetAtt": [ - "CognitoToApiGatewayToLambdaCognitoUserPoolsmsRole62C22F60", - "Arn" - ] - } - }, "SmsVerificationMessage": "The verification code to your new account is {####}", "UserPoolAddOns": { "AdvancedSecurityMode": "ENFORCED" @@ -743,25 +719,45 @@ "EmailSubject": "Verify your new account", "SmsMessage": "The verification code to your new account is {####}" } - } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" }, "CognitoToApiGatewayToLambdaCognitoUserPoolClientC6919938": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { "UserPoolId": { "Ref": "CognitoToApiGatewayToLambdaCognitoUserPool6EE989F1" - } + }, + "AllowedOAuthFlows": [ + "implicit", + "code" + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin" + ], + "CallbackURLs": [ + "https://example.com" + ], + "SupportedIdentityProviders": [ + "COGNITO" + ] } }, "CognitoToApiGatewayToLambdaCognitoAuthorizerAF023B99": { "Type": "AWS::ApiGateway::Authorizer", "Properties": { + "Name": "authorizer", "RestApiId": { "Ref": "CognitoToApiGatewayToLambdaLambdaRestApi31103AF0" }, "Type": "COGNITO_USER_POOLS", "IdentitySource": "method.request.header.Authorization", - "Name": "authorizer", "ProviderARNs": [ { "Fn::GetAtt": [ @@ -819,7 +815,11 @@ "Fn::Join": [ "", [ - "arn:aws:s3:::", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", { "Fn::ImportValue": "websiteBucket" }, @@ -844,49 +844,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791S3Bucket928903EC" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791S3VersionKey3C7BB3DD" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791S3VersionKey3C7BB3DD" - } - ] - } - ] - } - ] - ] - } + "S3Key": "3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791.zip" }, - "Handler": "update_s3_object.on_event", "Role": { "Fn::GetAtt": [ "updateConfigHandlerServiceRole3B176B96", "Arn" ] }, + "Handler": "update_s3_object.on_event", "Runtime": "python3.8", "Timeout": 300 }, @@ -934,12 +902,28 @@ { "Action": "lambda:InvokeFunction", "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "updateConfigHandler59840941", - "Arn" - ] - } + "Resource": [ + { + "Fn::GetAtt": [ + "updateConfigHandler59840941", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "updateConfigHandler59840941", + "Arn" + ] + }, + ":*" + ] + ] + } + ] } ], "Version": "2012-10-17" @@ -957,50 +941,17 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC" - } - ] - } - ] - } - ] - ] - } + "S3Key": "543c7a94b144a6259669eaf884305607b7a9abe85c43e4bfe62f9190ace37916.zip" }, - "Handler": "framework.onEvent", "Role": { "Fn::GetAtt": [ "CustomResourceProviderframeworkonEventServiceRole7EBC5835", "Arn" ] }, - "Runtime": "nodejs14.x", + "Description": "AWS CDK resource provider framework - onEvent (ServerlessBackendStack/CustomResourceProvider)", "Environment": { "Variables": { "USER_ON_EVENT_FUNCTION_ARN": { @@ -1011,6 +962,8 @@ } } }, + "Handler": "framework.onEvent", + "Runtime": "nodejs12.x", "Timeout": 900 }, "DependsOn": [ @@ -1083,6 +1036,9 @@ } ], "BillingMode": "PAY_PER_REQUEST", + "PointInTimeRecoverySpecification": { + "PointInTimeRecoveryEnabled": true + }, "SSESpecification": { "SSEEnabled": true }, @@ -1121,41 +1077,37 @@ } }, "Parameters": { - "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360S3Bucket20EEB389": { - "Type": "String", - "Description": "S3 bucket for asset \"9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360\"" - }, - "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360S3VersionKeyC46EC577": { - "Type": "String", - "Description": "S3 key for asset version \"9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360\"" - }, - "AssetParameters9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360ArtifactHash5ED5576F": { - "Type": "String", - "Description": "Artifact hash for asset \"9a9c398189879e9ca9700ba0658086063d8ee7ccd068043c722c28478c6c4360\"" - }, - "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791S3Bucket928903EC": { - "Type": "String", - "Description": "S3 bucket for asset \"3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791\"" - }, - "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791S3VersionKey3C7BB3DD": { - "Type": "String", - "Description": "S3 key for asset version \"3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791\"" - }, - "AssetParameters3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791ArtifactHashF30FBC00": { - "Type": "String", - "Description": "Artifact hash for asset \"3aa519f176d0d52023f4992f8ada07849f844467dcb0d4dfb94bb3b350a1d791\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3Bucket0A1029B1": { - "Type": "String", - "Description": "S3 bucket for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061S3VersionKeyFB75FDAC": { - "Type": "String", - "Description": "S3 key for asset version \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" - }, - "AssetParameters4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061ArtifactHash40CCFA64": { - "Type": "String", - "Description": "Artifact hash for asset \"4c2988a57571fd4c34de12bae67441541aeea1a59e085f95e5b708922ff45061\"" + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] } } } \ No newline at end of file diff --git a/source/use_cases/aws-serverless-web-app/test/s3-static-site-stack.test.ts b/source/use_cases/aws-serverless-web-app/test/s3-static-site-stack.test.ts index 615cc1ec2..ed46cbfb6 100644 --- a/source/use_cases/aws-serverless-web-app/test/s3-static-site-stack.test.ts +++ b/source/use_cases/aws-serverless-web-app/test/s3-static-site-stack.test.ts @@ -11,103 +11,203 @@ * and limitations under the License. */ -import * as cdk from '@aws-cdk/core'; -import { S3StaticWebsiteStack } from '../lib/s3-static-site-stack'; -import { SynthUtils } from '@aws-cdk/assert'; -import '@aws-cdk/assert/jest'; +import * as cdk from "@aws-cdk/core"; +import { S3StaticWebsiteStack } from "../lib/s3-static-site-stack"; +import { SynthUtils } from "@aws-cdk/assert"; +import "@aws-cdk/assert/jest"; -test('default stack', () => { +test("default stack", () => { const app = new cdk.App(); - const stack = new S3StaticWebsiteStack(app, 'S3StaticWebsiteStack'); + const stack = new S3StaticWebsiteStack(app, "S3StaticWebsiteStack"); expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot(); }); -test('check s3 bucket encryption setting', () => { +test("check s3 bucket encryption setting", () => { const app = new cdk.App(); - const stack = new S3StaticWebsiteStack(app, 'S3StaticWebsiteStack'); + const stack = new S3StaticWebsiteStack(app, "S3StaticWebsiteStack"); expect(stack).toHaveResource("AWS::S3::Bucket", { BucketEncryption: { ServerSideEncryptionConfiguration: [ { ServerSideEncryptionByDefault: { - SSEAlgorithm: "AES256" - } - } - ] - } + SSEAlgorithm: "AES256", + }, + }, + ], + }, }); }); -test('check s3 bucket public access setting', () => { +test("check s3 bucket public access setting", () => { const app = new cdk.App(); - const stack = new S3StaticWebsiteStack(app, 'S3StaticWebsiteStack'); + const stack = new S3StaticWebsiteStack(app, "S3StaticWebsiteStack"); expect(stack).toHaveResource("AWS::S3::Bucket", { PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, IgnorePublicAcls: true, - RestrictPublicBuckets: true - } + RestrictPublicBuckets: true, + }, }); }); -test('check CR lambda function permissions', () => { +test("check CR lambda function permissions", () => { const app = new cdk.App(); - const stack = new S3StaticWebsiteStack(app, 'S3StaticWebsiteStack'); - expect(stack).toHaveResource("AWS::IAM::Policy", { - PolicyDocument: { - Statement: [ - { - Action: [ - "s3:GetObject", - "s3:ListBucket" - ], - Effect: "Allow", - Resource: [ - "arn:aws:s3:::wildrydes-us-east-1", - "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" - ] - }, - { - Action: [ - "s3:ListBucket", - "s3:GetObject", - "s3:PutObject", - "s3:PutObjectAcl", - "s3:PutObjectVersionAcl", - "s3:DeleteObject", - "s3:DeleteObjectVersion", - "s3:CopyObject" - ], - Effect: "Allow", - Resource: [ - { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - Ref: "CloudFrontToS3S3Bucket9CE6AB04" - } + const stack = new S3StaticWebsiteStack(app, "S3StaticWebsiteStack"); + expect(stack).toHaveResourceLike("AWS::IAM::Policy",{ + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetObject", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::wildrydes-us-east-1" + ] ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - Ref: "CloudFrontToS3S3Bucket9CE6AB04" - }, - "/*" + }, + "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" + ] + }, + { + "Action": [ + "s3:ListBucket", + "s3:GetObject", + "s3:PutObject", + "s3:PutObjectAcl", + "s3:PutObjectVersionAcl", + "s3:DeleteObject", + "s3:DeleteObjectVersion", + "s3:CopyObject" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + } + ] ] - ] - } - ] - } - ], - Version: "2012-10-17" - } - }); -}); \ No newline at end of file + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + }, + "/*" + ] + ] + } + ] + } +] + }, + "PolicyName": "staticContentHandlerServiceRoleDefaultPolicy0F5C5865", + "Roles": [ + { + "Ref": "staticContentHandlerServiceRole3B648F21", + } + ], +}); + + // expect(stack).toHaveResourceLike("AWS::IAM::Policy",{ + // "Properties": { + // "PolicyDocument": { + // "Statement": [ + // { + // "Action": [ + // "s3:GetObject", + // "s3:ListBucket" + // ], + // "Effect": "Allow", + // "Resource": [ + // { + // "Fn::Join": [ + // "", + // [ + // "arn:", + // { + // "Ref": "AWS::Partition" + // }, + // ":s3:::wildrydes-us-east-1" + // ] + // ] + // }, + // "arn:aws:s3:::wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website/*" + // ] + // }, + // { + // "Action": [ + // "s3:ListBucket", + // "s3:GetObject", + // "s3:PutObject", + // "s3:PutObjectAcl", + // "s3:PutObjectVersionAcl", + // "s3:DeleteObject", + // "s3:DeleteObjectVersion", + // "s3:CopyObject" + // ], + // "Effect": "Allow", + // "Resource": [ + // { + // "Fn::Join": [ + // "", + // [ + // "arn:", + // { + // "Ref": "AWS::Partition" + // }, + // ":s3:::", + // { + // "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + // } + // ] + // ] + // }, + // { + // "Fn::Join": [ + // "", + // [ + // "arn:aws:s3:::", + // { + // "Ref": "CloudFrontToS3S3Bucket9CE6AB04" + // }, + // "/*" + // ] + // ] + // } + // ] + // } + // ], + // "Version": "2012-10-17" + // }, + // "PolicyName": "staticContentHandlerServiceRoleDefaultPolicy0F5C5865", + // "Roles": [ + // { + // "Ref": "staticContentHandlerServiceRole3B648F21" + // } + // ] + // } + // }); +}); diff --git a/source/use_cases/license-header.js b/source/use_cases/license-header.js index 0ff8f7478..f2c7f3da0 100644 --- a/source/use_cases/license-header.js +++ b/source/use_cases/license-header.js @@ -1,5 +1,5 @@ /** - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * with the License. A copy of the License is located at