Zero
Zero
Back

Securely Handle Secrets in AWS Lambda

Zero is a secrets manager as a service. Once you sign up for Zero, you can create a Zero token which can be used to retrieve API keys and other secrets from your Zero account using the SDK or one of the integrations, like our official GitHub Action.

Sam Magura

Sam Magura

Lockers for things

Zero is a secrets manager as a service. Once you sign up for Zero, you can create a Zero token which can be used to retrieve API keys and other secrets from your Zero account using the SDK  or one of the integrations, like our official GitHub Action .

This article shows how to use Zero to send an email via SendGrid from a TypeScript function hosted in AWS Lambda. The Lambda function only needs to be configured with the Zero token — the SendGrid API key is stored securely in your Zero account and can be fetched at runtime.

This design is beneficial because, if we needed to call additional APIs from the Lambda function in the future, we would not have to change the environment variable configuration at all. It is also quite secure — secrets fetched from Zero will never appear in Lambda logs, or in the configuration section in AWS web console.

🔗 The full code for this example is available in the zerosecrets/examples  GitHub repository.

Secure your secrets conveniently

Zero is a modern secrets manager built with usability at its core. Reliable and secure, it saves time and effort.

Zero dashboard

Setting up the Lambda Function

Before we can start sending emails, we need to set up a basic Lambda application in AWS. If you're already experienced with AWS Lambda, feel free to skip to the next section.

First, some prerequisites:

  1. Install the AWS CLI .
  2. Run aws configure and provide your credentials.
  3. Install the AWS Cloud Development Kit (CDK)  with npm install -g aws-cdk. The CDK allows you to define AWS resources in code so you do not have to manually create them via the AWS Console.

Once everything is installed, we can create a new project with:

1
2
3
shell
mkdir lambda-sendgrid
cd lambda-sendgrid
cdk init --language typescript

We'll roughly follow this tutorial  from the AWS Lambda documentation to create a simple "Hello World" function.

  1. Run npm install --save-dev @types/aws-lambda so that we have access to the TypeScript types for Lambda.

  2. Define a handler function that accepts POST requests and has basic error handling:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    typescript
    import {Context, APIGatewayEvent, APIGatewayProxyResult} from 'aws-lambda'
    
    export async function handler(event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> {
      try {
        if (!(event.httpMethod === 'POST' && event.path === '/')) {
          return {statusCode: 400, body: 'Only POST / is supported.'}
        }
    
        // TODO Send the email
    
        return {statusCode: 200, body: 'Email sent successfully!'}
      } catch (error) {
        const body = (error as {stack?: string}).stack || JSON.stringify(error, null, 2)
    
        return {statusCode: 500, body: JSON.stringify(body)}
      }
    }
    
  3. Define NodejsFunction and LambdaRestApi constructs to tell the CDK which resources to create:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typescript
    import * as cdk from 'aws-cdk-lib'
    import {Construct} from 'constructs'
    import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs'
    import {LambdaRestApi} from 'aws-cdk-lib/aws-apigateway'
    
    export class SendEmail extends Construct {
      constructor(scope: Construct, id: string) {
        super(scope, id)
    
        const sendEmailFunction = new NodejsFunction(this, 'function')
    
        new LambdaRestApi(this, 'apigw', {handler: sendEmailFunction})
      }
    }
    
  4. Import the SendEmail construct into our application stack:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typescript
    import * as cdk from 'aws-cdk-lib'
    import {Construct} from 'constructs'
    import {SendEmail} from './send-email'
    
    export class LambdaSendgridStack extends cdk.Stack {
      constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props)
    
        new SendEmail(this, 'send-email')
      }
    }
    

Now we're ready to deploy our code to the cloud! Run cdk deploy. It will provision the necessary resources and output the URL for our function at the end. The output will be of the form:

1
2
shell
Outputs:
   LambdaSendgridStack.sendemailapigwEndpoint3911AD3E = https://{ID}.execute-api.{REGION}.amazonaws.com/prod/

We can test the API using curl, Postman, or any other tool that can make a HTTP POST request. With curl, this would be:

1
shell
curl -X POST https://{ID}.execute-api.{REGION}.amazonaws.com/prod/

