Lambda Functions Without Unique IAM Roles

  • Query id: ae03f542-1423-402f-9cef-c834e7ee9583
  • Query name: Lambda Functions Without Unique IAM Roles
  • Platform: CloudFormation
  • Severity: Medium
  • Category: Insecure Configurations
  • URL: Github

Description

AWS Lambda Functions should not share IAM roles to ensure they will have the minimum privileges needed to perform the required tasks
Documentation

Code samples

Code samples with security vulnerabilities

Positive test num. 1 - yaml file
AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda function with cfn-response.
Resources:
    Primer01:
        Type: AWS::Lambda::Function
        Properties:
          Runtime: nodejs12.x
          Role: arn:aws:iam::123456789012:role/lambda-role
          Handler: index.handler
          Code:
              ZipFile: |
                var aws = require('aws-sdk')
                var response = require('cfn-response')
                exports.handler = function(event, context) {
                    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event))
                    // For Delete requests, immediately send a SUCCESS response.
                    if (event.RequestType == "Delete") {
                        response.send(event, context, "SUCCESS")
                        return
                    }
                    var responseStatus = "FAILED"
                    var responseData = {}
                    var functionName = event.ResourceProperties.FunctionName
                    var lambda = new aws.Lambda()
                    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                        if (err) {
                            responseData = {Error: "Invoke call failed"}
                            console.log(responseData.Error + ":\n", err)
                        }
                        else responseStatus = "SUCCESS"
                        response.send(event, context, responseStatus, responseData)
                    })
                }
          Description: Invoke a function during stack creation.
          TracingConfig:
              Mode: Active
    Primer02:
        Type: AWS::Lambda::Function
        Properties:
          Runtime: nodejs12.x
          Role: arn:aws:iam::123456789012:role/lambda-role
          Handler: index.handler
          Code:
              ZipFile: |
                var aws = require('aws-sdk')
                var response = require('cfn-response')
                exports.handler = function(event, context) {
                    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event))
                    // For Delete requests, immediately send a SUCCESS response.
                    if (event.RequestType == "Delete") {
                        response.send(event, context, "SUCCESS")
                        return
                    }
                    var responseStatus = "FAILED"
                    var responseData = {}
                    var functionName = event.ResourceProperties.FunctionName
                    var lambda = new aws.Lambda()
                    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                        if (err) {
                            responseData = {Error: "Invoke call failed"}
                            console.log(responseData.Error + ":\n", err)
                        }
                        else responseStatus = "SUCCESS"
                        response.send(event, context, responseStatus, responseData)
                    })
                }
          Description: Invoke a function during stack creation.
          TracingConfig:
              Mode: Active
Positive test num. 2 - json file
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Lambda function with cfn-response.",
  "Resources": {
    "Primer01": {
      "Properties": {
        "Role": "arn:aws:iam::123456789012:role/lambda-role",
        "Handler": "index.handler",
        "Code": {
          "ZipFile": "var aws = require('aws-sdk')\nvar response = require('cfn-response')\nexports.handler = function(event, context) {\n    console.log(\"REQUEST RECEIVED:\\n\" + JSON.stringify(event))\n    // For Delete requests, immediately send a SUCCESS response.\n    if (event.RequestType == \"Delete\") {\n        response.send(event, context, \"SUCCESS\")\n        return\n    }\n    var responseStatus = \"FAILED\"\n    var responseData = {}\n    var functionName = event.ResourceProperties.FunctionName\n    var lambda = new aws.Lambda()\n    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {\n        if (err) {\n            responseData = {Error: \"Invoke call failed\"}\n            console.log(responseData.Error + \":\\n\", err)\n        }\n        else responseStatus = \"SUCCESS\"\n        response.send(event, context, responseStatus, responseData)\n    })\n}\n"
        },
        "Description": "Invoke a function during stack creation.",
        "TracingConfig": {
          "Mode": "Active"
        },
        "Runtime": "nodejs12.x"
      },
      "Type": "AWS::Lambda::Function"
    },
    "Primer02": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Runtime": "nodejs12.x",
        "Role": "arn:aws:iam::123456789012:role/lambda-role",
        "Handler": "index.handler",
        "Code": {
          "ZipFile": "var aws = require('aws-sdk')\nvar response = require('cfn-response')\nexports.handler = function(event, context) {\n    console.log(\"REQUEST RECEIVED:\\n\" + JSON.stringify(event))\n    // For Delete requests, immediately send a SUCCESS response.\n    if (event.RequestType == \"Delete\") {\n        response.send(event, context, \"SUCCESS\")\n        return\n    }\n    var responseStatus = \"FAILED\"\n    var responseData = {}\n    var functionName = event.ResourceProperties.FunctionName\n    var lambda = new aws.Lambda()\n    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {\n        if (err) {\n            responseData = {Error: \"Invoke call failed\"}\n            console.log(responseData.Error + \":\\n\", err)\n        }\n        else responseStatus = \"SUCCESS\"\n        response.send(event, context, responseStatus, responseData)\n    })\n}\n"
        },
        "Description": "Invoke a function during stack creation.",
        "TracingConfig": {
          "Mode": "Active"
        }
      }
    }
  }
}

