Create and Configure KMS Keys

The aws:kms/key:Key resource, part of the Pulumi AWS provider, defines a KMS key: its cryptographic spec, usage type, rotation behavior, and access policy. This guide focuses on four capabilities: symmetric encryption with automatic rotation, asymmetric keys for signing and HMAC generation, multi-region key replication, and inline vs standalone policy configuration.

KMS keys don’t operate independently. They rely on IAM users and roles referenced in their access policies. The examples are intentionally small and show how to configure each key type. Combine them with your own IAM infrastructure and application code that calls KMS APIs.

Create a symmetric key with inline policy

Most encryption workflows use a symmetric key that protects data at rest or in transit, with automatic rotation to meet compliance requirements.

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

const current = aws.getCallerIdentity({});
const example = new aws.kms.Key("example", {
    description: "An example symmetric encryption KMS key",
    enableKeyRotation: true,
    deletionWindowInDays: 20,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Id: "key-default-1",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:root`),
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow administration of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:user/Alice`),
                },
                Action: [
                    "kms:ReplicateKey",
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                Resource: "*",
            },
            {
                Sid: "Allow use of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:user/Bob`),
                },
                Action: [
                    "kms:DescribeKey",
                    "kms:Encrypt",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                    "kms:GenerateDataKey",
                    "kms:GenerateDataKeyWithoutPlaintext",
                ],
                Resource: "*",
            },
        ],
    }),
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
example = aws.kms.Key("example",
    description="An example symmetric encryption KMS key",
    enable_key_rotation=True,
    deletion_window_in_days=20,
    policy=json.dumps({
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:root",
                },
                "Action": "kms:*",
                "Resource": "*",
            },
            {
                "Sid": "Allow administration of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:user/Alice",
                },
                "Action": [
                    "kms:ReplicateKey",
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                "Resource": "*",
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:user/Bob",
                },
                "Action": [
                    "kms:DescribeKey",
                    "kms:Encrypt",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                    "kms:GenerateDataKey",
                    "kms:GenerateDataKeyWithoutPlaintext",
                ],
                "Resource": "*",
            },
        ],
    }))
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"Version": "2012-10-17",
			"Id":      "key-default-1",
			"Statement": []interface{}{
				map[string]interface{}{
					"Sid":    "Enable IAM User Permissions",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
					},
					"Action":   "kms:*",
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow administration of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:user/Alice", current.AccountId),
					},
					"Action": []string{
						"kms:ReplicateKey",
						"kms:Create*",
						"kms:Describe*",
						"kms:Enable*",
						"kms:List*",
						"kms:Put*",
						"kms:Update*",
						"kms:Revoke*",
						"kms:Disable*",
						"kms:Get*",
						"kms:Delete*",
						"kms:ScheduleKeyDeletion",
						"kms:CancelKeyDeletion",
					},
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow use of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:user/Bob", current.AccountId),
					},
					"Action": []string{
						"kms:DescribeKey",
						"kms:Encrypt",
						"kms:Decrypt",
						"kms:ReEncrypt*",
						"kms:GenerateDataKey",
						"kms:GenerateDataKeyWithoutPlaintext",
					},
					"Resource": "*",
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("An example symmetric encryption KMS key"),
			EnableKeyRotation:    pulumi.Bool(true),
			DeletionWindowInDays: pulumi.Int(20),
			Policy:               pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.Kms.Key("example", new()
    {
        Description = "An example symmetric encryption KMS key",
        EnableKeyRotation = true,
        DeletionWindowInDays = 20,
        Policy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-default-1",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow administration of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:user/Alice",
                    },
                    ["Action"] = new[]
                    {
                        "kms:ReplicateKey",
                        "kms:Create*",
                        "kms:Describe*",
                        "kms:Enable*",
                        "kms:List*",
                        "kms:Put*",
                        "kms:Update*",
                        "kms:Revoke*",
                        "kms:Disable*",
                        "kms:Get*",
                        "kms:Delete*",
                        "kms:ScheduleKeyDeletion",
                        "kms:CancelKeyDeletion",
                    },
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow use of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:user/Bob",
                    },
                    ["Action"] = new[]
                    {
                        "kms:DescribeKey",
                        "kms:Encrypt",
                        "kms:Decrypt",
                        "kms:ReEncrypt*",
                        "kms:GenerateDataKey",
                        "kms:GenerateDataKeyWithoutPlaintext",
                    },
                    ["Resource"] = "*",
                },
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new Key("example", KeyArgs.builder()
            .description("An example symmetric encryption KMS key")
            .enableKeyRotation(true)
            .deletionWindowInDays(20)
            .policy(serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-default-1"),
                    jsonProperty("Statement", jsonArray(
                        jsonObject(
                            jsonProperty("Sid", "Enable IAM User Permissions"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:root", current.accountId()))
                            )),
                            jsonProperty("Action", "kms:*"),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow administration of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:user/Alice", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:ReplicateKey", 
                                "kms:Create*", 
                                "kms:Describe*", 
                                "kms:Enable*", 
                                "kms:List*", 
                                "kms:Put*", 
                                "kms:Update*", 
                                "kms:Revoke*", 
                                "kms:Disable*", 
                                "kms:Get*", 
                                "kms:Delete*", 
                                "kms:ScheduleKeyDeletion", 
                                "kms:CancelKeyDeletion"
                            )),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow use of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:user/Bob", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:DescribeKey", 
                                "kms:Encrypt", 
                                "kms:Decrypt", 
                                "kms:ReEncrypt*", 
                                "kms:GenerateDataKey", 
                                "kms:GenerateDataKeyWithoutPlaintext"
                            )),
                            jsonProperty("Resource", "*")
                        )
                    ))
                )))
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: An example symmetric encryption KMS key
      enableKeyRotation: true
      deletionWindowInDays: 20
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-default-1
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
            - Sid: Allow administration of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:user/Alice
              Action:
                - kms:ReplicateKey
                - kms:Create*
                - kms:Describe*
                - kms:Enable*
                - kms:List*
                - kms:Put*
                - kms:Update*
                - kms:Revoke*
                - kms:Disable*
                - kms:Get*
                - kms:Delete*
                - kms:ScheduleKeyDeletion
                - kms:CancelKeyDeletion
              Resource: '*'
            - Sid: Allow use of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:user/Bob
              Action:
                - kms:DescribeKey
                - kms:Encrypt
                - kms:Decrypt
                - kms:ReEncrypt*
                - kms:GenerateDataKey
                - kms:GenerateDataKeyWithoutPlaintext
              Resource: '*'
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

