Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Lambda Cross Account Access

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: Lambda-002

Ensure that all your Amazon Lambda functions are configured to allow access only to trusted AWS accounts in order to protect against unauthorized cross-account access. Before running this rule by the Trend Cloud One™ – Conformity engine, the list with the trusted AWS account identifiers must be configured in the rule settings, on your Conformity account console. Conformity tracks Amazon Lambda permission policies (also known as resource-based policies) and alerts if a function can be invoked from a foreign AWS cloud account (unless the account has been explicitly specified within the rule settings as a trusted account).

This rule can help you with the following compliance standards:

  • PCI
  • APRA
  • MAS
  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

Allowing unknown (unauthorized) AWS accounts to invoke your Amazon Lambda functions can lead to data exposure, data loss, and unexpected charges on your AWS monthly bill. To prevent any unauthorized invocation requests for your Lambda functions, restrict access only to trusted entities by implementing the appropriate permissions policies.


Audit

To determine if there are any Amazon Lambda functions that allow unknown cross-account access in your AWS account, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

03 In the left navigation panel, under AWS Lambda, choose Functions.

04 Click on the name (link) of the function that you want to examine.

05 Select the Configuration tab and choose Permissions from the left menu.

06 In the Resource-based policy section, choose View policy document to access the resource-based policy attached to the selected function.

07 Within the Resource-based policy document box, identify the "Principal" element defined for each policy statement and check the element value (ARN).

08 Sign in to your Trend Cloud One™ – Conformity account, access the Unknown Lambda Cross-Account Access conformity rule settings, and compare the ARN(s) identified at the previous step against each AWS account ARN defined in the rule configuration section. If one or more ARNs are not included in the list of trusted AWS identities defined in the conformity rule settings, the cross-account access configuration defined for the selected Amazon Lambda function is not secure.

09 Repeat steps no. 4 – 8 for each Lambda function available within the current AWS region.

10 Change the AWS cloud region from the console navigation bar and repeat the Audit process for other regions.

Using AWS CLI

01 Run list-functions command (OSX/Linux/UNIX) to list the names of all the Amazon Lambda functions available in the selected AWS region:

aws lambda list-functions
  --region us-east-1
  --output table
  --query 'Functions[*].FunctionName'

02 The command output should return a table with the requested function name(s):

----------------------
|   ListFunctions    |
+--------------------+
|   cc-sqs-poller    |
|   cc-s3-logging    |
|   s3-get-object    |
+--------------------+

03 Run get-policy command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to examine as the identifier parameter, to describe the resource-based policy attached to the selected Lambda function:

aws lambda get-policy
  --region us-east-1
  --function-name cc-sqs-poller
  --output text
  --query 'Policy'

04 The command output should return the requested resource-based policy:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "CrossAccountAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123412341234:function:cc-sqs-poller"
    }
  ]
}

Identify the "Principal" element defined for each policy statement and check the element value (ARN – highlighted).

05 Sign in to your Trend Cloud One™ – Conformity account, access the Unknown Lambda Cross-Account Access conformity rule settings, and compare the ARN(s) identified at the previous step against each AWS account ARN defined in the rule configuration section. If one or more ARNs are not included in the list of trusted AWS identities defined in the conformity rule settings, the cross-account access configuration defined for the selected Amazon Lambda function is not secure.

06 Repeat steps no. 3 – 5 for each Lambda function available in the selected AWS region.

07 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 6 to perform the Audit process for other regions.

Remediation / Resolution

