.NET 8 Series has started! Join Now for FREE

11 min read

Automated AWS IAM Access Key Rotation with .NET, AWS Lambda, SNS, and EventBridge Scheduler

#dotnet #aws

Let’s build an automated AWS IAM Access Key Rotation Lambda using AWS Lambda, SNS Notifications, and Amazon EventBridge Schedulers. We will be writing the entire AWS Lambda code in C#. You can get the source code of the entire implementation here.

Why Rotate IAM Access Keys?

Refreshing your IAM Access Keys once in a while is considered to be a good security practice. As you know, depending on the permissions attached to an IAM Access Key, anyone who has them will be able to perform various operations within your AWS Account that might lead to serious security incidents. Hence, changing them once in a while ensures a reduction in the probability of security compromises.

This process of changing your IAM Access Keys is also called Key Rotation. Here are a couple of reasons why access key rotation is crucial:

  1. Compliance Requirements: Many compliance standards and regulations, such as PCI DSS and HIPAA, require regular key rotation as part of their security requirements.
  2. Limits Damage if keys are compromised: If a key is compromised, rotating it quickly can limit the damage an attacker can do using that key.
  3. Recommended Security Best Practice.

How Frequently Should You Rotate IAM Access Keys?

When it comes to rotating IAM access keys, the frequency depends on your organization’s security policies. However, a common best practice is to rotate IAM access keys regularly, such as every 90 days, to minimize the risk of unauthorized access.

It’s also important to rotate keys whenever there’s a suspicion of compromise or when an employee or contractor who had access leaves the organization. Additionally, consider using IAM policies and roles to limit the permissions associated with access keys, reducing the potential impact of a compromised key.

Prerequisites

To proceed with this implementation, there are the fundamentals that you need to have,

IAM Access Key Rotation Workflow Explained

You can have various algorithms or workflows to execute Access Key Rotation.

Here is a simple workflow that can handle most of the requirements.

Automated AWS IAM Access Key Rotation Workflow Diagram

