Configure AWS Lambda Code Signing

The aws:lambda/codeSigningConfig:CodeSigningConfig resource, part of the Pulumi AWS provider, defines which signing profiles Lambda trusts and how to handle unsigned or untrusted code. This guide focuses on two capabilities: enforcement vs warning policies and multi-profile trust configuration.

Code signing configs reference AWS Signer signing profiles that must exist before you create the config. The examples are intentionally small. Combine them with your own signing profiles and Lambda function associations.

Enforce code signing with multiple signing profiles

Production deployments often require strict code integrity checks to prevent unauthorized or tampered code from executing.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Create signing profiles for different environments
const prod = new aws.signer.SigningProfile("prod", {
    platformId: "AWSLambda-SHA384-ECDSA",
    namePrefix: "prod_lambda_",
    tags: {
        Environment: "production",
    },
});
const dev = new aws.signer.SigningProfile("dev", {
    platformId: "AWSLambda-SHA384-ECDSA",
    namePrefix: "dev_lambda_",
    tags: {
        Environment: "development",
    },
});
// Code signing configuration with enforcement
const example = new aws.lambda.CodeSigningConfig("example", {
    description: "Code signing configuration for Lambda functions",
    allowedPublishers: {
        signingProfileVersionArns: [
            prod.versionArn,
            dev.versionArn,
        ],
    },
    policies: {
        untrustedArtifactOnDeployment: "Enforce",
    },
    tags: {
        Environment: "production",
        Purpose: "code-signing",
    },
});
import pulumi
import pulumi_aws as aws

# Create signing profiles for different environments
prod = aws.signer.SigningProfile("prod",
    platform_id="AWSLambda-SHA384-ECDSA",
    name_prefix="prod_lambda_",
    tags={
        "Environment": "production",
    })
dev = aws.signer.SigningProfile("dev",
    platform_id="AWSLambda-SHA384-ECDSA",
    name_prefix="dev_lambda_",
    tags={
        "Environment": "development",
    })
