diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/cdk.out new file mode 100644 index 0000000000000..560dae10d018f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"33.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.assets.json new file mode 100644 index 0000000000000..5237c75bb083b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.assets.json @@ -0,0 +1,19 @@ +{ + "version": "33.0.0", + "files": { + "065ae19c4c6accff85009f33f18e0ec2e2ed000b2cd704aed4eaa1778b943256": { + "source": { + "path": "integ-realtime-config.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "065ae19c4c6accff85009f33f18e0ec2e2ed000b2cd704aed4eaa1778b943256.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.template.json new file mode 100644 index 0000000000000..93c80311c6c2e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ-realtime-config.template.json @@ -0,0 +1,128 @@ +{ + "Resources": { + "Role1ABCC5F0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "cloudfront.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "RoleDefaultPolicy5FFB7DAB": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:DescribeStream", + "kinesis:DescribeStreamSummary", + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "stream19075594", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "RoleDefaultPolicy5FFB7DAB", + "Roles": [ + { + "Ref": "Role1ABCC5F0" + } + ] + } + }, + "stream19075594": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "RetentionPeriodHours": 24, + "StreamEncryption": { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + }, + "StreamModeDetails": { + "StreamMode": "ON_DEMAND" + } + } + }, + "RealtimeLog31F8FA14": { + "Type": "AWS::CloudFront::RealtimeLogConfig", + "Properties": { + "EndPoints": [ + { + "KinesisStreamConfig": { + "RoleArn": { + "Fn::GetAtt": [ + "Role1ABCC5F0", + "Arn" + ] + }, + "StreamArn": { + "Fn::GetAtt": [ + "stream19075594", + "Arn" + ] + } + }, + "StreamType": "Kinesis" + } + ], + "Fields": [ + "timestamp" + ], + "Name": "testing", + "SamplingRate": 1 + } + } + }, + "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/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ.json new file mode 100644 index 0000000000000..6c40b4585e6e4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "33.0.0", + "testCases": { + "integ-realtime-config/realtime-log-config/DefaultTest": { + "stacks": [ + "integ-realtime-config" + ], + "assertionStack": "integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert", + "assertionStackName": "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets.json new file mode 100644 index 0000000000000..443d1ebe58568 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets.json @@ -0,0 +1,19 @@ +{ + "version": "33.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.template.json @@ -0,0 +1,36 @@ +{ + "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/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/manifest.json new file mode 100644 index 0000000000000..ab15aaab94e0e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/manifest.json @@ -0,0 +1,129 @@ +{ + "version": "33.0.0", + "artifacts": { + "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integrealtimeconfigrealtimelogconfigDefaultTestDeployAssert02ABDB2F.assets" + ], + "metadata": { + "/integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert" + }, + "integ-realtime-config.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-realtime-config.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-realtime-config": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-realtime-config.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/065ae19c4c6accff85009f33f18e0ec2e2ed000b2cd704aed4eaa1778b943256.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-realtime-config.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-realtime-config.assets" + ], + "metadata": { + "/integ-realtime-config/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Role1ABCC5F0" + } + ], + "/integ-realtime-config/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RoleDefaultPolicy5FFB7DAB" + } + ], + "/integ-realtime-config/stream/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "stream19075594" + } + ], + "/integ-realtime-config/RealtimeLog/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RealtimeLog31F8FA14" + } + ], + "/integ-realtime-config/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-realtime-config/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-realtime-config" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/tree.json new file mode 100644 index 0000000000000..73e223f71a372 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.js.snapshot/tree.json @@ -0,0 +1,271 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-realtime-config": { + "id": "integ-realtime-config", + "path": "integ-realtime-config", + "children": { + "Role": { + "id": "Role", + "path": "integ-realtime-config/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "integ-realtime-config/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-realtime-config/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "cloudfront.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-realtime-config/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-realtime-config/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:DescribeStream", + "kinesis:DescribeStreamSummary", + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "stream19075594", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "RoleDefaultPolicy5FFB7DAB", + "roles": [ + { + "Ref": "Role1ABCC5F0" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "stream": { + "id": "stream", + "path": "integ-realtime-config/stream", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-realtime-config/stream/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::Stream", + "aws:cdk:cloudformation:props": { + "retentionPeriodHours": 24, + "streamEncryption": { + "encryptionType": "KMS", + "keyId": "alias/aws/kinesis" + }, + "streamModeDetails": { + "streamMode": "ON_DEMAND" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnStream", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.Stream", + "version": "0.0.0" + } + }, + "RealtimeLog": { + "id": "RealtimeLog", + "path": "integ-realtime-config/RealtimeLog", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-realtime-config/RealtimeLog/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFront::RealtimeLogConfig", + "aws:cdk:cloudformation:props": { + "endPoints": [ + { + "kinesisStreamConfig": { + "roleArn": { + "Fn::GetAtt": [ + "Role1ABCC5F0", + "Arn" + ] + }, + "streamArn": { + "Fn::GetAtt": [ + "stream19075594", + "Arn" + ] + } + }, + "streamType": "Kinesis" + } + ], + "fields": [ + "timestamp" + ], + "name": "testing", + "samplingRate": 1 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudfront.CfnRealtimeLogConfig", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_cloudfront.RealtimeLogConfig", + "version": "0.0.0" + } + }, + "realtime-log-config": { + "id": "realtime-log-config", + "path": "integ-realtime-config/realtime-log-config", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-realtime-config/realtime-log-config/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-realtime-config/realtime-log-config/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.69" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-realtime-config/realtime-log-config/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-realtime-config/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-realtime-config/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.69" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.ts new file mode 100644 index 0000000000000..0897e599028b3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.realtime-log-config.ts @@ -0,0 +1,30 @@ +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; +import { Stream, StreamEncryption, StreamMode } from 'aws-cdk-lib/aws-kinesis'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-realtime-config'); + +const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), +}); + +const kinesis = new Stream(stack, 'stream', { + streamMode: StreamMode.ON_DEMAND, + encryption: StreamEncryption.MANAGED, +}); + +new cloudfront.RealtimeLogConfig(stack, 'RealtimeLog', { + endPoints: [ + cloudfront.Endpoint.fromKinesisStream(kinesis, role), + ], + fields: ['timestamp'], + realtimeLogConfigName: 'testing', + samplingRate: 1, +}); + +new IntegTest(stack, 'realtime-log-config', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index aab05433fd4f6..f3abddd464ba7 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -601,6 +601,42 @@ distribution.grant(lambdaFn, 'cloudfront:ListInvalidations', 'cloudfront:GetInva distribution.grantCreateInvalidation(lambdaFn); ``` +### Realtime Log Config + +CloudFront supports realtime log delivery from your distribution to a Kinesis stream. + +See [Real-time logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html) in the CloudFront User Guide. + +Example: + +```ts +// Adding realtime logs config to a Cloudfront Distribution on default behavior. +import * as kinesis from 'aws-cdk-lib/aws-kinesis'; + +declare const stream: kinesis.Stream; + +const realTimeConfig = new cloudfront.RealtimeLogConfig(this, 'realtimeLog', { + endPoints: [ + cloudfront.Endpoint.fromKinesisStream(stream), + ], + fields: [ + 'timestamp', + 'c-ip', + 'time-to-first-byte', + 'sc-status', + ], + realtimeLogConfigName: 'my-delivery-stream', + samplingRate: 100, +}); + +new cloudfront.Distribution(this, 'myCdn', { + defaultBehavior: { + origin: new origins.HttpOrigin('www.example.com'), + realtimeLogConfig: realTimeConfig, + }, +}); +``` + ## Migrating from the original CloudFrontWebDistribution to the newer Distribution construct It's possible to migrate a distribution from the original to the modern API. diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 7918a5e996cbd..bc0e8d58c8d96 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -8,6 +8,7 @@ import { IOrigin, OriginBindConfig, OriginBindOptions } from './origin'; import { IOriginRequestPolicy } from './origin-request-policy'; import { CacheBehavior } from './private/cache-behavior'; import { formatDistributionArn } from './private/utils'; +import { IRealtimeLogConfig } from './realtime-log-config'; import { IResponseHeadersPolicy } from './response-headers-policy'; import * as acm from '../../aws-certificatemanager'; import * as iam from '../../aws-iam'; @@ -777,6 +778,13 @@ export interface AddBehaviorOptions { */ readonly originRequestPolicy?: IOriginRequestPolicy; + /** + * The real-time log configuration to be attached to this cache behavior. + * + * @default - none + */ + readonly realtimeLogConfig?: IRealtimeLogConfig; + /** * The response headers policy for this behavior. The response headers policy determines which headers are included in responses * diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts new file mode 100644 index 0000000000000..d7069944f2560 --- /dev/null +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/endpoint.ts @@ -0,0 +1,65 @@ +import { Construct } from 'constructs'; +import * as iam from '../../aws-iam'; +import * as kinesis from '../../aws-kinesis'; +import { PhysicalName } from '../../core'; + +/** + * Represents the endpoints available for targetting within a realtime log config resource + */ +export abstract class Endpoint { + + /** + * Configure a Kinesis Stream Endpoint for Realtime Log Config + * + * @default - a role will be created and used across your endpoints + */ + public static fromKinesisStream(stream: kinesis.IStream, role?: iam.IRole): Endpoint { + return new (class extends Endpoint { + public _renderEndpoint(scope: Construct) { + const cloudfrontRole = role ?? this.singletonKinesisRole(scope); + + stream.grant(cloudfrontRole, + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ); + + if (stream.encryptionKey) { + stream.encryptionKey.grant(cloudfrontRole, 'kms:GenerateDataKey'); + } + + return { + kinesisStreamConfig: { + roleArn: cloudfrontRole.roleArn, + streamArn: stream.streamArn, + }, + streamType: 'Kinesis', + }; + } + }); + } + + private constructor() {} + + /** + * @internal + */ + private singletonKinesisRole(scope: Construct): iam.IRole { + const id = 'RealtimeLogKinesisRole'; + const existing = scope.node.tryFindChild(id) as iam.IRole; + if (existing) { return existing; } + + const role = new iam.Role(scope, id, { + roleName: PhysicalName.GENERATE_IF_NEEDED, + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), + }); + + return role; + } + + /** + * @internal + */ + public abstract _renderEndpoint(scope: Construct): any; +} diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/index.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/index.ts index e5abe99c0bfbd..fec6239124609 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/index.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/index.ts @@ -1,5 +1,6 @@ export * from './cache-policy'; export * from './distribution'; +export * from './endpoint'; export * from './function'; export * from './geo-restriction'; export * from './key-group'; @@ -7,6 +8,7 @@ export * from './origin'; export * from './origin-access-identity'; export * from './origin-request-policy'; export * from './public-key'; +export * from './realtime-log-config'; export * from './response-headers-policy'; export * from './web-distribution'; diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts index dcd25b3eb5e88..b4a7e8bd4c483 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/private/cache-behavior.ts @@ -48,6 +48,7 @@ export class CacheBehavior { cachePolicyId: (this.props.cachePolicy ?? CachePolicy.CACHING_OPTIMIZED).cachePolicyId, compress: this.props.compress ?? true, originRequestPolicyId: this.props.originRequestPolicy?.originRequestPolicyId, + realtimeLogConfigArn: this.props?.realtimeLogConfig?.realtimeLogConfigArn, responseHeadersPolicyId: this.props.responseHeadersPolicy?.responseHeadersPolicyId, smoothStreaming: this.props.smoothStreaming, viewerProtocolPolicy: this.props.viewerProtocolPolicy ?? ViewerProtocolPolicy.ALLOW_ALL, diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/realtime-log-config.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/realtime-log-config.ts new file mode 100644 index 0000000000000..d30f3668c8891 --- /dev/null +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/realtime-log-config.ts @@ -0,0 +1,84 @@ +import { Construct } from 'constructs'; +import { CfnRealtimeLogConfig } from './cloudfront.generated'; +import { Endpoint } from '../'; +import { IResource, Lazy, Names, Resource } from '../../core'; + +/** + * Represents Realtime Log Configuration + */ +export interface IRealtimeLogConfig extends IResource { + /** + * The name of the realtime log config. + * @attribute + */ + readonly realtimeLogConfigName: string; + /** + * The arn of the realtime log config. + * @attribute + */ + readonly realtimeLogConfigArn: string; +} + +/** + * Properties for defining a RealtimeLogConfig resource. + */ +export interface RealtimeLogConfigProps { + /** + * The unique name of this real-time log configuration. + * + * @default - the unique construct ID + */ + readonly realtimeLogConfigName?: string; + /** + * A list of fields that are included in each real-time log record. + * + * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html#understand-real-time-log-config-fields + */ + readonly fields: string[]; + /** + * The sampling rate for this real-time log configuration. + */ + readonly samplingRate: number; + /** + * Contains information about the Amazon Kinesis data stream where you are sending real-time log data for this real-time log configuration. + */ + readonly endPoints: Endpoint[]; +} + +/** + * A Realtime Log Config configuration + * + * @resource AWS::CloudFront::RealtimeLogConfig + */ +export class RealtimeLogConfig extends Resource implements IRealtimeLogConfig { + public readonly realtimeLogConfigName: string; + public readonly realtimeLogConfigArn: string; + + constructor(scope: Construct, id: string, props: RealtimeLogConfigProps) { + super(scope, id, { + physicalName: props.realtimeLogConfigName ?? Lazy.string({ produce: () => Names.uniqueResourceName(this, {}) }), + }); + + if ((props.samplingRate < 1 || props.samplingRate > 100)) { + throw new Error(`Sampling rate must be between 1 and 100 (inclusive), received ${props.samplingRate}`); + } + + const resource = new CfnRealtimeLogConfig(this, 'Resource', { + endPoints: props.endPoints.map(endpoint => { + return endpoint._renderEndpoint(this); + }), + fields: props.fields, + name: this.physicalName, + samplingRate: props.samplingRate, + }); + + this.realtimeLogConfigArn = this.getResourceArnAttribute(resource.attrArn, { + service: 'cloudfront', + region: '', + resource: 'realtime-log-config', + resourceName: this.physicalName, + }); + + this.realtimeLogConfigName = this.getResourceNameAttribute(resource.ref); + } +} diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index af3b268688703..4797ec8dd4fa6 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -2,12 +2,14 @@ import { defaultOrigin, defaultOriginGroup } from './test-origin'; import { Match, Template } from '../../assertions'; import * as acm from '../../aws-certificatemanager'; import * as iam from '../../aws-iam'; +import * as kinesis from '../../aws-kinesis'; import * as lambda from '../../aws-lambda'; import * as s3 from '../../aws-s3'; import { App, Duration, Stack } from '../../core'; import { CfnDistribution, Distribution, + Endpoint, Function, FunctionCode, FunctionEventType, @@ -16,6 +18,7 @@ import { IOrigin, LambdaEdgeEventType, PriceClass, + RealtimeLogConfig, SecurityPolicyProtocol, SSLMethod, } from '../lib'; @@ -1146,3 +1149,95 @@ test('grants createInvalidation', () => { }, }); }); + +test('render distribution behavior with realtime log config', () => { + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), + }); + + const stream = new kinesis.Stream(stack, 'stream', { + streamMode: kinesis.StreamMode.ON_DEMAND, + encryption: kinesis.StreamEncryption.MANAGED, + }); + + const realTimeConfig = new RealtimeLogConfig(stack, 'RealtimeConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: ['timestamp'], + realtimeLogConfigName: 'realtime-config', + samplingRate: 50, + }); + + new Distribution(stack, 'MyDist', { + defaultBehavior: { + origin: defaultOrigin(), + realtimeLogConfig: realTimeConfig, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', + Match.objectLike({ + DistributionConfig: { + DefaultCacheBehavior: { + RealtimeLogConfigArn: { + 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + }, + }, + }, + })); +}); + +test('render distribution behavior with realtime log config - multiple behaviors', () => { + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), + }); + + const stream = new kinesis.Stream(stack, 'stream', { + streamMode: kinesis.StreamMode.ON_DEMAND, + encryption: kinesis.StreamEncryption.MANAGED, + }); + + const realTimeConfig = new RealtimeLogConfig(stack, 'RealtimeConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: ['timestamp'], + realtimeLogConfigName: 'realtime-config', + samplingRate: 50, + }); + + const origin2 = defaultOrigin('origin2.example.com'); + + new Distribution(stack, 'MyDist', { + defaultBehavior: { + origin: defaultOrigin(), + realtimeLogConfig: realTimeConfig, + }, + additionalBehaviors: { + '/api/*': { + origin: origin2, + realtimeLogConfig: realTimeConfig, + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', + Match.objectLike({ + DistributionConfig: { + DefaultCacheBehavior: { + RealtimeLogConfigArn: { + 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + }, + TargetOriginId: 'StackMyDistOrigin1D6D5E535', + }, + CacheBehaviors: [{ + PathPattern: '/api/*', + RealtimeLogConfigArn: { + 'Fn::GetAtt': ['RealtimeConfigB6004E8E', 'Arn'], + }, + TargetOriginId: 'StackMyDistOrigin20B96F3AD', + }], + }, + })); +}); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/endpoint.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/endpoint.test.ts new file mode 100644 index 0000000000000..73eb9061423f8 --- /dev/null +++ b/packages/aws-cdk-lib/aws-cloudfront/test/endpoint.test.ts @@ -0,0 +1,85 @@ +import { Template } from '../../assertions'; +import * as iam from '../../aws-iam'; +import * as kinesis from '../../aws-kinesis'; +import * as kms from '../../aws-kms'; +import { App, Stack } from '../../core'; +import { Endpoint } from '../lib'; + +describe('Endpoint', () => { + let app: App; + let stack: Stack; + + let stream: kinesis.IStream; + let role: iam.Role; + + beforeEach(() => { + app = new App(); + stack = new Stack(app, 'Stack', { + env: { account: '1234', region: 'testregion' }, + }); + stream = new kinesis.Stream(stack, 'stream'); + role = new iam.Role(stack, 'my-role', { + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), + }); + }); + + test('realtime config setup', () => { + const endpoint = Endpoint.fromKinesisStream(stream, role); + + expect(stack.resolve(endpoint._renderEndpoint(stack))).toStrictEqual({ + kinesisStreamConfig: { + roleArn: { + 'Fn::GetAtt': ['myrole97476C1B', 'Arn'], + }, + streamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + streamType: 'Kinesis', + }); + }); + + test('realtime config setup - default role', () => { + const endpoint = Endpoint.fromKinesisStream(stream); + + expect(stack.resolve(endpoint._renderEndpoint(stack))).toStrictEqual({ + kinesisStreamConfig: { + roleArn: { + 'Fn::GetAtt': ['RealtimeLogKinesisRoleBBD6D0F3', 'Arn'], + }, + streamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + streamType: 'Kinesis', + }); + }); + + test('Endpoint with specified role - and encrypted kinesis stream', () => { + const myStream = new kinesis.Stream(stack, 'MyStream', { + encryption: kinesis.StreamEncryption.KMS, + encryptionKey: new kms.Key(stack, 'key'), + }); + + Endpoint.fromKinesisStream(myStream, role)._renderEndpoint(stack); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [{ + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['MyStream5C050E93', 'Arn'] }, + }, { + Action: 'kms:GenerateDataKey', + Resource: { 'Fn::GetAtt': ['keyFEDD6EC0', 'Arn'] }, + }], + Version: '2012-10-17', + }, + }); + }); + +}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/realtime-log-config.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/realtime-log-config.test.ts new file mode 100644 index 0000000000000..699a8c6d94ae2 --- /dev/null +++ b/packages/aws-cdk-lib/aws-cloudfront/test/realtime-log-config.test.ts @@ -0,0 +1,324 @@ +import { Match, Template } from '../../assertions'; +import * as iam from '../../aws-iam'; +import * as kinesis from '../../aws-kinesis'; +import * as kms from '../../aws-kms'; +import { App, Stack } from '../../core'; +import { Endpoint, RealtimeLogConfig } from '../lib'; + +describe('RealtimeLogConfig', () => { + let app: App; + let stack: Stack; + + let stream: kinesis.IStream; + let role: iam.Role; + + beforeEach(() => { + app = new App(); + stack = new Stack(app, 'Stack', { + env: { account: '1234', region: 'testregion' }, + }); + stream = new kinesis.Stream(stack, 'stream'); + role = new iam.Role(stack, 'my-role', { + assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'), + }); + }); + + test('realtime config setup', () => { + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + realtimeLogConfigName: 'realtime-log-collector', + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::RealtimeLogConfig', { + EndPoints: [{ + KinesisStreamConfig: { + RoleArn: { + 'Fn::GetAtt': ['myrole97476C1B', 'Arn'], + }, + StreamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + }], + Fields: ['timestamp', 'c-ip'], + Name: 'realtime-log-collector', + SamplingRate: 1, + }); + }); + + test('throws on sampling rate being 111', () => { + const errorMessage = 'Sampling rate must be between 1 and 100 (inclusive), received 111'; + expect(() => { + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + realtimeLogConfigName: 'realtime-log-collector', + samplingRate: 111, + }); + }).toThrow(errorMessage); + }); + + test('throws on sampling rate being 0', () => { + const errorMessage = 'Sampling rate must be between 1 and 100 (inclusive), received 0'; + expect(() => { + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + realtimeLogConfigName: 'realtime-log-collector', + samplingRate: 0, + }); + }).toThrow(errorMessage); + }); + + test('realtime config setup - generate unique id', () => { + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream, role), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::RealtimeLogConfig', { + EndPoints: [{ + KinesisStreamConfig: { + RoleArn: { + 'Fn::GetAtt': ['myrole97476C1B', 'Arn'], + }, + StreamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + }], + Fields: ['timestamp', 'c-ip'], + Name: 'StackMyRealtimeLogConfig4A2E70EF', + SamplingRate: 1, + }); + }); + + test('realtime config setup default role', () => { + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::RealtimeLogConfig', { + EndPoints: [{ + KinesisStreamConfig: { + RoleArn: { + 'Fn::GetAtt': ['MyRealtimeLogConfigRealtimeLogKinesisRole3AD572A6', 'Arn'], + }, + StreamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + }], + Fields: ['timestamp', 'c-ip'], + Name: 'StackMyRealtimeLogConfig4A2E70EF', + SamplingRate: 1, + }); + }); + + test('realtime config setup default role - multiple kinesis endpoints', () => { + const secondStream = new kinesis.Stream(stack, 'stream2'); + + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream), + Endpoint.fromKinesisStream(secondStream), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::RealtimeLogConfig', { + EndPoints: [{ + KinesisStreamConfig: { + RoleArn: { + 'Fn::GetAtt': ['MyRealtimeLogConfigRealtimeLogKinesisRole3AD572A6', 'Arn'], + }, + StreamArn: { + 'Fn::GetAtt': ['stream19075594', 'Arn'], + }, + }, + }, { + KinesisStreamConfig: { + RoleArn: { + 'Fn::GetAtt': ['MyRealtimeLogConfigRealtimeLogKinesisRole3AD572A6', 'Arn'], + }, + StreamArn: { + 'Fn::GetAtt': ['stream25EB1FBCF', 'Arn'], + }, + }, + }], + Fields: ['timestamp', 'c-ip'], + Name: 'StackMyRealtimeLogConfig4A2E70EF', + SamplingRate: 1, + }); + }); + + test('realtime config setup default role - multiple kinesis endpoints with generated iam role', () => { + const secondStream = new kinesis.Stream(stack, 'stream2'); + + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream), + Endpoint.fromKinesisStream(secondStream), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [{ + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['stream19075594', 'Arn'] }, + }, + { + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['stream25EB1FBCF', 'Arn'] }, + }], + Version: '2012-10-17', + }, + }); + }); + + test('realtime config setup default role - multiple kinesis endpoints with generated iam and kms', () => { + const secondStream = new kinesis.Stream(stack, 'stream2', { + encryption: kinesis.StreamEncryption.KMS, + encryptionKey: new kms.Key(stack, 'key'), + }); + + const thirdStream = new kinesis.Stream(stack, 'stream3', { + encryption: kinesis.StreamEncryption.MANAGED, + }); + + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream), + Endpoint.fromKinesisStream(secondStream), + Endpoint.fromKinesisStream(thirdStream), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [{ + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['stream19075594', 'Arn'] }, + }, + { + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['stream25EB1FBCF', 'Arn'] }, + }, + { + Action: 'kms:GenerateDataKey', + Resource: { 'Fn::GetAtt': ['keyFEDD6EC0', 'Arn'] }, + }, + { + Action: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:DescribeStream', + 'kinesis:PutRecord', + 'kinesis:PutRecords', + ], + Resource: { 'Fn::GetAtt': ['stream358FA433A', 'Arn'] }, + }], + Version: '2012-10-17', + }, + }); + }); + + test('realtime config setup with both default and specified role', () => { + const secondStream = new kinesis.Stream(stack, 'secondstream', { + encryption: kinesis.StreamEncryption.MANAGED, + }); + + new RealtimeLogConfig(stack, 'MyRealtimeLogConfig', { + endPoints: [ + Endpoint.fromKinesisStream(stream), + Endpoint.fromKinesisStream(secondStream, role), + ], + fields: [ + 'timestamp', + 'c-ip', + ], + samplingRate: 1, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::RealtimeLogConfig', { + EndPoints: [ + Match.objectLike({ + KinesisStreamConfig: { + RoleArn: { 'Fn::GetAtt': ['MyRealtimeLogConfigRealtimeLogKinesisRole3AD572A6', 'Arn'] }, + StreamArn: { 'Fn::GetAtt': ['stream19075594', 'Arn'] }, + }, + }), + Match.objectLike({ + KinesisStreamConfig: { + RoleArn: { 'Fn::GetAtt': ['myrole97476C1B', 'Arn'] }, + StreamArn: { 'Fn::GetAtt': ['secondstreamB4F8BA11', 'Arn'] }, + }, + }), + ], + }); + }); +});