How to Rotate IAM Access Keys Safely#

Every developer who’s worked with AWS has felt that flutter of anxiety: “When was the last time I rotated my access keys?” If you haven’t rotated them, you’re not alone—but you should be thinking about it. Access key rotation is one of those security hygiene tasks that feels tedious until you realize it’s often the difference between a contained incident and a major breach.

The good news is that rotating IAM access keys doesn’t have to be disruptive. With a careful, methodical approach, you can swap out old credentials for fresh ones without taking down a single application or service. This guide walks you through exactly how to do it—from creating new keys to decommissioning the old ones—along with practical strategies to make the process repeatable and even automatable.

Why Access Key Rotation Matters#

Let’s start with the “why” because it informs everything else you’ll do. IAM access keys are long-term credentials that never expire on their own. Unlike temporary security credentials generated by AWS Security Token Service (STS), which have explicit lifespans measured in hours or minutes, long-lived access keys persist indefinitely. If a key becomes exposed—through a leaked GitHub repository, a compromised developer machine, or a disgruntled former employee—it remains valid until you explicitly deactivate or delete it.

Access key rotation reduces your window of vulnerability. AWS recommends rotating access keys at least once every 90 days, though many organizations adopt more aggressive schedules like monthly or even quarterly rotations. The rotation itself doesn’t eliminate the risk of an already-compromised key, but it ensures that any leaked credential has a limited lifespan before it’s retired from active use.

Now, here’s an important nuance: if you have a choice, use IAM roles instead of long-lived access keys. Roles are the modern, preferred approach for granting permissions to AWS resources and workloads. They generate temporary credentials automatically and don’t require manual rotation. EC2 instances, Lambda functions, ECS containers, and other AWS services should use IAM roles whenever possible. Access keys are best reserved for human users and for a narrow set of external integrations where roles simply aren’t feasible—like scripts on on-premises servers or CI/CD platforms that don’t natively support role assumption.

That said, if you’re using access keys, you need to rotate them properly. And even with roles as your primary strategy, you may have legacy access keys to manage or occasional situations where keys are still necessary.

Understanding the Two-Key Strategy#

The safest way to rotate access keys is to use a two-key approach: create a new key alongside the existing one, migrate your applications to use the new key, and only then deactivate the old one. This eliminates the “moment of truth” where you swap keys and hope nothing breaks.

Each IAM user can have up to two active access keys at a time. AWS designed this limitation specifically to enable this rotation pattern. The idea is straightforward: while one key is actively in use, you can create a second key and stage it across your applications. Once everything’s running smoothly on the new key, you deactivate (and eventually delete) the old one.

Step 1: Create a New Access Key#

Begin by generating a fresh access key for the IAM user whose credentials you’re rotating. You’ll need AWS Management Console access or programmatic access with sufficient permissions (typically iam:CreateAccessKey).

In the AWS Management Console, navigate to the IAM service, select the user, and click on the Security credentials tab. You’ll see a section for Access keys where you can click “Create access key.” The console will generate a new access key ID (which looks like AKIAIOSFODNN7EXAMPLE) and a secret access key (a longer string that you’ll see only once).

Here’s the critical step: download and securely store both components immediately. The secret key is never displayed again, and you won’t be able to recover it if you navigate away without saving it. Store it in a secure location—your password manager, a secrets management system like AWS Secrets Manager, or a temporary secure file that you’ll delete once you’ve deployed the new key.

If you prefer the command line, you can use the AWS CLI:

aws iam create-access-key --user-name my-user

This outputs the new key pair in JSON format, which you can capture and store securely.

Step 2: Update Your Applications with the New Key#

Now that you have both keys, it’s time to introduce the new one to your applications. The approach here depends on where these keys live: environment variables, configuration files, secrets management systems, or application code.

For environment variables, update them wherever they’re defined. If you’re using EC2 instances, that might mean updating .bashrc or a systemd service file. For containerized workloads, update your task definitions or Kubernetes secrets. If you’re using a secrets management system like AWS Secrets Manager, Vault, or Parameter Store, update the stored secret and ensure your application reloads or restarts to pick up the new value.

