-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(aws-iam): add aws iam instance profile: fixes #1223 #1224
Changes from all commits
32827f1
0904436
aa082b4
b5b02de
3e0d0d1
c0a865d
e85e4a0
0c6fdd2
dda44a6
d3a292b
fbf3841
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -227,6 +227,7 @@ export abstract class BaseService extends cdk.Construct | |
private makeAutoScalingRole(): iam.IRole { | ||
// Use a Service Linked Role. | ||
return iam.Role.import(this, 'ScalingRole', { | ||
roleName: 'ECSServiceAutoScalingRole', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. revert |
||
roleArn: cdk.ArnUtils.fromComponents({ | ||
service: 'iam', | ||
resource: 'role/aws-service-role/ecs.application-autoscaling.amazonaws.com', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import { PolicyStatement } from './policy-document'; | ||
import { IRole } from './role'; | ||
|
||
export interface InstanceProfileRefProps { | ||
|
||
/** | ||
* The path associated with this instance profile. For information about IAM Instance Profiles, see | ||
* Friendly Names and Paths in IAM User Guide. | ||
* @link http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html#Identifiers_FriendlyNames | ||
* @default / By default, AWS CloudFormation specifies '/' for the path. | ||
*/ | ||
path: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't that be optional? |
||
|
||
/** | ||
* The name of an existing IAM role to associate with this instance profile. | ||
* Currently, you can assign a maximum of one role to an instance profile. | ||
* @default Role a default Role with ServicePrincipal(ec2.amazonaws.com). | ||
*/ | ||
role: IRole; | ||
|
||
/** | ||
* The name of the instance profile that you want to create. | ||
* This parameter allows (per its regex pattern) a string consisting of | ||
* upper and lowercase alphanumeric characters with no spaces. | ||
* You can also include any of the following characters: = , . @ - | ||
* @default none instance profile name does not have a default value. | ||
*/ | ||
instanceProfileName?: string; | ||
cmaurer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
} | ||
|
||
export abstract class InstanceProfileRef extends cdk.Construct { | ||
|
||
/** | ||
* Creates an IAM Instance Profile object which represents an | ||
* instance profile not defined within this stack. | ||
* | ||
* `InstanceProfile.import(this, 'MyImportedInstanceProfile', {})` | ||
* | ||
* @param parent The parent construct | ||
* @param name The name for the CloudFormation InstanceProfile Element. Note: this is not the same as the | ||
* InstanceProfileName. | ||
* @param ref A reference to an Instance Profile. Can be created manually (see example above) or | ||
* obtained through a call to `instanceProfile.export()` | ||
* @returns InstanceProfileRef | ||
*/ | ||
public static import(parent: cdk.Construct, name: string, ref: InstanceProfileRefProps): InstanceProfileRef { | ||
return new InstanceProfileRefImport(parent, name, ref); | ||
} | ||
|
||
/** | ||
* Path for the Instance Profile | ||
* @link http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html#Identifiers_FriendlyNames | ||
* @default / If a path is not provided, CloudFormation defaults the path to '/'. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it cfn that provides the default? |
||
*/ | ||
public abstract readonly path: string; | ||
|
||
/** | ||
* The name of an existing IAM role to associate with this instance profile. | ||
* Currently, you can assign a maximum of one role to an instance profile. | ||
* @default Role a default Role with ServicePrincipal(ec2.amazonaws.com). | ||
*/ | ||
public abstract readonly role: IRole; | ||
|
||
/** | ||
* The name of the instance profile that you want to create. | ||
* This parameter allows (per its regex pattern) a string consisting of | ||
* upper and lowercase alphanumeric characters with no spaces. | ||
* You can also include any of the following characters: = , . @ - | ||
* @default none instance profile name does not have a default value. | ||
*/ | ||
public abstract readonly instanceProfileName?: string; | ||
|
||
/** | ||
* Adds a PolicyStatement to the Role associated with this InstanceProfile | ||
* @param statement the statement to add | ||
*/ | ||
public abstract addToRolePolicy(statement: PolicyStatement): void; | ||
|
||
/** | ||
* Exports this InstanceProfile | ||
*/ | ||
public export(): InstanceProfileRefProps { | ||
return { | ||
path: this.path, | ||
role: this.role, | ||
instanceProfileName: this.instanceProfileName | ||
}; | ||
} | ||
|
||
} | ||
|
||
class InstanceProfileRefImport extends InstanceProfileRef { | ||
public readonly path: string; | ||
public readonly role: IRole; | ||
public readonly instanceProfileName?: string; | ||
|
||
constructor(parent: cdk.Construct, name: string, props: InstanceProfileRefProps) { | ||
super(parent, name); | ||
this.path = props.path; | ||
this.role = props.role; | ||
this.instanceProfileName = props.instanceProfileName; | ||
} | ||
|
||
public addToRolePolicy(_statement: PolicyStatement) { | ||
// FIXME: Add warning that we're ignoring this | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { Construct } from '@aws-cdk/cdk'; | ||
import { cloudformation } from './iam.generated'; | ||
import { InstanceProfileRef } from './instance-profile-ref'; | ||
import { PolicyStatement, ServicePrincipal } from './policy-document'; | ||
import { IRole, Role } from './role'; | ||
export interface InstanceProfileProps { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. newline |
||
|
||
/** | ||
* The path associated with this instance profile. For information about IAM Instance Profiles, see | ||
* Friendly Names and Paths in IAM User Guide. | ||
* @link http://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html#Identifiers_FriendlyNames | ||
* @default / By default, AWS CloudFormation specifies '/' for the path. | ||
*/ | ||
path?: string; | ||
|
||
/** | ||
* The name of an existing IAM role to associate with this instance profile. | ||
* Currently, you can assign a maximum of one role to an instance profile. | ||
* @default Role a default Role with ServicePrincipal(ec2.amazonaws.com). | ||
*/ | ||
role?: IRole; | ||
|
||
/** | ||
* The name of the instance profile that you want to create. | ||
* This parameter allows (per its regex pattern) a string consisting of | ||
* upper and lowercase alphanumeric characters with no spaces. | ||
* You can also include any of the following characters: = , . @ - | ||
* @default none instance profile name does not have a default value. | ||
*/ | ||
instanceProfileName?: string; | ||
cmaurer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
} | ||
|
||
/** | ||
* IAM Instance Profile | ||
* | ||
* Defines an IAM Instance Profile that can be used with IAM roles for EC2 instances. | ||
* @link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-instanceprofile.html | ||
*/ | ||
export class InstanceProfile extends InstanceProfileRef { | ||
|
||
public readonly path: string; | ||
public readonly role: IRole; | ||
public readonly instanceProfileName?: string; | ||
cmaurer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
constructor(parent: Construct, name: string, props: InstanceProfileProps) { | ||
super(parent, name); | ||
|
||
this.role = props.role || new Role(this, 'EC2Role', { | ||
assumedBy: new ServicePrincipal('ec2.amazonaws.com') | ||
}); | ||
|
||
this.path = props.path || "/"; | ||
const resource = new cloudformation.InstanceProfileResource(this, 'Resource', { | ||
roles: [ this.role.roleName ], | ||
path: this.path, | ||
instanceProfileName: props.instanceProfileName | ||
}); | ||
this.instanceProfileName = resource.instanceProfileName; | ||
} | ||
|
||
/** | ||
* Adds a PolicyStatement to the Role associated with this InstanceProfile | ||
* @param statement the statement to add | ||
*/ | ||
public addToRolePolicy(statement: PolicyStatement) { | ||
if (!this.role) { | ||
return; | ||
} | ||
this.role.addToPolicy(statement); | ||
} | ||
|
||
cmaurer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Construct, IDependable } from '@aws-cdk/cdk'; | ||
import { ArnUtils, Construct, IDependable, Output, unresolved } from '@aws-cdk/cdk'; | ||
import { cloudformation } from './iam.generated'; | ||
import { IPrincipal, Policy } from './policy'; | ||
import { ArnPrincipal, PolicyDocument, PolicyPrincipal, PolicyStatement } from './policy-document'; | ||
|
@@ -182,6 +182,14 @@ export class Role extends Construct implements IRole { | |
this.attachedPolicies.attach(policy); | ||
policy.attachToRole(this); | ||
} | ||
|
||
public export(): ImportedRoleProps { | ||
return { | ||
roleArn: new Output(this, 'RoleArn', { value: this.roleArn }).makeImportValue().toString(), | ||
roleName: new Output(this, 'RoleName', { value: this.roleName }).makeImportValue().toString() | ||
}; | ||
} | ||
|
||
} | ||
|
||
/** | ||
|
@@ -192,6 +200,11 @@ export interface IRole extends IPrincipal, IDependable { | |
* Returns the ARN of this role. | ||
*/ | ||
readonly roleArn: string; | ||
|
||
/** | ||
* Returns this role's Name. | ||
*/ | ||
readonly roleName: string; | ||
} | ||
|
||
function createAssumeRolePolicy(principal: PolicyPrincipal) { | ||
|
@@ -218,20 +231,45 @@ export interface ImportedRoleProps { | |
/** | ||
* The role's ARN | ||
*/ | ||
roleArn: string; | ||
roleArn?: string; | ||
|
||
/** | ||
* The role's Name | ||
*/ | ||
roleName?: string; | ||
} | ||
|
||
/** | ||
* A role that already exists | ||
*/ | ||
class ImportedRole extends Construct implements IRole { | ||
public readonly roleArn: string; | ||
public readonly roleName: string; | ||
public readonly principal: PolicyPrincipal; | ||
public readonly dependencyElements: IDependable[] = []; | ||
|
||
constructor(parent: Construct, id: string, props: ImportedRoleProps) { | ||
super(parent, id); | ||
this.roleArn = props.roleArn; | ||
if (props.roleArn) { | ||
this.roleArn = props.roleArn; | ||
} else { | ||
if (!props.roleName) { | ||
throw new Error('If "roleArn" is not specified, you must specify "roleName"'); | ||
} | ||
this.roleArn = ArnUtils.fromComponents({ | ||
service: 'iam', | ||
resource: 'role' | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is |
||
} | ||
|
||
if (props.roleName) { | ||
this.roleName = props.roleName; | ||
} else { | ||
if (unresolved(this.roleArn)) { | ||
throw new Error('roleArn is a late-bound value, and therefore roleName is required'); | ||
} | ||
this.roleName = this.roleArn.split('/').slice(1).join('/'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @eladb There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nevermind, I think I figured it out. |
||
} | ||
this.principal = new ArnPrincipal(this.roleArn); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert