AWS KMS
Configure AWS KMS for deployment
Overview
The Guardian Platform uses AWS Key Management Service (KMS) for managing cryptographic keys for DID (Decentralized Identifier) signing operations.
AWS KMS provides:
- Managed Key Storage – Secure, FIPS 140-3 validated hardware security modules
- Audit Trail – CloudTrail integration for all key usage
Platform behavior:
- Automatically creates and manages KMS keys with the configured alias prefix
- Stores key IDs in the database
- Uses asymmetric keys (ECC_SECG_P256K1) for signing operations
This guide covers:
- Setting up an IAM user with KMS permissions (CLI or AWS Console), or an IAM role on EKS
- Configuring the Helm chart for AWS KMS
- Verifying the configuration
Prerequisites
- AWS account with permissions to use KMS and create IAM policies and users, or roles for an IAM role
- AWS CLI installed and configured (for CLI method)
- AWS region selected for key storage (e.g.
us-east-1)
Helm Configuration
Add the following to the values.yaml and secrets.yaml files. Placeholders will be filled in throughout the steps below.
values.yaml:
auth-service:
config:
keyManagement:
provider: "aws_kms"
aws_kms:
region: "<aws-region>" # Chosen before step 1
aliasPrefix: "alias/eqtylab/did"
deletionWindowDays: 7 # 7–30secrets.yaml:
global:
secrets:
create: true
keyManagement:
provider: "aws_kms"
aws_kms:
secretName: "platform-aws-kms"
values:
accessKeyId: "<access-key-id>" # Filled in after step 4
secretAccessKey: "<secret-access-key>" # Filled in after step 4
sessionToken: ""With an IAM role, Auth Service needs no access key, and these values stay out of secrets.yaml.
Quick Start (CLI Method - Recommended)
Choose an AWS region for key storage (e.g. us-east-1, eu-west-1). Update values.yaml with the chosen region.
values.yaml -> auth-service.config.keyManagement.aws_kms:
region: "<aws-region>"1. Create IAM Policy
To find the AWS account ID:
aws sts get-caller-identity --query Account --output textCreate a policy document file named kms-policy.json with the following content. Replace <aws-region> and <account-id>, and change alias/eqtylab/did if you set a different aliasPrefix:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowKMSKeyCreation",
"Effect": "Allow",
"Action": "kms:CreateKey",
"Resource": "*"
},
{
"Sid": "AllowPrefixedAliases",
"Effect": "Allow",
"Action": ["kms:CreateAlias", "kms:DeleteAlias"],
"Resource": "arn:aws:kms:<aws-region>:<account-id>:alias/eqtylab/did/*"
}
]
}Note on permissions: the IAM policy grants no operations on existing keys. Auth Service sets a key policy on each key it creates, granting its own IAM user or role describe, public key, sign, tag, alias, and deletion operations on that key only. The account root keeps kms:* so IAM administrators stay in control, which lets Auth Service skip the KMS policy lockout safety check without granting itself kms:PutKeyPolicy. An SCP or IAM policy that denies kms:BypassPolicyLockoutSafetyCheck blocks key creation. The platform user cannot sign with, tag, alias, or delete any other key in the account.
The key policy each new key gets, where <platform-principal-arn> is the IAM user you create in step 2, or the role Auth Service runs as (AWS GovCloud and China Regions use their own partition in both ARNs):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnableIAMUserPermissions",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::<account-id>:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowGuardianPlatformKeyUse",
"Effect": "Allow",
"Principal": { "AWS": "<platform-principal-arn>" },
"Action": [
"kms:CreateAlias",
"kms:DeleteAlias",
"kms:DescribeKey",
"kms:GetPublicKey",
"kms:ScheduleKeyDeletion",
"kms:Sign",
"kms:TagResource"
],
"Resource": "*"
}
]
}Auth Service finds its IAM user or role from the credentials it runs with, using STS. An assumed role (IRSA or an instance profile) maps to its role ARN without a path, so for a role with a path, or a cluster that cannot reach STS, set the full ARN in values.yaml:
auth-service:
config:
keyManagement:
aws_kms:
keyPolicyPrincipalArn: "arn:aws:iam::<account-id>:role/<path>/<role-name>"Create the IAM policy:
aws iam create-policy \
--policy-name governance-kms-access \
--policy-document file://kms-policy.json \
--description "Allows Guardian Platform to manage KMS keys for DID signing"Save the policy ARN from the output — it will look like arn:aws:iam::123456789012:policy/governance-kms-access.
2. Create IAM User
aws iam create-user --user-name guardian-platform-kms3. Attach Policy to User
Attach the policy. Replace <account-id> with the value from step 1:
aws iam attach-user-policy \
--user-name guardian-platform-kms \
--policy-arn arn:aws:iam::<account-id>:policy/governance-kms-access4. Create Access Key
aws iam create-access-key --user-name guardian-platform-kmsSave both the AccessKeyId and SecretAccessKey from the output. The secret access key is only shown once and cannot be retrieved later.
The output will look like:
{
"AccessKey": {
"UserName": "guardian-platform-kms",
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Status": "Active"
}
}Update secrets.yaml with the credentials.
secrets.yaml -> global.secrets.keyManagement.aws_kms.values:
accessKeyId: "<access-key-id>"
secretAccessKey: "<secret-access-key>"Alternative: Web UI Setup
Click to expand AWS Console instructions
Using the AWS Console
1. Create IAM Policy
- Navigate to IAM console
- Go to Policies > Create policy
- Switch to JSON editor
- Paste the KMS policy JSON from step 1 above
- Name: “governance-kms-access”
- Create the policy
2. Create IAM User
- Navigate to IAM > Users
- Click “Create user”
- Username: “guardian-platform-kms”
- Click “Next”
3. Attach Policy
- Select “Attach policies directly”
- Search for “governance-kms-access”
- Select the policy
- Click “Next” and “Create user”
4. Create Access Key
- Click on the created user
- Navigate to “Security credentials” tab
- Click “Create access key”
- Select “Application running outside AWS”
- Click “Next” and “Create access key”
- Save the Access Key ID and Secret Access Key
Update secrets.yaml with the credentials.
secrets.yaml -> global.secrets.keyManagement.aws_kms.values:
accessKeyId: "<access-key-id>"
secretAccessKey: "<secret-access-key>"IAM Roles for Service Accounts
On EKS, Auth Service can use an IAM role through IAM roles for service accounts instead of an access key. Attach the step 1 policy to a role that trusts Auth Service’s Kubernetes service account, skip steps 2 to 4, leave global.secrets.keyManagement.aws_kms.values out of secrets.yaml, and set:
values.yaml:
auth-service:
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::<account-id>:role/<role-name>"
config:
keyManagement:
aws_kms:
useIamRole: trueWith useIamRole set, the chart omits the access key variables and does not create or read the platform-aws-kms secret, and Auth Service uses the AWS SDK’s default credential chain. The role is the key policy’s <platform-principal-arn>; for a role with a path, set keyPolicyPrincipalArn as in step 1.
Nodes with an instance profile work the same way without IRSA: attach the step 1 policy to the node role and leave out serviceAccount. Every pod on those nodes can then use the role.
Verification
Auth Service creates the shared platform key, alias/eqtylab/did/organization-key, at startup. After installing, confirm it exists using the IAM user’s credentials from step 4 (with an IAM role, use credentials for an identity the key policy allows, such as an account administrator):
export AWS_ACCESS_KEY_ID="<access-key-id>"
export AWS_SECRET_ACCESS_KEY="<secret-access-key>"Describe the platform key (should return "KeySpec": "ECC_SECG_P256K1"):
aws kms describe-key --key-id alias/eqtylab/did/organization-key --region <aws-region>Read its public key (should succeed):
aws kms get-public-key --key-id alias/eqtylab/did/organization-key --region <aws-region>Clean up the temporary credentials:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEYIf the key is missing, check the Auth Service logs for KMS AccessDeniedException errors.
Key Management
The Guardian Platform will automatically:
- Create new KMS keys as needed for DID signing
- Name each alias
<aliasPrefix>/<user-id>, with|and any character other than letters, digits,/,:,-, and_replaced by-; the shared platform key is<aliasPrefix>/organization-key - Set the key policy from step 1, which limits the platform user to its own keys, then tag each key with
userId,type: did, anddidKeyId - Store key IDs in the platform database
- Cache keys according to the configured TTL
Note: Manual key creation is not supported. The platform manages all key lifecycle operations automatically.
Security Best Practices
- Audit Logging: Enable CloudTrail to log all KMS operations for compliance and security monitoring
- Access Key Rotation: Regularly rotate IAM access keys and update Kubernetes secrets
- Secure Storage: Store IAM credentials in Kubernetes secrets with appropriate RBAC restrictions
- Key Deletion: Be cautious when deleting keys — the platform stores key IDs in the database and expects keys to persist
Cost Considerations
- Key Storage: $1/month per key
- API Requests: $0.15 per 10,000 ECC sign requests; requests to asymmetric keys are excluded from the free tier
- The platform creates one key per DID, so costs scale with the number of DIDs
Consider budgeting and setting up billing alerts.
Official Documentation
- AWS KMS CLI Reference
- AWS KMS Developer Guide
- KMS Best Practices
- Asymmetric Keys in KMS
- Helm Chart Examples
Related
- Key Management — how AWS KMS compares with the other key providers
- Key Configuration — what Auth Service signs with these keys and how to plan rotation
- Backup and Restore — protecting non-exportable keys from deletion
- AWS S3 Bucket — the AWS object storage the platform needs
- AWS RDS — the AWS managed database the platform can use
- Chart Values — the full values and secrets files these settings go into