The best practices of using IAM credentials is to have them rotated frequently (eg. every 90 days, every 6 months). This is because if credentials are compromised, you can ensure that the existing credentials are deleted, and a new credential is issued. Another best practice includes having the credentials stored securely on Secrets Manager, so that the credentials are never hard-coded on the application end.
In this blog, we will see how Step Functions helps in orchestrating a workflow which implements the rotation of credentials (creating a new programmatic access credentials and deleting existing programmatic access credentials), updates the secret stored on Secrets Manager, and notifies the admin that a new credential is generated and has updated the secret as well.
Alternatively, Secrets Manager natively supports the feature of secrets rotation. However, in that case, based on the CRON expression, a specific Lambda Function is executed. This blog-post is to demonstrate Step Functions' SDK integration capabilities to orchestrate the same flow.
Understanding the workflow
The Step Functions workflows integrates with the services for the respective SDK APIs
- IAM -
iam:listAccessKeys
,iam:deleteAccessKey
andiam:createAccessKey
- Secrets Manager -
secretsmanager:updateSecret
- SES -
ses:sendEmail
Note : The IAM role created by Step Functions would also require the above mentioned fine grained access to the specific actions of the respective resources.
ListAccessKeys state
In this state, the IAM SDK API iam:listAccessKeys
is used to list the available active credentials of the user specified.
DeleteAccessKey state
In this state, the IAM SDK API iam:deleteAccessKey
is used to delete the available active credential of the user specified with the access key ID.
CreateAccessKey state
In this state, the IAM SDK API iam:createAccessKey
is used to create a new access key and secret key for the specified user.
UpdateSecret state
In this state, the Secret Manager SDK API secretsmanager:updateSecret
is used to update the credential stored on Secret Manager.
SendEmail state
In this state, the Simple Email Service (SES) SDK API ses:sendEmail
is used to notify the users via email that a new IAM credential has been updated on the Secret Manager. Alternatively, ses:sendTemplatedEmail
is also used to send a formatted email, but that would require a creation of template prior to this workflow execution. The email body is designed to be a general HTML text to ensure that no other specific credentials is revealed over emails.
The complete JSON of State Machine is -
{
"Comment": "A description of my state machine",
"StartAt": "ListAccessKeys",
"States": {
"ListAccessKeys": {
"Type": "Task",
"Parameters": {
"UserName.$": "$.userName"
},
"Resource": "arn:aws:states:::aws-sdk:iam:listAccessKeys",
"Next": "DeleteAccessKey",
"ResultPath": "$.listAccessKey"
},
"DeleteAccessKey": {
"Type": "Task",
"Next": "CreateAccessKey",
"Parameters": {
"AccessKeyId.$": "$.listAccessKey.AccessKeyMetadata[0].AccessKeyId",
"UserName.$": "$.userName"
},
"Resource": "arn:aws:states:::aws-sdk:iam:deleteAccessKey",
"ResultPath": "$.deleteAccessKey"
},
"CreateAccessKey": {
"Type": "Task",
"Parameters": {
"UserName.$": "$.userName"
},
"Resource": "arn:aws:states:::aws-sdk:iam:createAccessKey",
"Next": "UpdateSecret",
"ResultPath": "$.createAccessKey"
},
"UpdateSecret": {
"Type": "Task",
"Parameters": {
"SecretId.$": "$.secretName",
"SecretString.$": "States.JsonToString($.createAccessKey.AccessKey)"
},
"Resource": "arn:aws:states:::aws-sdk:secretsmanager:updateSecret",
"Next": "SendEmail",
"ResultPath": "$.updateSecret"
},
"SendEmail": {
"Type": "Task",
"End": true,
"Parameters": {
"Destination": {
"ToAddresses": [
"zachjonesnoel@mailinator.com"
]
},
"Message": {
"Body": {
"Html": {
"Charset": "UTF-8",
"Data": "The IAM Credential is rotated and updated on Secrets Manager"
}
},
"Subject": {
"Data": "New IAM Credential updated!!!"
}
},
"Source": "test@zachjonesnoel.com"
},
"Resource": "arn:aws:states:::aws-sdk:ses:sendEmail",
"ResultPath": "$.sendEmail"
}
}
}
Workflow execution
When all the states have executed successfully, the end result of the State Machine would mean that your IAM user's programmatic credentials are updated on Secrets Manager.
Also, an email notification is sent to designated users/admins as this is an automation process.
Now, your applications can always use the secrets from Secrets Manager without the hurdle of updating it every time the IAM credentials are rotated.
For all the security reasons, the complete workflow walkthrough is not provided as that exposes the IAM credentials.
Conclusion
This is an orchestration of IAM credentials rotation which ensures your application is ways using secured credentials that can be updated in time of need. Even though this blog-post features only the Step Function module, this Step Function execution could be started from an event from EventBridge making it an event-triggered automation.
Top comments (3)
Great stepfunction usecase! As I had this problem to tackle before: how do the users/apps access their new keys if they cannot access with the old key? We had added a deletion delay for that.
@megaproaktiv and @nthienan yep good question, in this example I'm making an assumption that the credentials would be pulled in always from Secrets Manager not from external sources like GitHub secrets or anything such. So whenever the IAM credentials are updated the application only refers to the key defined in Secrets Manager and it gets the latest credentials.
That's why added a SES step in the end to notify admins whenever it is changed. You could have a Lambda fn or SNS which can notify or update external systems that IAM creds are updated.
Does that answer your question?
I have a same question. And how do applications notice that keys were rotated?