-
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
fix(codebuild): cannot use immutable roles for Project #5608
Changes from 1 commit
57cc5e7
6ff1ad9
87c908c
b13905a
360bdf1
cab660c
72eacc1
f3e6be4
3b1663f
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 |
---|---|---|
|
@@ -56,6 +56,22 @@ export interface PolicyProps { | |
* @default - No statements. | ||
*/ | ||
readonly statements?: PolicyStatement[]; | ||
|
||
/** | ||
* Whether an `AWS::IAM::Policy` must be created | ||
* | ||
* Unless set to `true`, this `Policy` construct will not materialize to an | ||
* `AWS::IAM::Policy` CloudFormation resource in case it would have no effect | ||
* (for example, if it remains unattached to an IAM identity or if it has no | ||
* statements). This is generally desired behavior, since it prevents | ||
* creating invalid--and hence undeployable--CloudFormation templates. | ||
* | ||
* In cases where you know the policy must be created and it is actually | ||
* an error if no statements have been added to it, you can se this to `true`. | ||
* | ||
* @default false | ||
*/ | ||
readonly mustCreate?: boolean; | ||
} | ||
|
||
/** | ||
|
@@ -79,16 +95,12 @@ export class Policy extends Resource implements IPolicy { | |
*/ | ||
public readonly document = new PolicyDocument(); | ||
|
||
/** | ||
* The name of this policy. | ||
* | ||
* @attribute | ||
*/ | ||
public readonly policyName: string; | ||
|
||
private readonly _policyName: string; | ||
private readonly roles = new Array<IRole>(); | ||
private readonly users = new Array<IUser>(); | ||
private readonly groups = new Array<IGroup>(); | ||
private readonly mustCreate: boolean; | ||
private referenceTaken = false; | ||
|
||
constructor(scope: Construct, id: string, props: PolicyProps = {}) { | ||
super(scope, id, { | ||
|
@@ -107,7 +119,8 @@ export class Policy extends Resource implements IPolicy { | |
groups: undefinedIfEmpty(() => this.groups.map(g => g.groupName)), | ||
}); | ||
|
||
this.policyName = this.physicalName!; | ||
this._policyName = this.physicalName!; | ||
this.mustCreate = props.mustCreate !== undefined ? props.mustCreate : false; | ||
|
||
if (props.users) { | ||
props.users.forEach(u => this.attachToUser(u)); | ||
|
@@ -160,19 +173,60 @@ export class Policy extends Resource implements IPolicy { | |
group.attachInlinePolicy(this); | ||
} | ||
|
||
/** | ||
* The name of this policy. | ||
* | ||
* @attribute | ||
*/ | ||
public get policyName(): string { | ||
this.referenceTaken = true; | ||
return this._policyName; | ||
} | ||
|
||
protected validate(): string[] { | ||
const result = new Array<string>(); | ||
|
||
// validate that the policy document is not empty | ||
if (this.document.isEmpty) { | ||
result.push('Policy is empty. You must add statements to the policy'); | ||
if (this.mustCreate) { | ||
result.push('Policy created with mustCreate=true is empty. You must add statements to the policy'); | ||
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. References old property name. |
||
} | ||
if (!this.mustCreate && this.referenceTaken) { | ||
result.push('Policy name has been read of empty policy. You must add statements to the policy so it can exist.'); | ||
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. See #5569 (comment) |
||
} | ||
} | ||
|
||
// validate that the policy is attached to at least one principal (role, user or group). | ||
if (this.groups.length + this.users.length + this.roles.length === 0) { | ||
result.push(`Policy must be attached to at least one principal: user, group or role`); | ||
if (!this.isAttached) { | ||
if (this.mustCreate) { | ||
result.push(`Policy created with mustCreate=true must be attached to at least one principal: user, group or 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. References old property name. |
||
} | ||
if (!this.mustCreate && this.referenceTaken) { | ||
result.push('Policy name has been read of unattached policy. Attach to at least one principal: user, group or 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. See here: #5569 (comment) |
||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
protected prepare() { | ||
// Remove the resource if it shouldn't exist. This will prevent it from being rendered to the template. | ||
if (!this.shouldExist) { | ||
this.node.removeChild('Resource'); | ||
} | ||
} | ||
|
||
/** | ||
* Whether the policy resource has been attached to any identity | ||
*/ | ||
private get isAttached() { | ||
return this.groups.length + this.users.length + this.roles.length > 0; | ||
} | ||
|
||
/** | ||
* Whether the policy resource should be created | ||
*/ | ||
private get shouldExist() { | ||
return this.mustCreate || this.referenceTaken || (!this.document.isEmpty && this.isAttached); | ||
} | ||
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. since this is temporal (i.e. only relevant after the tree has been fully initialized) and used only in one place, I think this code should just be part of |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -438,6 +438,15 @@ export class ConstructNode { | |
return ret; | ||
} | ||
|
||
/** | ||
* Remove the child with the given name, if present. | ||
* | ||
* It is not an error if a child with the given name does not exist. | ||
*/ | ||
public removeChild(childName: 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. Maybe rename to I am a bit worried by potential abuse of this API. Maybe we can make it a bit safer and only allow this during "prepare" somehow? What do you think? Can you please also mark this as This also resolves #1408 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. I'm not too worried about misuse. The methods on I would hope that people venturing there will be aware they're messing with internals which can do what they want, or have unintentional effects they themselves will be responsible for cleaning up. Not sure that limiting to |
||
delete this._children[childName]; | ||
} | ||
|
||
/** | ||
* Locks this construct from allowing more children to be added. After this | ||
* call, no more children can be added to this construct or to any children. | ||
|
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.
I still don't love this name... I proposed changing it to
lazy?: boolean
in the previous PR, but I'm also open to other suggestions 🙂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.
forceResource?
mustExist?
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.
I feel "lazy" is usually used to communicate something else.
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.
Maybe just
force
?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.
I was considering
force
, slightly on the fence but I also don't have a better alternative. I can doforce
.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.
forceReify? forceRender?