Skip to content

Instantly share code, notes, and snippets.

@crazyguitar
Last active July 14, 2021 10:49
Show Gist options
  • Save crazyguitar/6672d2142e3268aa6607617ebe5cc65f to your computer and use it in GitHub Desktop.
Save crazyguitar/6672d2142e3268aa6607617ebe5cc65f to your computer and use it in GitHub Desktop.
AWS assume role

AWS assume role

Based on AWS document, we can use a role on AWS to delegate access AWS resources. For example, we can create a role throw IAM console then grant a permission to access S3 bucket without creating a IAM user. Following steps show how to assume a role to access S3 bucket.

Upload file via temporary credential

Step 1: Create a role to delegate access AWS S3

Creating an IAM Role (Console)

Step 2: Using AWS SDK to acquire temporary credential

const AWS = require('aws-sdk');
const sts = new AWS.STS({apiVersion: '2011-06-15'});

const policy = {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::bucket"
    }
  ]
};

const param = {
  RoleArn: 'arn:aws:iam::123456789012:role/assume-role',
  Policy: JSON.stringify(policy),
  RoleSessionName: 'web',
  ExternalId: 'role',
  DurationSeconds: 900
};

sts.assumeRole(param, (err, data) => {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});

output:

{ ResponseMetadata: { RequestId: '4a789786-5641-11e8-b80c-75e1be362f4c' },
  Credentials: 
   { AccessKeyId: 'ASIAJ725FQAGURRKGQXQ',
     SecretAccessKey: '9U+Y3hVrXCP7Vk5prEAuKZ6OVFxbMHZwXvV6gD3w',
     SessionToken: 'FQoDYXdzEDkaDKDCkuXrE6xIgvqJYiLsAfjRqRbTUH1PFJxGL81iMgFDcEqBxBHCvU1kMfFUzLOo4gSOOOkAZFpxITSIRCPCZBfy5jfKFjDxiisKc3KjSaS+xjCvLcdC1ApTeAMvvApNmDBwFAjZGjHKzZLKQMZwN2i/yfiSXHhNuBOmQpWsyKOSavYyRP4BlbZojzWwPmLmkiPhGbMdAgnMQkZbnczLvTiYN4XiqQ1XfqrTHrDn/3SM5x8qWkTZnUwnttseuWHvj6PfvU3Bkyl0bpdd3SO8dHdLOm/0hFwUkNaNTxrpIgEhzXxTpxEQup9RGL6dU3Ew0Ne+4VBZC4Ky7OpUKLGC3tcF',
     Expiration: 2018-05-13T00:20:05.000Z },
  AssumedRoleUser: 
   { AssumedRoleId: 'AROAIYR3WAOK2KZWW2NCY:web',
     Arn: 'arn:aws:iam::123456789012:role/assume-role/web' },
  PackedPolicySize: 5 }

Step 3: Using temporary credential to access s3 bucket

const AWS = require('aws-sdk');

const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
const sessionToken = process.env.AWS_SESSION_TOKEN;
const credentials = new AWS.Credentials(accessKeyId, secretAccessKey, sessionToken);

AWS.config.credentials = credentials;
const s3 = new AWS.S3({apiVersion: '2006-03-01'});;

const param = {
  Bucket: 'bucket',
  MaxKeys: 10,
};

s3.listObjectsV2(param, (err, data) => {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});

Step 4: Upload a file

const AWS = require('aws-sdk');
const fs = require('fs');

const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
const sessionToken = process.env.AWS_SESSION_TOKEN;
const credentials = new AWS.Credentials(accessKeyId, secretAccessKey, sessionToken);

AWS.config.credentials = credentials;
const s3 = new AWS.S3({apiVersion: '2006-03-01'});;

const buf = fs.readFileSync('file.txt');

s3.putObject({
    Bucket: 'bucket',
    Key: 'file.txt',
    Body: new Buffer(buf, 'binary'),
    ACL: 'public-read'
  },function (resp) {
    console.log(arguments);
    console.log('Successfully uploaded package.');
  });
  
// output
// { '0': null,
//   '1': { ETag: '"64e00c56d89e2ba3ff69defe516b02b9"' } }
// Successfully uploaded package.

Note:

If token has expired, the output will look like following result:

{ ExpiredToken: The security token included in the request is expired
    at Request.extractError (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/protocol/query.js:47:29)
    at Request.callListeners (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
    at Request.emit (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
    at Request.emit (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/Users/chang-ning/Documents/sheets/va/test/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
  message: 'The security token included in the request is expired',
  code: 'ExpiredToken',
  time: 2018-05-13T01:05:41.659Z,
  requestId: 'c19aa9dc-5649-11e8-a984-17f0a5fa2461',
  statusCode: 403,
  retryable: true }

Reference:

  1. Assuming a Role
  2. Creating a Role to Delegate Permissions to an IAM User
  3. AWS: Use the Session Token Service to Securely Upload Files to S3
  4. Upload files Securely to AWS S3 Directly from Browser
  5. How do I allow users or roles in a separate AWS account access to my AWS account
  6. A guide on Aws Security Token Service
  7. Browser-Based Upload using HTTP POST
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment