Is it possible to assume a role from a lambda function?


#1

Is it possible to assume a role from a lambda function?

Role for my lambda contains appropriate policy:

provider:
  iamRoleStatements:
    -
      Action:
        - "sts:AssumeRole"
      Effect: Allow
      Resource:
        - "arn:aws:iam::${file(./env.yml):ACCOUNT_ID}:role/${file(./env.yml):SERVICE_NAME}_ecr_*"

but calling of

sts.assumeRole({ 
    RoleSessionName: `some_role`,
    RoleArn: `arn:aws:iam::${this.env.ACCOUNT_ID}:role/${this.env.SERVICE_NAME}_ecr_${repository}`,
})

fails on User: arn:aws:sts::061240556736:assumed-role/jakub-dev-portal-novpc-dev-IamRoleLambdaExecution-WBS3SVNRT0SF/jakub-dev-portal-novpc-dev-vendorAppsRepositoryGet is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::061240556736:role/jakub-dev-portal-novpc_ecr_test_repository.

So I wonder if it is possible at all. I need the function to assume that role because I want to provide push access to an ECR repository to a user but I need to limit it to the one repository only.

Something like:

return sts.assumeRole({
  RoleSessionName: `${this.getRoleName(vendor, appId)}_role`,
  RoleArn: `arn:aws:iam::${this.env.ACCOUNT_ID}:role/${this.env.SERVICE_NAME}_ecr_${repository}`,
}).promise()
.then((res) => {
  const ecr = new aws.ECR({
    region: this.env.REGION,
    credentials: {
      accessKeyId: res.Credentials.AccessKeyId,
      secretAccessKey: res.Credentials.SecretAccessKey,
      sessionToken: res.Credentials.SessionToken,
    },
  });
  return ecr.getAuthorizationToken().promise();
});

Thanks for help.


#2

So I can vouch that it is totally possible to assume a role from within a Lambda function. You just need to watch out because once you’ve assumed a role (especially if it is in another account) then you might not have permission to log to CloudWatch Logs as you did before you assumed the role - so your debugging might be difficult.

I will try and find the code I used, but it wasn’t in a Serverless project so may not be immediately useable for you. Have you tired giving it permission to assume all roles (i.e. Resource: "*" in the iamRoleStatements section), and get that working before you try restricting it? You’re definitely right to want to restrict it, but first make sure it’s not that that’s causing you issues.


#3

Yes, I started with the broadest permissions (*) but it doesn’t work either. Glad to hear that it should work so that I know I just miss some piece in the puzzle and thanks for pointing out to the logs permisions, I probably wouldn’t realized it at the first go. But it shouldn’t influence the assuming itself, right? (When the role to assume doesn’t exist at all, it still fails on “Not authorized to perform sts:AssumeRole”.)


#4

I just found the code that I used, and realised that I didn’t actually do an assume role - I simply updated the SDK to use the target’s Access Key Id and Secret Access Key.

In my code I set them like this:

    AWS.config.update({
      accessKeyId: user.accessKeyId,
      secretAccessKey: user.secretAccessKey,
    });

Unfortunately it means you need long-lived keys, which may or may not work for you.


#5

This is an old issue, but you don’t need long lived keys. If the lambda is invoked using a role that has trust with the other account you can use sts.assumerole(). For posterity, so no one goes down the long lived keys route I’ll post the answer :slight_smile:

I only gave this link a quick review but it seems to have the goods.

This is a stackoverflow answer, which doesn’t show all the trust policies, but just some concise code: