Search code examples
amazon-web-servicesaws-lambdaaws-cloudformation

How to isolate environment variables from the shared lambda function template in cloudformation


This is my function.yaml which creates the lambda function here I have put the environment variables but it's shared all across the lambda function stack I make function.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: Event Lambda function

Parameters:
  # Existing parameters...
  ENVVAR1:
    Type: String
    Description: Environment variable 1
    Default: 'value1'
  ENVVAR2:
    Type: String
    Description: Environment variable 2
    Default: 'value2'
  ENVVAR3:
    Type: String
    Description: Environment variable 3
    Default: 'value3'
  ENVVAR4:
    Type: String
    Description: Environment variable 4
    Default: 'value4'

Resources:
  LambdaLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      CompatibleRuntimes:
        - !Ref LayerRuntimePython
      Content:
        S3Bucket: !Ref LayerS3BucketName
        S3Key: !Ref LayerS3Key
        S3ObjectVersion: !Ref LayerS3ObjectVersion
      Description: !Ref LayerDescription
      LayerName: !Ref LayerName
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      ### lambda function permissions

  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Handler: !Ref HandlerFunction
      Role: !GetAtt LambdaRole.Arn
      Code:
        S3Bucket: !Ref S3CodeBucket
        S3Key: !Ref S3CodeBucketKey
        S3ObjectVersion: !Ref CodeS3ObjectVersion
      Runtime: !Ref LayerRuntimePython
      Timeout: !Ref LambdaExecutionTimeout
      MemorySize: !Ref LambdaMemorySize
      Layers:
        - !Ref LambdaLayer
      Environment:
        Variables:
          ENVVAR1: !Ref ENVVAR1
          ENVAR2: !Ref ENVVAR2
          ENVVAR3: !Ref ENVVAR3
          ENVVAR4: !Ref ENVVAR4

Outputs:
  LambdaFunctionArn:
    Description: ARN of the Lambda function
    Value: !GetAtt LambdaFunction.Arn
    Export:
      Name: !Sub "${AWS::StackName}-LambdaFunctionArn"
  LambdaFunctionName:
    Description: Name of the Lambda function
    Value: !Ref LambdaFunctionName

And my dev.yaml looklike this

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS EC2 Backup Policy for Production Environment

Parameters:
  Function1CodeS3Version:
    Type: String
    Description: S3 object version of the OOOCalendarSync code.
    Default: '1'
  GoogleLayerS3:
    Type: String
    Description: S3 object version of the Google Layer.
    Default: '1'
  Function2CodeS3Version:
    Type: String
    Description: S3 object version of the Auto MSCK Lambda function code.
    Default: '1'
  

Resources:
  MyFunction1:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: common/lambda/function.yaml
      Parameters:
        LayerS3BucketName: layer-aws-s3-bucket
        LayerS3Key: google-layer.zip
        LayerName: "google-layer"
        LayerDescription: "Layer for Common Function"
        LayerRuntimePython: "python3.12"
        S3CodeBucket: my-s3-aws-lambda-code-bucket
        S3CodeBucketKey: function1.zip
        LambdaExecutionTimeout: 300
        LambdaMemorySize: 256
        HandlerFunction: "lambda_function.lambda_handler"
        LayerS3ObjectVersion: !Ref GoogleLayerS3
        CodeS3ObjectVersion: !Ref Function1CodeS3Version
        LambdaFunctionName: 'ooo_calendar_sync-dev'
        ENVVAR1: '{{resolve:secretsmanager:env/lambda:SecretString:MYVAR1}}'
        ENVVAR2: '{{resolve:secretsmanager:env/lambda:SecretString:MYVAR2}}'

  MyFunction2:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: common/lambda/function.yaml
      Parameters:
        LayerS3BucketName: layer-aws-s3-bucket
        LayerS3Key: google-layer.zip
        LayerName: "google-layer"
        LayerDescription: "Layer for Common Function"
        LayerRuntimePython: "python3.12"
        S3CodeBucket: my-s3-aws-lambda-code-bucket
        S3CodeBucketKey: function2.zip
        LambdaExecutionTimeout: 300
        LambdaMemorySize: 256
        HandlerFunction: "lambda_function.lambda_handler"
        LayerS3ObjectVersion: !Ref GoogleLayerS3
        CodeS3ObjectVersion: !Ref Function2CodeS3Version
        LambdaFunctionName: 'auto_msck-dev'
        ENVVAR3: '{{resolve:secretsmanager:env/lambda:SecretString:MYVAR3}}'
        ENVVAR4: '{{resolve:secretsmanager:env/lambda:SecretString:MYVAR4}}'