# Code signing configuration with enforcement
example = aws.lambda_.CodeSigningConfig("example",
    description="Code signing configuration for Lambda functions",
    allowed_publishers={
        "signing_profile_version_arns": [
            prod.version_arn,
            dev.version_arn,
        ],
    },
    policies={
        "untrusted_artifact_on_deployment": "Enforce",
    },
    tags={
        "Environment": "production",
        "Purpose": "code-signing",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/signer"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create signing profiles for different environments
		prod, err := signer.NewSigningProfile(ctx, "prod", &signer.SigningProfileArgs{
			PlatformId: pulumi.String("AWSLambda-SHA384-ECDSA"),
			NamePrefix: pulumi.String("prod_lambda_"),
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("production"),
			},
		})
		if err != nil {
			return err
		}
		dev, err := signer.NewSigningProfile(ctx, "dev", &signer.SigningProfileArgs{
			PlatformId: pulumi.String("AWSLambda-SHA384-ECDSA"),
			NamePrefix: pulumi.String("dev_lambda_"),
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("development"),
			},
		})
		if err != nil {
			return err
		}
		// Code signing configuration with enforcement
		_, err = lambda.NewCodeSigningConfig(ctx, "example", &lambda.CodeSigningConfigArgs{
			Description: pulumi.String("Code signing configuration for Lambda functions"),
			AllowedPublishers: &lambda.CodeSigningConfigAllowedPublishersArgs{
				SigningProfileVersionArns: pulumi.StringArray{
					prod.VersionArn,
					dev.VersionArn,
				},
			},
			Policies: &lambda.CodeSigningConfigPoliciesArgs{
				UntrustedArtifactOnDeployment: pulumi.String("Enforce"),
			},
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("production"),
				"Purpose":     pulumi.String("code-signing"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    // Create signing profiles for different environments
    var prod = new Aws.Signer.SigningProfile("prod", new()
    {
        PlatformId = "AWSLambda-SHA384-ECDSA",
        NamePrefix = "prod_lambda_",
        Tags = 
        {
            { "Environment", "production" },
        },
    });

    var dev = new Aws.Signer.SigningProfile("dev", new()
    {
        PlatformId = "AWSLambda-SHA384-ECDSA",
        NamePrefix = "dev_lambda_",
        Tags = 
        {
            { "Environment", "development" },
        },
    });

    // Code signing configuration with enforcement
    var example = new Aws.Lambda.CodeSigningConfig("example", new()
    {
        Description = "Code signing configuration for Lambda functions",
        AllowedPublishers = new Aws.Lambda.Inputs.CodeSigningConfigAllowedPublishersArgs
        {
            SigningProfileVersionArns = new[]
            {
                prod.VersionArn,
                dev.VersionArn,
            },
        },
        Policies = new Aws.Lambda.Inputs.CodeSigningConfigPoliciesArgs
        {
            UntrustedArtifactOnDeployment = "Enforce",
        },
        Tags = 
        {
            { "Environment", "production" },
            { "Purpose", "code-signing" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.signer.SigningProfile;
import com.pulumi.aws.signer.SigningProfileArgs;
import com.pulumi.aws.lambda.CodeSigningConfig;
import com.pulumi.aws.lambda.CodeSigningConfigArgs;
import com.pulumi.aws.lambda.inputs.CodeSigningConfigAllowedPublishersArgs;
import com.pulumi.aws.lambda.inputs.CodeSigningConfigPoliciesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        // Create signing profiles for different environments
        var prod = new SigningProfile("prod", SigningProfileArgs.builder()
            .platformId("AWSLambda-SHA384-ECDSA")
            .namePrefix("prod_lambda_")
            .tags(Map.of("Environment", "production"))
            .build());

        var dev = new SigningProfile("dev", SigningProfileArgs.builder()
            .platformId("AWSLambda-SHA384-ECDSA")
            .namePrefix("dev_lambda_")
            .tags(Map.of("Environment", "development"))
            .build());

        // Code signing configuration with enforcement
        var example = new CodeSigningConfig("example", CodeSigningConfigArgs.builder()
            .description("Code signing configuration for Lambda functions")
            .allowedPublishers(CodeSigningConfigAllowedPublishersArgs.builder()
                .signingProfileVersionArns(                
                    prod.versionArn(),
                    dev.versionArn())
                .build())
            .policies(CodeSigningConfigPoliciesArgs.builder()
                .untrustedArtifactOnDeployment("Enforce")
                .build())
            .tags(Map.ofEntries(
                Map.entry("Environment", "production"),
                Map.entry("Purpose", "code-signing")
            ))
            .build());

    }
}
resources:
  # Create signing profiles for different environments
  prod:
    type: aws:signer:SigningProfile
    properties:
      platformId: AWSLambda-SHA384-ECDSA
      namePrefix: prod_lambda_
      tags:
        Environment: production
  dev:
    type: aws:signer:SigningProfile
    properties:
      platformId: AWSLambda-SHA384-ECDSA
      namePrefix: dev_lambda_
      tags:
        Environment: development
  # Code signing configuration with enforcement
  example:
    type: aws:lambda:CodeSigningConfig
    properties:
      description: Code signing configuration for Lambda functions
      allowedPublishers:
        signingProfileVersionArns:
          - ${prod.versionArn}
          - ${dev.versionArn}
      policies:
        untrustedArtifactOnDeployment: Enforce
      tags:
        Environment: production
        Purpose: code-signing

When a Lambda function uses this code signing config, AWS validates the deployment package signature against the allowed signing profiles. The allowedPublishers block lists trusted signing profile version ARNs. The policies block controls what happens when validation fails: “Enforce” blocks deployment of unsigned or untrusted code, while “Warn” logs the issue but allows deployment. Here, any code signed by either the prod or dev profile is trusted, and unsigned code is rejected.

Allow unsigned code with warnings in development

Development environments need flexibility to deploy unsigned code for rapid iteration while maintaining visibility into signing status.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.lambda.CodeSigningConfig("example", {
    description: "Development code signing configuration",
    allowedPublishers: {
        signingProfileVersionArns: [dev.versionArn],
    },
    policies: {
        untrustedArtifactOnDeployment: "Warn",
    },
    tags: {
        Environment: "development",
        Purpose: "code-signing",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.lambda_.CodeSigningConfig("example",
    description="Development code signing configuration",
    allowed_publishers={
        "signing_profile_version_arns": [dev["versionArn"]],
    },
    policies={
        "untrusted_artifact_on_deployment": "Warn",
    },
    tags={
        "Environment": "development",
        "Purpose": "code-signing",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := lambda.NewCodeSigningConfig(ctx, "example", &lambda.CodeSigningConfigArgs{
			Description: pulumi.String("Development code signing configuration"),
			AllowedPublishers: &lambda.CodeSigningConfigAllowedPublishersArgs{
				SigningProfileVersionArns: pulumi.StringArray{
					dev.VersionArn,
				},
			},
			Policies: &lambda.CodeSigningConfigPoliciesArgs{
				UntrustedArtifactOnDeployment: pulumi.String("Warn"),
			},
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("development"),
				"Purpose":     pulumi.String("code-signing"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Lambda.CodeSigningConfig("example", new()
    {
        Description = "Development code signing configuration",
        AllowedPublishers = new Aws.Lambda.Inputs.CodeSigningConfigAllowedPublishersArgs
        {
            SigningProfileVersionArns = new[]
            {
                dev.VersionArn,
            },
        },
        Policies = new Aws.Lambda.Inputs.CodeSigningConfigPoliciesArgs
        {
            UntrustedArtifactOnDeployment = "Warn",
        },
        Tags = 
        {
            { "Environment", "development" },
            { "Purpose", "code-signing" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.CodeSigningConfig;
import com.pulumi.aws.lambda.CodeSigningConfigArgs;
import com.pulumi.aws.lambda.inputs.CodeSigningConfigAllowedPublishersArgs;
import com.pulumi.aws.lambda.inputs.CodeSigningConfigPoliciesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new CodeSigningConfig("example", CodeSigningConfigArgs.builder()
            .description("Development code signing configuration")
            .allowedPublishers(CodeSigningConfigAllowedPublishersArgs.builder()
                .signingProfileVersionArns(dev.versionArn())
                .build())
            .policies(CodeSigningConfigPoliciesArgs.builder()
                .untrustedArtifactOnDeployment("Warn")
                .build())
            .tags(Map.ofEntries(
                Map.entry("Environment", "development"),
                Map.entry("Purpose", "code-signing")
            ))
            .build());

    }
}
resources:
  example:
    type: aws:lambda:CodeSigningConfig
    properties:
      description: Development code signing configuration
      allowedPublishers:
        signingProfileVersionArns:
          - ${dev.versionArn}
      policies:
        untrustedArtifactOnDeployment: Warn
      tags:
        Environment: development
        Purpose: code-signing

Setting untrustedArtifactOnDeployment to “Warn” allows unsigned code to deploy but logs a warning. This gives development teams freedom to iterate quickly without the overhead of signing every deployment, while still tracking which functions lack signatures. In contrast to the enforcement policy in the first example, this configuration prioritizes velocity over strict validation.

Beyond these examples

These snippets focus on specific code signing config features: enforcement vs warning policies and multi-profile trust configuration. They’re intentionally minimal rather than full Lambda security setups.

The examples reference pre-existing infrastructure such as AWS Signer signing profiles with version ARNs. They focus on configuring the code signing policy rather than creating signing profiles or attaching configs to functions.

To keep things focused, common code signing patterns are omitted, including:

  • Attaching code signing configs to Lambda functions
  • Signing profile creation and management
  • IAM permissions for code signing operations
  • Rotation and revocation of signing profiles

These omissions are intentional: the goal is to illustrate how code signing policies are wired, not provide drop-in security modules. See the Lambda CodeSigningConfig resource reference for all available configuration options.

Let's configure AWS Lambda Code Signing

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Code Signing Policies
What's the difference between Enforce and Warn policies?
Enforce blocks deployment of unsigned or untrusted code, while Warn allows deployment but logs a warning. Examples show Enforce for production environments and Warn for development.
What does code signing configuration do for Lambda functions?
Code signing configurations ensure code integrity and authenticity by defining allowed signing profiles and validation policies for Lambda functions.
Signing Profiles & Configuration
Can I use multiple signing profiles in one configuration?
Yes, signingProfileVersionArns accepts an array of profile ARNs. Examples show configurations with both single profiles and multiple profiles like [prod.versionArn, dev.versionArn].
How do I set up code signing for different environments?
Create separate CodeSigningConfig resources for each environment with appropriate policies. The multiple environment example shows production using Enforce for strict validation and development using Warn for flexibility.
What signing platform should I use for Lambda functions?
Examples use AWSLambda-SHA384-ECDSA as the platformId when creating signing profiles for Lambda.
Why do I need to use versionArn instead of the profile ARN?
The signingProfileVersionArns property requires version-specific ARNs (accessed via .versionArn) rather than the base profile ARN to ensure immutable references to signing profiles.

Using a different cloud?

Explore security guides for other cloud providers: