Skip to content
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

Can't use runtime generated role for a Provider #673

Open
beetahnator opened this issue Jul 23, 2019 · 4 comments
Open

Can't use runtime generated role for a Provider #673

beetahnator opened this issue Jul 23, 2019 · 4 comments
Labels
area/credentials Authenticating the provider awaiting-upstream The issue cannot be resolved without action in another repository (may be owned by Pulumi). kind/bug Some behavior is incorrect or out of spec

Comments

@beetahnator
Copy link

beetahnator commented Jul 23, 2019

I have a usecase where I need to generate an IAM Role and then use it as a provider to generate more AWS resources.

When trying the example below, the first pulumi up always fails since Pulumi tries to assume the role immediately after creation.

import * as aws from "@pulumi/aws";

const role = new aws.iam.Role("testrole", {
  assumeRolePolicy: aws.getCallerIdentity().then(id => {
    return {
      Version: "2012-10-17",
      Statement: [
        {
          Effect: "Allow",
          Principal: {
            AWS: `arn:aws:iam::${id.accountId}:root`
          },
          Action: "sts:AssumeRole"
        }
      ]
    };
  })
});

const rolePolicy = new aws.iam.RolePolicy("test", {
  role: role,
  policy: {
    Version: "2012-10-17",
    Statement: [
      {
        Effect: "Allow",
        Action: "s3:*",
        Resource: "*"
      }
    ]
  }
});

const roleProvider = new aws.Provider(
  "test",
  {
    assumeRole: {
      roleArn: role.arn
    }
  },
  { dependsOn: rolePolicy }
);

// try to make an s3 bucket using role provider
// this will fail once and then work
const s3Bucket = new aws.s3.Bucket(
  "test",
  {},
  { provider: roleProvider, dependsOn: roleProvider }
);

Error output when trying to apply

Do you want to perform this update? yes
Updating (dev):

     Type                     Name       Status         Info
 +   pulumi:pulumi:Stack      tests-dev  created        
 +   ├─ aws:iam:Role          testrole   created        
 +   ├─ aws:iam:RolePolicy    test       created        
 +   ├─ pulumi:providers:aws  test       created        
     └─ aws:s3:Bucket         test       **failed**     1 error
 
Diagnostics:
  aws:s3:Bucket (test):
    error: The role "arn:aws:iam::XXXXXXXXX:role/testrole-6671910" cannot be assumed.
    
      There are a number of possible causes of this - the most common are:
        * The credentials used in order to assume the role are invalid
        * The credentials do not have appropriate permission to assume the role
        * The role ARN is not valid
@lukehoban
Copy link
Member

What is the error message that you get here?

Note that you could put a delay inside an apply (setTimeout inside the apply) as a workaround

Sounds like the root issue is that the provider needs to retry the assume role lookup to deal with eventual consistency of IAM. That likely require an upstream AWS provider fix.

@lukehoban lukehoban self-assigned this Jul 25, 2019
@beetahnator
Copy link
Author

beetahnator commented Jul 25, 2019

@lukehoban I added the error output above.

Do you have an example for using setTimeout inside apply?

I found this example, will try the setTimeout method now.

UPDATE: This seems to work, could be further improved by checking if the role can be assumed inside the .apply instead of using setTimeout

const roleProvider = new aws.Provider(
  "test",
  {
    assumeRole: {
      roleArn: role.arn.apply(async(arn) => {
        if (!pulumi.runtime.isDryRun()) {
          await new Promise(resolve => setTimeout(resolve, 30 * 1000));
        }
        return arn
      })
    }
  },
  { dependsOn: rolePolicy}
);

@bincyber
Copy link

@mazamats Thanks for updating the issue with a clear example. I was stuck on the same issue and your example really helped.

For the Python users out there, here's a similar example of how to do the above, but with sts.assume_role() from boto3:

import asyncio
import boto3
import botocore.exceptions
import pulumi_aws as aws
import pulumi


async def wait_for_iam_eventual_consistency(args: list) -> str:
    role_arn          = args[0]
    role_session_name = args[1]

    duration = 3
    attempts = 10

    if not pulumi.runtime.is_dry_run():
        pulumi.log.info(f"Waiting up to {attempts * duration} seconds for IAM eventual consistency for IAM Role: {role_arn}")

        sts = boto3.client('sts')

        for i in range(attempts):
            try:
                sts.assume_role(
                    RoleArn=role_arn,
                    RoleSessionName=role_session_name
                )
            except botocore.exceptions.ClientError:
                await asyncio.sleep(duration)
            else:
                break
    return role_arn


account_id = aws.get_caller_identity().account_id

iam_role = aws.iam.Role(
    resource_name="vpc-admin",
    description='IAM Role for VPC Administration',
    path='/',
    force_detach_policies=True,
    assume_role_policy={
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "AllowAccountAssumeRole",
            "Action": "sts:AssumeRole",
            "Principal": {
                "AWS": f"arn:aws:iam::{account_id}:root"
            },
            "Effect": "Allow"
        }]
    }
)

iam_role_policy_attachment = aws.iam.RolePolicyAttachment(
    resource_name="vpc-admin-policy-attachment",
    role=iam_role.id,
    policy_arn="arn:aws:iam::aws:policy/AmazonVPCFullAccess"
)

session_name = "VpcAdmin"
role_arn     = pulumi.Output.all(iam_role.arn, session_name).apply(wait_for_iam_eventual_consistency)

iam_role_provider = aws.Provider(
    resource_name='vpc-admin-provider',
    assume_role={
        "role_arn": role_arn,
        "session_name": session_name
    },
    opts=pulumi.ResourceOptions(
        depends_on=[
            iam_role_policy_attachment
        ]
    )
)

aws.ec2.Vpc(
    resource_name="test-vpc",
    cidr_block="10.100.0.0/16",
    enable_dns_hostnames=True,
    enable_dns_support=True,
    tags={
        "Name": "test-vpc",
        "CreatedBy": "vpc-admin-provider"
    },
    opts=pulumi.ResourceOptions(
        parent=iam_role_provider,
        provider=iam_role_provider
    )
)

@lukehoban
Copy link
Member

This appears to be due to upstream hashicorp/terraform-provider-aws#6566.

@lukehoban lukehoban added kind/bug Some behavior is incorrect or out of spec awaiting-upstream The issue cannot be resolved without action in another repository (may be owned by Pulumi). labels Nov 19, 2022
@lukehoban lukehoban removed their assignment Nov 19, 2022
@t0yv0 t0yv0 added the area/credentials Authenticating the provider label Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/credentials Authenticating the provider awaiting-upstream The issue cannot be resolved without action in another repository (may be owned by Pulumi). kind/bug Some behavior is incorrect or out of spec
Projects
None yet
Development

No branches or pull requests

4 participants