When you enable rotation, KMS automatically rotates the key material annually while preserving the same key ID and ARN. The policy property defines a JSON document with three statements: root account permissions, administrative actions for user Alice, and encryption/decryption operations for user Bob. The deletionWindowInDays property delays key deletion to prevent accidental data loss.

Separate key policy from key resource

Teams managing keys through policy modules often split the key resource from its policy to enable independent updates.

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

const current = aws.getCallerIdentity({});
const example = new aws.kms.Key("example", {
    description: "An example symmetric encryption KMS key",
    enableKeyRotation: true,
    deletionWindowInDays: 20,
});
const exampleKeyPolicy = new aws.kms.KeyPolicy("example", {
    keyId: example.id,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Id: "key-default-1",
        Statement: [{
            Sid: "Enable IAM User Permissions",
            Effect: "Allow",
            Principal: {
                AWS: current.then(current => `arn:aws:iam::${current.accountId}:root`),
            },
            Action: "kms:*",
            Resource: "*",
        }],
    }),
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
example = aws.kms.Key("example",
    description="An example symmetric encryption KMS key",
    enable_key_rotation=True,
    deletion_window_in_days=20)
example_key_policy = aws.kms.KeyPolicy("example",
    key_id=example.id,
    policy=json.dumps({
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [{
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": f"arn:aws:iam::{current.account_id}:root",
            },
            "Action": "kms:*",
            "Resource": "*",
        }],
    }))
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		example, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("An example symmetric encryption KMS key"),
			EnableKeyRotation:    pulumi.Bool(true),
			DeletionWindowInDays: pulumi.Int(20),
		})
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"Version": "2012-10-17",
			"Id":      "key-default-1",
			"Statement": []map[string]interface{}{
				map[string]interface{}{
					"Sid":    "Enable IAM User Permissions",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
					},
					"Action":   "kms:*",
					"Resource": "*",
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = kms.NewKeyPolicy(ctx, "example", &kms.KeyPolicyArgs{
			KeyId:  example.ID(),
			Policy: pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.Kms.Key("example", new()
    {
        Description = "An example symmetric encryption KMS key",
        EnableKeyRotation = true,
        DeletionWindowInDays = 20,
    });

    var exampleKeyPolicy = new Aws.Kms.KeyPolicy("example", new()
    {
        KeyId = example.Id,
        Policy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-default-1",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.kms.KeyPolicy;
import com.pulumi.aws.kms.KeyPolicyArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new Key("example", KeyArgs.builder()
            .description("An example symmetric encryption KMS key")
            .enableKeyRotation(true)
            .deletionWindowInDays(20)
            .build());

        var exampleKeyPolicy = new KeyPolicy("exampleKeyPolicy", KeyPolicyArgs.builder()
            .keyId(example.id())
            .policy(serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-default-1"),
                    jsonProperty("Statement", jsonArray(jsonObject(
                        jsonProperty("Sid", "Enable IAM User Permissions"),
                        jsonProperty("Effect", "Allow"),
                        jsonProperty("Principal", jsonObject(
                            jsonProperty("AWS", String.format("arn:aws:iam::%s:root", current.accountId()))
                        )),
                        jsonProperty("Action", "kms:*"),
                        jsonProperty("Resource", "*")
                    )))
                )))
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: An example symmetric encryption KMS key
      enableKeyRotation: true
      deletionWindowInDays: 20
  exampleKeyPolicy:
    type: aws:kms:KeyPolicy
    name: example
    properties:
      keyId: ${example.id}
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-default-1
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

The KeyPolicy resource manages the policy separately from the key itself. This allows you to update access control without modifying the key resource, useful when policies are generated by separate modules or managed through different approval workflows.

Create an asymmetric key for signing

Applications that sign tokens or verify signatures without encryption use asymmetric keys with RSA key pairs.

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

const current = aws.getCallerIdentity({});
const example = new aws.kms.Key("example", {
    description: "RSA-3072 asymmetric KMS key for signing and verification",
    customerMasterKeySpec: "RSA_3072",
    keyUsage: "SIGN_VERIFY",
    enableKeyRotation: false,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Id: "key-default-1",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:root`),
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow administration of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:role/Admin`),
                },
                Action: [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                Resource: "*",
            },
            {
                Sid: "Allow use of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:role/Developer`),
                },
                Action: [
                    "kms:Sign",
                    "kms:Verify",
                    "kms:DescribeKey",
                ],
                Resource: "*",
            },
        ],
    }),
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
example = aws.kms.Key("example",
    description="RSA-3072 asymmetric KMS key for signing and verification",
    customer_master_key_spec="RSA_3072",
    key_usage="SIGN_VERIFY",
    enable_key_rotation=False,
    policy=json.dumps({
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:root",
                },
                "Action": "kms:*",
                "Resource": "*",
            },
            {
                "Sid": "Allow administration of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:role/Admin",
                },
                "Action": [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                "Resource": "*",
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:role/Developer",
                },
                "Action": [
                    "kms:Sign",
                    "kms:Verify",
                    "kms:DescribeKey",
                ],
                "Resource": "*",
            },
        ],
    }))
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"Version": "2012-10-17",
			"Id":      "key-default-1",
			"Statement": []interface{}{
				map[string]interface{}{
					"Sid":    "Enable IAM User Permissions",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
					},
					"Action":   "kms:*",
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow administration of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:role/Admin", current.AccountId),
					},
					"Action": []string{
						"kms:Create*",
						"kms:Describe*",
						"kms:Enable*",
						"kms:List*",
						"kms:Put*",
						"kms:Update*",
						"kms:Revoke*",
						"kms:Disable*",
						"kms:Get*",
						"kms:Delete*",
						"kms:ScheduleKeyDeletion",
						"kms:CancelKeyDeletion",
					},
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow use of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:role/Developer", current.AccountId),
					},
					"Action": []string{
						"kms:Sign",
						"kms:Verify",
						"kms:DescribeKey",
					},
					"Resource": "*",
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:           pulumi.String("RSA-3072 asymmetric KMS key for signing and verification"),
			CustomerMasterKeySpec: pulumi.String("RSA_3072"),
			KeyUsage:              pulumi.String("SIGN_VERIFY"),
			EnableKeyRotation:     pulumi.Bool(false),
			Policy:                pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.Kms.Key("example", new()
    {
        Description = "RSA-3072 asymmetric KMS key for signing and verification",
        CustomerMasterKeySpec = "RSA_3072",
        KeyUsage = "SIGN_VERIFY",
        EnableKeyRotation = false,
        Policy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-default-1",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow administration of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:role/Admin",
                    },
                    ["Action"] = new[]
                    {
                        "kms:Create*",
                        "kms:Describe*",
                        "kms:Enable*",
                        "kms:List*",
                        "kms:Put*",
                        "kms:Update*",
                        "kms:Revoke*",
                        "kms:Disable*",
                        "kms:Get*",
                        "kms:Delete*",
                        "kms:ScheduleKeyDeletion",
                        "kms:CancelKeyDeletion",
                    },
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow use of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:role/Developer",
                    },
                    ["Action"] = new[]
                    {
                        "kms:Sign",
                        "kms:Verify",
                        "kms:DescribeKey",
                    },
                    ["Resource"] = "*",
                },
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new Key("example", KeyArgs.builder()
            .description("RSA-3072 asymmetric KMS key for signing and verification")
            .customerMasterKeySpec("RSA_3072")
            .keyUsage("SIGN_VERIFY")
            .enableKeyRotation(false)
            .policy(serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-default-1"),
                    jsonProperty("Statement", jsonArray(
                        jsonObject(
                            jsonProperty("Sid", "Enable IAM User Permissions"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:root", current.accountId()))
                            )),
                            jsonProperty("Action", "kms:*"),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow administration of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:role/Admin", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:Create*", 
                                "kms:Describe*", 
                                "kms:Enable*", 
                                "kms:List*", 
                                "kms:Put*", 
                                "kms:Update*", 
                                "kms:Revoke*", 
                                "kms:Disable*", 
                                "kms:Get*", 
                                "kms:Delete*", 
                                "kms:ScheduleKeyDeletion", 
                                "kms:CancelKeyDeletion"
                            )),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow use of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:role/Developer", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:Sign", 
                                "kms:Verify", 
                                "kms:DescribeKey"
                            )),
                            jsonProperty("Resource", "*")
                        )
                    ))
                )))
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: RSA-3072 asymmetric KMS key for signing and verification
      customerMasterKeySpec: RSA_3072
      keyUsage: SIGN_VERIFY
      enableKeyRotation: false
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-default-1
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
            - Sid: Allow administration of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:role/Admin
              Action:
                - kms:Create*
                - kms:Describe*
                - kms:Enable*
                - kms:List*
                - kms:Put*
                - kms:Update*
                - kms:Revoke*
                - kms:Disable*
                - kms:Get*
                - kms:Delete*
                - kms:ScheduleKeyDeletion
                - kms:CancelKeyDeletion
              Resource: '*'
            - Sid: Allow use of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:role/Developer
              Action:
                - kms:Sign
                - kms:Verify
                - kms:DescribeKey
              Resource: '*'
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

