AWS KMS Integration (Pro)
AWS KMS integration requires ChainLaunch Pro. Learn more.
Use AWS Key Management Service as a key provider for cloud-native, FIPS 140-2 Level 3 validated key storage. Supports all key types including secp256k1 for Besu/Ethereum networks.
Authentication Modes
ChainLaunch supports four ways to authenticate with AWS KMS, from most to least recommended:
| Mode | Use when | Credentials needed |
|---|---|---|
| Instance role / IRSA | ChainLaunch runs on EC2 or EKS | None (automatic) |
| STS AssumeRole | Cross-account or least-privilege | Role ARN only |
| Named profile (SSO) | Local dev with AWS SSO | Profile name |
| Static credentials | Dev/testing with LocalStack | Access key + secret |
Option 1: Instance Role / IRSA (Recommended)
When ChainLaunch runs on EC2 or EKS, the AWS SDK picks up credentials automatically.
Prerequisites
Create an IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:CreateKey",
"kms:CreateAlias",
"kms:DeleteAlias",
"kms:DescribeKey",
"kms:GetPublicKey",
"kms:Sign",
"kms:Verify",
"kms:ListAliases",
"kms:ListKeys",
"kms:TagResource",
"kms:ScheduleKeyDeletion"
],
"Resource": "*"
}
]
}
Attach it to your EC2 instance profile or EKS service account.
Via API
curl -X POST http://localhost:8100/api/v1/key-providers \
-H "Content-Type: application/json" \
-d '{
"name": "aws-kms-production",
"type": "AWS_KMS",
"isDefault": true,
"awsKmsConfig": {
"operation": "IMPORT",
"awsRegion": "us-east-1",
"kmsKeyAliasPrefix": "chainlaunch/"
}
}'
No credentials needed — the SDK uses the instance role automatically.
Via Terraform
resource "chainlaunch_key_provider" "aws_kms" {
name = "aws-kms-production"
type = "AWS_KMS"
is_default = true
aws_kms_config = {
operation = "IMPORT"
aws_region = "us-east-1"
kms_key_alias_prefix = "chainlaunch/"
}
}
Option 2: STS AssumeRole
ChainLaunch assumes a dedicated IAM role. Works with instance role as base credentials or with static credentials from outside AWS.
resource "chainlaunch_key_provider" "aws_kms" {
name = "aws-kms-cross-account"
type = "AWS_KMS"
is_default = false
aws_kms_config = {
operation = "IMPORT"
aws_region = "us-east-1"
assume_role_arn = "arn:aws:iam::123456789012:role/ChainLaunchKMSRole"
external_id = "chainlaunch-unique-id"
kms_key_alias_prefix = "chainlaunch/"
}
}
The target role's trust policy must allow the ChainLaunch principal:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/ChainLaunchInstanceRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "chainlaunch-unique-id"
}
}
}
]
}
Option 3: Static Credentials (Dev/LocalStack)
For development with LocalStack or when running outside AWS:
resource "chainlaunch_key_provider" "aws_kms_local" {
name = "aws-kms-localstack"
type = "AWS_KMS"
is_default = false
aws_kms_config = {
operation = "IMPORT"
aws_region = "us-east-1"
aws_access_key_id = "test"
aws_secret_access_key = "test"
endpoint_url = "http://localhost:4566"
kms_key_alias_prefix = "chainlaunch/"
}
}
Never use static credentials in production. Use instance roles or STS AssumeRole instead.
Use KMS for an Organization
resource "chainlaunch_fabric_organization" "org1" {
msp_id = "Org1MSP"
description = "Production org with AWS KMS"
provider_id = tonumber(chainlaunch_key_provider.aws_kms.id)
}
Use KMS for Besu Validator Keys
AWS KMS supports secp256k1 — required for Besu/Ethereum:
resource "chainlaunch_key" "validator_keys" {
count = 4
name = "besu-validator-${count.index}"
algorithm = "EC"
curve = "secp256k1"
provider_id = tonumber(chainlaunch_key_provider.aws_kms.id)
}
resource "chainlaunch_besu_network" "main" {
name = "production-besu"
chain_id = 1337
consensus = "qbft"
block_period = 5
epoch_length = 30000
request_timeout = 10
initial_validator_key_ids = [
for key in chainlaunch_key.validator_keys : tonumber(key.id)
]
}
Supported Key Types
| Algorithm | Curves/Sizes | Supported | Notes |
|---|---|---|---|
| RSA | 2048, 4096 | Yes | |
| EC (ECDSA) | P-256, P-384 | Yes | NIST curves |
| EC (ECDSA) | secp256k1 | Yes | Ethereum/Besu curve |
| Ed25519 | — | No | Not supported by AWS KMS |
Verify Provider Status
curl http://localhost:8100/api/v1/key-providers/{providerId}/awskms/status | jq
Expected:
{
"kms_reachable": true,
"has_credentials": true,
"kms_status": "available"
}
Key Aliases
ChainLaunch creates KMS key aliases with the configured prefix:
chainlaunch/org1-identity-key
chainlaunch/org1-tls-key
chainlaunch/org1-ca-key
chainlaunch/besu-validator-0
You can view them in the AWS Console under KMS > Customer managed keys, or:
aws kms list-aliases --query 'Aliases[?starts_with(AliasName, `alias/chainlaunch/`)]'
Cost Considerations
| Operation | AWS Price | ChainLaunch usage |
|---|---|---|
| KMS key (per month) | $1.00 | 1 per node key |
| API request (per 10K) | $0.03 | Signs, encrypts |
| Asymmetric sign | $0.15/10K | Transaction signing |
For a 4-validator Besu network: ~$4/mo for keys + ~$1-5/mo for API calls.
Multi-Region
For disaster recovery, use KMS multi-region keys:
- Create a multi-region primary key in your main region
- Create replicas in backup regions
- ChainLaunch can use either the primary or replica — same key ID works
Troubleshooting
"kms_reachable: false"
- Check AWS credentials are valid:
aws sts get-caller-identity - Verify the region matches your KMS keys
- For LocalStack: ensure it's running on the configured endpoint
"Access Denied"
- Check the IAM policy has all required KMS actions
- For AssumeRole: verify the trust policy allows the ChainLaunch principal
- Check the external ID matches (if configured)
"KMS key not found"
- Verify the key alias prefix matches
- Check the key is in the correct region
- Ensure the key isn't in "Pending Deletion" state
Next Steps
- HashiCorp Vault Integration for on-premise key management
- Key Management for the complete overview
- Besu Genesis Configuration for Besu-specific key requirements