I have 2 cloudformation templates - one that creates a kms key and the other template uses the kms key to encrypt a env variable used in the lambda function.
I wanted to know if there is a way to run the kms encrypt command from within the cloudformation as a prior step and then use the encrypted text for the environment variable while creating the lambda function.
aws kms encrypt --key-id <key-id-output-from-stack1> --plaintext fileb://file.txt --query CiphertextBlob --output text > fileoutput.txt
This command outputs the encrypted text and I would need to use this text in the lambda function for one of the environment variables as below.
GTMLambdaFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://test.google.com/lambdas/09yu567943879
Handler: src/lambda.handler
FunctionName: !Ref GTMLambdaFunctionName
Runtime: nodejs10.x
MemorySize: !Ref GTMLambdaMemorySize
Timeout: !Ref GTMLambdaTimeout
AutoPublishAlias: prod
Role: !GetAtt GTMLambdaRole.Arn
KmsKeyArn: !ImportValue GTMKMSKeyArn
Environment:
Variables:
url: >-
**{insert encrypted text}**
tbl_prefix: gtm-
If this is not possible is there any recommendations on how to achieve this? Thanks in advance.
You can use a custom resource for this. It will execute a Lambda function that will encrypt and return the value. That value can then be used in the environment variable.
Something like the following. Make sure to have a resource/parameter/output called KeyId
with the KMS key id.
Resources:
EncryptEnvRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: DescribeImages
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action: kms:Encrypt
Effect: Allow
Resource: "*"
EncryptEnvFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.6
Handler: index.handler
Role: !Sub ${EncryptEnvRole.Arn}
Timeout: 60
Code:
ZipFile:
Fn::Sub: |
import base64
import boto3
import cfnresponse
import traceback
def handler(event, context):
try:
t = event['ResourceProperties']['Value']
k = event['ResourceProperties']['KeyId']
v = base64.b64encode(boto3.client('kms').encrypt(KeyId=k, Plaintext=t.encode('utf-8'))['CiphertextBlob']).decode('utf-8')
cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, v)
except:
traceback.print_last()
cfnresponse.send(event, context, cfnresponse.FAIL, {}, 'ok')
EncryptedEnv:
Type: Custom::EncryptEnv
Properties:
ServiceToken: !Sub ${EncryptEnvFunction.Arn}
Value: "hello world"
KeyId: !ImportValue KeyId
GTMLambdaFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://test.google.com/lambdas/09yu567943879
Handler: src/lambda.handler
FunctionName: !Ref GTMLambdaFunctionName
Runtime: nodejs10.x
MemorySize: !Ref GTMLambdaMemorySize
Timeout: !Ref GTMLambdaTimeout
AutoPublishAlias: prod
Role: !GetAtt GTMLambdaRole.Arn
KmsKeyArn: !ImportValue GTMKMSKeyArn
Environment:
Variables:
url: !Ref EncryptedEnv
tbl_prefix: gtm-