# Access AWS Resources using IAM Role through AWS SDK of NodeJS

### Problem Statement

In General, to initialize NodeJS AWS-SDK we need to use the access key and the secret to configure it as per one of the methods describe below.


1. Loaded from the shared credentials file (~/.aws/credentials)
1. Loaded through ENV variables
     - AWS_ACCESS_KEY_ID
     - AWS_SECRET_ACCESS_KEY
1. Configure at AWS SDK initialization config

```
var AWS = require('aws-sdk');
const credentials = {
  accessKeyId: <AWS_ACCESS_KEY_ID>,
  secretAccessKey: <AWS_SECRET_ACCESS_KEY>,
  region: <REGION>
};
AWS.config.update(credentials);
``` 

In all of the above cases the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY need to be exposed to the execution machine, In some cases, it may be a security issue as per the use case. Now How we will get the AWS account permission without having these credentials?

To achieve this we will use the IAM Role assignment to access the services.

### Prerequisites

- AWS Account Access (To create IAM Role)
- EC2 Instance (Host the Node App and to use IAM Role)

### Solution
#### 1. Create IAM Role
a. Select IAM from AWS Services Menu
![aws-iam.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032244891/ST5F1IVDr.png)

b. Select Roles from Access Management Menu and Click on Create Role
![aws-iam-roles-add.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032301765/7BndwNkyW.png)

c.  Select Entity Type as AWS Service and Use Case to EC2 and Click Next
![aws-iam-role-create.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032338048/3ePbKaVck.png)

d. Select Appropriate permissions needed, In our case to test S3 select AmazonS3FullAccess and Click Next
![aws-iam-role-create-permissions.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032370050/O-A7yQapr.png)

e. Give Role Name, Description, and Review Permission and Click Create Role
![aws-iam-role-create-final.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032401747/k5KLrVHcq.png)

#### 2. NodeJS AWS-SDK Usage
Creating NodeJS App to use aws-sdk and perform actions on AWS resources. We will use S3 resource to

- i. List buckets
- ii. Create bucket
- iii. List Objects in bucket
- iv. Upload the file into the bucket
- v. Remove file from bucket
- vi. Remove Bucket

For the above requirement, we have created the app with the following directory structure and code snippets.

> Directory Structure of NodeJS Application
![s3-filestructures.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648032540423/YUthfrdIB.png)

##### a. listBucket.js
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk'); 

// Set the region 
AWS.config.update({region: 'ap-southeast-1'}); 

// Create S3 service object 
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Call S3 to list the buckets 
s3.listBuckets(function(err, data) { 
  if (err) { 
    console.log("Error", err); 
  } else { 
    console.log("Success", data.Buckets);   
  } 
});
``` 

#### b. createBucket.js
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'ap-southeast-1'});

// Create S3 service object
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Create the parameters for calling createBucket
var bucketParams = {
  Bucket : 'shashibadhuk-test-bucket-demo-22'
};

// call S3 to create the bucket
s3.createBucket(bucketParams, function(err, data) {
  if (err) {
    console.log("Bucket Creation Error", err);
  } else {
    console.log(`Bucket ${bucketParams.Bucket} is created`, data.Location);
  }
});
``` 
#### c. listBucket.js 
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region 
AWS.config.update({region: 'ap-southeast-1'});

// Create S3 service object
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Create the parameters for calling listObjects
var bucketParams = {
  Bucket : 'shashibadhuk-test-bucket-demo-22',
};

// Call S3 to obtain a list of the objects in the bucket
s3.listObjects(bucketParams, function(err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data);
  }
});
``` 

#### d. uploadS3.js
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region 
AWS.config.update({region: 'ap-southeast-1'});

// Create S3 service object
var s3 = new AWS.S3({apiVersion: '2006-03-01'});

// call S3 to retrieve upload file to specified bucket
var uploadParams = {
  Bucket: 'shashibadhuk-test-bucket-demo-22', 
  Key: '', 
  Body: ''
};
var file = 'myCustomFile.txt';

// Configure the file stream and obtain the upload parameters
var fs = require('fs');
var fileStream = fs.createReadStream(file);
fileStream.on('error', function(err) {
  console.log('File Error', err);
});
uploadParams.Body = fileStream;
var path = require('path');
uploadParams.Key = path.basename(file);

// call S3 to retrieve upload file to specified bucket
s3.upload (uploadParams, function (err, data) {
  if (err) {
    console.log(`File ${file} Upload Error`, err);
  } if (data) {
    console.log(`File ${file} Uploaded on Bucket ${uploadParams.Bucket} `, data.Location);
  }
});
``` 
#### e. removeObject.js
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'ap-southeast-1'});

// Create S3 service object
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Create params for S3.deleteBucket
var bucketParams = {
  Bucket: 'shashibadhuk-test-bucket-demo-22',
  Key: 'myCustomFile.txt'
};

s3.deleteObject(bucketParams, function(err, data) {
  if (err) 
    console.log(err, err.stack); // an error occurred
  else    
    console.log(data);           // successful response
});
``` 

#### f. removeBucket.js
```
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'ap-southeast-1'});

// Create S3 service object
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Create params for S3.deleteBucket
var bucketParams = {
  Bucket : 'shashibadhuk-test-bucket-demo-22'
};

// Call S3 to delete the bucket
s3.deleteBucket(bucketParams, function(err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data);
  }
});
``` 

Now create myCustomFile.txt with some random text, which will be used by uploadS3 to upload file in S3

#### 3. Verify Code without IAM Role

Now executing the node application to list bucket without having any permission config and IAM Role assignment

![Screenshot 2022-03-22 at 4.54.13 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648033525219/30pCngvun.png)

#### 4. Attach IAM Role to EC2 Instance

Select EC2 from AWS Service Menu and from instance listing select instance, select Actions > Security > Modify IAM Role

![aws-modify-iam-menu.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648033606367/N-uZcN-NN.png)

Now select the IAM Role created earlier and click save

![aws-modify-iam-role.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648033637946/_oWcK7nBD.png)

#### 5. Verify Code with IAM Role
After the assignment of IAM Role now its time to test the application
![output.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648033864793/LbYq9afVv.png)

#### 6. Verify Bucket on AWS Console

![Screenshot 2022-03-22 at 5.05.31 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1648033730249/Q89QgkL58.png)

Similarly, we can access other AWS resources by assigning respective IAM Roles, but make sure to follow least privilege as per AWS standard.

Please share this article if seems useful and connect with me on [linkedin](https://www.linkedin.com/in/shashibadhuk/).

If you find this helpful, then please support me by [buying a coffee](https://www.buymeacoffee.com/shashibadhuk).