This design includes the following components.

  1. AWS Lambda (which we will write in C#)
  2. Amazon SNS, to notify users.
  3. Amazon EventBridge Scheduler to schedule timely triggers for the Rotation Lambda.

Let me explain the design.

  1. The Lambda will hold the core application logic. We will first get a list of IAM users in the AWS account. This can be configurable. If you want to rotate only a particular user’s keys, you are free to do so.
  2. For each user, we will retrieve the associated access key details, including the key creation date. From this, we will be able to derive the age of the access key.
  3. If the key age is within 60 - 70 days and is in an active state, we will create a new access key. The new key details will be sent over to the user, via SNS notification.
  4. If the key age is within 80 - 90 days, we will consider it eligible for deactivation. The keys will be deactivated and the notification will be sent over to the user. It is expected that the user will use the new set of credentials, and deprecate the old set of access keys as soon as possible. We will give them a buffer of about 10 days.
  5. If the key age is above 90 days, the keys will be deactivated and the notifications will be sent to the user.
  6. Using Amazon Event Bridge Scheduler, we will have to ensure that the Lambda is scheduled to run every week. Again this depends on your requirements.

This way, you will have a completely automated way to securely rotate the IAM Access Keys.

Creating the SNS Topic and Registering the Email ID Subscription

Log in to your AWS Management Console, and open up Simple Notification Service (SNS). Here we will do 2 things:

  1. Create a new SNS Topic to which our Lambda will publish notifications.
  2. Attach an Email Subscription to this newly created SNS Topic, so that whenever there is a new notification pushed to this topic, an email is sent.

Firstly, let’ create a new topic as the following. Once created, make sure that you copy the Topic’s ARN to your clipboard. The ARN will be something like arn:aws:sns:<region>:<account-number>:access-key-rotation

automated-aws-iam-access-key-rotation

Once the topic is created, you will have to create a new email subscription and attach it to this topic. Make sure to select the Email Protocol and enter the email id. Note that this is the email id where you will be receiving Access Key Rotation emails.

Learn more about AWS SNS and .NET Integration: https://codewithmukesh.com/blog/scalable-notifications-with-amazon-sns-and-aspnet-core/

Note that you will also have to verify your email ID so that it can start getting notifications whenever any new notifications are pushed to the SNS Topic. Make sure to verify your email ID by clicking on the verification link that AWS will send as soon as you add in your email ID.

automated-aws-iam-access-key-rotation

Building the Automated AWS IAM Access Key Rotation Lambda with .NET

Let’s start coding our Access Key Rotation Lambda. Open up Visual Studio, and create a new AWS Lambda C# project. In the Blueprint selection screen, select the Empty function.

Learn the basics of AWS Lambda from here: https://codewithmukesh.com/blog/aws-lambda-with-net-6/

Let’s first install the required NuGet packages.

  • AWSSDK.IdentityManagement
  • AWSSDK.SimpleNotificationService

Paste in the following code.

public class Function
{
private static readonly string TopicArn = "<your sns topic arn>";
private static readonly IAmazonIdentityManagementService iamClient = new AmazonIdentityManagementServiceClient();
private static readonly IAmazonSimpleNotificationService snsClient = new AmazonSimpleNotificationServiceClient();
public async Task FunctionHandler(ILambdaContext context)
{
var usersResponse = await iamClient.ListUsersAsync();
var expiryThreshold = 90;
var deactivationThreshold = 70;
foreach (var user in usersResponse.Users)
{
var accessKeyRequst = new ListAccessKeysRequest()
{
UserName = user.UserName
};
var accessKeyDetails = await iamClient.ListAccessKeysAsync(accessKeyRequst);
foreach (var accessKey in accessKeyDetails.AccessKeyMetadata)
{
var createdDate = accessKey.CreateDate;
var keyAge = DateTime.Now - createdDate;
var keyAgeInDays = keyAge.Days;
if (keyAgeInDays >= deactivationThreshold - 10
&& keyAgeInDays < deactivationThreshold
&& accessKeyDetails.AccessKeyMetadata.Count == 1
&& accessKey.Status == StatusType.Active)
{
//eligible to create new access key.
await CreateAccessKey(user.UserName);
}
else if (keyAgeInDays >= expiryThreshold - 10
&& keyAgeInDays < expiryThreshold
&& accessKey.Status == StatusType.Active)
{
//eligible for deactivation
await DeactivateAccessKey(user.UserName, accessKey.AccessKeyId);
}
else if (keyAgeInDays >= expiryThreshold && accessKey.Status == StatusType.Inactive)
{
//expired and inactive, so delete
await DeleteAccessKey(user.UserName, accessKey.AccessKeyId);
}
}
}
}
public async Task CreateAccessKey(string userName)
{
var request = new CreateAccessKeyRequest()
{
UserName = userName
};
var keyDetails = await iamClient.CreateAccessKeyAsync(request);
var message = $"New Access Key Generated for user : {userName}. " +
$"New Access Key Id : {keyDetails.AccessKey.AccessKeyId}. " +
$"New Secret Access Key : {keyDetails.AccessKey.SecretAccessKey}." +
$"Old Key will be Deactivated in about 10 days.";
var publishRequest = new PublishRequest()
{
TopicArn = TopicArn,
Message = message
};
await snsClient.PublishAsync(publishRequest);
}
public async Task DeleteAccessKey(string userName, string accessKeyId)
{
var request = new DeleteAccessKeyRequest()
{
UserName = userName,
AccessKeyId = accessKeyId
};
await iamClient.DeleteAccessKeyAsync(request);
var message = $"Access Key : {accessKeyId} has been deleted for user : {userName}.";
var publishRequest = new PublishRequest()
{
TopicArn = TopicArn,
Message = message
};
await snsClient.PublishAsync(publishRequest);
}
public async Task DeactivateAccessKey(string userName, string accessKeyId)
{
var request = new UpdateAccessKeyRequest()
{
UserName = userName,
AccessKeyId = accessKeyId,
Status = StatusType.Inactive
};
await iamClient.UpdateAccessKeyAsync(request);
var message = $"Access Key : {accessKeyId} has been deactivated for user : {userName}.";
var publishRequest = new PublishRequest()
{
TopicArn = TopicArn,
Message = message
};
await snsClient.PublishAsync(publishRequest);
}
}

Let me explain this line by line.

  • Lines 1 to 48, are the actual function that gets invoked as part of the lambda initialization.
  • Lines 47 to 64 hold the logic to create new Access Keys.
  • Lines 66 to 81 are how we delete access keys.
  • Finally, the deactivation logic is present in Lines 83 to 98.

In line 3, we will hardcode the topic arn. You can probably make this configurable by fetching this data from a DynamoDB table maybe?

Then, in lines 4 and 5 we initialize IAM and SNS clients. We will use the IAM client to retrieve user and access key-related data. The SNS client will be used to publish the notification to the registered email address.

Note that I have 2 constants defined here, which are the expiry threshold and the deactivation threshold.

  • Any key is eligible for deactivation if its age is between 80 to 90 days and is in the active state.
  • Any key is eligible for deletion if its age is above 90 days and is in an inactive state.
  • If a key is in the age range of about 60-70, we will consider that the deactivation period is nearing and will create a new access key, which will be notified to the user.

For this demonstration, I am going to retrieve all the users in my AWS account. This might vary with your scenario. Here too, all you need is the usernames of the accounts that you need to rotate the access keys for. You can store this data in the DynamoDB table as a configuration if you like.

Once we have the list of users, we will iterate through the access keys attached to the user. We will calculate the current age of the access key at line 21. Based on this and the business rules mentioned in the above paragraph, we will decide if the keys are to be deleted, deactivated or new access keys have to be generated.

At line 47, we will be creating new access keys. Here, we will form a CreateAccessKeyRequest and pass it on to the IAM Client that we created earlier. Once the key is created, I have added a templated message which contains the access key details. This message will be published to the SNS topic using the SNS client. Note that this message has crucial data, and it’s often better for you to decide how you want to deliver this sensitive information to the user.

In almost a similar way, we will be deleting and deactivating the access keys as well.

Deploying the AWS Lambda

Once the code changes are done as per your requirement, simply build the Lambda project. To deploy this Lambda, right-click on the project and click on Publish to AWS Lambda. For this make sure you have the required Visual Studio Extension installed.

automated-aws-iam-access-key-rotation

Follow the dialogs to get your Lambda deployed to the cloud. If you do not have prior experience working with AWS Lambda, here is a detailed step-by-step guide for you to deploy your .NET Lambda to AWS.

Provide IAM Permissions to AWS Lambda

To get the entire setup working, you will need to provide enough permissions to our Lambda. It should have the following permissions:

  1. IAM

    • Delete Access Key
    • Update Access Key
    • List Users
    • Create Access Key
    • List Access Keys
  2. SNS

    • Publish

To add these permissions, open up your newly uploaded Lambda. Go to Configuration -> Permissions and click on the associated Role. This will open up IAM. Here, you can attach inline policies.

automated-aws-iam-access-key-rotation

Following are the inline permissions that I have added for both IAM and SNS.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:DeleteAccessKey",
"iam:UpdateAccessKey",
"iam:ListUsers",
"iam:CreateAccessKey",
"iam:ListAccessKeys"
],
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "*"
}
]
}