The customerMasterKeySpec property sets the key algorithm to RSA_3072, and keyUsage specifies SIGN_VERIFY instead of the default ENCRYPT_DECRYPT. Asymmetric keys cannot rotate automatically (enableKeyRotation must be false), so the policy grants administrative access to an Admin role and signing operations to a Developer role.

Generate and verify MACs for tokens

Token-based authentication often requires HMAC generation without exposing the secret key outside KMS.

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

const current = aws.getCallerIdentity({});
const example = new aws.kms.Key("example", {
    description: "HMAC_384 key for tokens",
    customerMasterKeySpec: "HMAC_384",
    keyUsage: "GENERATE_VERIFY_MAC",
    enableKeyRotation: false,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Id: "key-default-1",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:root`),
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow administration of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:role/Admin`),
                },
                Action: [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                Resource: "*",
            },
            {
                Sid: "Allow use of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:role/Developer`),
                },
                Action: [
                    "kms:GenerateMac",
                    "kms:VerifyMac",
                    "kms:DescribeKey",
                ],
                Resource: "*",
            },
        ],
    }),
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
example = aws.kms.Key("example",
    description="HMAC_384 key for tokens",
    customer_master_key_spec="HMAC_384",
    key_usage="GENERATE_VERIFY_MAC",
    enable_key_rotation=False,
    policy=json.dumps({
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:root",
                },
                "Action": "kms:*",
                "Resource": "*",
            },
            {
                "Sid": "Allow administration of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:role/Admin",
                },
                "Action": [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                "Resource": "*",
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:role/Developer",
                },
                "Action": [
                    "kms:GenerateMac",
                    "kms:VerifyMac",
                    "kms:DescribeKey",
                ],
                "Resource": "*",
            },
        ],
    }))
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"Version": "2012-10-17",
			"Id":      "key-default-1",
			"Statement": []interface{}{
				map[string]interface{}{
					"Sid":    "Enable IAM User Permissions",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
					},
					"Action":   "kms:*",
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow administration of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:role/Admin", current.AccountId),
					},
					"Action": []string{
						"kms:Create*",
						"kms:Describe*",
						"kms:Enable*",
						"kms:List*",
						"kms:Put*",
						"kms:Update*",
						"kms:Revoke*",
						"kms:Disable*",
						"kms:Get*",
						"kms:Delete*",
						"kms:ScheduleKeyDeletion",
						"kms:CancelKeyDeletion",
					},
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow use of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:role/Developer", current.AccountId),
					},
					"Action": []string{
						"kms:GenerateMac",
						"kms:VerifyMac",
						"kms:DescribeKey",
					},
					"Resource": "*",
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:           pulumi.String("HMAC_384 key for tokens"),
			CustomerMasterKeySpec: pulumi.String("HMAC_384"),
			KeyUsage:              pulumi.String("GENERATE_VERIFY_MAC"),
			EnableKeyRotation:     pulumi.Bool(false),
			Policy:                pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.Kms.Key("example", new()
    {
        Description = "HMAC_384 key for tokens",
        CustomerMasterKeySpec = "HMAC_384",
        KeyUsage = "GENERATE_VERIFY_MAC",
        EnableKeyRotation = false,
        Policy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-default-1",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow administration of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:role/Admin",
                    },
                    ["Action"] = new[]
                    {
                        "kms:Create*",
                        "kms:Describe*",
                        "kms:Enable*",
                        "kms:List*",
                        "kms:Put*",
                        "kms:Update*",
                        "kms:Revoke*",
                        "kms:Disable*",
                        "kms:Get*",
                        "kms:Delete*",
                        "kms:ScheduleKeyDeletion",
                        "kms:CancelKeyDeletion",
                    },
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow use of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:role/Developer",
                    },
                    ["Action"] = new[]
                    {
                        "kms:GenerateMac",
                        "kms:VerifyMac",
                        "kms:DescribeKey",
                    },
                    ["Resource"] = "*",
                },
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new Key("example", KeyArgs.builder()
            .description("HMAC_384 key for tokens")
            .customerMasterKeySpec("HMAC_384")
            .keyUsage("GENERATE_VERIFY_MAC")
            .enableKeyRotation(false)
            .policy(serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-default-1"),
                    jsonProperty("Statement", jsonArray(
                        jsonObject(
                            jsonProperty("Sid", "Enable IAM User Permissions"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:root", current.accountId()))
                            )),
                            jsonProperty("Action", "kms:*"),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow administration of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:role/Admin", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:Create*", 
                                "kms:Describe*", 
                                "kms:Enable*", 
                                "kms:List*", 
                                "kms:Put*", 
                                "kms:Update*", 
                                "kms:Revoke*", 
                                "kms:Disable*", 
                                "kms:Get*", 
                                "kms:Delete*", 
                                "kms:ScheduleKeyDeletion", 
                                "kms:CancelKeyDeletion"
                            )),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow use of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:role/Developer", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:GenerateMac", 
                                "kms:VerifyMac", 
                                "kms:DescribeKey"
                            )),
                            jsonProperty("Resource", "*")
                        )
                    ))
                )))
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: HMAC_384 key for tokens
      customerMasterKeySpec: HMAC_384
      keyUsage: GENERATE_VERIFY_MAC
      enableKeyRotation: false
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-default-1
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
            - Sid: Allow administration of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:role/Admin
              Action:
                - kms:Create*
                - kms:Describe*
                - kms:Enable*
                - kms:List*
                - kms:Put*
                - kms:Update*
                - kms:Revoke*
                - kms:Disable*
                - kms:Get*
                - kms:Delete*
                - kms:ScheduleKeyDeletion
                - kms:CancelKeyDeletion
              Resource: '*'
            - Sid: Allow use of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:role/Developer
              Action:
                - kms:GenerateMac
                - kms:VerifyMac
                - kms:DescribeKey
              Resource: '*'
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

