Connect to AWS IAM API from MuleSoft.

Anupam Chakraborty
5 min readJul 20, 2020

Introduction to AWS IAM

In this blog, we will see, how to access AWS Identity and Access Management API from an external system using the AWS Signature Version 4 signing and then we will access these API from MuleSoft. For this blog, I will only use Create User and Delete User API, however, the process to access any other API should be the same.

AWS Identity and Access Management (IAM) is a web service for securely controlling access to AWS services. IAM consists of Users, Groups (A way to group users and apply policy), Roles, Policy Documents (Saved as JSON). IAM is universal, does not apply to regions, the root account has complete admin access by default. It is important to note that new users have no permission when created, New User has access key, secret key, and also a password.

Prerequisite

  • MuleSoft Anypoint Studio 7.1 With Mule Runtime 4.2
  • Amazon Web Service Account with Access to IAM

AWS Signature Version 4

AWS Suggest that to make any AWS API Call, Requests must be signed using an access key ID and a secret access key. To sign requests, AWS now recommends that we use Signature Version 4.

Signature Version 4 is the process to add authentication information to AWS requests sent by HTTP. For security, most requests to AWS must be signed with an access key, which consists of an access key ID and secret access key.

Creating a Signature with AWS Signature Version 4 comprises of 4 steps. Let us try to go through these steps here.

Task 1: Create a canonical request for Signature Version 4

Canonical Request is a standardized string format with the following details. AWS suggests that we should use these exact details otherwise, the request will be declined.

CanonicalRequest = HTTPRequestMethod + ‘\n’ +
CanonicalURI + ‘\n’ +
CanonicalQueryString + ‘\n’ +
CanonicalHeaders + ‘\n’ +
SignedHeaders + ‘\n’ +
HexEncode(Hash(RequestPayload))

Now in our case, we need to make an API call to the AWS IAM API as follows:

GET https://iam.amazonaws.com/?Action=CreateUser&UserName=<UserName>&Version=2010-05-08

Hence as per the above details, our request method is GET

HTTPRequestMethod = GET

We have to create canonical URI — the part of the URI from domain to query string (we will use / if no path)

CanonicalURI = /

We have to create a canonical query string. In our API call, request parameters are in the query string. Query string values must be URL-encoded (space=%20). The parameters must be sorted by name.

canonical_querystring = ‘Action=CreateUser&UserName=<UserName>&Version=2010–05–08&X-Amz-Algorithm=AWS4-HMAC-&X-Amz-Credential=<URLEncode(access_key + ‘/’ + credential_scope)>&X-Amz-Date=<DateTimeStampInUTC>&X-Amz-Expires=30&X-Amz-SignedHeaders=host

Now there is one unknown variable that is Credential_Scope. This should be created as follows

credential_scope = <DateStampInUTC>/<region>/iam/aws4_request

We have to create the canonical headers and signed headers. Header names must be trimmed and lowercase and sorted in code point order from low to high. Note trailing New Line in canonical_headers. signed_headers is the list of headers that are being included as part of the signing process. For requests that use query strings, only “host” is included in the signed headers.

canonical_headers = ‘host:iam.amazonaws.com<newline>’
signed_headers = ‘host’

We have to create a payload hash. For GET requests, the payload is an empty string. So, we need to hash this with SHA-256. So in my case, the canonical request is created as

GET
/
Action=CreateUser&UserName=TestAPCUser&Version=2010–05–08&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=*****************%2F20200718%2Fus-east-1%2Fiam%2Faws4_request&X-Amz-Date=20200718T211159Z&X-Amz-Expires=30&X-Amz-SignedHeaders=host
host:iam.amazonaws.com
host
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Task 2: Create a string to sign for Signature Version 4

The string to sign includes meta-information about our request and about the canonical request that you created in the earlier steps. To create the string to sign, we will concatenate the algorithm, date and time, credential scope, and digest of the canonical request, as shown in the following pseudocode:

StringToSign = Algorithm + \n +
RequestDateTime + \n +
CredentialScope + \n +
HashedCanonicalRequest

Here let us again derive each variable.

  • As we discussed earlier, we use SHA-256 for our Hash, the Algorithm is defined as algorithm = ‘AWS4-HMAC-SHA256’
  • RequestDateTime = <DateTimeStampInUTC>
  • We have already defined the Credential Scope in our earlier section.
  • The final part is again an SHA-256 hashed Canonical Request that we have retrieved earlier.

In my case, this turned out something like this.

AWS4-HMAC-SHA25620200718T211159Z20200718/us-east-1/iam/aws4_requesta402b5461e3e5893bece467a33f434bf674a20c35f434d9059bd8c97d6cddd44

Task 3: Calculate the signature for AWS Signature Version 4

This is again a 4 Step process of recursive Hashing with Key. Following is the step that will define this

kSecret = <our AWS secret access key>kDate = Sign DateStampInUTC with the key “AWS4” + kSecretkRegion = Sign Region with the key kDatekService = Sign Service with the key kRegionkSigning = Sign “aws4_request” with the key kService

This is an example python function to do this signature

def sign(key, msg):   return hmac.new(key, msg.encode(‘utf-8’), hashlib.sha256).digest()def getSignatureKey(key, dateStamp, regionName, serviceName):   kDate = sign((‘AWS4’ + key).encode(‘utf-8’), dateStamp)   kRegion = sign(kDate, regionName)   kService = sign(kRegion, serviceName)   kSigning = sign(kService, ‘aws4_request’)   return kSigning

Finally, we will generate a signature by signing the String to Sign generated in Step 2 with the signature key generated in the above step.

For me, the signature got created something like this:

5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

Task 4: Add the signature to the HTTP request

Now consider the canonical query string that we created in our step 1. For my case it was like this:

canonical_querystring = ‘Action=CreateUser&UserName=<UserName>&Version=2010–05–08&X-Amz-Algorithm=AWS4-HMAC-&X-Amz-Credential=<URLEncode(access_key + ‘/’ + credential_scope)>&X-Amz-Date=<DateTimeStampInUTC>&X-Amz-Expires=30&X-Amz-SignedHeaders=host’

I will add the final Signature to this query string with the key X-Amz-Signature and then add the Host details at the beginning. For me, it turned out something like this:

https://iam.amazonaws.com?Action=CreateUser&UserName=<UserName>&Version=2010-05-08&X-Amz-Algorithm=AWS4-HMAC-&X-Amz-Credential=<URLEncode(access_key + ‘/’ + credential_scope)>&X-Amz-Date=<DateTimeStampInUTC>&X-Amz-Expires=30&X-Amz-SignedHeaders=host&X-Amz-Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

Now, all we need to do is make an API GET call with the above URL and our requested user will be created in the AWS IAM System.

To connect from Mulesoft to this AWS IAM, please visit my blog at https://www.wedointegration.com/post.php?posturl=connect_to_aws_iam_api_from_mulesoft..

This concludes this blog where we learned how to use AWS Signature Version 4 and also how to access them in MuleSoft using DataWeave. Thank you for reading my blog and do let me know if you were able to get this going. Let me know if you have any other questions as well in the comment section.

--

--

Anupam Chakraborty

Solution Architect — API / Mulesoft / Dell Boomi / AWS / SAP PI. Dell Boomi and Mulesoft Certified.