/
cross-account-destination.ts
118 lines (104 loc) · 3.59 KB
/
cross-account-destination.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { Construct } from 'constructs';
import { ILogGroup } from './log-group';
import { CfnDestination } from './logs.generated';
import { ILogSubscriptionDestination, LogSubscriptionDestinationConfig } from './subscription-filter';
import * as iam from '../../aws-iam';
import { ArnFormat } from '../../core';
import * as cdk from '../../core';
/**
* Properties for a CrossAccountDestination
*/
export interface CrossAccountDestinationProps {
/**
* The name of the log destination.
*
* @default Automatically generated
*/
readonly destinationName?: string;
/**
* The role to assume that grants permissions to write to 'target'.
*
* The role must be assumable by 'logs.{REGION}.amazonaws.com'.
*/
readonly role: iam.IRole;
/**
* The log destination target's ARN
*/
readonly targetArn: string;
}
/**
* A new CloudWatch Logs Destination for use in cross-account scenarios
*
* CrossAccountDestinations are used to subscribe a Kinesis stream in a
* different account to a CloudWatch Subscription.
*
* Consumers will hardly ever need to use this class. Instead, directly
* subscribe a Kinesis stream using the integration class in the
* `aws-cdk-lib/aws-logs-destinations` package; if necessary, a
* `CrossAccountDestination` will be created automatically.
*
* @resource AWS::Logs::Destination
*/
export class CrossAccountDestination extends cdk.Resource implements ILogSubscriptionDestination {
/**
* Policy object of this CrossAccountDestination object
*/
public readonly policyDocument: iam.PolicyDocument = new iam.PolicyDocument();
/**
* The name of this CrossAccountDestination object
* @attribute
*/
public readonly destinationName: string;
/**
* The ARN of this CrossAccountDestination object
* @attribute
*/
public readonly destinationArn: string;
/**
* The inner resource
*/
private readonly resource: CfnDestination;
constructor(scope: Construct, id: string, props: CrossAccountDestinationProps) {
super(scope, id, {
physicalName: props.destinationName ||
// In the underlying model, the name is not optional, but we make it so anyway.
cdk.Lazy.string({ produce: () => this.generateUniqueName() }),
});
this.resource = new CfnDestination(this, 'Resource', {
destinationName: this.physicalName!,
// Must be stringified policy
destinationPolicy: this.lazyStringifiedPolicyDocument(),
roleArn: props.role.roleArn,
targetArn: props.targetArn,
});
this.destinationArn = this.getResourceArnAttribute(this.resource.attrArn, {
service: 'logs',
resource: 'destination',
resourceName: this.physicalName,
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
});
this.destinationName = this.getResourceNameAttribute(this.resource.ref);
}
public addToPolicy(statement: iam.PolicyStatement) {
this.policyDocument.addStatements(statement);
}
public bind(_scope: Construct, _sourceLogGroup: ILogGroup): LogSubscriptionDestinationConfig {
return { arn: this.destinationArn };
}
/**
* Generate a unique Destination name in case the user didn't supply one
*/
private generateUniqueName(): string {
// Combination of stack name and LogicalID, which are guaranteed to be unique.
return cdk.Stack.of(this).stackName + '-' + this.resource.logicalId;
}
/**
* Return a stringified JSON version of the PolicyDocument
*/
private lazyStringifiedPolicyDocument(): string {
return cdk.Lazy.string({
produce: () =>
this.policyDocument.isEmpty ? '' : cdk.Stack.of(this).toJsonString(this.policyDocument),
});
}
}