packages/constructs/L2/iam-constructs/lib/policies.ts (99 lines of code) (raw):

/*! * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import { MdaaConstructProps, MdaaParamAndOutput } from '@aws-mdaa/construct'; //NOSONAR import { Arn, Stack } from 'aws-cdk-lib'; import { IGroup, IManagedPolicy, IRole, IUser, ManagedPolicy, ManagedPolicyProps, PolicyDocument, PolicyStatement, } from 'aws-cdk-lib/aws-iam'; import { Construct } from 'constructs'; /** * Interface definging a compliant IAM ManagedPolicy */ export interface MdaaManagedPolicyProps extends MdaaConstructProps { /** * The name of the managed policy. If you specify multiple policies for an entity, * specify unique names. For example, if you specify a list of policies for * an IAM role, each policy must have a unique name. * * @default - A name is automatically generated. */ readonly managedPolicyName?: string; /** * A description of the managed policy. Typically used to store information about the * permissions defined in the policy. For example, "Grants access to production DynamoDB tables." * The policy description is immutable. After a value is assigned, it cannot be changed. * * @default - empty */ readonly description?: string; /** * The path for the policy. This parameter allows (through its regex pattern) a string of characters * consisting of either a forward slash (/) by itself or a string that must begin and end with forward slashes. * In addition, it can contain any ASCII character from the ! (\u0021) through the DEL character (\u007F), * including most punctuation characters, digits, and upper and lowercased letters. * * For more information about paths, see IAM Identifiers in the IAM User Guide. * * @default - "/" */ readonly path?: string; /** * Users to attach this policy to. * You can also use `attachToUser(user)` to attach this policy to a user. * * @default - No users. */ readonly users?: IUser[]; /** * Roles to attach this policy to. * You can also use `attachToRole(role)` to attach this policy to a role. * * @default - No roles. */ readonly roles?: IRole[]; /** * Groups to attach this policy to. * You can also use `attachToGroup(group)` to attach this policy to a group. * * @default - No groups. */ readonly groups?: IGroup[]; /** * Initial set of permissions to add to this policy document. * You can also use `addPermission(statement)` to add permissions later. * * @default - No statements. */ readonly statements?: PolicyStatement[]; /** * Initial PolicyDocument to use for this ManagedPolicy. If omited, any * `PolicyStatement` provided in the `statements` property will be applied * against the empty default `PolicyDocument`. * * @default - An empty policy. */ readonly document?: PolicyDocument; /** * If specified, policy names will be created using this prefix instead of using the naming module. * This is useful when policy names need to be portable across accounts (such as for integration with SSO permission sets) */ readonly verbatimPolicyName?: boolean; } /** * Interface representing a compliant ManagedPolicy */ export type IMdaaManagedPolicy = IManagedPolicy; /** * Construct for creating compliant IAM ManagedPolicys */ export class MdaaManagedPolicy extends ManagedPolicy { private static setProps(props: MdaaManagedPolicyProps): ManagedPolicyProps { const overrideProps = { managedPolicyName: props.verbatimPolicyName ? props.managedPolicyName : props.naming.resourceName(props.managedPolicyName, 64), }; return { ...props, ...overrideProps }; } private props: MdaaManagedPolicyProps; constructor(scope: Construct, id: string, props: MdaaManagedPolicyProps) { super(scope, id, MdaaManagedPolicy.setProps(props)); this.props = props; this.checkPolicyLength(); new MdaaParamAndOutput( this, { ...{ resourceType: 'managed-policy', resourceId: props.managedPolicyName, name: 'arn', value: this.managedPolicyArn, }, ...props, }, scope, ); new MdaaParamAndOutput( this, { ...{ resourceType: 'managed-policy', resourceId: props.managedPolicyName, name: 'name', value: this.managedPolicyName, }, ...props, }, scope, ); } public addStatements(...statement: PolicyStatement[]): void { super.addStatements(...statement); this.checkPolicyLength(); } public checkPolicyLength(alwaysLog = false) { const policyDocLength = this.computePolicyLength(); if (policyDocLength > 5500 || alwaysLog) { console.warn( `${this.props.managedPolicyName} policy length ~${policyDocLength} chars of maximum 6144. Note that the character length may increase after processing by CFN.`, ); } } public computePolicyLength(): number { const policyDoc = this.document.toJSON(); if (policyDoc) { const policyDocLength = JSON.stringify(policyDoc).replace(/\s*/i, '').replace(/\n*/i, '').length; return policyDocLength; } return 0; } /** * Re-implemented from cdk ManagedPolicy.fromAwsManagedPolicyName * in order to allow partition name literals */ public static fromAwsManagedPolicyNameWithPartition(scope: Construct, managedPolicyName: string): IManagedPolicy { return { managedPolicyArn: Arn.format({ partition: Stack.of(scope).partition, service: 'iam', region: '', // no region for managed policy account: 'aws', // the account for a managed policy is 'aws' resource: 'policy', resourceName: managedPolicyName, }), }; } }