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
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.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
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.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.customerMasterKeySpec and keyUsage properties are immutable. Changing them requires creating a new key and re-encrypting your data.Key Rotation
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.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
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).multiRegion property is immutable. You’ll need to create a new multi-Region key and migrate your data.Key Lifecycle & Deletion
multiRegion, customerMasterKeySpec, keyUsage, customKeyStoreId, and xksKeyId. Changing any of these forces recreation of the key.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