The customerMasterKeySpec property selects HMAC_384, and keyUsage becomes GENERATE_VERIFY_MAC. KMS generates and verifies message authentication codes using the key material, which never leaves the service. The policy grants GenerateMac and VerifyMac permissions to a Developer role.

Enable cross-region encryption with multi-region keys

Applications deployed across multiple regions need consistent encryption keys without cross-region data movement for decryption.

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

const current = aws.getCallerIdentity({});
const example = new aws.kms.Key("example", {
    description: "An example multi-Region primary key",
    multiRegion: true,
    enableKeyRotation: true,
    deletionWindowInDays: 10,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Id: "key-default-1",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:root`),
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow administration of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:user/Alice`),
                },
                Action: [
                    "kms:ReplicateKey",
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                Resource: "*",
            },
            {
                Sid: "Allow use of the key",
                Effect: "Allow",
                Principal: {
                    AWS: current.then(current => `arn:aws:iam::${current.accountId}:user/Bob`),
                },
                Action: [
                    "kms:DescribeKey",
                    "kms:Encrypt",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                    "kms:GenerateDataKey",
                    "kms:GenerateDataKeyWithoutPlaintext",
                ],
                Resource: "*",
            },
        ],
    }),
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
example = aws.kms.Key("example",
    description="An example multi-Region primary key",
    multi_region=True,
    enable_key_rotation=True,
    deletion_window_in_days=10,
    policy=json.dumps({
        "Version": "2012-10-17",
        "Id": "key-default-1",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:root",
                },
                "Action": "kms:*",
                "Resource": "*",
            },
            {
                "Sid": "Allow administration of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:user/Alice",
                },
                "Action": [
                    "kms:ReplicateKey",
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion",
                ],
                "Resource": "*",
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:aws:iam::{current.account_id}:user/Bob",
                },
                "Action": [
                    "kms:DescribeKey",
                    "kms:Encrypt",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                    "kms:GenerateDataKey",
                    "kms:GenerateDataKeyWithoutPlaintext",
                ],
                "Resource": "*",
            },
        ],
    }))
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"Version": "2012-10-17",
			"Id":      "key-default-1",
			"Statement": []interface{}{
				map[string]interface{}{
					"Sid":    "Enable IAM User Permissions",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
					},
					"Action":   "kms:*",
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow administration of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:user/Alice", current.AccountId),
					},
					"Action": []string{
						"kms:ReplicateKey",
						"kms:Create*",
						"kms:Describe*",
						"kms:Enable*",
						"kms:List*",
						"kms:Put*",
						"kms:Update*",
						"kms:Revoke*",
						"kms:Disable*",
						"kms:Get*",
						"kms:Delete*",
						"kms:ScheduleKeyDeletion",
						"kms:CancelKeyDeletion",
					},
					"Resource": "*",
				},
				map[string]interface{}{
					"Sid":    "Allow use of the key",
					"Effect": "Allow",
					"Principal": map[string]interface{}{
						"AWS": fmt.Sprintf("arn:aws:iam::%v:user/Bob", current.AccountId),
					},
					"Action": []string{
						"kms:DescribeKey",
						"kms:Encrypt",
						"kms:Decrypt",
						"kms:ReEncrypt*",
						"kms:GenerateDataKey",
						"kms:GenerateDataKeyWithoutPlaintext",
					},
					"Resource": "*",
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("An example multi-Region primary key"),
			MultiRegion:          pulumi.Bool(true),
			EnableKeyRotation:    pulumi.Bool(true),
			DeletionWindowInDays: pulumi.Int(10),
			Policy:               pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var example = new Aws.Kms.Key("example", new()
    {
        Description = "An example multi-Region primary key",
        MultiRegion = true,
        EnableKeyRotation = true,
        DeletionWindowInDays = 10,
        Policy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-default-1",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow administration of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:user/Alice",
                    },
                    ["Action"] = new[]
                    {
                        "kms:ReplicateKey",
                        "kms:Create*",
                        "kms:Describe*",
                        "kms:Enable*",
                        "kms:List*",
                        "kms:Put*",
                        "kms:Update*",
                        "kms:Revoke*",
                        "kms:Disable*",
                        "kms:Get*",
                        "kms:Delete*",
                        "kms:ScheduleKeyDeletion",
                        "kms:CancelKeyDeletion",
                    },
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow use of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:user/Bob",
                    },
                    ["Action"] = new[]
                    {
                        "kms:DescribeKey",
                        "kms:Encrypt",
                        "kms:Decrypt",
                        "kms:ReEncrypt*",
                        "kms:GenerateDataKey",
                        "kms:GenerateDataKeyWithoutPlaintext",
                    },
                    ["Resource"] = "*",
                },
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var example = new Key("example", KeyArgs.builder()
            .description("An example multi-Region primary key")
            .multiRegion(true)
            .enableKeyRotation(true)
            .deletionWindowInDays(10)
            .policy(serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-default-1"),
                    jsonProperty("Statement", jsonArray(
                        jsonObject(
                            jsonProperty("Sid", "Enable IAM User Permissions"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:root", current.accountId()))
                            )),
                            jsonProperty("Action", "kms:*"),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow administration of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:user/Alice", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:ReplicateKey", 
                                "kms:Create*", 
                                "kms:Describe*", 
                                "kms:Enable*", 
                                "kms:List*", 
                                "kms:Put*", 
                                "kms:Update*", 
                                "kms:Revoke*", 
                                "kms:Disable*", 
                                "kms:Get*", 
                                "kms:Delete*", 
                                "kms:ScheduleKeyDeletion", 
                                "kms:CancelKeyDeletion"
                            )),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow use of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:aws:iam::%s:user/Bob", current.accountId()))
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:DescribeKey", 
                                "kms:Encrypt", 
                                "kms:Decrypt", 
                                "kms:ReEncrypt*", 
                                "kms:GenerateDataKey", 
                                "kms:GenerateDataKeyWithoutPlaintext"
                            )),
                            jsonProperty("Resource", "*")
                        )
                    ))
                )))
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: An example multi-Region primary key
      multiRegion: true
      enableKeyRotation: true
      deletionWindowInDays: 10
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-default-1
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
            - Sid: Allow administration of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:user/Alice
              Action:
                - kms:ReplicateKey
                - kms:Create*
                - kms:Describe*
                - kms:Enable*
                - kms:List*
                - kms:Put*
                - kms:Update*
                - kms:Revoke*
                - kms:Disable*
                - kms:Get*
                - kms:Delete*
                - kms:ScheduleKeyDeletion
                - kms:CancelKeyDeletion
              Resource: '*'
            - Sid: Allow use of the key
              Effect: Allow
              Principal:
                AWS: arn:aws:iam::${current.accountId}:user/Bob
              Action:
                - kms:DescribeKey
                - kms:Encrypt
                - kms:Decrypt
                - kms:ReEncrypt*
                - kms:GenerateDataKey
                - kms:GenerateDataKeyWithoutPlaintext
              Resource: '*'
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}

