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

Enable Code Signing

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

Risk Level: Medium (should be achieved)

Ensure that all your Amazon Lambda functions are configured to use the Code Signing feature in order to restrict the deployment of unverified code. With Code Signing, you can ensure that the function code has been signed by an approved (trusted) source, has not been altered since signing, and that the code signature has not expired or been revoked.

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

Security

Code Signing for Lambda provides a first-class mechanism to ensure that only verified code from trusted publishers is deployed within Amazon Lambda. With Code Signing for Lambda, you can configure your Amazon Lambda functions to only accept signed code on deployment. When your developers deploy signed code to such functions, Amazon Lambda checks the signatures to ensure that the code is not altered. In addition, the cloud service ensures that the code is signed by trusted developers before accepting the deployment. The Code Signing feature uses AWS Signer, a fully managed code signing service from AWS cloud. AWS Signer provides a mechanism to ensure that only signed and trusted Amazon Lambda functions are deployed by an organization. The Signer service defines a trusted publisher in a signing profile. Authorized developers use this profile to generate certified code packages, and Amazon Lambda verifies signatures and package integrity when the code is deployed.


Audit

To determine if your Amazon Lambda functions are configured to use Code Signing, perform the following operations:

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 Code signing from the left menu.

06 In the Code signing configuration section, check for any code signing configurations created for the selected function. A code signing configuration defines a list of allowed signing profiles and defines the code-signing validation policy (i.e. action to be taken if the function deployment validation checks fail). If there are no code signing configurations available in the Code signing configuration section, the Code Signing feature is not enabled for the selected Amazon Lambda function.

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

08 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 name of each Amazon Lambda function available in the selected AWS cloud 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-function-code-signing-config command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to examine as the identifier parameter and custom query filters to describe the Amazon Resource Name (ARN) of each code signing configuration created for the selected function:

aws lambda get-function-code-signing-config
  --region us-east-1
  --function-name cc-sqs-poller
  --query 'CodeSigningConfigArn'

04 The command output should return an array with the requested ARN(s):

null

If the get-function-code-signing-config command output returns null, as shown in the example above, there are no code signing configurations created for the selected resource, therefore the Code Signing feature is not enabled for the selected Amazon Lambda function.

05 Repeat step no. 3 and 4 for each Lambda function available in the selected AWS region.

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

Remediation / Resolution