The key principle: update your applications to use the new key, then verify they’re working correctly before deactivating the old key. This might take anywhere from minutes to hours depending on your infrastructure. If you have dozens of applications scattered across different environments, you might stage the rollout: update development and staging first, observe for errors, and then move to production.

Here’s a practical scenario: suppose you have a Lambda function that reads from an S3 bucket using long-lived credentials stored in environment variables. You’d update the environment variable to contain the new access key ID and secret, then manually invoke the Lambda to confirm it still works. Only after confirming success would you move on to the next step.

Step 3: Monitor and Verify New Key Usage#

Before you retire the old key, spend some time watching it in action. This is where CloudTrail and CloudWatch come into play.

CloudTrail logs all AWS API calls, including which access key was used to make each call. You can query CloudTrail to see exactly which keys are being used and by which services. This visibility is invaluable during a rotation: you want to confirm that your applications have truly migrated to the new key and that API calls are no longer coming through the old one.

You can search CloudTrail logs in the Management Console, or use the AWS CLI to programmatically analyze them:

aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE --max-results 50

Replace the placeholder access key ID with your old key, and this command will return the most recent API calls made with that key. If the results show activity from several minutes ago but nothing recent, that’s a good sign that your applications have transitioned to the new key.

You can also set up CloudWatch alarms or use AWS Config rules to monitor access key usage patterns. Some organizations use custom Lambda functions that periodically query CloudTrail and alert on any activity from “retired” keys that should have been deleted weeks ago—a safety net to catch keys that slip through the cracks.

Step 4: Deactivate the Old Access Key#

Once you’ve confirmed that all applications are using the new key and the old one shows no recent activity, it’s time to deactivate (not delete) the old key.

Deactivation is a crucial intermediate step. A deactivated key can’t be used for API calls, but it hasn’t been permanently removed. If you discover an application you missed during the migration, you can reactivate the old key and give yourself time to fix things without having to regenerate credentials. Deletion is permanent and can’t be undone.

In the Management Console, go to the user’s Security credentials tab, find the old access key, and choose “Deactivate.” Via CLI:

aws iam update-access-key --user-name my-user --access-key-id AKIAIOSFODNN7OLD --status Inactive

After deactivating, monitor your applications for a period—perhaps a day or a week, depending on your risk tolerance and how frequently your applications attempt authentication. If everything continues to run smoothly, you’ve confirmed that no lingering references to the old key remain.

Step 5: Delete the Old Access Key#

Once you’re confident the old key isn’t needed, delete it. Deletion is permanent and irreversible, so you want to be certain before taking this step.

In the console, select the inactive access key and choose “Delete.” Via CLI:

aws iam delete-access-key --user-name my-user --access-key-id AKIAIOSFODNN7OLD

After deletion, that access key pair is gone forever. Any attempt to use it for authentication will fail immediately. This is the final step in the rotation.

Automating Key Rotation#

For organizations managing dozens or hundreds of IAM users, manual rotation becomes unwieldy. Automation is a natural next step.

One common approach is to use AWS Lambda and EventBridge. You can write a Lambda function that periodically checks the age of access keys across your AWS account, automatically creates new keys for users whose keys exceed a certain age (say, 90 days), and stores the new credentials in AWS Secrets Manager. The function can then send notifications to the relevant teams with instructions to update their applications.

Here’s a simplified example of what such a function might do:

import boto3
import json
from datetime import datetime, timedelta

iam = boto3.client('iam')
secrets = boto3.client('secretsmanager')

def rotate_old_keys(max_age_days=90):
    users = iam.list_users()['Users']
    threshold = datetime.now(datetime.now().astimezone().tzinfo) - timedelta(days=max_age_days)
    
    for user in users:
        access_keys = iam.list_access_keys(UserName=user['UserName'])['AccessKeyMetadata']
        for key in access_keys:
            key_age = key['CreateDate']
            if key_age < threshold:
                # Create new key and notify
                new_key = iam.create_access_key(UserName=user['UserName'])['AccessKey']
                # Store in Secrets Manager, send notification, etc.
                print(f"New key created for user {user['UserName']}")

