Skip to content

Instantly share code, notes, and snippets.

@thereisnotime
Created July 28, 2023 18:55
Show Gist options
  • Save thereisnotime/31569e00a430ef4c85b2d1673ed934f3 to your computer and use it in GitHub Desktop.
Save thereisnotime/31569e00a430ef4c85b2d1673ed934f3 to your computer and use it in GitHub Desktop.
Deploy / update AWS Lambda environment variables / secrets from .env or key-value file
- name: Prepare | Secrets
id: prep_secret
run: echo "::set-output name=LAMBDA_SECRET_NAME::LAMBDA_$(echo '${{ github.event.inputs.lambda_name }}' | tr '[:lower:]' '[:upper:]')_ENV"
- name: Setup | Serverless Secret Config
# Write a big ENV secret to a .env file
run: |
echo "${{ secrets[steps.prep_secret.outputs.LAMBDA_SECRET_NAME] }}" >> .env
- name: Deploy | Update Lambda Secrets
uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r ./deployments/scripts/requirements.txt
- run: |
python ./deployments/scripts/updateLambdaEnvironment.py --lambda_name lambda-${{ inputs.environment }}-${{ inputs.lambda_name }} --aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID }} --aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY }} --aws_region ${{ env.AWS_REGION }}
boto3==1.20.23
python-dotenv==0.19.2
import os
import boto3
import argparse
from dotenv import load_dotenv
"""
Script for updating AWS Lambda function environment variables from a .env file.
Usage:
python lambda_env_updater.py --lambda_name <your_lambda_function_name> [--debug] [--aws_access_key_id <your_access_key>] [--aws_secret_access_key <your_secret_key>] [--aws_region <your_region>] [--aws_profile <your_profile>] [--env_file <path_to_your_.env_file>]
Arguments:
--debug: Enable debug mode to print changes without applying them.
--lambda_name: Name of the Lambda function to update (Required).
--aws_access_key_id: AWS Access Key ID.
--aws_secret_access_key: AWS Secret Access Key.
--aws_region: AWS Region.
--aws_profile: AWS CLI profile to use. Defaults to 'default'.
--env_file: Path to the .env file. Defaults to '.env' in the current folder.
In the absence of AWS credentials (access key, secret access key, and region) in the arguments, the script will use the default AWS CLI profile's credentials.
The .env file should contain one 'KEY=VALUE' pair per line. Lines starting with '#' are treated as comments and ignored.
Example usage:
python lambda_env_updater.py --lambda_name my_lambda_function --debug --aws_access_key_id XXXX --aws_secret_access_key YYYY --aws_region us-west-2 --aws_profile my_profile --env_file /path/to/my/.env
"""
def load_env_variables(file_path=".env"):
load_dotenv(file_path)
def get_env_variables_from_file(file_path=".env"):
env_variables = {}
with open(file_path) as f:
for i, line in enumerate(f, start=1):
line = line.strip()
if line and not line.startswith("#"):
try:
key, value = line.split("=", 1)
env_variables[key] = value
except ValueError:
raise ValueError(f"Line {i} in {file_path} is not correctly formatted. "
f"Each line should be in the form 'KEY=VALUE'.")
return env_variables
def update_lambda_environment(function_name, env_variables, debug_mode, aws_credentials):
# AWS reserved keys
reserved_keys = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_REGION"]
session = boto3.Session(**aws_credentials)
lambda_client = session.client('lambda')
# Get the current configuration of the Lambda function
response = lambda_client.get_function(FunctionName=function_name)
current_env_variables = response['Configuration']['Environment']['Variables']
# Placeholder for new environment variables
new_env_variables = current_env_variables.copy()
# Compare and update the environment variables
for key, value in env_variables.items():
# Skip if the key is an AWS reserved key
if key in reserved_keys:
continue
if key in new_env_variables:
if new_env_variables[key] != value:
# Print the changes
print(f"Updating: {key}")
if not debug_mode:
new_env_variables[key] = value
else:
# Print the changes
print(f"Adding: {key}")
if not debug_mode:
new_env_variables[key] = value
# Remove any environment variables that are not in the .env file
for key in list(new_env_variables.keys()):
# Skip if the key is an AWS reserved key
if key in reserved_keys:
continue
if key not in env_variables:
# Print the changes
print(f"Removing: {key}")
if not debug_mode:
del new_env_variables[key]
# Update the Lambda function configuration with the new environment variables
if not debug_mode:
lambda_client.update_function_configuration(
FunctionName=function_name,
Environment={
'Variables': new_env_variables
}
)
lambda_client.close()
def get_aws_credentials_from_args_or_file(args):
if args.aws_access_key_id and args.aws_secret_access_key and args.aws_region:
return {
"aws_access_key_id": args.aws_access_key_id,
"aws_secret_access_key": args.aws_secret_access_key,
"region_name": args.aws_region
}
else:
# Use the default AWS CLI profile if AWS credentials are not provided
session = boto3.Session(profile_name=args.aws_profile)
credentials = session.get_credentials()
if credentials is None:
raise ValueError("AWS credentials not found. Make sure to set --aws_access_key_id, "
"--aws_secret_access_key, --aws_region, or configure AWS CLI credentials.")
return {
"region_name": session.region_name
}
def parse_arguments():
parser = argparse.ArgumentParser(description="Update Lambda function environment variables from .env file")
parser.add_argument("--debug", action="store_true", help="Enable debug mode to print changes without applying them")
parser.add_argument("--lambda_name", required=True, help="Name of the Lambda function to update")
parser.add_argument("--aws_access_key_id", help="AWS Access Key ID")
parser.add_argument("--aws_secret_access_key", help="AWS Secret Access Key")
parser.add_argument("--aws_region", help="AWS Region")
parser.add_argument("--aws_profile", default="default", help="AWS CLI profile to use (default: default)")
parser.add_argument("--env_file", help="Path to the .env file (default: .env in current folder)")
return parser.parse_args()
if __name__ == "__main__":
args = parse_arguments()
# Load environment variables from .env file
env_file_path = args.env_file or ".env"
load_env_variables(env_file_path)
print(f"Loaded environment variables from: {os.path.abspath(env_file_path)}")
if args.debug:
print("Running in debug mode. No changes will be applied.")
if args.aws_access_key_id and args.aws_secret_access_key and args.aws_region:
print("Using AWS credentials from command-line arguments")
else:
print("Using AWS credentials from the default AWS CLI configuration file")
# Specify the name of the Lambda function you want to update
lambda_function_name = args.lambda_name
# Define the environment variables to be updated (loaded from .env file)
env_variables = get_env_variables_from_file(env_file_path)
# Get AWS credentials either from command-line arguments or from AWS CLI configuration file
aws_credentials = get_aws_credentials_from_args_or_file(args)
# Update the Lambda function environment
update_lambda_environment(lambda_function_name, env_variables, args.debug, aws_credentials)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment