AWS Boto3 is the Python SDK for AWS. Boto3 can be used to directly interact with AWS resources from Python scripts. In this tutorial, we will look at how we can use the Boto3 library to perform various operations on AWS Secrets Manager.

Table of contents

Prerequisites

  • Python3
  • Boto3: Boto3 can be installed using pip: pip install boto3
  • AWS Credentials: If you haven’t set up AWS credentials before, this resource from AWS is helpful.

How to create a secret?

We will use the create_secret method to create a Secrets Manager secret. The secret can either be in a binary format or a string format.


def create(name, secret_value):
    """
    Creates a new secret. The secret value can be a string or bytes.
    """
    secrets_client = boto3.client("secretsmanager")
    kwargs = {"Name": name}
    if isinstance(secret_value, str):
        kwargs["SecretString"] = secret_value
    elif isinstance(secret_value, bytes):
        kwargs["SecretBinary"] = secret_value
    response = secrets_client.create_secret(**kwargs)
    return response

The output of creating a string secret would be:

create("my-test-secret-str", "test-secret-str")

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'VersionId': '490a3ce1-c3d1-496a-b65e-cde9b8a7631c',
 'ResponseMetadata': {'RequestId': '8af459a0-98f0-44d9-9690-c349920f2b56',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 05:35:32 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '167',
   'connection': 'keep-alive',
   'x-amzn-requestid': '8af459a0-98f0-44d9-9690-c349920f2b56'},
  'RetryAttempts': 0}}


How to retrieve a secret value?


def get_secret_value(name, version=None):
    """Gets the value of a secret.

    Version (if defined) is used to retrieve a particular version of
    the secret.

    """
    secrets_client = boto3.client("secretsmanager")
    kwargs = {'SecretId': name}
    if version is not None:
        kwargs['VersionStage'] = version
    response = secrets_client.get_secret_value(**kwargs)
    return response

The output of this function would be:

get_secret_value("my-test-secret-str")

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'VersionId': '490a3ce1-c3d1-496a-b65e-cde9b8a7631c',
 'SecretString': 'test-secret-str',
 'VersionStages': ['AWSCURRENT'],
 'CreatedDate': datetime.datetime(2021, 2, 26, 21, 35, 32, 273000, tzinfo=tzlocal()),
 'ResponseMetadata': {'RequestId': '64163213-1f39-430a-9ad2-816983695e51',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 05:56:38 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '262',
   'connection': 'keep-alive',
   'x-amzn-requestid': '64163213-1f39-430a-9ad2-816983695e51'},
  'RetryAttempts': 0}}

If the secret is of the string format, then the secret will be in the SecretString key. If the secret is in the binary format, then the secret will be in the SecretsBinary key.


How to modify an existing secret?

To modify an existing secret, we will use the update_secret method. Similar to the create_secret method, we need to provide either a string or binary secret.


def update_secret(name, secret_value):
    """Updates the value of an existing secret"""
    secrets_client = boto3.client("secretsmanager")

    kwargs = {'SecretId': name}

    if isinstance(secret_value, str):
        kwargs["SecretString"] = secret_value
    elif isinstance(secret_value, bytes):
        kwargs["SecretBinary"] = secret_value

    response = secrets_client.update_secret(**kwargs)
    return response

Output of running the function to update the secret:


update_secret("my-test-secret-str", "test-secret-str-new-value")

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'VersionId': '4e746767-91d3-4abc-a6ee-15fbe092e3d9',
 'ResponseMetadata': {'RequestId': '5892aa73-b1b8-4242-952a-7b0bf21b3a26',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 06:12:49 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '167',
   'connection': 'keep-alive',
   'x-amzn-requestid': '5892aa73-b1b8-4242-952a-7b0bf21b3a26'},
  'RetryAttempts': 0}}

How to create a new version of the secret?

We will use the put_secret_value method to create a new version of an existing secret. The new secret would automatically become the latest version of the secret.


def update_secret_version(name, secret_value, versions=None):
    """Puts a value into an existing secret."""
    secrets_client = boto3.client("secretsmanager")

    kwargs = {'SecretId': name}
    if isinstance(secret_value, str):
        kwargs['SecretString'] = secret_value
    elif isinstance(secret_value, bytes):
        kwargs['SecretBinary'] = secret_value
    if versions is not None:
        kwargs['VersionStages'] = versions
    response = secrets_client.put_secret_value(**kwargs)
    return response

Now, to update the secret, we can run the function like follows:


update_secret_version("my-test-secret-str", "test-secret-str-new-versio
    ...: n", versions=["new-version"])

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'VersionId': 'b9e6a990-0bb0-4724-af63-16c7c314c3d3',
 'VersionStages': ['new-version'],
 'ResponseMetadata': {'RequestId': '8bbf368c-0caf-4555-a2bb-d3ddde593259',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 06:27:30 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '199',
   'connection': 'keep-alive',
   'x-amzn-requestid': '8bbf368c-0caf-4555-a2bb-d3ddde593259'},
  'RetryAttempts': 0}}

Now, we can use the previous get_secret method with the version we want to retrieve:

get_secret_value("my-test-secret-str", version="new-version")

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'VersionId': 'b9e6a990-0bb0-4724-af63-16c7c314c3d3',
 'SecretString': 'test-secret-str-new-version',
 'VersionStages': ['new-version'],
 'CreatedDate': datetime.datetime(2021, 2, 26, 22, 27, 30, 931000, tzinfo=tzlocal()),
 'ResponseMetadata': {'RequestId': 'a77e4ecc-78c2-4143-96eb-00c14bfc2c08',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 06:31:14 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '275',
   'connection': 'keep-alive',
   'x-amzn-requestid': 'a77e4ecc-78c2-4143-96eb-00c14bfc2c08'},
  'RetryAttempts': 0}}


How to delete a secret?

We will use the delete_secret method to delete the secret we created previously. By default, any deleted secrets can be retrieved within 30 days of deletion. If you want to disable recovery, we can disable recovery.


def delete_secret(name, without_recovery=False):
    """Deletes the secret."""
    secrets_client = boto3.client("secretsmanager")
    response = secrets_client.delete_secret(
        SecretId=name, ForceDeleteWithoutRecovery=without_recovery)
    return response

We can delete the secret by running the function like:


delete_secret("my-test-secret-str", True)

{'ARN': 'arn:aws:secretsmanager:us-west-2:xxx:secret:my-test-secret-str-k4sx86',
 'Name': 'my-test-secret-str',
 'DeletionDate': datetime.datetime(2021, 2, 26, 22, 44, 11, 848000, tzinfo=tzlocal()),
 'ResponseMetadata': {'RequestId': '233ccfa4-4094-4660-8c96-9776e4d9630f',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sat, 27 Feb 2021 06:44:11 GMT',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '148',
   'connection': 'keep-alive',
   'x-amzn-requestid': '233ccfa4-4094-4660-8c96-9776e4d9630f'},
  'RetryAttempts': 0}}