Lesson 2

Mastering AWS Secrets Manager with Boto3: Creating, Retrieving, and Rotating Secrets

Introduction to AWS Secrets Manager and Its Importance

In applications, managing sensitive data like usernames, passwords, and API keys — collectively referred to as "secrets" — is a common yet crucial task. Inadequate secret management can lead to serious security breaches. Besides, directly embedding these secrets in the code creates maintenance burdens, making tasks like password changes cumbersome as they require updating, recompiling, and redeploying the code. AWS Secrets Manager neatly addresses these issues, providing a robust service to protect access to applications, services, and IT resources. This service allows for the secure management, rotation, and retrieval of database credentials, API keys, and other secrets throughout their lifecycle, thus reducing the risk of secret exposure in your code and shrinking the potential attack surface.

AWS Secrets Manager Features and Use-Cases

Let's delve into some key features of AWS Secrets Manager:

  • Secure and Manage Secrets: AWS Secrets Manager protects access to applications, services, and IT resources. This not only facilitates the easy management and rotation of secrets like database credentials and API keys but also offers their secure retrieval.
  • Automate Secrets Rotation: AWS Secrets Manager can be configured to rotate secrets automatically at specified intervals without requiring any code deployments, thus enhancing secret security.
  • Integration with IAM Policy: You can use AWS Identity and Access Management (IAM) policies to manage access controls specific to secrets, which downplays the necessity for password management in code.

The primary use-cases of AWS Secrets Manager include the following:

  • Database Credentials: AWS Secrets Manager provides seamless rotation of database credentials hosted on AWS, ensuring their secure use in applications.
  • API Keys: By centralizing the management of API keys, AWS Secrets Manager prevents their unauthorized access, thereby protecting valuable data and services.
  • On-Premise Resources: AWS Secrets Manager extends its functionality to store and retrieve credentials for on-premises resources securely.

For more details, you can refer to the official AWS Secrets Manager documentation.

Creating, Retrieving, Updating, and Deleting Secrets

Managing secrets with AWS Secrets Manager involves several operations like creating, retrieving, updating, or deleting secrets. Let's dive into how to carry out these operations.

1import boto3 2 3# Create a client for Secrets Manager 4client = boto3.client("secretsmanager") 5 6# Create a secret 7response_create = client.create_secret(Name="TestSecret", SecretString='{"username":"test","password":"password"}') 8print("Secret Created: ", response_create['Name'])

After creating a secret with the create_secret() function, you can retrieve the secret's string using the get_secret_value() function.

1# Retrieve a secret 2response_get = client.get_secret_value(SecretId="TestSecret") 3print("Secret Retrieved: ", response_get['SecretString'])

Updating and deleting secrets can be done with the update_secret() and delete_secret() methods respectively.

1# Update a secret 2response_update = client.update_secret(SecretId="TestSecret", SecretString='{"username":"test","password":"newpassword"}') 3print("Secret Updated: ", response_update['Name']) 4 5# Delete a secret 6response_delete = client.delete_secret(SecretId="TestSecret") 7print("Secret Deleted: ", response_delete['Name'])
Secret Versions

Every time you update a secret, AWS Secrets Manager assigns a version to the secret with specific version stages. By default, the two stages used are AWSCURRENT and AWSPREVIOUS. The current version is indicated with AWSCURRENT, while the previous version is indicated with AWSPREVIOUS.

Let's retrieve a secret version with a specific stage, such as AWSPREVIOUS:

1# Retrieve a specific version of a secret (previous version) 2response_get_previous = client.get_secret_value(SecretId="TestSecret", VersionStage="AWSPREVIOUS") 3print("Previous Secret Version Retrieved: ", response_get_previous['SecretString'])

It's also possible to create and assign a custom stage to a secret, and a secret can have multiple version stages assigned to it. However, managing custom stages is beyond the basic operations.

Describing a Secret

The describe_secret operation provides metadata about a secret without including the actual secret value. This operation is useful for fetching details such as the secret's creation date, last accessed date, and configured rotation details.

Here's an example of how to use the describe_secret() function:

1# Describe a secret 2response_describe = client.describe_secret(SecretId="TestSecret") 3print("Secret Description: ", response_describe)

The response from describe_secret() includes various pieces of information such as:

  • Secret Name
  • Status (Active or Deleted)
  • Created Date
  • Last Rotated Date
  • ARN of the secret
  • KMS Key ID used to encrypt the secret
  • Rotation Configuration (if enabled)
  • Version IDs to Stages (VersionIdsToStages), which maps each version of the secret to its respective stages (e.g., AWSCURRENT, AWSPREVIOUS)
Secrets Rotation

Secrets rotation is crucial for maintaining security, requiring the automatic update of secrets like passwords or API keys at set intervals. AWS Secrets Manager handles this by integrating with AWS Lambda to automate the rotation process. Note that there will be no practice exercises on this topic as our environment doesn't support Lambdas.

Below is a basic example of how to enable rotation for a secret using a Lambda function, assuming the function is already set up:

1# ARN of your Lambda rotation function 2rotation_lambda_arn = 'arn:aws:lambda:your-region:account-id:function:YourLambdaFunctionName' 3 4# Enable rotation by attaching the Lambda function to your secret 5response = client.rotate_secret( 6 SecretId='YourSecretId', 7 RotationLambdaARN=rotation_lambda_arn, 8 RotationRules={'AutomaticallyAfterDays': 30} # Rotate every 30 days 9) 10 11print("Rotation enabled for secret:", response['ARN'])

This code snippet activates secret rotation, specifying the Lambda function ARN responsible for the rotation logic. The strategy ensures that secrets are regularly refreshed to protect against unauthorized access.

Additionally, here's an extremely simplified Lambda function example that demonstrates how such a function might rotate a secret:

1import boto3 2 3def rotate_secret(event, context): 4 secret_id = event['SecretId'] 5 client = boto3.client('secretsmanager') 6 7 # Logic to generate a new secret value goes here 8 new_secret_value = 'newSecretValue123' 9 10 # Update the secret in Secrets Manager 11 client.update_secret(SecretId=secret_id, SecretString=new_secret_value) 12 13 return { 'message': f'Secret {secret_id} rotated successfully.' }

This Lambda function example assumes you've passed SecretId as an event parameter when invoking the function, and it simplifies the process of generating and applying a new secret. In a real-world scenario, you would include more complex logic for generating the new secret value and validating its effectiveness before the rotation is considered complete.

Recap and Next Steps

Throughout this lesson, we delved into the basics of secrets management using AWS Secrets Manager, including its significant features and use-cases. You've experienced creating, retrieving, updating, deleting and versioning secrets.

In the upcoming practice exercises, you'll get to apply these concepts, allowing you to reinforce your understanding of managing secrets with AWS Secrets Manager and Python.

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.