Skip to content

Commit 01601c2

Browse files
rix0rrrElad Ben-Israel
authored and
Elad Ben-Israel
committed
fix(logs): move log destinations into 'aws-logs-destinations' (#2655)
In accordance with new guidelines, we're centralizing cross-service integrations into their own package. In this case, centralizing CloudWatch Logs Subscription Destinations into @aws-cdk/aws-logs-destinations. Fixes #2444. BREAKING CHANGE: using a Lambda or Kinesis Stream as CloudWatch log subscription destination now requires an integration object from the `@aws-cdk/aws-logs-destinations` package.
1 parent 38a9894 commit 01601c2

22 files changed

+5516
-237
lines changed

Diff for: packages/@aws-cdk/aws-kinesis/lib/stream.ts

+2-68
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import iam = require('@aws-cdk/aws-iam');
22
import kms = require('@aws-cdk/aws-kms');
3-
import logs = require('@aws-cdk/aws-logs');
4-
import { Construct, HashedAddressingScheme, IResource, Resource } from '@aws-cdk/cdk';
3+
import { Construct, IResource, Resource } from '@aws-cdk/cdk';
54
import { CfnStream } from './kinesis.generated';
65

7-
export interface IStream extends IResource, logs.ILogSubscriptionDestination {
6+
export interface IStream extends IResource {
87
/**
98
* The ARN of the stream.
109
*
@@ -102,11 +101,6 @@ abstract class StreamBase extends Resource implements IStream {
102101
*/
103102
public abstract readonly encryptionKey?: kms.IKey;
104103

105-
/**
106-
* The role that can be used by CloudWatch logs to write to this stream
107-
*/
108-
private cloudWatchLogsRole?: iam.Role;
109-
110104
/**
111105
* Grant write permissions for this stream and its contents to an IAM
112106
* principal (Role/Group/User).
@@ -164,66 +158,6 @@ abstract class StreamBase extends Resource implements IStream {
164158
return ret;
165159
}
166160

167-
public logSubscriptionDestination(sourceLogGroup: logs.ILogGroup): logs.LogSubscriptionDestination {
168-
// Following example from https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#DestinationKinesisExample
169-
if (!this.cloudWatchLogsRole) {
170-
// Create a role to be assumed by CWL that can write to this stream and pass itself.
171-
this.cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsCanPutRecords', {
172-
assumedBy: new iam.ServicePrincipal(`logs.${this.node.stack.region}.amazonaws.com`)
173-
});
174-
this.cloudWatchLogsRole.addToPolicy(new iam.PolicyStatement().addAction('kinesis:PutRecord').addResource(this.streamArn));
175-
this.cloudWatchLogsRole.addToPolicy(new iam.PolicyStatement().addAction('iam:PassRole').addResource(this.cloudWatchLogsRole.roleArn));
176-
}
177-
178-
// We've now made it possible for CloudWatch events to write to us. In case the LogGroup is in a
179-
// different account, we must add a Destination in between as well.
180-
const sourceStack = sourceLogGroup.node.stack;
181-
const thisStack = this.node.stack;
182-
183-
// Case considered: if both accounts are undefined, we can't make any assumptions. Better
184-
// to assume we don't need to do anything special.
185-
const sameAccount = sourceStack.env.account === thisStack.env.account;
186-
187-
if (!sameAccount) {
188-
return this.crossAccountLogSubscriptionDestination(sourceLogGroup);
189-
}
190-
191-
return { arn: this.streamArn, role: this.cloudWatchLogsRole };
192-
}
193-
194-
/**
195-
* Generate a CloudWatch Logs Destination and return the properties in the form o a subscription destination
196-
*/
197-
private crossAccountLogSubscriptionDestination(sourceLogGroup: logs.ILogGroup): logs.LogSubscriptionDestination {
198-
const sourceLogGroupConstruct: Construct = sourceLogGroup as any;
199-
const sourceStack = sourceLogGroupConstruct.node.stack;
200-
const thisStack = this.node.stack;
201-
202-
if (!sourceStack.env.account || !thisStack.env.account) {
203-
throw new Error('SubscriptionFilter stack and Destination stack must either both have accounts defined, or both not have accounts');
204-
}
205-
206-
// Take some effort to construct a unique ID for the destination that is unique to the
207-
// combination of (stream, loggroup).
208-
const uniqueId = new HashedAddressingScheme().allocateAddress([
209-
sourceLogGroupConstruct.node.path.replace('/', ''),
210-
sourceStack.env.account!
211-
]);
212-
213-
// The destination lives in the target account
214-
const dest = new logs.CrossAccountDestination(this, `CWLDestination${uniqueId}`, {
215-
targetArn: this.streamArn,
216-
role: this.cloudWatchLogsRole!
217-
});
218-
219-
dest.addToPolicy(new iam.PolicyStatement()
220-
.addAction('logs:PutSubscriptionFilter')
221-
.addAwsAccountPrincipal(sourceStack.env.account)
222-
.addAllResources());
223-
224-
return dest.logSubscriptionDestination(sourceLogGroup);
225-
}
226-
227161
private grant(grantee: iam.IGrantable, ...actions: string[]) {
228162
return iam.Grant.addToPrincipal({
229163
grantee,

Diff for: packages/@aws-cdk/aws-kinesis/test/test.stream.ts

+13
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ export = {
2727

2828
test.done();
2929
},
30+
31+
'stream from attributes'(test: Test) {
32+
const stack = new Stack();
33+
34+
const s = Stream.fromStreamAttributes(stack, 'MyStream', {
35+
streamArn: 'arn:aws:kinesis:region:account-id:stream/stream-name'
36+
});
37+
38+
test.equals(s.streamArn, 'arn:aws:kinesis:region:account-id:stream/stream-name');
39+
40+
test.done();
41+
},
42+
3043
"uses explicit shard count"(test: Test) {
3144
const stack = new Stack();
3245

Diff for: packages/@aws-cdk/aws-kinesis/test/test.subscriptiondestination.ts

-83
This file was deleted.

Diff for: packages/@aws-cdk/aws-lambda/lib/function-base.ts

+1-25
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import cloudwatch = require('@aws-cdk/aws-cloudwatch');
22
import ec2 = require('@aws-cdk/aws-ec2');
33
import iam = require('@aws-cdk/aws-iam');
4-
import logs = require('@aws-cdk/aws-logs');
54
import { IResource, Resource } from '@aws-cdk/cdk';
65
import { IEventSource } from './event-source';
76
import { EventSourceMapping, EventSourceMappingOptions } from './event-source-mapping';
87
import { CfnPermission } from './lambda.generated';
98
import { Permission } from './permission';
109

11-
export interface IFunction extends IResource, logs.ILogSubscriptionDestination,
12-
ec2.IConnectable, iam.IGrantable {
10+
export interface IFunction extends IResource, ec2.IConnectable, iam.IGrantable {
1311

1412
/**
1513
* Logical ID of this Function.
@@ -156,11 +154,6 @@ export abstract class FunctionBase extends Resource implements IFunction {
156154
*/
157155
protected _connections?: ec2.Connections;
158156

159-
/**
160-
* Indicates if the policy that allows CloudWatch logs to publish to this lambda has been added.
161-
*/
162-
private logSubscriptionDestinationPolicyAddedFor: string[] = [];
163-
164157
/**
165158
* Adds a permission to the Lambda resource policy.
166159
* @param id The id ƒor the permission construct
@@ -251,23 +244,6 @@ export abstract class FunctionBase extends Resource implements IFunction {
251244
});
252245
}
253246

254-
public logSubscriptionDestination(sourceLogGroup: logs.ILogGroup): logs.LogSubscriptionDestination {
255-
const arn = sourceLogGroup.logGroupArn;
256-
257-
if (this.logSubscriptionDestinationPolicyAddedFor.indexOf(arn) === -1) {
258-
// NOTE: the use of {AWS::Region} limits this to the same region, which shouldn't really be an issue,
259-
// since the Lambda must be in the same region as the SubscriptionFilter anyway.
260-
//
261-
// (Wildcards in principals are unfortunately not supported.
262-
this.addPermission('InvokedByCloudWatchLogs', {
263-
principal: new iam.ServicePrincipal(`logs.${this.node.stack.region}.amazonaws.com`),
264-
sourceArn: arn
265-
});
266-
this.logSubscriptionDestinationPolicyAddedFor.push(arn);
267-
}
268-
return { arn: this.functionArn };
269-
}
270-
271247
/**
272248
* Adds an event source to this function.
273249
*

Diff for: packages/@aws-cdk/aws-lambda/test/test.subscriptiondestination.ts

-44
This file was deleted.

Diff for: packages/@aws-cdk/aws-logs-destinations/.gitignore

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
*.js
2+
tsconfig.json
3+
tslint.json
4+
*.js.map
5+
*.d.ts
6+
*.generated.ts
7+
dist
8+
lib/generated/resources.ts
9+
.jsii
10+
11+
.LAST_BUILD
12+
.nyc_output
13+
coverage
14+
.nycrc
15+
.LAST_PACKAGE
16+
*.snk

Diff for: packages/@aws-cdk/aws-logs-destinations/.npmignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Don't include original .ts files when doing `npm pack`
2+
*.ts
3+
!*.d.ts
4+
coverage
5+
.nyc_output
6+
*.tgz
7+
8+
dist
9+
.LAST_PACKAGE
10+
.LAST_BUILD
11+
!*.js
12+
13+
# Include .jsii
14+
!.jsii
15+
16+
*.snk
17+
18+
*.tsbuildinfo

0 commit comments

Comments
 (0)