To update the resource-based policies associated with your Amazon Lambda functions in order to allow function invocation from trusted AWS accounts only, perform the following actions:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Description": "Allow Trusted Cross-Account Access Only",
  "Resources":{
    "FunctionExecutionRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
          "RoleName": "LambdaExecutionRole",
          "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
              "Effect": "Allow",
              "Principal": {
                "Service": [ "lambda.amazonaws.com" ]
              },
              "Action": [ "sts:AssumeRole" ]
            }]
          },
          "Path": "/",
          "Policies": [{
            "PolicyName": "AWSLambdaBasicExecutionRole",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [{
                "Effect": "Allow",
                "Action": [
                  "logs:CreateLogGroup",
                  "logs:CreateLogStream",
                  "logs:PutLogEvents"
                ],
                "Resource": "*"
              }]
            }
          }]
       }
    },
    "ConsumerFunction": {
        "Type": "AWS::Lambda::Function",
        "Properties": {
            "FunctionName": "cc-sqs-poller",
            "Handler": "lambda_function.lambda_handler",
            "Role": {
                "Fn::GetAtt": [
                    "FunctionExecutionRole",
                    "Arn"
                ]
            },
            "Code": {
                "S3Bucket": "cc-lambda-functions",
                "S3Key": "poller.zip"
            },
            "Runtime": "python3.9",
            "MemorySize" : 1024,
            "Timeout": 45
        }
      }
    },
    "CrossAccountAccessPermission": {
        "Type": "AWS::Lambda::Permission",
        "Properties": {
          "FunctionName": {
              "Fn::GetAtt": [
                  "ConsumerFunction",
                  "Arn"
              ]
          },
          "Action": "lambda:InvokeFunction",
          "Principal": "111122223333"
      }
    }
  }
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
Description: Allow Trusted Cross-Account Access Only
Resources:
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: LambdaExecutionRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: AWSLambdaBasicExecutionRole
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: '*'
  ConsumerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: cc-sqs-poller
      Handler: lambda_function.lambda_handler
      Role: !GetAtt 'FunctionExecutionRole.Arn'
      Code:
        S3Bucket: cc-lambda-functions
        S3Key: poller.zip
      Runtime: python3.9
      MemorySize: 1024
      Timeout: 45
CrossAccountAccessPermission:
  Type: AWS::Lambda::Permission
  Properties:
    FunctionName: !GetAtt 'ConsumerFunction.Arn'
    Action: lambda:InvokeFunction
    Principal: '111122223333'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

provider "aws" {
  profile = "default"
  region  = "us-east-1"
}

resource "aws_iam_role" "function-execution-role" {
  name = "LambdaExecutionRole"
  path = "/"
  managed_policy_arns = [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" ]

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_lambda_function" "lambda-function" {
  function_name    = "cc-sqs-poller"
  s3_bucket        = "cc-lambda-functions"
  s3_key           = "poller.zip"
  role             = aws_iam_role.function-execution-role.arn
  handler          = "lambda_function.lambda_handler"
  runtime          = "python3.9"
  memory_size      = 1024
  timeout          = 45
}

# Allow Trusted Cross-Account Access Only
resource "aws_lambda_permission" "allow-cross-account-access" {
  statement_id  = "TrustedCrossAccountAccess"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.lambda-function.function_name
  principal     = "111122223333"
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

03 In the left navigation panel, under AWS Lambda, choose Functions.

04 Click on the name of the function that you want to reconfigure.

05 Select the Configuration tab and choose Permissions from the left menu.

06 In the Resource-based policy section, under Policy statements, select the policy statement that allows unknown cross-account access and choose Edit.

07 On the Edit permissions page, replace the ARN of the unauthorized principal, available in the Principal box, with the ARN of the trusted principal (AWS account) defined in the conformity rule settings. Choose Save to apply the changes.

08 Repeat steps no. 4 – 7 for each Amazon Lambda function that you want to reconfigure, available within the current AWS region.

09 Change the AWS cloud region from the console navigation bar and repeat the Remediation process for other regions.

Using AWS CLI

01 Run remove-permission command (OSX/Linux/UNIX) to remove the permission statement that allows unknown cross-account access via the resource-based policy associated with the selected function, using the policy statement ID as the identifier parameter. The following command request example removes an individual policy statement identified by the ID "CrossAccountAccess" for an Amazon Lambda function named "cc-sqs-poller" (the command does not produce an output):

aws lambda remove-permission
  --region us-east-1
  --function-name cc-sqs-poller
  --statement-id CrossAccountAccess

02 Run add-permission command (OSX/Linux/UNIX) to add a new policy statement that grants permissions to another, trusted AWS account, to invoke the selected function (i.e. authorized cross-account access). The ID of the trusted AWS account is provided as the value of the --principal command parameter:

aws lambda add-permission
  --region us-east-1
  --function-name cc-sqs-poller
  --statement-id TrustedCrossAccountAccess
  --principal 111122223333
  --action lambda:InvokeFunction

03 The command output should return the newly created policy statement:

{
  "Statement": "{\"Sid\":\"TrustedCrossAccountAccess\",\"Resource\":\"arn:aws:lambda:us-east-1:123412341234:function:cc-sqs-poller\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::111122223333:root\"},\"Action\":[\"lambda:InvokeFunction\"]}"
}

04 Repeat steps no. 1 – 3 for each Lambda function that you want to reconfigure, available in the selected AWS region.

05 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 4 to perform the Remediation process for other regions.

References

Publication date Jun 12, 2017