This is a starting point. A production implementation would include error handling, logging, notification mechanisms, and safeguards to prevent accidentally rotating all keys simultaneously.

Another approach is to use third-party tools and services built specifically for credential management and rotation. Tools like HashiCorp Vault, AWS Secrets Manager’s built-in rotation features, and various compliance and identity management platforms can automate this process with more sophistication than a basic Lambda function.

Best Practices for Key Rotation#

Keep rotation predictable. Establish a schedule—monthly, quarterly, whatever your organization decides—and stick to it. Predictable rotation is easier to automate and reduces the likelihood of keys living far beyond their planned lifespan.

Separate keys by purpose. If an IAM user needs access to multiple services or environments, consider using separate access keys for each context (one for development, one for production; one for your application, one for your CI/CD pipeline). If one key is compromised, the blast radius is limited.

Use Secrets Manager or Parameter Store. Instead of storing access keys directly in application code or configuration files, use AWS Secrets Manager or Systems Manager Parameter Store. Both services offer rotation capabilities and integrate with your applications through SDKs and environment variables. This centralizes your credential management and makes rotations less disruptive.

Document your rotation process. Write down the steps, the tools involved, who needs to be notified, and how long the process typically takes. When rotation time comes around, you won’t be improvising—you’ll be following a well-tested playbook.

Monitor access key age in your account. Use AWS Config to track access key age and alert when keys exceed your retention policy. This prevents forgotten keys from lingering indefinitely.

Prefer roles over keys whenever possible. This bears repeating because it’s the most effective way to reduce the burden of key management. Every access key you eliminate is one fewer credential to rotate. If you’re authoring infrastructure as code, make sure new users and services default to role-based access unless there’s a specific reason they need long-lived keys.

Never commit access keys to version control. If a key accidentally makes its way into a Git repository, consider it compromised. Immediately deactivate and delete the key, then initiate an incident response. Use .gitignore files and pre-commit hooks to prevent this.

Handling Accidental Key Exposure#

If you discover that an access key has been exposed—perhaps found in a GitHub repository or in application logs—don’t panic, but act quickly. Deactivate the key immediately using the steps outlined above, then review CloudTrail logs to see if the key was used by anyone other than your authorized applications. If there’s evidence of unauthorized usage, escalate to your security team and consider it a potential breach.

You don’t necessarily need to wait days before deleting an exposed key. In fact, you might delete it right away if you’re confident you can update your applications with the new key quickly. The difference between deactivation and deletion is less critical in this scenario; what matters is stopping the exposed key from being useful.

The Bigger Picture: Moving Away from Long-Lived Keys#

Access key rotation is a good practice, but it’s a Band-Aid solution to a deeper architectural question: why are you using long-lived keys in the first place?

AWS resources should use IAM roles. Your on-premises applications and services should use temporary credentials obtained through cross-account role assumption or AWS STS. Your CI/CD pipelines should assume roles, not use hardcoded keys. Your third-party integrations should use OIDC federation or other token-based mechanisms.

As you establish your rotation routine, simultaneously work on eliminating the keys you’re rotating. The fewer long-lived access keys your organization maintains, the smaller your credential management burden and the stronger your security posture. Rotation is a necessary tool, but the real win is not needing to rotate in the first place.

Conclusion#

Rotating IAM access keys is a straightforward process—create a new key, migrate your applications, monitor for successful usage, deactivate the old key, and eventually delete it. The two-key approach eliminates downtime and gives you room to maneuver if something goes wrong. With automation and a clear process, rotation becomes a routine part of your operational hygiene rather than a source of anxiety.

The broader lesson is that access key rotation is a symptom of necessary security practices, not the ultimate solution. Combine rotation with a strategic migration toward IAM roles and temporary credentials, and you’ll find yourself with fewer keys to manage, less rotation overhead, and a more secure AWS environment overall.