The multiRegion property creates a primary key that can be replicated to other regions. Once replicated, any region’s key can decrypt data encrypted by another region’s replica. The policy includes ReplicateKey permission for administrators. Multi-region keys support automatic rotation and maintain synchronized key material across all replicas.

Beyond These Examples

These snippets focus on specific KMS key features: symmetric encryption, asymmetric signing, and HMAC generation; inline and standalone key policies; and multi-region key replication. They’re intentionally minimal rather than full encryption solutions.

The examples may reference pre-existing infrastructure such as IAM users and roles in policy statements. They focus on configuring the key rather than provisioning IAM identities around it.

To keep things focused, common key patterns are omitted, including:

  • Custom key stores (CloudHSM integration via customKeyStoreId)
  • External key stores (xksKeyId for bring-your-own-key)
  • Rotation period customization (rotationPeriodInDays)
  • Key disabling and re-enabling (isEnabled)
  • Policy lockout bypass (bypassPolicyLockoutSafetyCheck)

These omissions are intentional: the goal is to illustrate how each key feature is wired, not provide drop-in encryption modules. See the KMS Key resource reference for all available configuration options.

Frequently Asked Questions

Key Policy Management
Should I configure my key policy inline or use a separate KeyPolicy resource?
Choose one approach, not both. Configuring the policy both inline (via the policy parameter) and with a standalone aws.kms.KeyPolicy resource causes inconsistencies and may overwrite your configuration. Use the policy parameter for simple setups or a separate aws.kms.KeyPolicy resource for better separation of concerns.
What happens if I don't specify a key policy?
AWS applies a default key policy that gives all principals in your account unlimited access to all KMS operations for the key. This effectively delegates all access control to IAM policies and KMS grants. For better security, explicitly define a key policy to control access.
What does bypassPolicyLockoutSafetyCheck do?
This flag bypasses the key policy lockout safety check, but increases the risk that your KMS key becomes unmanageable. The default is false. Only set this to true if you understand the risks and have reviewed the Default Key Policy scenarios in the AWS KMS Developer Guide.
Key Types & Configuration
What key types are available and when should I use each?
KMS supports three key types via keyUsage: ENCRYPT_DECRYPT (default, for symmetric encryption), SIGN_VERIFY (for asymmetric signing with RSA or ECC keys), and GENERATE_VERIFY_MAC (for HMAC keys). Set customerMasterKeySpec to choose the algorithm: SYMMETRIC_DEFAULT for encryption, RSA/ECC variants for signing, or HMAC variants for MAC generation.
What's the difference between symmetric and asymmetric keys?
Symmetric keys (SYMMETRIC_DEFAULT) use the same key for encryption and decryption, support automatic rotation, and are used for most encryption scenarios. Asymmetric keys (RSA or ECC) use public/private key pairs, don’t support automatic rotation, and are used for signing/verification or public key encryption scenarios.
Can I change my key type or usage after creation?
No. The customerMasterKeySpec and keyUsage properties are immutable. Changing them requires creating a new key and re-encrypting your data.
Key Rotation
How does automatic key rotation work?
Set enableKeyRotation: true to enable automatic rotation (default is false). You can customize the rotation period using rotationPeriodInDays (90-2560 days). Rotation is only supported for symmetric encryption keys, not asymmetric or HMAC keys.
Why can't I enable rotation on my asymmetric or HMAC key?
Automatic key rotation only works with symmetric encryption keys (SYMMETRIC_DEFAULT). Asymmetric keys (RSA, ECC) and HMAC keys don’t support automatic rotation, as shown in the examples where enableKeyRotation is set to false for these key types.
Multi-Region Keys
How do I create a multi-Region key?
Set multiRegion: true when creating the key. Multi-Region keys can be replicated to other regions and support automatic rotation just like regional keys. The default is false (regional key).
Can I convert a regional key to multi-Region?
No. The multiRegion property is immutable. You’ll need to create a new multi-Region key and migrate your data.
What happens when I delete a multi-Region primary key?
For multi-Region primary keys with replicas, the deletion waiting period begins only when the last replica key is deleted. Delete all replica keys first, or expect extended deletion timing.
Key Lifecycle & Deletion
What properties can't be changed after creating a key?
The following properties are immutable: multiRegion, customerMasterKeySpec, keyUsage, customKeyStoreId, and xksKeyId. Changing any of these forces recreation of the key.
How long is the deletion window for a KMS key?
The deletion waiting period (deletionWindowInDays) must be between 7 and 30 days, with a default of 30 days. During this window, you can cancel the deletion. After the window ends, AWS KMS deletes the key permanently.

Ready to get started?

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

Create free account