To enable and configure the Code Signing feature for your Amazon Lambda functions, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"LambdaFunctionExecutionRole": {
			"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",
										"ec2:DescribeNetworkInterfaces",
										"ec2:CreateNetworkInterface",
										"ec2:DeleteNetworkInterface",
										"ec2:DescribeInstances",
										"ec2:AttachNetworkInterface"
									],
									"Resource": "*"
								}
							]
						}
					}
				]
			}
		},
		"AWSSignerProfile": {
			"Type": "AWS::Signer::SigningProfile",
			"Properties": {
				"PlatformId": "AWSLambda-SHA384-ECDSA",
				"SignatureValidityPeriod": {
					"Type": "YEARS",
					"Value": 5
				}
			}
		},
		"LambdaCodeSigningConfig": {
			"Type": "AWS::Lambda::CodeSigningConfig",
			"Properties": {
				"AllowedPublishers": {
					"SigningProfileVersionArns": [
						{
							"Fn::GetAtt": [
								"AWSSignerProfile",
								"Arn"
							]
						}
					]
				},
				"CodeSigningPolicies": {
					"UntrustedArtifactOnDeployment": "Enforce"
				}
			}
		},
		"LambdaFunction": {
			"Type": "AWS::Lambda::Function",
			"Properties": {
				"FunctionName": "cc-app-worker-function",
				"Handler": "lambda_function.lambda_handler",
				"Role": {
					"Fn::GetAtt": [
						"LambdaFunctionExecutionRole",
						"Arn"
					]
				},
				"Code": {
					"S3Bucket": "cc-lambda-functions",
					"S3Key": "worker.zip"
				},
				"Runtime": "python3.9",
				"MemorySize": 1024,
				"Timeout": 45,
				"VpcConfig": {
					"SecurityGroupIds": [
						"sg-0abcd1234abcd1234"
					],
					"SubnetIds": [
						"subnet-abcd1234",
						"subnet-1234abcd"
					]
				},
				"CodeSigningConfigArn": {
					"Ref": "LambdaCodeSigningConfig"
				}
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	LambdaFunctionExecutionRole:
		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
					- ec2:DescribeNetworkInterfaces
					- ec2:CreateNetworkInterface
					- ec2:DeleteNetworkInterface
					- ec2:DescribeInstances
					- ec2:AttachNetworkInterface
					Resource: '*'
	AWSSignerProfile:
		Type: AWS::Signer::SigningProfile
		Properties:
		PlatformId: AWSLambda-SHA384-ECDSA
		SignatureValidityPeriod:
			Type: YEARS
			Value: 5
	LambdaCodeSigningConfig:
		Type: AWS::Lambda::CodeSigningConfig
		Properties:
		AllowedPublishers:
			SigningProfileVersionArns:
			- !GetAtt 'AWSSignerProfile.Arn'
		CodeSigningPolicies:
			UntrustedArtifactOnDeployment: Enforce
	LambdaFunction:
		Type: AWS::Lambda::Function
		Properties:
		FunctionName: cc-app-worker-function
		Handler: lambda_function.lambda_handler
		Role: !GetAtt 'LambdaFunctionExecutionRole.Arn'
		Code:
			S3Bucket: cc-lambda-functions
			S3Key: worker.zip
		Runtime: python3.9
		MemorySize: 1024
		Timeout: 45
		VpcConfig:
			SecurityGroupIds:
			- sg-0abcd1234abcd1234
			SubnetIds:
			- subnet-abcd1234
			- subnet-1234abcd
		CodeSigningConfigArn: !Ref 'LambdaCodeSigningConfig'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

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

	required_version = ">= 0.14.9"
}

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

resource "aws_iam_role" "lambda-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_signer_signing_profile" "aws-signing-profile" {
	name_prefix = "cc-lambda-signing-profile"
	platform_id = "AWSLambda-SHA384-ECDSA"
	signature_validity_period {
		type  = "YEARS"
		value = 5
	}
}

resource "aws_lambda_code_signing_config" "lambda-code-signing-config" {
	allowed_publishers {
		signing_profile_version_arns = [aws_signer_signing_profile.aws-signing-profile.version_arn]
	}
	policies {
		untrusted_artifact_on_deployment = "Enforce"
	}
}

resource "aws_lambda_function" "lambda-function" {
	function_name    = "cc-app-worker-function"
	role             = aws_iam_role.lambda-execution-role.arn
	handler          = "lambda_function.lambda_handler"
	runtime          = "python3.9"
	memory_size      = 1024
	timeout          = 45   
	vpc_config {
		subnet_ids         = [ "subnet-01234abcd1234abcd", "subnet-0abcd1234abcd1234" ]
		security_group_ids = [ "sg-0abcd1234abcd1234" ]
	}
	code_signing_config_arn = aws_lambda_code_signing_config.lambda-code-signing-config.arn
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Create a Signing Profile using AWS Signer. A Signing Profile is a trusted publisher and is analogous to the use of a digital signing certificate to generate signatures for your application code. To get started, navigate to AWS Signer console at https://console.aws.amazon.com/signer.

03 In the left navigation panel, under AWS Signer, select Signing Profiles.

04 Choose Create Signing Profile to create a Signing Profile that can be used to create signed code packages.

05 On the Create Signing Profile setup page, provide a unique name for your new Signing Profile and specify the Signature Validity period (between 1 day and 135 months) for the signatures generated by the Signing Profile. Choose Create Profile to create the required Signing Profile.

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

07 In the left navigation panel, under Additional resources, choose Code signing configurations.

08 Choose Create configuration to create a code signing configuration that defines signing profiles that are allowed to sign code artifacts for the new configuration, and set a signature validation policy.

09 On the Create code signing configuration setup page, perform the following actions:

  1. In the Description box, provide a short description to identify this configuration when you add it to a Lambda function.
  2. Click inside the Signing profile version ARN box and select the Amazon Resource Name (ARN) of the Signing Profile created at step no. 5.
  3. For Signature validation policy, choose the signature validation policy suitable for your Lambda function. A signature check can fail if the code is not signed by an allowed Signing Profile, or if the signature has expired or has been revoked. When a signature check fails, Amazon Lambda can treat the deployment in two ways:
    • Warn – Amazon Lambda allows the deployment of the code bundle but issues a warning. The service also stores a warning containing the details about the signature check in the CloudTrail log.
    • Enforce – Lambda blocks the deployment of the code and also issues a warning. However, regardless of your validation policy, if your code has been tampered or altered since signing, the deployment will be blocked.
  4. Choose Create configuration to deploy your new code signing configuration.

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

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

12 Select the Configuration tab and choose Code signing from the left menu.

13 Click on the Edit button available in the Code signing configuration section to add a code signing configuration.

14 On the Edit code signing page, select the code signing configuration created at step no. 9 from the Code signing configuration dropdown list. Choose Save to apply the changes and enable the Code Signing feature.

15 Once your Amazon Lambda function is configured to use code signing, you need to upload a signed .zip file or provide an S3 URL of a signed .zip made by a signing job in AWS Signer. To start a signing job, navigate back to AWS Signer console at https://console.aws.amazon.com/signer.

16 In the left navigation panel, under AWS Signer, select Signing Jobs.

17 Choose Start Signing Job to deploy a new Signing Job. A Signing Job represents an asynchronous process that generates a signature for your code package and puts the signed code package in the specified destination path.

18 On the Start Signing Job setup page, perform the following actions:

  1. Select the Signing Profile created at step no. 5 from the Signing Profile to use dropdown list.
  2. For Code asset source location, specify the Amazon S3 location of the code package (.zip file) to be signed. Only S3 buckets available in the current region are displayed. Cross-region signing is not yet supported.
  3. For Signature destination path with prefix, specify a destination path where the signed code package should be uploaded.
  4. Choose Start Job to deploy your new Signing Job. Once the job status becomes Succeeded, you can find the signed .zip package in your assigned S3 bucket.

19 You can now publish the signed code package to the selected Lambda function. Amazon Lambda will perform signature checks to verify that the code has not been altered since signing. Also, the service verifies if the code is signed by one of the allowed signing profiles available.

20 Repeat steps no. 2 – 19 to enable and configure Code Signing feature for each Amazon Lambda function available within the current AWS region.

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

Using AWS CLI

01 Run put-signing-profile command (OSX/Linux/UNIX) to create a new AWS Signer Signing Profile. A Signing Profile defines a trusted publisher who can sign a code package:

aws signer put-signing-profile
  --region us-east-1
  --profile-name cc_lambda_signing_profile
  --platform-id AWSLambda-SHA384-ECDSA
  --signature-validity-period value=135,type="MONTHS"

02 The command output should return the ARN (including the version ARN) of the newly created Signing Profile:

{
	"arn": "arn:aws:signer:us-east-1:123456789012:/signing-profiles/cc_lambda_signing_profile",
	"profileVersion": "abcdabcdac",
	"profileVersionArn": "arn:aws:signer:us-east-1:123456789012:/signing-profiles/cc_lambda_signing_profile/abcdabcdac"
}

03 Run create-code-signing-config command (OSX/Linux/UNIX) to create a code signing configuration for the Amazon Lambda function that you want to enable Code Signing. A code signing configuration defines signing profiles that are allowed to sign code artifacts for the new configuration and set a signature validation policy. Use the Signing Profile created at the previous step as allowed (trusted) publisher. The following command example makes use of the "Enforce" code signing configuration policy for deployment validation failure. With this policy type, Amazon Lambda blocks the deployment of the code when a signature check fails:

aws lambda create-code-signing-config
  --region us-east-1
  --description cc-sqs-poller-code-signing-config
  --allowed-publishers SigningProfileVersionArns=arn:aws:signer:us-east-1:123456789012:/signing-profiles/cc_lambda_signing_profile/abcdabcdac
  --code-signing-policies UntrustedArtifactOnDeployment="Enforce"

04 The command output should return the metadata available for the new Lambda code signing configuration:

{
	"CodeSigningConfig": {
		"CodeSigningConfigId": "csc-0abcd1234abcd1234",
		"CodeSigningConfigArn": "arn:aws:lambda:us-east-1:123456789012:code-signing-config:csc-0abcd1234abcd1234",
		"Description": "cc-sqs-poller-code-signing-config",
		"AllowedPublishers": {
			"SigningProfileVersionArns": [
				"arn:aws:signer:us-east-1:123456789012:/signing-profiles/cc_lambda_signing_profile/abcdabcdac"
			]
		},
		"CodeSigningPolicies": {
			"UntrustedArtifactOnDeployment": "Enforce"
		},
		"LastModified": "2021-01-13T10:10:10.000000Z"
	}
}

05 Run put-function-code-signing-config command (OSX/Linux/UNIX) to apply the newly created code signing configuration to the specified Lambda function. This will enable Code Signing feature for your Amazon Lambda function:

aws lambda put-function-code-signing-config
  --region us-east-1
  --code-signing-config-arn arn:aws:lambda:us-east-1:123456789012:code-signing-config:csc-0abcd1234abcd1234
  --function-name cc-sqs-poller

06 The output should return the put-function-code-signing-config command request metadata:

{
	"CodeSigningConfigArn": "arn:aws:lambda:us-east-1:123456789012:code-signing-config:csc-0abcd1234abcd1234",
	"FunctionName": "cc-sqs-poller"
}

07 Once your Amazon Lambda function is configured to use code signing, you need to upload a signed .zip file or provide an S3 URL of a signed .zip made by a signing job in AWS Signer. To initiate a Signing Job to be performed on the code provided, run start-signing-job command (OSX/Linux/UNIX). A Signing Job represents an asynchronous process that generates a signature for your code package and puts the signed code package in the specified destination path. Choose the Signing Profile created at step no. 1 and specify the Amazon S3 location of the code package (.zip file) to be signed. Also, include the destination path where the signed code package should be uploaded:

aws signer start-signing-job
  --region us-east-1
  --source 's3={bucketName=cc-signer-source,key=code.zip,version=ABCDABCDABCDABCDABCDABCDABCDABCD}'
  --destination 's3={bucketName=cc-signer-destination,prefix=signed-}'
  --profile-name cc_lambda_signing_profile

08 The command output should return the identifier (ID) of the new AWS Signer Signing Job:

{
	"jobId": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"jobOwner": "123456789012"
}

09 You can now publish the signed code package to the selected Lambda function. Amazon Lambda will perform signature checks to verify that the code has not been altered since signing. Also, the Lambda service verifies if the code is signed by one of the allowed signing profiles available.

10 Repeat steps no. 1 – 9 to enable and configure Code Signing feature for each Amazon Lambda function available in the selected AWS region.

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

References

Publication date Jan 14, 2021

Unlock the Remediation Steps


Free 30-day Trial

Automatically audit your configurations with Conformity
and gain access to our cloud security platform.

Confirmity Cloud Platform

No thanks, back to article

You are auditing:

Enable Code Signing

Risk Level: Medium