Application Security
Welcome to this chapter on securing AWS Lambda functions with built-in AWS security tools. We're going to walk through a full example of locking down a Lambda function using three key services:
- SSM Parameter Store to store secrets securely;
- KMS for encrypting environment variables;
- API Gateway to control access using API keys.
By the end of this lab, you'll have a secure Lambda function protected with multiple layers — and you'll clean everything up to avoid unnecessary charges.
Storing Secrets Securely
We'll start by storing a sensitive token in the AWS Systems Manager (SSM) Parameter Store.
The value is going to be a secure string: "ThisIsASecureToken123"
.
We'll use the AWS CLI to add this parameter, and AWS will automatically encrypt it using the default KMS key:
aws ssm put-parameter \
--name "/prod/secretToken" \
--value "ThisIsASecureToken123" \
--type SecureString
That secret is now safely stored and encrypted. We'll later retrieve it from the Lambda function.
Creating the Lambda Role and Permissions
Next up, we need a role that Lambda can assume. This includes a trust policy that defines who can assume the role:
aws iam create-role \
--role-name LambdaSecurityRole \
--assume-role-policy-document file://./6.2-trust_policy.json
Then, we attach a policy to allow access to Parameter Store. Specifically, Lambda will need permissions to call ssm:GetParameter
.
aws iam put-role-policy \
--role-name LambdaSecurityRole \
--policy-name LambdaSSMPolicy \
--policy-document file://./6.2-ssm_policy.json
At this point, our Lambda function will be able to read the secret from SSM.
Deploying the Lambda Function
Let's zip up the Lambda code first:
zip functions.zip lambdas_function.py
Then we'll create the function and pass in an environment variable called SECRET_TOKEN
.
But instead of a plain string, we're using AWS's {{resolve:ssm-secure:...}}
syntax. This tells Lambda to fetch the value securely at runtime.
aws lambda create-function \
--function-name SecureLambda \
--runtime python3.8 \
--role arn:aws:iam::822033172740:role/LambdaSecurityRole \
--handler lambdas_function.lambda_handler \
--zip-file fileb://functions.zip \
--environment '{"Variables":{"SECRET_TOKEN":"{{resolve:ssm-secure:/prod/secretToken}}"}}'
Now our Lambda function is up and running, and the secret will only be pulled when it runs. Nothing is hardcoded or exposed in the code.
Securing API Gateway
We want to expose our Lambda via an API Gateway — but only to users with a valid API key.
First, we create the API and grab the REST API ID and root resource ID:
rest_api_id=$(aws apigateway create-rest-api \
--name SecureLambdaAPI \
--query 'id' --output text)
root_id=$(aws apigateway get-resources \
--rest-api-id $rest_api_id \
--query 'items[0].id' --output text)
Then we add a GET method to the root path and enforce API key usage:
aws apigateway put-method \
--rest-api-id $rest_api_id \
--resource-id $root_id \
--http-method GET \
--authorization-type NONE \
--api-key-required
Now we link the method to our Lambda using an AWS\_PROXY
integration:
aws apigateway put-integration \
--rest-api-id $rest_api_id \
--resource-id $root_id \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:822033172740:function:SecureLambda/invocations
And we give API Gateway permission to invoke our function:
aws lambda add-permission \
--function-name SecureLambda \
--statement-id AllowAPIGWInvoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn 'arn:aws:execute-api:us-east-2:822033172740:$rest_api_id/*/GET/'
Then we deploy the API to a stage named prod
:
aws apigateway create-deployment \
--rest-api-id $rest_api_id \
--stage-name prod
Adding the API Key
Now we'll create the actual API key and a usage plan to manage access:
api_key_id=$(aws apigateway create-api-key \
--name SecureDemoKey \
--enabled \
--query 'id' --output text)
usage_plan_id=$(aws apigateway create-usage-plan \
--name "SecureLambdaPlan" \
--api-stages apiId=$rest_api_id,stage=prod \
--query 'id' --output text)
Then associate the key with the usage plan:
aws apigateway create-usage-plan-key \
--usage-plan-id $usage_plan_id \
--key-id $api_key_id \
--key-type API_KEY
At this point, only users with this key can call your Lambda function via the API.
Invoking the Lambda Function
Let's test the whole setup.
First, we fetch the actual API key value so we can pass it in the request:
api_key_value=$(aws apigateway get-api-key \
--api-key $api_key_id \
--include-value \
--query 'value' --output text)
Then invoke the Lambda directly to confirm it works:
aws lambda invoke --function-name SecureLambda out.txt
If everything worked, you should see a status code 200
and the secret printed in the response body.
In a real environment, the environment variable will resolve to the actual secret — but here in the demo, it may just show the placeholder path.
Cleaning Up
Once you're done testing, it's important to clean up all resources to avoid extra charges:
aws lambda delete-function --function-name SecureLambda
aws apigateway delete-rest-api --rest-api-id $rest_api_id
aws ssm delete-parameter --name "/prod/secretToken"
aws apigateway delete-api-key --api-key $api_key_id
aws apigateway delete-usage-plan --usage-plan-id $usage_plan_id
aws iam delete-role-policy \
--role-name LambdaSecurityRole \
--policy-name LambdaSSMPolicy
aws iam delete-role --role-name LambdaSecurityRole
Wrapping Up
In this hands-on section, you learned how to:
- Store and encrypt secrets using SSM Parameter Store;
- Encrypt Lambda environment variables with KMS;
- Protect a Lambda endpoint with API Gateway and API keys.
This is a strong example of building real-world security directly into your AWS workloads.
1. What AWS service is used to store secrets like tokens or passwords in this lab?
2. Which CLI parameter makes the stored SSM parameter encrypted?
3. What is the purpose of the IAM trust policy when creating the Lambda role?
4. What does the {{resolve:ssm-secure:/prod/secretToken}}
syntax do in
Lambda environment variables?
5. Why is the Lambda environment variable considered secure in this setup?
6. What does setting --api-key-required to true in the API Gateway method do?
7. Which AWS service was used to protect the Lambda endpoint with throttling and
access control?
8. Which command allows API Gateway to invoke your Lambda function?
9. What does the usage plan in API Gateway control?
10. What's the last thing you should always do after a lab like this?
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Awesome!
Completion rate improved to 6.25
Application Security
Stryg for at vise menuen
Welcome to this chapter on securing AWS Lambda functions with built-in AWS security tools. We're going to walk through a full example of locking down a Lambda function using three key services:
- SSM Parameter Store to store secrets securely;
- KMS for encrypting environment variables;
- API Gateway to control access using API keys.
By the end of this lab, you'll have a secure Lambda function protected with multiple layers — and you'll clean everything up to avoid unnecessary charges.
Storing Secrets Securely
We'll start by storing a sensitive token in the AWS Systems Manager (SSM) Parameter Store.
The value is going to be a secure string: "ThisIsASecureToken123"
.
We'll use the AWS CLI to add this parameter, and AWS will automatically encrypt it using the default KMS key:
aws ssm put-parameter \
--name "/prod/secretToken" \
--value "ThisIsASecureToken123" \
--type SecureString
That secret is now safely stored and encrypted. We'll later retrieve it from the Lambda function.
Creating the Lambda Role and Permissions
Next up, we need a role that Lambda can assume. This includes a trust policy that defines who can assume the role:
aws iam create-role \
--role-name LambdaSecurityRole \
--assume-role-policy-document file://./6.2-trust_policy.json
Then, we attach a policy to allow access to Parameter Store. Specifically, Lambda will need permissions to call ssm:GetParameter
.
aws iam put-role-policy \
--role-name LambdaSecurityRole \
--policy-name LambdaSSMPolicy \
--policy-document file://./6.2-ssm_policy.json
At this point, our Lambda function will be able to read the secret from SSM.
Deploying the Lambda Function
Let's zip up the Lambda code first:
zip functions.zip lambdas_function.py
Then we'll create the function and pass in an environment variable called SECRET_TOKEN
.
But instead of a plain string, we're using AWS's {{resolve:ssm-secure:...}}
syntax. This tells Lambda to fetch the value securely at runtime.
aws lambda create-function \
--function-name SecureLambda \
--runtime python3.8 \
--role arn:aws:iam::822033172740:role/LambdaSecurityRole \
--handler lambdas_function.lambda_handler \
--zip-file fileb://functions.zip \
--environment '{"Variables":{"SECRET_TOKEN":"{{resolve:ssm-secure:/prod/secretToken}}"}}'
Now our Lambda function is up and running, and the secret will only be pulled when it runs. Nothing is hardcoded or exposed in the code.
Securing API Gateway
We want to expose our Lambda via an API Gateway — but only to users with a valid API key.
First, we create the API and grab the REST API ID and root resource ID:
rest_api_id=$(aws apigateway create-rest-api \
--name SecureLambdaAPI \
--query 'id' --output text)
root_id=$(aws apigateway get-resources \
--rest-api-id $rest_api_id \
--query 'items[0].id' --output text)
Then we add a GET method to the root path and enforce API key usage:
aws apigateway put-method \
--rest-api-id $rest_api_id \
--resource-id $root_id \
--http-method GET \
--authorization-type NONE \
--api-key-required
Now we link the method to our Lambda using an AWS\_PROXY
integration:
aws apigateway put-integration \
--rest-api-id $rest_api_id \
--resource-id $root_id \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:822033172740:function:SecureLambda/invocations
And we give API Gateway permission to invoke our function:
aws lambda add-permission \
--function-name SecureLambda \
--statement-id AllowAPIGWInvoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn 'arn:aws:execute-api:us-east-2:822033172740:$rest_api_id/*/GET/'
Then we deploy the API to a stage named prod
:
aws apigateway create-deployment \
--rest-api-id $rest_api_id \
--stage-name prod
Adding the API Key
Now we'll create the actual API key and a usage plan to manage access:
api_key_id=$(aws apigateway create-api-key \
--name SecureDemoKey \
--enabled \
--query 'id' --output text)
usage_plan_id=$(aws apigateway create-usage-plan \
--name "SecureLambdaPlan" \
--api-stages apiId=$rest_api_id,stage=prod \
--query 'id' --output text)
Then associate the key with the usage plan:
aws apigateway create-usage-plan-key \
--usage-plan-id $usage_plan_id \
--key-id $api_key_id \
--key-type API_KEY
At this point, only users with this key can call your Lambda function via the API.
Invoking the Lambda Function
Let's test the whole setup.
First, we fetch the actual API key value so we can pass it in the request:
api_key_value=$(aws apigateway get-api-key \
--api-key $api_key_id \
--include-value \
--query 'value' --output text)
Then invoke the Lambda directly to confirm it works:
aws lambda invoke --function-name SecureLambda out.txt
If everything worked, you should see a status code 200
and the secret printed in the response body.
In a real environment, the environment variable will resolve to the actual secret — but here in the demo, it may just show the placeholder path.
Cleaning Up
Once you're done testing, it's important to clean up all resources to avoid extra charges:
aws lambda delete-function --function-name SecureLambda
aws apigateway delete-rest-api --rest-api-id $rest_api_id
aws ssm delete-parameter --name "/prod/secretToken"
aws apigateway delete-api-key --api-key $api_key_id
aws apigateway delete-usage-plan --usage-plan-id $usage_plan_id
aws iam delete-role-policy \
--role-name LambdaSecurityRole \
--policy-name LambdaSSMPolicy
aws iam delete-role --role-name LambdaSecurityRole
Wrapping Up
In this hands-on section, you learned how to:
- Store and encrypt secrets using SSM Parameter Store;
- Encrypt Lambda environment variables with KMS;
- Protect a Lambda endpoint with API Gateway and API keys.
This is a strong example of building real-world security directly into your AWS workloads.
1. What AWS service is used to store secrets like tokens or passwords in this lab?
2. Which CLI parameter makes the stored SSM parameter encrypted?
3. What is the purpose of the IAM trust policy when creating the Lambda role?
4. What does the {{resolve:ssm-secure:/prod/secretToken}}
syntax do in
Lambda environment variables?
5. Why is the Lambda environment variable considered secure in this setup?
6. What does setting --api-key-required to true in the API Gateway method do?
7. Which AWS service was used to protect the Lambda endpoint with throttling and
access control?
8. Which command allows API Gateway to invoke your Lambda function?
9. What does the usage plan in API Gateway control?
10. What's the last thing you should always do after a lab like this?
Tak for dine kommentarer!