This product is not supported for your selected Datadog site. ().

Metadata

Id: 8df8e857-bd59-44fa-9f4c-d77594b95b46

Cloud Provider: AWS

Platform: CloudFormation

Severity: Low

Category: Insecure Configurations

Learn More

Description

Lambda functions must be tagged so resources can be reliably identified, assigned ownership, and included in incident response, access reviews, and automated security workflows. The Tags property on AWS::Lambda::Function resources must be defined and contain tag objects (Key and Value pairs). Resources missing the Tags property will be flagged. Tags should be provided as an array of objects with Key and Value fields.

Secure configuration example:

MyFunction:
  Type: AWS::Lambda::Function
  Properties:
    FunctionName: my-function
    Runtime: python3.9
    Handler: index.handler
    Role: arn:aws:iam::123456789012:role/lambda-exec
    Code:
      S3Bucket: my-bucket
      S3Key: my-function.zip
    Tags:
      - Key: Environment
        Value: production
      - Key: Owner
        Value: team-security

Compliant Code Examples

AWSTemplateFormatVersion: '2010-09-09'
Description: VPC function.
Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: arn:aws:iam::123456789012:role/lambda-role
      Code:
        S3Bucket: my-bucket
        S3Key: function.zip
      Runtime: nodejs12.x
      Timeout: 5
      TracingConfig:
        Mode: Active
      VpcConfig:
        SecurityGroupIds:
          - sg-085912345678492fb
        SubnetIds:
          - subnet-071f712345678e7c8
          - subnet-07fd123456788a036
      Tags:
        - Key: Description
          Value: VPC Function
        - Key: Type
          Value: AWS Lambda Function
{
  "Description": "VPC function.",
  "Resources": {
    "Function": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Runtime": "nodejs12.x",
        "Timeout": 5,
        "TracingConfig": {
          "Mode": "Active"
        },
        "VpcConfig": {
          "SecurityGroupIds": [
            "sg-085912345678492fb"
          ],
          "SubnetIds": [
            "subnet-071f712345678e7c8",
            "subnet-07fd123456788a036"
          ]
        },
        "Tags": [
          {
            "Value": "VPC Function",
            "Key": "Description"
          },
          {
            "Key": "Type",
            "Value": "AWS Lambda Function"
          }
        ],
        "Handler": "index.handler",
        "Role": "arn:aws:iam::123456789012:role/lambda-role",
        "Code": {
          "S3Bucket": "my-bucket",
          "S3Key": "function.zip"
        }
      }
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09"
}

