Part 1: Secrets

Generating the Secret is pretty self explanatory. You just need to create a key/value pair. You can use the default encryption key. You also have to assign a secret name. I followed the example given, using “prod/github/issues” (prod for production).

Secrets manager itself seems very cool. You can configure automatically rotating secrets which are generated via custom Lambda functions. You can essentially customize as much or as little as you want, and AWS is overall full of great services. You can learn more about it here if you’d like.

The secret manager also gives you an example of code you could use in your Lambda function in multiple languages, for which I’ve included the python version below. boto3 is the library used to access AWS secrets by creating a “session” and then using the secrets manager within that session. The rest should be pretty self explanatory.

# Use this code snippet in your app.
# If you need more information about configurations
# or implementing the sample code, visit the AWS docs:
# https://aws.amazon.com/developer/language/python/

import boto3
from botocore.exceptions import ClientError


def get_secret():

    secret_name = "prod/github/issues"
    region_name = "us-east-2"

    # Create a Secrets Manager client
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
        # For a list of exceptions thrown, see
        # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
        raise e

    secret = get_secret_value_response['SecretString']

    # Your code goes here.

Part 2: Lambdas

I’ve already worked with Lambdas before and have a guide for them here. In short, Lambdas allow you to run code segments without a server, sorta like how you can run a jupyter notebook cell without a server needing to be deployed. They are useful for many different applications, and in our case they’re helping us keep our secret key safe by finding the key in the AWS Secrets for us and sending it to our frontend server.

Here is an example of the Lambda Code. You’ll notice it looks very similar to the code above:

import json

import boto3
import os
from botocore.exceptions import ClientError

def lambda_handler(event, context):
    secret_name = "prod/github/issues"
    region_name = "us-east-2"

    # Create a Secrets Manager client
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
        # For a list of exceptions thrown, see
        # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
        raise e

    secret = get_secret_value_response['SecretString']    
    return {
        'statusCode': 200,
        'body': json.dumps(secret)
    }

Lambda Booboos

  1. Make sure you create a tester event to test your lambda. Don’t worry about the test body because we don’t have one. You click the dropdown arrow next to the test and then create the event by following the instructions.
  2. Updating Permissions: If you get a secretsManager GetSecretKey not allowed or something along those lines make sure you update the role. The Lambda is automatically assigned a role, and it’s fine to just use that role, but make sure you add permissions by going to the IAM page, clicking on the roles tab on the left sidebar, searching for you role, and adding the permissions policy.

Part #3: API Gateway

Amazon API Gateway lets you create an API that you can call a Lambda through. Otherwise to call the Lambda directly you need a secret key from Amazon which defeats the enitre purpose of doing this. So instead we use an API Gateway. When making one use the HTTP Api, it’s lighter weight and simpler than the REST Api and it’s all we need for this. Here’s an example of an api request.

import requests
import json

def getToken():
    api_endpoint = 'API_Endpoint'

    headers = {
        'Content-Type': 'application/json',
    }

    try:
        response = requests.post(api_endpoint, headers=headers)

        if response.status_code == 200:
            return json.loads(response.json())
        else:
            print("Request failed with status code:", response.status_code)
            print("Response:", response.text)

    except Exception as e:
        print("Error:", str(e))

print(getToken()["GithubApi"])

Once you have those steps, you can easily keep your secret key secret and continue to use it!