aws-cdk icon indicating copy to clipboard operation
aws-cdk copied to clipboard

Role.addManagedPolicy does not work for imported roles

Open its-mirus-lu opened this issue 5 years ago • 9 comments
trafficstars

Inconsistent Behavior: aws_iam.Role.attachManagedPolicy vs aws_iam.ManagedPolicy.attachToRole

The Scenario

TLDR; aws_iam.Role.attachManagedPolicy does not attach the specified managed policy to the role, aws_iam.ManagedPolicy.attachToRole does.

I have two stacks: one stack deploys roles another deploys an application stack (both are in the same account). The roles stack is deployed first.

In the application stack, I would like to attach a managed policy to a role in the first.

Attempting to use aws_iam.Role.attachManagedPolicy does not create the association but aws_iam.ManagedPolicy.attachToRole does.

Environment

  • CDK CLI Version: 1.39.0 (build 5d727c1)
  • Module Version: 1.38.0
  • Node.js Version: v14.0.0
  • OS: macOS Mojave 10.14.6 (18G4032)
  • Language: Typescript and Python

Other information

Steps to reproduce

  1. Deploy one stack with an IAM role
  2. In a second stack create a managed policy
  3. In the second stack Import the role using aws_iam.Role.fromRoleArn (importedRole)
  4. In the second stack attempt to add the managed policy to importedRole via importedRole.attachManagedPolicy
Observed
  1. cdk synth does not show any associations made between the role and the managed policy
  2. using ManagedPolicy.attachToRole works however
Expected
  1. cdk synth (and subsequently) cdk deploy should associate the role and managed policy when Role.attachManagedPolicy is used

its-mirus-lu avatar Jun 01 '20 19:06 its-mirus-lu

It looks like addManagedPolicy is not implemented... https://github.com/aws/aws-cdk/blob/v1.42.1/packages/@aws-cdk/aws-iam/lib/role.ts#L216

Is there a way that this can be clearly stated in documentation?

its-mirus-lu avatar Jun 01 '20 19:06 its-mirus-lu

We can certainly add that to the documentation.

rix0rrr avatar Jun 03 '20 12:06 rix0rrr

Could this be resolved by changing addManagedPolicy to take a ManagedPolicy instead of IManagedPolicy as its argument (and then calling the appropriate method on the managed policy to attach it to the role)?

I feel like this could fit in with the design guidelines - "It's okay to enable multiple ways to achieve the same thing, in order to make it more natural for users who come from different mental models", even though it technically violates [awslint:ref-via-interface]. Also the attachInlinePolicy method on imported roles requires a Policy (opposed to an IPolicy), so this wouldn't be especially out of place.

Chriscbr avatar Jul 30 '20 18:07 Chriscbr

Just run into this bug, trying to configure some policies for roles managed outside of cdk app 😢

OperationalFallacy avatar Nov 23 '20 23:11 OperationalFallacy

Same here, this is really unfortunate. It fails silently and doesn't attach anything. I guess I'll be forced to create a proper inline policy and do the right thing following the principle of least privilege.

guilarteH avatar Nov 25 '20 17:11 guilarteH

We just hit this issue. Especially surprising that even a warning is not getting printed. https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/aws-iam/lib/role.ts#L227

valters avatar Dec 10 '20 07:12 valters

The workaround I found is below. It's not perfect, but it's pretty good:

  1. define the policy statement(s)
  2. create the managed policy with that policy statement
  3. attach the policy statement to the imported role.

Example

const statement = new PolicyStatement({
    effect: Effect.ALLOW,
    actions: ['execute-api:Invoke'],
    resources: [
        //SOME RESOURCE
    ]
})
this.cloudAuthAccessPolicy = new ManagedPolicy(this, 'FOO', {
    managedPolicyName: 'FOO',
    description: "BAR",
    statements: [
        statement
    ]
})

const role = Role.fromRoleArn(this, `name`, `arn:aws:iam::${props.account}:role/SOME_ROLE_NAME`)
role.addToPolicy(statement)

jayhilden avatar Nov 19 '21 01:11 jayhilden

I know this issue has been open for some time now. Is there a fix team is working on ?. I have a use case where I want to create roles and policies separately and then associate them later using Role.addManagedPolicy.

The only way right now is to attach the policy to the role to policy during the role creation itself (using managed_policies) which is not ideal.

digven avatar Apr 02 '22 20:04 digven

This is still wrong in the documentation when importing an existing role.

One can set a mutable option when importing the role (by default it's set to true) The docs say:

Whether the imported role can be modified by attaching policy resources to it.

Which is untrue. You may only modify the role by adding inline policies. Not managed policies.

rdinardi-bw avatar Aug 08 '22 20:08 rdinardi-bw

https://github.com/aws/aws-cdk/blob/070f5ecebfba8a3f9b5771b251ee9b584aa89b67/packages/%40aws-cdk/aws-iam/lib/private/imported-role.ts#L70

the function addManagedPolicy for ImportedRole only adds a warning Not adding managed policy: ${policy.managedPolicyArn} to imported role: ${this.roleName}, is this a missing implementation or an intended behavior?

the warning isn't even really shown to the user, it just prints

[Warning at /MyStack/ImportedRole] [object Object]

Is there any other way to add an AWS Managed Policy to an Imported Role?

molok avatar Jan 27 '23 09:01 molok

@jayhilden's solution could work, even if it requires to copy&paste the statements from a Managed Policy to a new one (handled by us). In our case, we're needing the ReadOnlyAccess policy, so we're going to duplicate it while this issue is solved.

jorgemaroto-eb avatar Feb 13 '23 12:02 jorgemaroto-eb

It would be nice to have this solved, in the meantime a solution like this works:

  const statement = new PolicyStatement({
    effect: Effect.ALLOW,
    actions: ['execute-api:Invoke'],
    resources: [
          //SOME RESOURCE
    ],
    });

  const role = Role.fromRoleArn(this, 'role', 'arn:aws:iam::${props.account}:role/SOME_ROLE_NAME');

  role.attachInlinePolicy(new Policy(
    this,
    'inline-policy', {
      policyName: 'CustomPolicyName',
      statements: [statement],
    },
  ));

taabrcr avatar May 25 '23 13:05 taabrcr

This shouldn't be marked as documentation issue, it rather should just be implemented - I don't see anything wrong in idea of adding managed policies to the imported role (for example to the auto-generated service roles).

Lanayx avatar Jul 24 '23 22:07 Lanayx