

# Get a Secrets Manager secret value using Python
<a name="retrieving-secrets-python"></a>

In applications, you can retrieve your secrets by calling `GetSecretValue` or `BatchGetSecretValue`in any of the AWS SDKs. However, we recommend that you cache your secret values by using client-side caching. Caching secrets improves speed and reduces your costs.

**Topics**
+ [

# Get a Secrets Manager secret value using Python with client-side caching
](retrieving-secrets_cache-python.md)
+ [

# Get a Secrets Manager secret value using the Python AWS SDK
](retrieving-secrets-python-sdk.md)
+ [

# Get a batch of Secrets Manager secret values using the Python AWS SDK
](retrieving-secrets-python-batch.md)

# Get a Secrets Manager secret value using Python with client-side caching
<a name="retrieving-secrets_cache-python"></a>

When you retrieve a secret, you can use the Secrets Manager Python-based caching component to cache it for future use. Retrieving a cached secret is faster than retrieving it from Secrets Manager. Because there is a cost for calling Secrets Manager APIs, using a cache can reduce your costs. For all of the ways you can retrieve secrets, see [Get secrets](retrieving-secrets.md).

The cache policy is Least Recently Used (LRU), so when the cache must discard a secret, it discards the least recently used secret. By default, the cache refreshes secrets every hour. You can configure [how often the secret is refreshed](retrieving-secrets_cache-ref-secretcacheconfig.md) in the cache, and you can [hook into the secret retrieval](retrieving-secrets_cache-ref-secretcachehook.md) to add more functionality.

The cache does not force garbage collection once cache references are freed. The cache implementation does not include cache invalidation. The cache implementation is focused around the cache itself, and is not security hardened or focused. If you require additional security such as encrypting items in the cache, use the interfaces and abstract methods provided.

