DEV Community

Cover image for IAM Credentials Rotation Automation with Step Functions
Jones Zachariah Noel for AWS Community Builders

Posted on • Originally published at aws.hashnode.com

IAM Credentials Rotation Automation with Step Functions

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 and iam: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.


Step Functions workflow with different states of SDK integration

ListAccessKeys state


State definition for ListAccessKeys

In this state, the IAM SDK API iam:listAccessKeys is used to list the available active credentials of the user specified.

DeleteAccessKey state


State definition for DeleteAccessKey

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


State definition for CreateAccessKey

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


State definition for UpdateSecret

In this state, the Secret Manager SDK API secretsmanager:updateSecret is used to update the credential stored on Secret Manager.

SendEmail state


State definition for SendEmail

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"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

A successful workflow execution

Also, an email notification is sent to designated users/admins as this is an automation process.

The received email from the successful execution of SendEmail

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.

Oldest comments (3)

Collapse
 
megaproaktiv profile image
Gernot Glawe

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.

Collapse
 
nthienan profile image
An Nguyen

I have a same question. And how do applications notice that keys were rotated?

Collapse
 
zachjonesnoel profile image
Jones Zachariah Noel

@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?