Non-Compliant Code Examples

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "ExistingVPC": {
      "Type": "AWS::EC2::VPC::Id",
      "Description": "The VPC ID that includes the security groups in the ExistingSecurityGroups parameter."
    },
    "InstanceType": {
      "Type": "String",
      "Default": "t2.micro",
      "AllowedValues": [
        "t2.micro",
        "m1.small"
      ]
    },
    "ExistingSecurityGroups": {
      "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e"
    }
  },
  "Mappings": {
    "AWSInstanceType2Arch": {
      "t2.micro": {
        "Arch": "HVM64"
      },
      "m1.small": {
        "Arch": "HVM64"
      }
    },
    "AWSRegionArch2AMI": {
      "us-east-1": {
        "HVM64": "ami-0ff8a91507f77f867",
        "HVMG2": "ami-0a584ac55a7631c0c"
      }
    }
  },
  "Resources": {
    "SecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Allow HTTP traffic to the host",
        "VpcId": {
          "Ref": "ExistingVPC"
        },
        "SecurityGroupIngress": [
          {
            "FromPort": "80",
            "ToPort": "80",
            "CidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          }
        ],
        "SecurityGroupEgress": [
          {
            "IpProtocol": "tcp",
            "FromPort": "80",
            "ToPort": "80",
            "CidrIp": "0.0.0.0/0"
          }
        ]
      }
    },
    "AllSecurityGroups": {
      "Type": "Custom::Split",
      "Properties": {
        "ServiceToken": "AppendItemToListFunction.Arn",
        "List": {
          "Ref": "ExistingSecurityGroups"
        },
        "AppendedItem": {
          "Ref": "SecurityGroup"
        }
      }
    },
    "AppendItemToListFunction": {
      "Properties": {
        "Handler": "index.handler",
        "Role": "LambdaExecutionRole.Arn",
        "Code": {
          "ZipFile": "var response = require('cfn-response');\nexports.handler = function(event, context) {\n   var responseData = {Value: event.ResourceProperties.List};\n   responseData.Value.push(event.ResourceProperties.AppendedItem);\n   response.send(event, context, response.SUCCESS, responseData);\n};\n"
        },
        "Runtime": "nodejs8.10"
      },
      "Type": "AWS::Lambda::Function"
    },
    "MyEC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId": {
          "Fn::FindInMap": [
            "AWSRegionArch2AMI",
            {
              "Ref": "AWS::Region"
            },
            {
              "Fn::FindInMap": [
                "AWSInstanceType2Arch",
                {
                  "Ref": "InstanceType"
                },
                "Arch"
              ]
            }
          ]
        },
        "SecurityGroupIds": "AllSecurityGroups.Value",
        "InstanceType": {
          "Ref": "InstanceType"
        }
      }
    },
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "Policies": [
          {
            "PolicyName": "root",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:*"
                  ],
                  "Resource": "arn:aws:logs:*:*:*"
                }
              ]
            }
          }
        ],
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": [
                "sts:AssumeRole"
              ],
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              }
            }
          ],
          "Version": "2012-10-17"
        },
        "Path": "/"
      }
    }
  },
  "Outputs": {
    "AllSecurityGroups": {
      "Description": "Security Groups that are associated with the EC2 instance",
      "Value": {
        "Fn::Join": [
          ", ",
          {
            "Fn::GetAtt": [
              "AllSecurityGroups",
              "Value"
            ]
          }
        ]
      }
    }
  }
}
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  ExistingSecurityGroups:
    Type: List<AWS::EC2::SecurityGroup::Id>
  ExistingVPC:
    Type: AWS::EC2::VPC::Id
    Description: The VPC ID that includes the security groups in the ExistingSecurityGroups
      parameter.
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
    - t2.micro
    - m1.small
Mappings:
  AWSInstanceType2Arch:
    t2.micro:
      Arch: HVM64
    m1.small:
      Arch: HVM64
  AWSRegionArch2AMI:
    us-east-1:
      HVM64: ami-0ff8a91507f77f867
      HVMG2: ami-0a584ac55a7631c0c
Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP traffic to the host
      VpcId:
        Ref: ExistingVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
  AllSecurityGroups:
    Type: Custom::Split
    Properties:
      ServiceToken: !GetAtt AppendItemToListFunction.Arn
      List:
        Ref: ExistingSecurityGroups
      AppendedItem:
        Ref: SecurityGroup
  AppendItemToListFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var response = require('cfn-response');
          exports.handler = function(event, context) {
             var responseData = {Value: event.ResourceProperties.List};
             responseData.Value.push(event.ResourceProperties.AppendedItem);
             response.send(event, context, response.SUCCESS, responseData);
          };
      Runtime: nodejs8.10
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId:
        Fn::FindInMap:
        - AWSRegionArch2AMI
        - Ref: AWS::Region
        - Fn::FindInMap:
          - AWSInstanceType2Arch
          - Ref: InstanceType
          - Arch
      SecurityGroupIds: !GetAtt AllSecurityGroups.Value
      InstanceType:
        Ref: InstanceType
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - logs:*
            Resource: arn:aws:logs:*:*:*
Outputs:
  AllSecurityGroups:
    Description: Security Groups that are associated with the EC2 instance
    Value:
      Fn::Join:
      - ", "
      - Fn::GetAtt:
        - AllSecurityGroups
        - Value