The aws:kms/customKeyStore:CustomKeyStore resource, part of the Pulumi AWS provider, connects AWS KMS to external cryptographic hardware or key management systems. This guide focuses on two capabilities: CloudHSM cluster integration and external key store connectivity through VPC or public endpoints.
Custom key stores require either a CloudHSM cluster or an external XKS proxy deployment with appropriate network connectivity. The examples are intentionally small. Combine them with your own HSM clusters, VPC infrastructure, or external key management systems.
Connect KMS to a CloudHSM cluster
Organizations with strict key management requirements often use CloudHSM to maintain physical control over cryptographic operations.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const test = new aws.kms.CustomKeyStore("test", {
cloudHsmClusterId: cloudHsmClusterId,
customKeyStoreName: "kms-custom-key-store-test",
keyStorePassword: "noplaintextpasswords1",
trustAnchorCertificate: std.file({
input: "anchor-certificate.crt",
}).then(invoke => invoke.result),
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std
test = aws.kms.CustomKeyStore("test",
cloud_hsm_cluster_id=cloud_hsm_cluster_id,
custom_key_store_name="kms-custom-key-store-test",
key_store_password="noplaintextpasswords1",
trust_anchor_certificate=std.file(input="anchor-certificate.crt").result)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
invokeFile, err := std.File(ctx, &std.FileArgs{
Input: "anchor-certificate.crt",
}, nil)
if err != nil {
return err
}
_, err = kms.NewCustomKeyStore(ctx, "test", &kms.CustomKeyStoreArgs{
CloudHsmClusterId: pulumi.Any(cloudHsmClusterId),
CustomKeyStoreName: pulumi.String("kms-custom-key-store-test"),
KeyStorePassword: pulumi.String("noplaintextpasswords1"),
TrustAnchorCertificate: pulumi.String(invokeFile.Result),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var test = new Aws.Kms.CustomKeyStore("test", new()
{
CloudHsmClusterId = cloudHsmClusterId,
CustomKeyStoreName = "kms-custom-key-store-test",
KeyStorePassword = "noplaintextpasswords1",
TrustAnchorCertificate = Std.File.Invoke(new()
{
Input = "anchor-certificate.crt",
}).Apply(invoke => invoke.Result),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.CustomKeyStore;
import com.pulumi.aws.kms.CustomKeyStoreArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.FileArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var test = new CustomKeyStore("test", CustomKeyStoreArgs.builder()
.cloudHsmClusterId(cloudHsmClusterId)
.customKeyStoreName("kms-custom-key-store-test")
.keyStorePassword("noplaintextpasswords1")
.trustAnchorCertificate(StdFunctions.file(FileArgs.builder()
.input("anchor-certificate.crt")
.build()).result())
.build());
}
}
resources:
test:
type: aws:kms:CustomKeyStore
properties:
cloudHsmClusterId: ${cloudHsmClusterId}
customKeyStoreName: kms-custom-key-store-test
keyStorePassword: noplaintextpasswords1
trustAnchorCertificate:
fn::invoke:
function: std:file
arguments:
input: anchor-certificate.crt
return: result
When you create a CloudHSM-backed custom key store, KMS delegates cryptographic operations to your HSM cluster. The cloudHsmClusterId identifies your cluster, keyStorePassword authenticates KMS to the cluster, and trustAnchorCertificate establishes trust. KMS keys created in this store have their key material generated and stored in your HSM hardware.
Connect to an external key manager via VPC endpoint
Some organizations maintain their own key management infrastructure and need KMS to delegate operations to external systems over private networking.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.kms.CustomKeyStore("example", {
customKeyStoreName: "example-vpc-xks",
customKeyStoreType: "EXTERNAL_KEY_STORE",
xksProxyAuthenticationCredential: {
accessKeyId: ephemeralAccessKeyId,
rawSecretAccessKey: ephemeralSecretAccessKey,
},
xksProxyConnectivity: "VPC_ENDPOINT_SERVICE",
xksProxyUriEndpoint: "https://myproxy-private.xks.example.com",
xksProxyUriPath: "/kms/xks/v1",
xksProxyVpcEndpointServiceName: "com.amazonaws.vpce.us-east-1.vpce-svc-example",
});
import pulumi
import pulumi_aws as aws
example = aws.kms.CustomKeyStore("example",
custom_key_store_name="example-vpc-xks",
custom_key_store_type="EXTERNAL_KEY_STORE",
xks_proxy_authentication_credential={
"access_key_id": ephemeral_access_key_id,
"raw_secret_access_key": ephemeral_secret_access_key,
},
xks_proxy_connectivity="VPC_ENDPOINT_SERVICE",
xks_proxy_uri_endpoint="https://myproxy-private.xks.example.com",
xks_proxy_uri_path="/kms/xks/v1",
xks_proxy_vpc_endpoint_service_name="com.amazonaws.vpce.us-east-1.vpce-svc-example")
package main
import (
"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 {
_, err := kms.NewCustomKeyStore(ctx, "example", &kms.CustomKeyStoreArgs{
CustomKeyStoreName: pulumi.String("example-vpc-xks"),
CustomKeyStoreType: pulumi.String("EXTERNAL_KEY_STORE"),
XksProxyAuthenticationCredential: &kms.CustomKeyStoreXksProxyAuthenticationCredentialArgs{
AccessKeyId: pulumi.Any(ephemeralAccessKeyId),
RawSecretAccessKey: pulumi.Any(ephemeralSecretAccessKey),
},
XksProxyConnectivity: pulumi.String("VPC_ENDPOINT_SERVICE"),
XksProxyUriEndpoint: pulumi.String("https://myproxy-private.xks.example.com"),
XksProxyUriPath: pulumi.String("/kms/xks/v1"),
XksProxyVpcEndpointServiceName: pulumi.String("com.amazonaws.vpce.us-east-1.vpce-svc-example"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Kms.CustomKeyStore("example", new()
{
CustomKeyStoreName = "example-vpc-xks",
CustomKeyStoreType = "EXTERNAL_KEY_STORE",
XksProxyAuthenticationCredential = new Aws.Kms.Inputs.CustomKeyStoreXksProxyAuthenticationCredentialArgs
{
AccessKeyId = ephemeralAccessKeyId,
RawSecretAccessKey = ephemeralSecretAccessKey,
},
XksProxyConnectivity = "VPC_ENDPOINT_SERVICE",
XksProxyUriEndpoint = "https://myproxy-private.xks.example.com",
XksProxyUriPath = "/kms/xks/v1",
XksProxyVpcEndpointServiceName = "com.amazonaws.vpce.us-east-1.vpce-svc-example",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.CustomKeyStore;
import com.pulumi.aws.kms.CustomKeyStoreArgs;
import com.pulumi.aws.kms.inputs.CustomKeyStoreXksProxyAuthenticationCredentialArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new CustomKeyStore("example", CustomKeyStoreArgs.builder()
.customKeyStoreName("example-vpc-xks")
.customKeyStoreType("EXTERNAL_KEY_STORE")
.xksProxyAuthenticationCredential(CustomKeyStoreXksProxyAuthenticationCredentialArgs.builder()
.accessKeyId(ephemeralAccessKeyId)
.rawSecretAccessKey(ephemeralSecretAccessKey)
.build())
.xksProxyConnectivity("VPC_ENDPOINT_SERVICE")
.xksProxyUriEndpoint("https://myproxy-private.xks.example.com")
.xksProxyUriPath("/kms/xks/v1")
.xksProxyVpcEndpointServiceName("com.amazonaws.vpce.us-east-1.vpce-svc-example")
.build());
}
}
resources:
example:
type: aws:kms:CustomKeyStore
properties:
customKeyStoreName: example-vpc-xks
customKeyStoreType: EXTERNAL_KEY_STORE
xksProxyAuthenticationCredential:
accessKeyId: ${ephemeralAccessKeyId}
rawSecretAccessKey: ${ephemeralSecretAccessKey}
xksProxyConnectivity: VPC_ENDPOINT_SERVICE
xksProxyUriEndpoint: https://myproxy-private.xks.example.com
xksProxyUriPath: /kms/xks/v1
xksProxyVpcEndpointServiceName: com.amazonaws.vpce.us-east-1.vpce-svc-example
The customKeyStoreType property set to EXTERNAL_KEY_STORE tells KMS to use an external proxy rather than CloudHSM. The xksProxyConnectivity value of VPC_ENDPOINT_SERVICE routes traffic through a VPC endpoint service, keeping communication private. The xksProxyAuthenticationCredential block provides access credentials, while xksProxyUriEndpoint and xksProxyUriPath define where KMS sends cryptographic requests.
Connect to an external key manager via public endpoint
When external key management systems are accessible over the internet, KMS can connect through public endpoints without VPC infrastructure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.kms.CustomKeyStore("example", {
customKeyStoreName: "example-public-xks",
customKeyStoreType: "EXTERNAL_KEY_STORE",
xksProxyAuthenticationCredential: {
accessKeyId: ephemeralAccessKeyId,
rawSecretAccessKey: ephemeralSecretAccessKey,
},
xksProxyConnectivity: "PUBLIC_ENDPOINT",
xksProxyUriEndpoint: "https://myproxy.xks.example.com",
xksProxyUriPath: "/kms/xks/v1",
});
import pulumi
import pulumi_aws as aws
example = aws.kms.CustomKeyStore("example",
custom_key_store_name="example-public-xks",
custom_key_store_type="EXTERNAL_KEY_STORE",
xks_proxy_authentication_credential={
"access_key_id": ephemeral_access_key_id,
"raw_secret_access_key": ephemeral_secret_access_key,
},
xks_proxy_connectivity="PUBLIC_ENDPOINT",
xks_proxy_uri_endpoint="https://myproxy.xks.example.com",
xks_proxy_uri_path="/kms/xks/v1")
package main
import (
"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 {
_, err := kms.NewCustomKeyStore(ctx, "example", &kms.CustomKeyStoreArgs{
CustomKeyStoreName: pulumi.String("example-public-xks"),
CustomKeyStoreType: pulumi.String("EXTERNAL_KEY_STORE"),
XksProxyAuthenticationCredential: &kms.CustomKeyStoreXksProxyAuthenticationCredentialArgs{
AccessKeyId: pulumi.Any(ephemeralAccessKeyId),
RawSecretAccessKey: pulumi.Any(ephemeralSecretAccessKey),
},
XksProxyConnectivity: pulumi.String("PUBLIC_ENDPOINT"),
XksProxyUriEndpoint: pulumi.String("https://myproxy.xks.example.com"),
XksProxyUriPath: pulumi.String("/kms/xks/v1"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Kms.CustomKeyStore("example", new()
{
CustomKeyStoreName = "example-public-xks",
CustomKeyStoreType = "EXTERNAL_KEY_STORE",
XksProxyAuthenticationCredential = new Aws.Kms.Inputs.CustomKeyStoreXksProxyAuthenticationCredentialArgs
{
AccessKeyId = ephemeralAccessKeyId,
RawSecretAccessKey = ephemeralSecretAccessKey,
},
XksProxyConnectivity = "PUBLIC_ENDPOINT",
XksProxyUriEndpoint = "https://myproxy.xks.example.com",
XksProxyUriPath = "/kms/xks/v1",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.CustomKeyStore;
import com.pulumi.aws.kms.CustomKeyStoreArgs;
import com.pulumi.aws.kms.inputs.CustomKeyStoreXksProxyAuthenticationCredentialArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new CustomKeyStore("example", CustomKeyStoreArgs.builder()
.customKeyStoreName("example-public-xks")
.customKeyStoreType("EXTERNAL_KEY_STORE")
.xksProxyAuthenticationCredential(CustomKeyStoreXksProxyAuthenticationCredentialArgs.builder()
.accessKeyId(ephemeralAccessKeyId)
.rawSecretAccessKey(ephemeralSecretAccessKey)
.build())
.xksProxyConnectivity("PUBLIC_ENDPOINT")
.xksProxyUriEndpoint("https://myproxy.xks.example.com")
.xksProxyUriPath("/kms/xks/v1")
.build());
}
}
resources:
example:
type: aws:kms:CustomKeyStore
properties:
customKeyStoreName: example-public-xks
customKeyStoreType: EXTERNAL_KEY_STORE
xksProxyAuthenticationCredential:
accessKeyId: ${ephemeralAccessKeyId}
rawSecretAccessKey: ${ephemeralSecretAccessKey}
xksProxyConnectivity: PUBLIC_ENDPOINT
xksProxyUriEndpoint: https://myproxy.xks.example.com
xksProxyUriPath: /kms/xks/v1
This configuration mirrors the VPC example but sets xksProxyConnectivity to PUBLIC_ENDPOINT and omits xksProxyVpcEndpointServiceName. KMS connects directly to the public DNS name specified in xksProxyUriEndpoint. The external proxy must be internet-accessible and secured with TLS.
Beyond these examples
These snippets focus on specific custom key store features: CloudHSM integration and external key store connectivity (VPC and public). They’re intentionally minimal rather than complete key management solutions.
The examples reference pre-existing infrastructure such as CloudHSM clusters with trust anchor certificates, VPC endpoint services for private connectivity, and external XKS proxy deployments. They focus on connecting KMS to external systems rather than provisioning the underlying infrastructure.
To keep things focused, common custom key store patterns are omitted, including:
- Key store lifecycle management (connecting, disconnecting, deleting)
- Credential rotation for XKS authentication
- TLS certificate validation for proxy endpoints
- Error handling and connection monitoring
These omissions are intentional: the goal is to illustrate how each connectivity model is wired, not provide drop-in key management modules. See the KMS Custom Key Store resource reference for all available configuration options.
Let's configure AWS KMS Custom Key Stores
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Types
AWS_CLOUDHSM (the default) and EXTERNAL_KEY_STORE. If you don’t specify customKeyStoreType, AWS defaults to AWS_CLOUDHSM.cloudHsmClusterId, keyStorePassword, and trustAnchorCertificate (loaded from a file).xksProxyAuthenticationCredential (with access key ID and secret), xksProxyConnectivity, xksProxyUriEndpoint, and xksProxyUriPath.Immutability & Limitations
customKeyStoreType, cloudHsmClusterId, and trustAnchorCertificate. Changing any of these requires replacing the resource.External Key Store Setup
VPC_ENDPOINT_SERVICE) uses xksProxyVpcEndpointServiceName for private access through a VPC endpoint. Public connectivity (PUBLIC_ENDPOINT) accesses the proxy over the internet without VPC configuration.xksProxyAuthenticationCredential with accessKeyId and rawSecretAccessKey for authentication.region property determines where the key store is managed, defaulting to your provider’s region.