AWS Secrets Manager integration

With BigAnimal, you can use AWS Secrets Manager. AWS Secrets Manager helps you manage, retrieve, and rotate database credentials, access keys, and other secrets throughout their lifecycle.

To create a secret manager:

  1. Create a PostgreSQL cluster on the BigAnimal portal.

  2. Create and save an access key.

  3. Create a secret in AWS Secrets Manager for your psql credentials.

    Create the secret manager using a Lambda script or using the AWS console:

    • Lambda script:

      import boto3
      import json
      
      def create_secret(secret_name, username, password, database, host):
                 client = boto3.client('secretsmanager')
      
                 secret_string = json.dumps({
            "username": username,
            "password": password,
            "engine": "postgresql",
            "host": host,
            "dbname": database,
            "port": 5432
          })
      
      response = client.create_secret(
         Name=secret_name,
         SecretString=secret_string
      )
      
      return response

      Using the created secret:

      create_secret('mySecretName', 'myUsername', 'myPassword', 'myDatabase', 'myHost')
    • AWS console:

      1. Search for Secret Manager under Services.
      2. Select Store a new secret.
      3. On the Choose secret type page, select Credentials for other databases and provide:
        • Username
        • Password
        • Encryption key
        • Database Provide the server address, database name and port as per the selected database engine. Select Next.
      4. On the Configure secret page, provide Secret name. Optionally, you can provide:
        • Description
        • Tags
        • Resource permissions
        • Replicate secret Select Next.
      5. Optionally, on the Configure rotation page, provide details.
      6. Review the code in different languages like: Java, JavaScript, C#, Python3, Ruby, Go, and Rust. To create the secret manager, select Store.
  4. Create the secret in the centralized Secrets Manager for your access key.

  5. Create a sample login application.

    For example, using a Lambda script:

    [cloudshell-user@ip-10-130-83-78 ~]$ cat lambda_connect.py 
    import json
    import boto3
    import base64
    import psycopg2
    region = 'us-east-1'
    
    client = boto3.client('secretsmanager', region_name=region)
    response = client.get_secret_value(
                SecretId='dev/toy/demo'
                    )
    
    secretDict = json.loads(response['SecretString'])
    
    connection = psycopg2.connect(
             user=secretDict['username'], 
              password=secretDict['password'],
               host=secretDict['host'], 
                 port=secretDict['port'],
                 sslmode='require',
                  database=secretDict['dbname'])
    
    mycursor = connection.cursor()
    
    create = "create table Demo0503(Toyota int)"
    #sql = "INSERT into secretmgr(id,name) values (%s, %s)"
    #value = (2, "Toyota_Demo")
    mycursor.execute(create)
    
    connection.commit()

    Fetch all the rows from the database:

    print(mycursor.rowcount, "record")

Example

In this example, a script file has all the commands required to create a Secrets Manager rotation Lambda function, execute the rotation script, and execute the sample application.

cat gen_pass_rotate_bigani_and_secretmgr_pass.py 
import os
import secrets
import string
import requests
import json
import boto3

# Get the key from an environment variable
key = os.getenv("MY_SECRET_KEY")
if not key:
    raise ValueError("Missing secret key")

def generate_password(length):
    alphabet = string.ascii_letters + string.digits + string.punctuation
    password = ''.join(secrets.choice(alphabet) for i in range(length))
    return password

# Generate a 12-character password
password = generate_password(12)

try:
  lambda_func = lambda: requests.patch(
    "https://portal.biganimal.com/api/v3/projects/prj_30GlIxgAyvWhtmn3/clusters/p-hxx6mp2mtw",
    data=json.dumps({"password": password}),
    headers={
        "Content-Type": "Application/JSON",
        "x-access-key": key
    }
   )

   # Display the password
   response = lambda_func()
   response.raise_for_status()  # Raises a HTTPError if the status is 4xx, 5xx
except requests.exceptions.RequestException as e:
    print(f"Request failed: {e}")
    raise

print(response.status_code)
print(response.text)

def update_password_in_secret(secret_name):
    new_password = password
    client = boto3.client('secretsmanager')
    
    try:
        # Get the current secret
        response = client.get_secret_value(SecretId=secret_name)
        secret_data = json.loads(response['SecretString'])

        # Update the password field
        secret_data['password'] = new_password

        # Store the updated secret
        update_response = client.update_secret(
            SecretId=secret_name,
            SecretString=json.dumps(secret_data) )
    
    except client.exceptions.ClientError as e:
        print(f"Failed to update secret: {e}")
        raise

    return new_password, update_response

# Usage - Run the the password update on AWS Secret Manager
try:
    new_password, response = update_password_in_secret('/dev/toyota/demo')
except Exception as e:
    print(f"Failed to update password in secret: {e}")
    raise