Code samples without security vulnerabilities

Negative test num. 1 - yaml file
AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda function with cfn-response.
Resources:
    Primer01:
        Type: AWS::Lambda::Function
        Properties:
          Runtime: nodejs12.x
          Role: arn:aws:iam::123456789012:role/lambda-role
          Handler: index.handler
          Code:
              ZipFile: |
                var aws = require('aws-sdk')
                var response = require('cfn-response')
                exports.handler = function(event, context) {
                    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event))
                    // For Delete requests, immediately send a SUCCESS response.
                    if (event.RequestType == "Delete") {
                        response.send(event, context, "SUCCESS")
                        return
                    }
                    var responseStatus = "FAILED"
                    var responseData = {}
                    var functionName = event.ResourceProperties.FunctionName
                    var lambda = new aws.Lambda()
                    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                        if (err) {
                            responseData = {Error: "Invoke call failed"}
                            console.log(responseData.Error + ":\n", err)
                        }
                        else responseStatus = "SUCCESS"
                        response.send(event, context, responseStatus, responseData)
                    })
                }
          Description: Invoke a function during stack creation.
          TracingConfig:
              Mode: Active
    Primer02:
        Type: AWS::Lambda::Function
        Properties:
          Runtime: nodejs12.x
          Role: arn:aws:iam::123456789012:role/lambda-ex
          Handler: index.handler
          Code:
              ZipFile: |
                var aws = require('aws-sdk')
                var response = require('cfn-response')
                exports.handler = function(event, context) {
                    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event))
                    // For Delete requests, immediately send a SUCCESS response.
                    if (event.RequestType == "Delete") {
                        response.send(event, context, "SUCCESS")
                        return
                    }
                    var responseStatus = "FAILED"
                    var responseData = {}
                    var functionName = event.ResourceProperties.FunctionName
                    var lambda = new aws.Lambda()
                    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                        if (err) {
                            responseData = {Error: "Invoke call failed"}
                            console.log(responseData.Error + ":\n", err)
                        }
                        else responseStatus = "SUCCESS"
                        response.send(event, context, responseStatus, responseData)
                    })
                }
          Description: Invoke a function during stack creation.
          TracingConfig:
              Mode: Active
Negative test num. 2 - json file
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Lambda function with cfn-response.",
  "Resources": {
    "Primer01": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Runtime": "nodejs12.x",
        "Role": "arn:aws:iam::123456789012:role/lambda-role",
        "Handler": "index.handler",
        "Code": {
          "ZipFile": "var aws = require('aws-sdk')\nvar response = require('cfn-response')\nexports.handler = function(event, context) {\n    console.log(\"REQUEST RECEIVED:\\n\" + JSON.stringify(event))\n    // For Delete requests, immediately send a SUCCESS response.\n    if (event.RequestType == \"Delete\") {\n        response.send(event, context, \"SUCCESS\")\n        return\n    }\n    var responseStatus = \"FAILED\"\n    var responseData = {}\n    var functionName = event.ResourceProperties.FunctionName\n    var lambda = new aws.Lambda()\n    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {\n        if (err) {\n            responseData = {Error: \"Invoke call failed\"}\n            console.log(responseData.Error + \":\\n\", err)\n        }\n        else responseStatus = \"SUCCESS\"\n        response.send(event, context, responseStatus, responseData)\n    })\n}\n"
        },
        "Description": "Invoke a function during stack creation.",
        "TracingConfig": {
          "Mode": "Active"
        }
      }
    },
    "Primer02": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "TracingConfig": {
          "Mode": "Active"
        },
        "Runtime": "nodejs12.x",
        "Role": "arn:aws:iam::123456789012:role/lambda-ex",
        "Handler": "index.handler",
        "Code": {
          "ZipFile": "var aws = require('aws-sdk')\nvar response = require('cfn-response')\nexports.handler = function(event, context) {\n    console.log(\"REQUEST RECEIVED:\\n\" + JSON.stringify(event))\n    // For Delete requests, immediately send a SUCCESS response.\n    if (event.RequestType == \"Delete\") {\n        response.send(event, context, \"SUCCESS\")\n        return\n    }\n    var responseStatus = \"FAILED\"\n    var responseData = {}\n    var functionName = event.ResourceProperties.FunctionName\n    var lambda = new aws.Lambda()\n    lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {\n        if (err) {\n            responseData = {Error: \"Invoke call failed\"}\n            console.log(responseData.Error + \":\\n\", err)\n        }\n        else responseStatus = \"SUCCESS\"\n        response.send(event, context, responseStatus, responseData)\n    })\n}\n"
        },
        "Description": "Invoke a function during stack creation."
      }
    }
  }
}