You'll need to use the actual URL that was printed when you deployed — ID and REGION are placeholders. If everything worked, you will get back the message "Email sent successfully!". If you get an Internal Server Error response, check the CloudWatch logs in the AWS Console to see what went wrong.

Creating a Zero Token

To send an email, we'll need a valid SendGrid API key. You can sign up for a free account at sendgrid.com . Once logged in, we recommend creating a Single Sender with your personal email address since this is the fastest way to get up and running. Then, you can obtain an API key by selecting "Email API > Integration Guide" from the left sidebar.

The next step is to copy the SendGrid API key into Zero. To do this, you'll need to sign up for Zero if you have not done so already. Once you complete the sign up process, you can create a Zero token by clicking the button in the center of the screen. We'll name our token lambda-sendgrid for this example.

Create a Zero token
Create a Zero token

After creating the token, click "Add a secret", select SendGrid from the dropdown, and paste in the API key. Delete the SECRET_ACCESS_KEY row because it is not used.

Adding a secret/API to the Zero token
Adding a secret/API to the Zero token

Fetching a Secret with the Zero SDK

The Zero SDK uses your Zero token to fetch the SendGrid API key from your Zero account. Your Zero token is a secret, so it should never be committed to your source repository. Instead, we'll add the Zero token as an environment variable in the AWS Lambda configuration. To do this:

  1. In the Zero Console, copy the Zero token by clicking the "Copy" icon under the name of your token.
  2. Log into the AWS Console.
  3. Search for and select "Lambda" in the search bar at the top.
  4. Click the "LambdaSendgridStack-sendemailfunction..." function.
  5. Switch to the "Configuration" tab.
  6. Click "Environment variables" in the menu on the left.
  7. Click the "Edit" button and add a new environment variable named ZERO_TOKEN.
Adding an environment variable in AWS Lambda
Adding an environment variable in AWS Lambda

Now we can update our Lambda function to fetch the SendGrid API key with the Zero SDK. Install the SDK with:

1
shell
npm install @zerosecrets/zero

and import it in send-email.function.ts like so:

1
typescript
import {zero} from '@zerosecrets/zero'

Then, update the handler function to fetch the SendGrid API key from Zero:

1
2
3
4
5
6
7
8
9
10
typescript
const secrets = await zero({
  token: process.env.ZERO_TOKEN!,
  pick: ['sendgrid'],
}).fetch()

if (!secrets.sendgrid) {
  throw new Error('Did not receive an API key for SendGrid.')
}

// TODO Use `secrets.sendgrid.api_key` to send the email

Integrating with the SendGrid API

The final step is to integrate with the SendGrid API. You can the TypeScript API client with

1
shell
npm install @sendgrid/mail

Import the API client in send-email.function.ts:

1
typescript
import * as sendgridMail from '@sendgrid/mail'

Then configure the API client with the API key you fetched from Zero and send the email!

1
2
3
4
5
6
7
8
typescript
sendgridMail.setApiKey(secrets.sendgrid.api_key)

await sendgridMail.send({
  to: '<your-email-address>', // TODO Replace with your real email
  from: '<your-email-address>',
  subject: 'Hello from Lambda & Zero!',
  text: 'It works!',
})

Run cdk deploy again to push your code to AWS. Then trigger your Lambda function via curl, Postman, .etc and you should receive an email! Make sure to check your spam folder if you do not see the email in your inbox.

Once you are done experimenting, make sure to run cdk destroy to clean up the AWS resources you created.

Wrapping Up

This guide demonstrated how to set up a simple serverless function in AWS Lambda that fetches an API key from Zero using the Zero TypeScript SDK. While the functionality of this example is very simple, you can use these same techniques to integrate Zero into a real application. Pass your Zero token in as an environment variable, call zero(...).fetch(), and you have your API key! That's really all there is to it.


Other articles

The Vercel logo

Announcing the Vercel Integration

The upcoming Zero Vercel integration will enable you to seamlessly sync secrets between Zero and the environment variables of your web apps hosted on Vercel!

Glasses

Improvements to Secrets Usage Monitoring in Zero

Zero has recently added two new features to help you detect unauthorized access to your secrets. In this post, I'll explain the new features and how they improve security.

Secure your secrets

Zero is a modern secrets manager built with usability at its core. Reliable and secure, it saves time and effort.