Scheduling the AWS Lambda with Amazon EventBridge Scheduler

In a previous article, we learned about all the features offered by Amazon EventBridge Scheduler. You can read all about it here.

Open up AWS Management Console, and search for EventBridge Scheduler. Let’s create a new scheduler.

automated-aws-iam-access-key-rotation

I will make the scheduler a rate-based one, which runs every 7 days. This ensures that our access keys are always checked against for expiry.

automated-aws-iam-access-key-rotation

As for the target, select AWS Lambda Invoke, and choose the newly uploaded access key rotation lambda. That’s it.

automated-aws-iam-access-key-rotation

automated-aws-iam-access-key-rotation

If things go as expected, you will start receiving such emails whenever the access keys are rotated.

automated-aws-iam-access-key-rotation

Improvements

Here are a few suggestions on how you can improve this.

  1. Instead of sending the access keys as plain text in email, you can adapt to a more secure approach, where you would just notify the users about the access key change and not send the actual keys. Instead, the keys can be stored as a Secret in AWS Secret Manager.
  2. Handle errors in more effective ways using the try-catch block in code.
  3. You can make this more configurable by adding DynamoDB to the mix. This way Lambda can be designed to load required parameters like username, account ID, and more.
  4. This Lambda can be improvised to manage Access Key Rotation across various AWS Accounts as well. This will be a very common requirement for organizations.

Let me know if you have more suggestions to improve this implementation. For now, it’s a wrap for this article. I hope you enjoyed reading it.

Summary

In this article, we learned about the importance of IAM Access Key Rotation, and how we can automate the entire process by using AWS Lambda, SNS, EventBridge Scheduler, and .NET. We built a Lambda that holds the logic to effectively rotate access keys based on the age of the access key, and also to notify the users whenever something has changed. You can find the source code of the entire implementation on this GitHub repository.

Feel free to share this article with your colleagues and network. This will help me get more eyes to this article. Thanks!

Source Code ✌️
Grab the source code of the entire implementation by clicking here. Do Follow me on GitHub .
Support ❤️
If you have enjoyed my content and code, do support me by buying a couple of coffees. This will enable me to dedicate more time to research and create new content. Cheers!
Share this Article
Share this article with your network to help others!
What's your Feedback?
Do let me know your thoughts around this article.

Boost your .NET Skills

I am starting a .NET 8 Zero to Hero Series soon! Join the waitlist.

Join Now

No spam ever, we are care about the protection of your data. Read our Privacy Policy