/
instance-profile.ts
192 lines (171 loc) · 5.55 KB
/
instance-profile.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import { Construct } from 'constructs';
import { CfnInstanceProfile } from './iam.generated';
import { ServicePrincipal } from './principals';
import { IRole, Role } from './role';
import { Resource, Arn, Stack, IResource, PhysicalName } from '../../core';
/**
* Represents an IAM Instance Profile
*/
export interface IInstanceProfile extends IResource {
/**
* The InstanceProfile's name.
* @attribute
*/
readonly instanceProfileName: string;
/**
* The InstanceProfile's ARN.
* @attribute
*/
readonly instanceProfileArn: string;
/**
* The role associated with the InstanceProfile.
*/
readonly role?: IRole;
}
/**
* Properties of an Instance Profile
*/
export interface InstanceProfileProps {
/**
* An IAM role to associate with the instance profile that is used by EC2 instances.
*
* The role must be assumable by the service principal `ec2.amazonaws.com`:
*
* @example
* const role = new iam.Role(this, 'MyRole', {
* assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')
* });
*
* @default - a role will be automatically created, it can be accessed via the `role` property
*/
readonly role?: IRole;
/**
* The name of the InstanceProfile to create.
*
* @default - generated by CloudFormation
*/
readonly instanceProfileName?: string;
/**
* The path to the InstanceProfile.
*
* @default /
*/
readonly path?: string;
}
/**
* Attributes of an Instance Profile
*/
export interface InstanceProfileAttributes {
/**
* The ARN of the InstanceProfile.
*
* Format: arn:<partition>:iam::<account-id>:instance-profile/<instance-profile-name-with-path>
*/
readonly instanceProfileArn: string;
/**
* The role associated with the InstanceProfile.
*
* @default - no role
*/
readonly role?: IRole;
}
/**
* Base class for an Instance Profile
*/
abstract class InstanceProfileBase extends Resource implements IInstanceProfile {
public abstract readonly instanceProfileName: string;
public abstract readonly instanceProfileArn: string;
/**
* The role associated with the InstanceProfile.
* @internal
*/
protected _role?: IRole;
/**
* Returns the role associated with this InstanceProfile.
*/
public get role(): IRole | undefined {
return this._role;
}
}
/**
* IAM Instance Profile
*/
export class InstanceProfile extends InstanceProfileBase {
/**
* Import an existing InstanceProfile from an InstanceProfile name.
*
* @param scope construct scope
* @param id construct id
* @param instanceProfileName the name of the existing InstanceProfile to import
*/
public static fromInstanceProfileName(scope: Construct, id: string, instanceProfileName: string): IInstanceProfile {
const instanceProfileArn = Stack.of(scope).formatArn({
service: 'iam',
region: '',
resource: 'instance-profile',
resourceName: instanceProfileName,
});
return InstanceProfile.fromInstanceProfileAttributes(scope, id, { instanceProfileArn });
}
/**
* Import an existing InstanceProfile from an InstanceProfile ARN.
*
* If the ARN comes from a Token, the InstanceProfile cannot have a path; if so, any attempt
* to reference its instanceProfileName will fail.
*
* @param scope construct scope
* @param id construct id
* @param instanceProfileArn the ARN of the exiting InstanceProfile to import
*/
public static fromInstanceProfileArn(scope: Construct, id: string, instanceProfileArn: string): IInstanceProfile {
return InstanceProfile.fromInstanceProfileAttributes(scope, id, { instanceProfileArn });
}
/**
* Import an existing InstanceProfile from given InstanceProfile attributes.
*
* If the ARN comes from a Token, the InstanceProfile cannot have a path; if so, any attempt
* to reference its instanceProfileName will fail.
*
* @param scope construct scope
* @param id construct id
* @param attrs the attributes of the InstanceProfile to import
*/
public static fromInstanceProfileAttributes(scope: Construct, id: string, attrs: InstanceProfileAttributes): IInstanceProfile {
class Import extends InstanceProfileBase {
public readonly instanceProfileName: string = Arn.extractResourceName(attrs.instanceProfileArn, 'instance-profile').split('/').pop()!;
public readonly instanceProfileArn: string = attrs.instanceProfileArn;
constructor(s: Construct, i: string) {
super(s, i);
this._role = attrs.role;
}
}
return new Import(scope, id);
}
/**
* Returns the name of this InstanceProfile.
*/
public readonly instanceProfileName: string;
/**
* Returns the ARN of this InstanceProfile.
*/
public readonly instanceProfileArn: string;
constructor(scope: Construct, id: string, props: InstanceProfileProps = {}) {
super(scope, id, { physicalName: props.instanceProfileName });
this._role = props.role || new Role(this, 'InstanceRole', {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new ServicePrincipal('ec2.amazonaws.com'),
});
const instanceProfile = new CfnInstanceProfile(this, 'Resource', {
roles: [this._role.roleName],
instanceProfileName: this.physicalName,
path: props.path,
});
this.instanceProfileName = this.getResourceNameAttribute(instanceProfile.ref);
this.instanceProfileArn = this.getResourceArnAttribute(instanceProfile.attrArn, {
region: '',
service: 'iam',
resource: 'instance-profile',
resourceName: `${props.path ? props.path.substring(props.path.charAt(0) === '/' ? 1 : 0) : ''}${this.physicalName}`,
});
}
}