Skip to content

Instantly share code, notes, and snippets.

@Rud5G
Last active August 11, 2025 15:31
Show Gist options
  • Select an option

  • Save Rud5G/857493f606f130d4a90b5e3de62e4aea to your computer and use it in GitHub Desktop.

Select an option

Save Rud5G/857493f606f130d4a90b5e3de62e4aea to your computer and use it in GitHub Desktop.
/**
* Default deletion override for Service linked role resources
*/
class IamServiceLinkedRoleAspect implements cdk.IAspect {
visit(node: IConstruct): void {
if (node instanceof cdk.CfnResource) {
if (node.cfnResourceType === 'AWS::IAM::ServiceLinkedRole') {
node.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
}
}
}
}
/**
* Default memory override for Lambda resources
*/
export class LambdaDefaultMemoryAspect implements cdk.IAspect {
visit(node: IConstruct): void {
if (node instanceof cdk.CfnResource) {
if (node.cfnResourceType === 'AWS::Lambda::Function') {
const cfnProps = (node as cdk.aws_lambda.CfnFunction)['_cfnProperties'];
let memorySize = cfnProps['MemorySize']?.toString();
if (!memorySize) {
memorySize = (node as cdk.aws_lambda.CfnFunction).memorySize;
}
if (!memorySize || memorySize < 512) {
node.addPropertyOverride('MemorySize', 512);
}
}
}
}
}
/**
* Permission boundary aspect
*/
export class PermissionsBoundaryAspect implements cdk.IAspect {
/**
* Account this will be applied in
*/
readonly account: string;
/**
* Partition this will be deployed to
*/
readonly partition: string;
constructor(account: string, partition: string) {
this.account = account;
this.partition = partition;
}
public visit(node: IConstruct): void {
const policyLength = (process.env['ACCELERATOR_PERMISSION_BOUNDARY'] ?? '').trim().length;
// check if node is type of cloudformation resource
if (!(node instanceof cdk.CfnResource)) {
return;
}
// check if node is type of IAM role
if (node.cfnResourceType !== 'AWS::IAM::Role') {
return;
}
// check if deployment is external
if (process.env['MANAGEMENT_ACCOUNT_ID'] && process.env['MANAGEMENT_ACCOUNT_ROLE_NAME']) {
return;
}
// check if its management account
if (this.account !== process.env['PIPELINE_ACCOUNT_ID']!) {
return;
}
// policy name is not empty
if (policyLength === 0) {
return;
}
try {
// Build permissions boundary ARN from input
const permissionsBoundaryArn = `arn:${this.partition}:iam::${this.account}:policy/${process.env[
'ACCELERATOR_PERMISSION_BOUNDARY'
]!}`;
// convert role in to cfn.role this allows for checking properties
const roleResource = node as cdk.aws_iam.CfnRole;
if (roleResource && roleResource.permissionsBoundary && roleResource.permissionsBoundary > '') {
//do nothing, use existing permission boundary
} else {
// no permission boundary was found, add permission boundary
roleResource.addPropertyOverride('PermissionsBoundary', permissionsBoundaryArn);
}
} catch (error) {
const msg = `Error while applying permission boundary to IAM role ${node.node.path}. Error: ${JSON.stringify(
error,
)}. Permission boundary will not be applied to stacks.`;
logger.error(msg);
throw new Error(msg);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment