Skip to content

Conversation

hslatman
Copy link
Member

@hslatman hslatman commented Mar 27, 2025

This PR:

  • Adds support for creating API tokens using mTLS with private keys backed by a KMS, such as a TPM.
    • The use of a KMS is transparently detected by parsing the filename of the key to contain a (supported) KMS scheme.
    • TSS2 PEM encoded private keys are automatically detected based on the PEM header.
  • Adds support for supplying a password for the private key using the --password-file flag.
  • Adds User-Agent and X-Request-Id HTTP request headers.

Using an ECDSA key:

$ step api token create <team-slug> ecdsa-chain.crt 'tpmkms:name=test-ecdsa;device=/path/to/tpmsimulator.sock'
✔ Token successfully created:
<token>

Using an RSA key:

$ step api token create <team-slug> rsa-chain.crt 'tpmkms:name=test-rsa;device=/path/to/tpmsimulator.sock'
✔ Token successfully created:
<token>

Using the TSS2 PEM encoded private key (exported using step tpm key get 'test-rsa' --device '/path/to/tpmsimulator.sock' --storage-directory /path/to/tpmstorage --tss2 > tpmrsa.tss2.pem), specified as a tpmkms URI:

$ step api token create <team-slug> rsa-chain.crt 'tpmkms:path=./tpmrsa.tss2.pem;device=/path/to/tpmsimulator.sock'
✔ Token successfully created:
<token>

Using the same TSS2 PEM encoded private key directly:

$ step api token create <team-slug> rsa-chain.crt tpmrsa.tss2.pem --tpm-device '/path/to/tpmsimulator.sock'
✔ Token successfully created:
<token>

Note that the device and tpm-device flags and URI parts can be omitted in case the default system TPM locations are to be used. The use of a TPM simulator is just for demonstration and testing purposes.

@hslatman hslatman changed the title Add support for creating API tokens backed by KMS signer Add support for creating API tokens backed by KMS signer (WIP) Mar 27, 2025
@github-actions github-actions bot added the needs triage Waiting for discussion / prioritization by team label Mar 27, 2025
azazeal
azazeal previously approved these changes Mar 27, 2025
@hslatman hslatman force-pushed the herman/policy-scep-prompt-fixes branch from 4f46e13 to 064866f Compare March 27, 2025 18:50
@hslatman hslatman force-pushed the herman/kms-api-token branch from 52d9a4b to cd18588 Compare March 28, 2025 11:24
@hslatman hslatman marked this pull request as ready for review March 28, 2025 13:11
@hslatman hslatman force-pushed the herman/kms-api-token branch from a71ac72 to 8a7cd1b Compare March 28, 2025 13:16
@hslatman hslatman requested review from azazeal and a team March 28, 2025 17:15
@hslatman hslatman changed the title Add support for creating API tokens backed by KMS signer (WIP) Add support for creating API tokens backed by KMS signer Mar 28, 2025
@hslatman hslatman changed the title Add support for creating API tokens backed by KMS signer Add support for creating API tokens backed by KMS signer (WIP) Mar 28, 2025
@hslatman hslatman added this to the v0.28.7 milestone Mar 28, 2025
Base automatically changed from herman/policy-scep-prompt-fixes to master March 28, 2025 18:11
@hslatman hslatman dismissed azazeal’s stale review March 28, 2025 18:11

The base branch was changed.

@hslatman hslatman force-pushed the herman/kms-api-token branch from 39ea27c to e53225b Compare March 28, 2025 18:12
@hslatman hslatman requested a review from maraino April 1, 2025 17:06
Copy link
Collaborator

@maraino maraino left a comment

Choose a reason for hiding this comment

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

Just a couple of minor things

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add a test that compares this with the one in the standard library?

func createClientCertificate(crtFile, keyFile, passwordFile, tpmDevice string) (*tls.Certificate, error) {
certs, err := pemutil.ReadCertificateBundle(crtFile)
if err != nil {
return nil, fmt.Errorf("failed reading %q: %w", crtFile, err)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Pemutil already returns a wrapped error, if we wrap it again, we will get:

failed reading "foo.crt": error parsing foo.crt: open foo.crt: no such file or directory

If we want a nicer message, we can fix crypto or use something like:

func maybeUnwrap(err error) error {
	if wrapped := errors.Unwrap(err); wrapped != nil {
		return wrapped
	}
	return err
}

// options, such as specifying the TPM device that backs the TSS2
// signer.
p, _ := pem.Decode(b)
if p.Type != "TSS2 PRIVATE KEY" {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've just added this smallstep/crypto#743 to avoid this condition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage Waiting for discussion / prioritization by team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants