Connect to AWS IAM API from MuleSoft.

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

AWS Signature Version 4

AWS suggests 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.

Plain Text
 




xxxxxxxxxx
1


 
1
CanonicalRequest =
2
HTTPRequestMethod + '\n' +
3
CanonicalURI + '\n' +
4
CanonicalQueryString + '\n' +
5
CanonicalHeaders + '\n' +
6
SignedHeaders + '\n' +
7
HexEncode(Hash(RequestPayload))



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

Plain Text
 




xxxxxxxxxx
1


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



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

Java
 




xxxxxxxxxx
1


 
1
HTTPRequestMethod = GET



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

Java
 




xxxxxxxxxx
1


 
1
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.

Java
 




xxxxxxxxxx
1


 
1
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

Java
 




xxxxxxxxxx
1


 
1
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.

Java
 




xxxxxxxxxx
1


1
canonical_headers = 'host:iam.amazonaws.com<newline>'
2
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

Plain Text
 




xxxxxxxxxx
1
13
9


1
GET
2
/
3
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
4
host:iam.amazonaws.com
5
 
           
6
host
7
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:

Plain Text
 




xxxxxxxxxx
1


 
1
StringToSign =
2
Algorithm + \n +
3
RequestDateTime + \n +
4
CredentialScope + \n +
5
HashedCanonicalRequest



Here let us again derive each variable.

In my case, this turned out something like this.

Plain Text
 




xxxxxxxxxx
1


1
AWS4-HMAC-SHA256
2
20200718T211159Z
3
20200718/us-east-1/iam/aws4_request
4
a402b5461e3e5893bece467a33f434bf674a20c35f434d9059bd8c97d6cddd44



Task 3: Calculate the signature for AWS Signature Version 4

This is again a four-step process of recursive Hashing with Key. Following is the step that will define this:

Plain Text
 




xxxxxxxxxx
1


1
kSecret = <our AWS secret access key>
2
kDate = Sign DateStampInUTC with the key "AWS4" + kSecret
3
kRegion = Sign Region with the key kDate
4
kService = Sign Service with the key kRegion
5
kSigning = Sign "aws4_request" with the key kService



This is an example Python function to do this signature:

Python
 




xxxxxxxxxx
1
17
9


1
def sign(key, msg):
2
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
3
 
           
4
def getSignatureKey(key, dateStamp, regionName, serviceName):
5
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
6
kRegion = sign(kDate, regionName)
7
kService = sign(kRegion, serviceName)
8
kSigning = sign(kService, 'aws4_request')
9
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:

Plain Text
 




xxxxxxxxxx
1


 
1
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:

Plain Text
 




xxxxxxxxxx
1


 
1
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.

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.

 

 

 

 

Top