3
votes

Lets say we have two aws account, account names are devo and prod. So on prod i have a dynamoDB table, which i want to access using a lambda function which is present in devo. Now what i did is created a policy in prod which is giving full access to dynamoDB, and attached that policy to a role in prod account which makes devo as trusted account. In devo i created a role which is having full access of lambda and also attached an inline policy which is allowing to assume the role of prod. Also, I am able to get the data from dynamoDB using aws console through assume role in devo account.

Below is lambda function :

const AWS = require('aws-sdk');
var cred = new AWS.CredentialProviderChain();
var sts = new AWS.STS({credentials: cred, region: 'us-east-1'});
var crd2 ;
var params = {
  RoleArn: "arn:aws:iam::123456789012:role/crossAccount", 
  RoleSessionName: "atul"
 };
 sts.assumeRole(params, function(err, data) {
   if (err) console.log(err, err.stack); // an error occurred
   else    { 
       crd2 = data;           // successful response
       console.log("Role assured");
   }
 });

const dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10', credentials: crd2, region: 'eu-west-1', endpoint: 'https://dynamodb.eu-west-1.amazonaws.com'});

exports.handler = (event, context, callback) => {
     console.log(crd2);
     console.log("**** " + JSON.stringify(dynamodb));

    dynamodb.getItem({
        TableName: "Testing",
        Key: {
            "Id": {
                S: "1121091591"
            }
        }
    }, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            callback(null, {
                statusCode: '500',
                body: err
            });
        } else {
            console.log(data);
            callback(null, {
                statusCode: '200',
                body: 'Hello '
            });
        }
    })
};

This is the error i am getting :

{
    "message": "Requested resource not found",
    "code": "ResourceNotFoundException",
    "time": "2019-03-05T17:54:35.920Z",
    "requestId": "LAN0EI8B2I6I4CVI4OUH01MI3JVV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 11.869537309323096
  }

Thanks

2
How did you solve this issue? I am facing a similar problemTheDominus
@TheDominus it was due to async call, I was calling ddb before STS returns credentialAtul Kumar

2 Answers

1
votes

I think your code is building the dynamodb client before the sts call is finishing since the AWS SDK for JavaScript is asynchronous. I think you can test this by adding a long sleep command to see if that makes it start to work. Once you determine if that is the problem, this page from AWS will help you change your code to work correctly

https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/calling-services-asynchronously.html

0
votes

Lambda do not assume all the assume role access provided to lambda. One needs to specifically ask the lambda to assume a particular role.

Here is a simple java implementation to assume a IAM with required permission to access DynamoDB

final AWSSecurityTokenService stsClient =
                AWSSecurityTokenServiceClientBuilder.standard()
                .withRegion(REGION)
                .withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
                .build();

final AssumeRoleResult assumeRoleResult = stsClient.assumeRole(
                new AssumeRoleRequest()
                        .withRoleArn("<DynamoDBRoleArn>")
                        .withRoleSessionName("DummyLambdaRoleSessionName"));

final BasicSessionCredentials sessionCredentials = new BasicSessionCredentials(
                assumeRoleResult.getCredentials().getAccessKeyId(),
                assumeRoleResult.getCredentials().getSecretAccessKey(),
                assumeRoleResult.getCredentials().getSessionToken());

return AmazonDynamoDBClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(sessionCredentials))
                .withRegion(REGION)
                .build();