To use the component, you must have the following: 
+ Python 3.6 or later.
+ botocore 1.12 or higher. See [AWS SDK for Python](https://aws.amazon.com/sdk-for-python/) and [Botocore](https://botocore.amazonaws.com/v1/documentation/api/latest/index.html). 
+ setuptools\$1scm 3.2 or higher. See [https://pypi.org/project/setuptools-scm/](https://pypi.org/project/setuptools-scm/).

To download the source code, see [Secrets Manager Python-based caching client component](https://github.com/aws/aws-secretsmanager-caching-python ) on GitHub.

To install the component, use the following command.

```
$ pip install aws-secretsmanager-caching
```

**Required permissions: **
+ `secretsmanager:DescribeSecret`
+ `secretsmanager:GetSecretValue`

For more information, see [Permissions reference](auth-and-access.md#reference_iam-permissions).

**Topics**
+ [

# SecretCache
](retrieving-secrets_cache-ref-secretcache.md)
+ [

# SecretCacheConfig
](retrieving-secrets_cache-ref-secretcacheconfig.md)
+ [

# SecretCacheHook
](retrieving-secrets_cache-ref-secretcachehook.md)
+ [

# @InjectSecretString
](retrieving-secrets_cache-decor-string.md)
+ [

# @InjectKeywordedSecretString
](retrieving-secrets_cache-decor-keyword.md)

**Example Retrieve a secret**  
The following example shows how to get the secret value for a secret named *mysecret*.  

```
import botocore 
import botocore.session 
from aws_secretsmanager_caching import SecretCache, SecretCacheConfig 

client = botocore.session.get_session().create_client('secretsmanager')
cache_config = SecretCacheConfig()
cache = SecretCache( config = cache_config, client = client)

secret = cache.get_secret_string('mysecret')
```

# SecretCache
<a name="retrieving-secrets_cache-ref-secretcache"></a>

An in-memory cache for secrets retrieved from Secrets Manager. You use [get\$1secret\$1string](#retrieving-secrets_cache-ref-secretcache_get_secret_string) or [get\$1secret\$1binary](#retrieving-secrets_cache-ref-secretcache_get_secret_binary) to retrieve a secret from the cache. You can configure the cache settings by passing in a [SecretCacheConfig](retrieving-secrets_cache-ref-secretcacheconfig.md) object in the constructor. 

For more information, including examples, see [Get a Secrets Manager secret value using Python with client-side caching](retrieving-secrets_cache-python.md).

```
cache = SecretCache(
    config = SecretCacheConfig,
    client = [client](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html)
)
```

**Topics**
+ [

## get\$1secret\$1string
](#retrieving-secrets_cache-ref-secretcache_get_secret_string)
+ [

## get\$1secret\$1binary
](#retrieving-secrets_cache-ref-secretcache_get_secret_binary)

## get\$1secret\$1string
<a name="retrieving-secrets_cache-ref-secretcache_get_secret_string"></a>

Retrieves the secret string value.

Request syntax  

```
response = cache.get_secret_string(
    secret_id='string',
    version_stage='string' )
```

Parameters  
+ `secret_id` (*string*): [Required] The name or ARN of the secret.
+ `version_stage` (*string*): The version of secrets that you want to retrieve. For more information, see [secret versions](whats-in-a-secret.md). The default is 'AWSCURRENT'. 

Return type  
string

## get\$1secret\$1binary
<a name="retrieving-secrets_cache-ref-secretcache_get_secret_binary"></a>

Retrieves the secret binary value.

Request syntax  

```
response = cache.get_secret_binary(
    secret_id='string',
    version_stage='string'
)
```

Parameters  
+ `secret_id` (*string*): [Required] The name or ARN of the secret.
+ `version_stage` (*string*): The version of secrets that you want to retrieve. For more information, see [secret versions](whats-in-a-secret.md). The default is 'AWSCURRENT'. 

Return type  
[base64-encoded](https://tools.ietf.org/html/rfc4648#section-4) string

# SecretCacheConfig
<a name="retrieving-secrets_cache-ref-secretcacheconfig"></a>

Cache configuration options for a [SecretCache](retrieving-secrets_cache-ref-secretcache.md) such as max cache size and Time to Live (TTL) for cached secrets.Parameters

`max_cache_size` (*int*)  
The maximum cache size. The default is `1024` secrets. 

`exception_retry_delay_base` (*int*)  
The number of seconds to wait after an exception is encountered before retrying the request. The default is `1`.

`exception_retry_growth_factor` (*int*)pur  
The growth factor to use for calculating the wait time between retries of failed requests. The default is `2`. 

`exception_retry_delay_max` (*int*)  
The maximum amount of time in seconds to wait between failed requests. The default is `3600`.

`default_version_stage` (*str*)  
The version of secrets that you want to cache. For more information, see [Secret versions](whats-in-a-secret.md#term_version). The default is `'AWSCURRENT'`.

`secret_refresh_interval` (*int*)  
The number of seconds to wait between refreshing cached secret information. The default is `3600`.

`secret_cache_hook` (*SecretCacheHook*)  
An implementation of the `SecretCacheHook` abstract class. The default value is `None`.

# SecretCacheHook
<a name="retrieving-secrets_cache-ref-secretcachehook"></a>

An interface to hook into a [SecretCache](retrieving-secrets_cache-ref-secretcache.md) to perform actions on the secrets being stored in the cache. 

**Topics**
+ [

## put
](#retrieving-secrets_cache-ref-secretcachehook_put)
+ [

## get
](#retrieving-secrets_cache-ref-secretcachehook_get)

## put
<a name="retrieving-secrets_cache-ref-secretcachehook_put"></a>

Prepares the object for storing in the cache.

Request syntax  

```
response = hook.put(
    obj='secret_object'
)
```

Parameters  
+ `obj` (*object*) -- [Required] The secret or object that contains the secret.

Return type  
object

## get
<a name="retrieving-secrets_cache-ref-secretcachehook_get"></a>

Derives the object from the cached object.

Request syntax  

```
response = hook.get(
    obj='secret_object'
)
```

Parameters  
+ `obj` (*object*): [Required] The secret or object that contains the secret.

Return type  
object

# @InjectSecretString
<a name="retrieving-secrets_cache-decor-string"></a>

This decorator expects a secret ID string and [SecretCache](retrieving-secrets_cache-ref-secretcache.md) as the first and second arguments. The decorator returns the secret string value. The secret must contain a string. 

```
from aws_secretsmanager_caching import SecretCache 
from aws_secretsmanager_caching import InjectKeywordedSecretString,  InjectSecretString 

cache = SecretCache()

@InjectSecretString ( 'mysecret' ,  cache ) 
def function_to_be_decorated( arg1,  arg2,  arg3):
```

# @InjectKeywordedSecretString
<a name="retrieving-secrets_cache-decor-keyword"></a>

This decorator expects a secret ID string and [SecretCache](retrieving-secrets_cache-ref-secretcache.md) as the first and second arguments. The remaining arguments map parameters from the wrapped function to JSON keys in the secret. The secret must contain a string in JSON structure. 

For a secret that contains this JSON:

```
{
  "username": "saanvi",
  "password": "EXAMPLE-PASSWORD"
}
```

The following example shows how to extract the JSON values for `username` and `password` from the secret.

```
from aws_secretsmanager_caching import SecretCache 
  from aws_secretsmanager_caching import InjectKeywordedSecretString,  InjectSecretString 
  
  cache = SecretCache()
  
  @InjectKeywordedSecretString ( secret_id = 'mysecret' ,  cache = cache ,  func_username = 'username' ,  func_password = 'password' ) 
  def function_to_be_decorated( func_username,  func_password):
       print( 'Do something with the func_username and func_password parameters')
```

# Get a Secrets Manager secret value using the Python AWS SDK
<a name="retrieving-secrets-python-sdk"></a>

In applications, you can retrieve your secrets by calling `GetSecretValue` or `BatchGetSecretValue`in any of the AWS SDKs. However, we recommend that you cache your secret values by using client-side caching. Caching secrets improves speed and reduces your costs.

For Python applications, use the [Secrets Manager Python-based caching component](retrieving-secrets_cache-python.md) or call the SDK directly with [https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager/client/get_secret_value.html](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager/client/get_secret_value.html) or [https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager/client/batch_get_secret_value.html](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager/client/batch_get_secret_value.html).

The following code examples show how to use `GetSecretValue`.

**Required permissions: **`secretsmanager:GetSecretValue`

```
"""
Purpose

Shows how to use the AWS SDK for Python (Boto3) with AWS
Secrets Manager to get a specific of secrets that match a
specified name
"""
import boto3
import logging

from get_secret_value import GetSecretWrapper

# Configure logging
logging.basicConfig(level=logging.INFO)


def run_scenario(secret_name):
    """
    Retrieve a secret from AWS Secrets Manager.

    :param secret_name: Name of the secret to retrieve.
    :type secret_name: str
    """
    try:
        # Validate secret_name
        if not secret_name:
            raise ValueError("Secret name must be provided.")
        # Retrieve the secret by name
        client = boto3.client("secretsmanager")
        wrapper = GetSecretWrapper(client)
        secret = wrapper.get_secret(secret_name)
        # Note: Secrets should not be logged.
        return secret
    except Exception as e:
        logging.error(f"Error retrieving secret: {e}")
        raise

class GetSecretWrapper:
    def __init__(self, secretsmanager_client):
        self.client = secretsmanager_client


    def get_secret(self, secret_name):
        """
        Retrieve individual secrets from AWS Secrets Manager using the get_secret_value API.
        This function assumes the stack mentioned in the source code README has been successfully deployed.
        This stack includes 7 secrets, all of which have names beginning with "mySecret".

        :param secret_name: The name of the secret fetched.
        :type secret_name: str
        """
        try:
            get_secret_value_response = self.client.get_secret_value(
                SecretId=secret_name
            )
            logging.info("Secret retrieved successfully.")
            return get_secret_value_response["SecretString"]
        except self.client.exceptions.ResourceNotFoundException:
            msg = f"The requested secret {secret_name} was not found."
            logger.info(msg)
            return msg
        except Exception as e:
            logger.error(f"An unknown error occurred: {str(e)}.")
            raise
```

# Get a batch of Secrets Manager secret values using the Python AWS SDK
<a name="retrieving-secrets-python-batch"></a>

The following code example shows how to get a batch of Secrets Manager secret values.

**Required permissions: **
+ `secretsmanager:BatchGetSecretValue` 
+ `secretsmanager:GetSecretValue` permission for each secret you want to retrieve.
+ If you use filters, you must also have `secretsmanager:ListSecrets`. 

For an example permissions policy, see [Example: Permission to retrieve a group of secret values in a batch](auth-and-access_iam-policies.md#auth-and-access_examples_batch).

**Important**  
If you have a VPCE policy that denies permission to retrieve an individual secret in the group you are retrieving, `BatchGetSecretValue` will not return any secret values, and it will return an error.

```
class BatchGetSecretsWrapper:
    def __init__(self, secretsmanager_client):
        self.client = secretsmanager_client


    def batch_get_secrets(self, filter_name):
        """
        Retrieve multiple secrets from AWS Secrets Manager using the batch_get_secret_value API.
        This function assumes the stack mentioned in the source code README has been successfully deployed.
        This stack includes 7 secrets, all of which have names beginning with "mySecret".

        :param filter_name: The full or partial name of secrets to be fetched.
        :type filter_name: str
        """
        try:
            secrets = []
            response = self.client.batch_get_secret_value(
                Filters=[{"Key": "name", "Values": [f"{filter_name}"]}]
            )
            for secret in response["SecretValues"]:
                secrets.append(json.loads(secret["SecretString"]))
            if secrets:
                logger.info("Secrets retrieved successfully.")
            else:
                logger.info("Zero secrets returned without error.")
            return secrets
        except self.client.exceptions.ResourceNotFoundException:
            msg = f"One or more requested secrets were not found with filter: {filter_name}"
            logger.info(msg)
            return msg
        except Exception as e:
            logger.error(f"An unknown error occurred:\n{str(e)}.")
            raise
```