Secrets
Resource Overview
A Secrets resource provides authorized cloud resources access to the Environment Secrets defined for the stack's current deployment environment. The Secrets resource is backed by AWS Secrets Manager.
A secret is any sensitive data, like credentials or connection details, that is required to access or configure secured resources within a stack. A secured resource is a resource within your stack whose access is controlled by an Environment Secret.
The secrets that can be accessed in an environment can be viewed or updated by navigating to Environments and selecting the appropriate environment. The Environment Secrets section allows administrators and developers to create, update, or delete environment secrets.
Examples of Secrets include:
- Database Credentials
- User Passwords
- API Keys
- OAuth Tokens
- Third-Party Account Credentials
Service Discovery
Service discovery wires (dashed line) provide compute resources (Function, Edge Function, Docker Task) with the permissions and environment variables required to perform actions using cloud resources within the stack. This resource is on the receiving end of a service discovery wire originating from compute resources.
The following compute resources can use a service discovery wire to access a Secrets resource:
- Function
- Docker Task
Storage and Encryption
Environment Secrets are encrypted using AWS Key Management Service. Stackery uses the default AWS KMS key of the account to encrypt the secret at rest. The default KMS encryption key does not incur charges.
Usage
A Function or Docker Task resource extends a service discovery wire (dashed line) to connect to a Secrets resource.
Permissions
When one of the above compute resources are connected to a Secrets resource via a service discovery wire, the following IAM permissions policy is automatically added to that compute resource's Permissions property:
AWSSecretsManagerGetSecretValuePolicy
This policy gives the compute resource permission to retrieve the values stored within the current environment's secrets section. (Environments navigation tab > Environment Secrets)
How to fetch your secrets
The following code snippets are examples of the required AWS Secrets Manager API calls made within a Functions's handler function. Each example below fetches the apiKey
stored in AWS Secrets Manager.
Some code in the following examples has been omitted to not distract from the AWS Secrets Manager API calls this section covers. Full Python, Java, and .NET Core examples are linked below
// Import AWS SDK and instantiate a variable for the AWS Secrets Manager
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
// Store the SECRETS_NAMESPACE value from the Function's environment variables
const secretsNamespace = process.env.SECRETS_NAMESPACE;
exports.handler = async message => {
// Construct paramaters to pass to AWS Secrets Manager API call
// SecretId is a combination of the secret's namespace and the specific secret to return
const params = {
SecretId: secretsNamespace + 'apiKey'
};
// AWS Secrets Manager API call passing through params for retrieval
const response = await secretsManager.getSecretValue(params).promise();
// Accessing the secret's value of the response object
const apiKey = response.SecretString;
return {};
}
import os
import boto3
from botocore.exceptions import ClientError
def handler(message, context):
# Store the SECRETS_NAMESPACE value from the Function's environment variables
secretsNamespace = os.environ['SECRETS_NAMESPACE']
secretsRegion = os.environ['AWS_REGION']
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager',
region_name=secretsRegion
)
try:
# SecretId is a combination of the secret's namespace and the specific secret to return
response = client.get_secret_value(SecretId=secretsNamespace + 'apiKey')
except ClientError as e:
# Handle specific errors (omitted)
else:
apiKey = response['SecretString']
import java.util.HashMap;
package aws.example.secretsmanager;
// ... For all required imports, see link above
public class Handler {
public static void main(String[] args) {
getSecret();
}
public static void getSecret() {
// Store the SECRETS_NAMESPACE, _ENDPOINT, and _REGION values from the Function's environment variables
String secretsName = System.getenv("SECRETS_NAMESPACE")
String endpoint = System.getenv("SECRETS_ENDPOINT")
String region = System.getenv("AWS_REGION")
AwsClientBuilder.EndpointConfiguration config = new AwsClientBuilder.EndpointConfiguration(endpoint, region);
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard();
clientBuilder.setEndpointConfiguration(config);
AWSSecretsManager client = clientBuilder.build();
String secret;
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretName + 'apiKey');
GetSecretValueResult getSecretValueResult = null;
try {
getSecretValueResult = client.getSecretValue(getSecretValueRequest);
} catch(ResourceNotFoundException e) {
// Handle specific errors (omitted)
}
if(getSecretValueResult == null) {
return;
}
// Verify SecretString exists, print
if(getSecretValueResult.getSecretString() != null) {
secret = getSecretValueResult.getSecretString();
System.out.println(secret);
}
}
}
using System;
using System.IO;
using Amazon;
using Amazon.Lambda.Core;
using Amazon.SecretsManager;
using Amazon.SecretsManager.Model;
namespace StackeryFunction
{
public class Handler
{
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public dynamic handler(dynamic message)
{
// Store the SECRETS_NAMESPACE AND _REGION value from the Function's environment variables
string secretName = Environment.GetEnvironmentVariable("SECRETS_NAMESPACE");
string region = Environment.GetEnvironmentVariable("AWS_REGION");
string secret = "";
MemoryStream memoryStream = new MemoryStream();
IAmazonSecretsManager client = new AmazonSecretsManagerClient(RegionEndpoint.GetBySystemName(region));
GetSecretValueRequest request = new GetSecretValueRequest();
request.SecretId = secretName;
request.VersionStage = "AWSCURRENT"; // VersionStage defaults to AWSCURRENT if unspecified.
GetSecretValueResponse response = null;
try
{
response = client.GetSecretValueAsync(request).Result;
}
catch { {**ExceptionName**} e } {
// Handle specific errors (omitted)
}
if (response.SecretString != null)
{
secret = response.SecretString;
}
}
}
}
Limits
Secrets can be up to 4096 characters. If they require more than 4096 characters, you can split it between two secrets and concatenate them back together before using them (in the handler)
IAM Permissions
When connected by a service discovery wire (dashed wire), a Function, Edge Function, or Docker Task will add the following IAM policy to its role and gain permission to access this resource.
AWSSecretsManagerGetSecretValuePolicy
Related AWS Documentation
AWS Documentation: AWS Secrets Manager
Full AWS Code Samples (Fetching Secrets):