But the ENVVAR1 and ENVVAR2 is appearing in MyFunction2 and same for MyFunction1 for ENVVAR3 and ENVVAR4 I don't want to be shared across other function. I tried referencing following link but I am kinda lost over here. Dynamic environment variables for AWS Lambda using cloudformation template. Please help and please mind suggesting if there is any mistakes.


Solution

  • Fixed and done using the conditions and if conditions in function.yaml

    AWSTemplateFormatVersion: '2010-09-09'
    Description: Event Lambda function
    
    Parameters:
      ENVVAR1:
        Type: String
        Description: Environment variable 1
        Default: ""
    
      ENVVAR2:
        Type: String
        Description: Environment variable 2
        Default: ""
    
      ENVVAR3:
        Type: String
        Description: Environment variable 3
        Default: ""
    
      ENVVAR4:
        Type: String
        Description: Environment variable 4
        Default: ""
      
      S3CodeBucket:
        Type: String
        Description: S3 bucket name for the Lambda function code
      LambdaFunctionName:
        Type: String
        Description: Name of the Lambda function
      S3CodeBucketKey:
        Type: String
        Description: S3 key for the Lambda function code
      CodeS3ObjectVersion:
        Type: String
        Description: S3 object version of the Lambda function code
      LambdaExecutionTimeout:
        Type: Number
        Description: Timeout for the Lambda function
      LambdaMemorySize:
        Type: Number
        Description: Memory size for the Lambda function
      HandlerFunction:
        Type: String
        Description: Handler function for the Lambda function
      LayerS3BucketName:
        Type: String
        Description: S3 bucket name for the Lambda layer
      LayerS3Key:
        Type: String
        Description: S3 key for the Lambda layer
      LayerS3ObjectVersion:
        Type: String
        Description: S3 object version of the Lambda layer
      LayerName:
        Type: String
        Description: Name of the Lambda layer
      LayerDescription:
        Type: String
        Description: Description of the Lambda layer
      LayerRuntimePython:
        Type: String
        Description: Python runtime for the Lambda layer
    
      
    
    Conditions:
      ENVVALUE1: !Not [!Equals [!Ref ENVVAR1, ""]]
      ENVVALUE2: !Not [!Equals [!Ref ENVVAR2, ""]]
      ENVVALUE3: !Not [!Equals [!Ref ENVVAR3, ""]]
      ENVVALUE4: !Not [!Equals [!Ref ENVVAR4, ""]]
    
    Resources:
      LambdaLayer:
        Type: AWS::Lambda::LayerVersion
        Properties:
          CompatibleRuntimes:
            - !Ref LayerRuntimePython
          Content:
            S3Bucket: !Ref LayerS3BucketName
            S3Key: !Ref LayerS3Key
            S3ObjectVersion: !Ref LayerS3ObjectVersion
          Description: !Ref LayerDescription
          LayerName: !Ref LayerName
    
      LambdaRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Principal:
                  Service:
                    - lambda.amazonaws.com
                Action:
                  - sts:AssumeRole
          Path: "/"
          Policies:
            - PolicyName: AppendToLogsPolicy
              PolicyDocument:
                Version: '2012-10-17'
                Statement:
                  - Effect: Allow
                    Action:
                      - logs:CreateLogGroup
                      - logs:CreateLogStream
                      - logs:PutLogEvents
                    Resource: "*"
    
      LambdaFunction:
        Type: AWS::Lambda::Function
        Properties:
          FunctionName: !Ref LambdaFunctionName
          Handler: !Ref HandlerFunction
          Role: !GetAtt LambdaRole.Arn
          Code:
            S3Bucket: !Ref S3CodeBucket
            S3Key: !Ref S3CodeBucketKey
            S3ObjectVersion: !Ref CodeS3ObjectVersion
          Runtime: !Ref LayerRuntimePython
          Timeout: !Ref LambdaExecutionTimeout
          MemorySize: !Ref LambdaMemorySize
          Layers:
            - !Ref LambdaLayer
          Environment:
            Variables:
              ENVVAR1: !If [ENVVALUE1, !Ref ENVVAR1, !Ref "AWS::NoValue"]
              ENVVAR2: !If [ENVVALUE2, !Ref ENVVAR2, !Ref "AWS::NoValue"]
              ENVVAR3: !If [ENVVALUE3, !Ref ENVVAR3, !Ref "AWS::NoValue"]
              ENVVAR4: !If [ENVVALUE4, !Ref ENVVAR4, !Ref "AWS::NoValue"]
    
    Outputs:
      LambdaFunctionArn:
        Description: ARN of the Lambda function
        Value: !GetAtt LambdaFunction.Arn
        Export:
          Name: !Sub "${AWS::StackName}-LambdaFunctionArn"
      LambdaFunctionName:
        Description: Name of the Lambda function
        Value: !Ref LambdaFunctionName