Skip to content

[ARCH-332] KMS keystore support#1767

Merged
connorwstein merged 17 commits into
mainfrom
ARCH-332-kms
Jan 14, 2026
Merged

[ARCH-332] KMS keystore support#1767
connorwstein merged 17 commits into
mainfrom
ARCH-332-kms

Conversation

@connorwstein
Copy link
Copy Markdown
Contributor

@connorwstein connorwstein commented Jan 12, 2026

It seems ed25519 is now also supported in KMS. Will add in a follow up.

Confirmed CLI works against real KMS in staging.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 12, 2026

✅ API Diff Results - No breaking changes


📄 View full apidiff report

Comment thread keystore/kms/asn1.go
"github.com/ethereum/go-ethereum/crypto/secp256k1"
)

// SPKI represents the SubjectPublicKeyInfo structure as defined in [RFC 5280] in ASN.1 format.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is partially lifted from https://github.com/smartcontractkit/chainlink-deployments-framework/blob/main/chain/evm/provider/kms_signer.go, however with the following changes:

  • Ethereum specific terminology removed. SEC1 is a format thats used in Ethereums and blockchains in general, but its not ethereum specific.
  • Added SEC1->ASN1 conversion functions as well so we can just round trip test converting sig/pubkeys between the 2 formats.

Originally I was going to keep it internal, but if I export the helpers then I can remove the second impl in chainlink-deployments-framework.

Comment thread keystore/kms/client.go
kmslib "github.com/aws/aws-sdk-go/service/kms"
)

// Client is an interface that defines the methods for interacting with AWS KMS. We only expose
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to whats used in CLD, except I exposed another 2 functions to allow for the Reader interface to be implemented. I also dropped the region stuff, that can be specified in the AWS profile so seems simpler to just let people specify that there.

KeyID string
}

func NewFakeKMSClient(keys []Key) (*FakeKMSClient, error) {
Copy link
Copy Markdown
Contributor Author

@connorwstein connorwstein Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A fake seemed to fit well here instead of mocking/mockery

Comment thread keystore/cli/cli.go
Short: "CLI for managing keystore keys",
SilenceUsage: true,
}
cmd.PersistentFlags().String("file-path", "", "Overrides KEYSTORE_FILE_PATH environment variable")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought I don't think these are worth the trouble just removing them (would have to add another one for KMS too).

Comment thread keystore/cli/cli.go
cmd.PersistentFlags().String("password", "", "Overrides KEYSTORE_PASSWORD environment variable. Not recommended as will leave shell traces.")

cmd.AddCommand(NewListCmd(), NewGetCmd(), NewCreateCmd(), NewDeleteCmd(), NewExportCmd(), NewImportCmd(), NewSetMetadataCmd(), NewSignCmd(), NewVerifyCmd(), NewEncryptCmd(), NewDecryptCmd())
// Check if KMS profile is set - if so, hide commands that don't work with KMS
Copy link
Copy Markdown
Contributor Author

@connorwstein connorwstein Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI can't be used to create KMS keys, so we hide admin intf

Comment thread keystore/kms/asn1.go Outdated
Comment thread keystore/kms/asn1.go

// padTo32Bytes pads the given byte slice to 32 bytes by trimming leading zeros and prepending
// zeros.
func padTo32Bytes(buffer []byte) []byte {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, what would this function do with make([]byte, 32) input? Will it 1. first trim each of the 32 bytes since they are zero, and 2. then readd each zero byte to the slice?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it would, I suppose it could be optimized for that specific case. But doesn't seem worth the trouble

Comment thread keystore/kms/keystore.go
}

keys = append(keys, keystore.GetKeyResponse{
KeyInfo: keystore.KeyInfo{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should newKeyInfo be used instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its unexported right now from the main package, I think we could export it though and use it. Can do in the next PR (planning to add ed25519 support for KMS next)

Comment thread keystore/cli/cli.go
Comment on lines +395 to +397
kmsProfile := os.Getenv("KEYSTORE_KMS_PROFILE")
if kmsProfile != "" {
client, err := kms.NewClient(kmsProfile)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this work with KMS already set in the environment variables? For example, does this work with aws-vault, which I know a lot of people use to have AWS tokens in the Apple Keychain.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I believe so because the profile credentials are top of the priority stack. Haven't tested that, but I suspect the KMS pointer/config may need to iterate a bit as we try it out in different scenarios

@connorwstein connorwstein added this pull request to the merge queue Jan 14, 2026
Merged via the queue into main with commit 3ff7d6f Jan 14, 2026
35 of 36 checks passed
@connorwstein connorwstein deleted the ARCH-332-kms branch January 14, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants