AWS KMS is an excellent piece of infrastructure. It is also frequently misused in SSH credential flows in ways that make incident response harder, not easier. The way we think about it is shaped by watching a handful of teams get bitten by the same mistakes.
What KMS actually gives you
KMS stores a master key you never see, encrypts/decrypts payloads under it, and logs every use. For SSH, the typical pattern is:
- Generate an SSH keypair in your CI or control plane.
- Encrypt the private key with KMS.
- Store the ciphertext in S3, Secrets Manager, or a database.
- At use time, decrypt the ciphertext with a KMS call.
This gives you: audit logs of who touched the key, centralized access control via IAM, and separation between “can see the encrypted blob” and “can decrypt it.”
Where it gets misused
Long-lived decrypted keys. Teams decrypt the key at app startup and hold it in memory for the process lifetime. If the app is compromised, so is the key. Decrypt per-use and zeroize.
Over-broad KMS grants. A single IAM role that can decrypt every SSH key in the org is the opposite of least privilege. Scope decrypt permissions per environment, and use KMS grants instead of IAM policies for fine-grained control.
Missing audit trails. CloudTrail logs every KMS Decrypt call, but only if you have a multi-region trail enabled. Many teams find this out during an incident.
The pattern that works
For SSH specifically, we use KMS to wrap session-scoped SSH certificates, not long-lived keys. The flow:
- Operator authenticates via SSO.
- Control plane mints a short-lived SSH cert signed by a CA private key.
- The CA private key lives in KMS; every signing operation is a
Signcall, the key itself never exits KMS. - The cert is delivered to the agent for the specific session.
- Cert expires in 15 minutes; no rotation needed.
Two properties fall out of this:
- The most sensitive secret (the CA private key) never leaves KMS.
- Every operator session shows up as a KMS
Signevent you can correlate to an operator identity.
When not to use KMS
If you don’t need audit or cross-account key sharing, a local KMS is overkill. For a single-region, single-account setup, Secrets Manager with rotation is simpler and serves most teams.
KMS is a force multiplier when you already have a multi-account, audit-heavy environment. It’s not a magic box that makes SSH safer, it’s a durable place to put the single keystone secret in a credential-minting flow.
Related posts
Ad-hoc scripts still need a paper trail
SSH in, run the fix, close the terminal. It worked, and six weeks later nobody can say what happened. What a script library and a recorded run change about that.
A release is not finished when it is applied
Most deploy tooling ends at apply. A release worth trusting has a verify stage after it, a rollback that is a button, and an approval that is not one person's judgement.
Patched is not protected: the reboot gap
A machine can be 97% compliant and still carry dozens of patches that are installed but not in effect. The number that matters sits in a different tile.