11import * as cdk from '@aws-cdk/core' ;
2- import * as iam from '@aws-cdk/aws-iam' ;
3- import { createRoleName , createName } from '@aws-accelerator/cdk-accelerator/src/core/accelerator-name-generator' ;
2+ import { createName } from '@aws-accelerator/cdk-accelerator/src/core/accelerator-name-generator' ;
43import * as kinesis from '@aws-cdk/aws-kinesis' ;
54import * as s3 from '@aws-cdk/aws-s3' ;
65import * as logs from '@aws-cdk/aws-logs' ;
76import * as kinesisfirehose from '@aws-cdk/aws-kinesisfirehose' ;
8- import { AccountStack } from '../../../common/account-stacks' ;
7+ import { AccountStacks } from '../../../common/account-stacks' ;
98import { Account } from '../../../utils/accounts' ;
109import { JsonOutputValue } from '../../../common/json-output' ;
1110import { CLOUD_WATCH_CENTRAL_LOGGING_BUCKET_PREFIX } from '@aws-accelerator/common/src/util/constants' ;
11+ import * as c from '@aws-accelerator/common-config' ;
12+ import { StackOutput } from '@aws-accelerator/common-outputs/src/stack-output' ;
13+ import { IamRoleOutputFinder } from '@aws-accelerator/common-outputs/src/iam-role' ;
14+ import { CfnLogDestinationOutput } from './outputs' ;
1215
1316export interface CentralLoggingToS3Step1Props {
14- accountStack : AccountStack ;
17+ accountStacks : AccountStacks ;
1518 accounts : Account [ ] ;
1619 logBucket : s3 . IBucket ;
17- shardCount ?: number ;
20+ outputs : StackOutput [ ] ;
21+ config : c . AcceleratorConfig ;
1822}
1923
2024/**
2125 * Enable Central Logging to S3 in "log-archive" account Step 1
2226 */
2327export async function step1 ( props : CentralLoggingToS3Step1Props ) {
24- const { accountStack , accounts, logBucket, shardCount } = props ;
28+ const { accountStacks , accounts, logBucket, config , outputs } = props ;
2529 // Setup for CloudWatch logs storing in logs account
2630 const allAccountIds = accounts . map ( account => account . id ) ;
27- await cwlSettingsInLogArchive ( {
28- scope : accountStack ,
29- accountIds : allAccountIds ,
30- bucketArn : logBucket . bucketArn ,
31- encryptionKey : logBucket . encryptionKey ?. keyArn ! ,
32- shardCount,
31+ const centralLogServices = config [ 'global-options' ] [ 'central-log-services' ] ;
32+ const cwlRegionsConfig = config [ 'global-options' ] [ 'additional-cwl-regions' ] ;
33+ if ( ! cwlRegionsConfig [ centralLogServices . region ] ) {
34+ cwlRegionsConfig [ centralLogServices . region ] = {
35+ 'kinesis-stream-shard-count' : centralLogServices [ 'kinesis-stream-shard-count' ] ,
36+ } ;
37+ }
38+
39+ const cwlLogStreamRoleOutput = IamRoleOutputFinder . tryFindOneByName ( {
40+ outputs,
41+ accountKey : centralLogServices . account ,
42+ roleKey : 'CWLLogsStreamRole' ,
43+ } ) ;
44+
45+ const cwlKinesisStreamRoleOutput = IamRoleOutputFinder . tryFindOneByName ( {
46+ outputs,
47+ accountKey : centralLogServices . account ,
48+ roleKey : 'CWLKinesisStreamRole' ,
3349 } ) ;
50+
51+ if ( ! cwlLogStreamRoleOutput || ! cwlKinesisStreamRoleOutput ) {
52+ console . error ( `Skipping CWL Central logging setup due to unavailability of roles in output` ) ;
53+ return ;
54+ }
55+
56+ // Setting up in default "central-log-services" and "additional-cwl-regions" region
57+ for ( const [ region , regionConfig ] of Object . entries ( cwlRegionsConfig ) ) {
58+ // Setup CWL Central logging in default region
59+ const logAccountStack = accountStacks . tryGetOrCreateAccountStack ( centralLogServices . account , region ) ;
60+ if ( ! logAccountStack ) {
61+ console . error (
62+ `Cannot find account stack ${ centralLogServices . account } : ${ region } while setting up cloudWatch central logging to S3` ,
63+ ) ;
64+ continue ;
65+ }
66+ await cwlSettingsInLogArchive ( {
67+ scope : logAccountStack ,
68+ accountIds : allAccountIds ,
69+ bucketArn : logBucket . bucketArn ,
70+ shardCount : regionConfig [ 'kinesis-stream-shard-count' ] ,
71+ logStreamRoleArn : cwlLogStreamRoleOutput . roleArn ,
72+ kinesisStreamRoleArn : cwlKinesisStreamRoleOutput . roleArn ,
73+ } ) ;
74+ }
3475}
3576
3677/**
@@ -41,10 +82,11 @@ async function cwlSettingsInLogArchive(props: {
4182 scope : cdk . Construct ;
4283 accountIds : string [ ] ;
4384 bucketArn : string ;
44- encryptionKey : string ;
85+ logStreamRoleArn : string ;
86+ kinesisStreamRoleArn : string ;
4587 shardCount ?: number ;
4688} ) {
47- const { scope, accountIds, bucketArn, encryptionKey , shardCount } = props ;
89+ const { scope, accountIds, bucketArn, logStreamRoleArn , kinesisStreamRoleArn , shardCount } = props ;
4890
4991 // Create Kinesis Stream for Logs streaming
5092 const logsStream = new kinesis . Stream ( scope , 'Logs-Stream' , {
@@ -56,27 +98,6 @@ async function cwlSettingsInLogArchive(props: {
5698 shardCount,
5799 } ) ;
58100
59- // Create IAM Role for reading logs from stream and push to destination
60- const logsRole = new iam . Role ( scope , 'CloudWatch-Logs-Stream-Role' , {
61- roleName : createRoleName ( 'CWL-Logs-Stream-Role' ) ,
62- assumedBy : new iam . ServicePrincipal ( 'logs.amazonaws.com' ) ,
63- } ) ;
64-
65- // Create IAM Policy for reading logs from stream and push to destination
66- const logsRolePolicy = new iam . Policy ( scope , 'CWL-Logs-Stream-Policy' , {
67- roles : [ logsRole ] ,
68- statements : [
69- new iam . PolicyStatement ( {
70- resources : [ logsStream . streamArn ] ,
71- actions : [ 'kinesis:PutRecord' ] ,
72- } ) ,
73- new iam . PolicyStatement ( {
74- resources : [ logsRole . roleArn ] ,
75- actions : [ 'iam:PassRole' ] ,
76- } ) ,
77- ] ,
78- } ) ;
79-
80101 const destinationName = createName ( {
81102 name : 'LogDestination' ,
82103 suffixLength : 0 ,
@@ -100,57 +121,18 @@ async function cwlSettingsInLogArchive(props: {
100121 const logDestination = new logs . CfnDestination ( scope , 'Log-Destination' , {
101122 destinationName,
102123 targetArn : logsStream . streamArn ,
103- roleArn : logsRole . roleArn ,
124+ roleArn : logStreamRoleArn ,
104125 destinationPolicy : destinationPolicyStr ,
105126 } ) ;
106- logDestination . node . addDependency ( logsRolePolicy ) ;
107-
108- // Creating IAM role for Kinesis Delivery Stream Role
109- const kinesisStreamRole = new iam . Role ( scope , 'CWL-Kinesis-Stream-Role' , {
110- roleName : createRoleName ( 'Kinesis-Stream-Role' ) ,
111- assumedBy : new iam . ServicePrincipal ( 'firehose.amazonaws.com' ) ,
112- } ) ;
113127
114- const kinesisStreamPolicy = new iam . Policy ( scope , 'CWL-Kinesis-Stream-Policy' , {
115- roles : [ kinesisStreamRole ] ,
116- statements : [
117- new iam . PolicyStatement ( {
118- resources : [ encryptionKey ] ,
119- actions : [ 'kms:DescribeKey' , 'kms:GenerateDataKey*' , 'kms:Decrypt' , 'kms:Encrypt' , 'kms:ReEncrypt*' ] ,
120- } ) ,
121- new iam . PolicyStatement ( {
122- resources : [ bucketArn , `${ bucketArn } /*` ] ,
123- actions : [
124- 's3:PutObject' ,
125- 's3:PutObjectAcl' ,
126- 's3:GetEncryptionConfiguration' ,
127- 's3:AbortMultipartUpload' ,
128- 's3:GetBucketLocation' ,
129- 's3:GetObject' ,
130- 's3:ListBucket' ,
131- 's3:ListBucketMultipartUploads' ,
132- 's3:PutObject' ,
133- ] ,
134- } ) ,
135- new iam . PolicyStatement ( {
136- resources : [ '*' ] ,
137- actions : [ 'kinesis:DescribeStream' , 'kinesis:GetShardIterator' , 'kinesis:GetRecords' , 'kinesis:ListShards' ] ,
138- } ) ,
139- new iam . PolicyStatement ( {
140- resources : [ 'arn:aws:logs:*:*:*' ] ,
141- actions : [ 'logs:PutLogEvents' ] ,
142- } ) ,
143- ] ,
144- } ) ;
145-
146- const kinesisDeliveryStream = new kinesisfirehose . CfnDeliveryStream ( scope , 'Kinesis-Firehouse-Stream' , {
128+ new kinesisfirehose . CfnDeliveryStream ( scope , 'Kinesis-Firehouse-Stream' , {
147129 deliveryStreamName : createName ( {
148130 name : 'Kinesis-Delivery-Stream' ,
149131 } ) ,
150132 deliveryStreamType : 'KinesisStreamAsSource' ,
151133 kinesisStreamSourceConfiguration : {
152134 kinesisStreamArn : logsStream . streamArn ,
153- roleArn : kinesisStreamRole . roleArn ,
135+ roleArn : kinesisStreamRoleArn ,
154136 } ,
155137 extendedS3DestinationConfiguration : {
156138 bucketArn,
@@ -159,18 +141,15 @@ async function cwlSettingsInLogArchive(props: {
159141 sizeInMBs : 50 ,
160142 } ,
161143 compressionFormat : 'UNCOMPRESSED' ,
162- roleArn : kinesisStreamRole . roleArn ,
144+ roleArn : kinesisStreamRoleArn ,
163145 prefix : CLOUD_WATCH_CENTRAL_LOGGING_BUCKET_PREFIX ,
164146 } ,
165147 } ) ;
166- kinesisDeliveryStream . node . addDependency ( kinesisStreamPolicy ) ;
167- kinesisDeliveryStream . node . addDependency ( logsRolePolicy ) ;
168148
169149 // Store LogDestination ARN in output so that subsequent phases can access the output
170- new JsonOutputValue ( scope , `CloudWatchCentralLoggingOutput` , {
171- type : 'CloudWatchCentralLogging' ,
172- value : {
173- logDestination : logDestination . attrArn ,
174- } ,
150+ new CfnLogDestinationOutput ( scope , `CloudWatchCentralLoggingOutput` , {
151+ destinationArn : logDestination . attrArn ,
152+ destinationName : logDestination . destinationName ,
153+ destinationKey : 'CwlCentralLogDestination' ,
175154 } ) ;
176155}
0 commit comments