Files
nomad/api/keyring.go
Tim Gross 2f4353412d keyring: support prepublishing keys (#23577)
When a root key is rotated, the servers immediately start signing Workload
Identities with the new active key. But workloads may be using those WI tokens
to sign into external services, which may not have had time to fetch the new
public key and which might try to fetch new keys as needed.

Add support for prepublishing keys. Prepublished keys will be visible in the
JWKS endpoint but will not be used for signing or encryption until their
`PublishTime`. Update the periodic key rotation to prepublish keys at half the
`root_key_rotation_threshold` window, and promote prepublished keys to active
after the `PublishTime`.

This changeset also fixes two bugs in periodic root key rotation and garbage
collection, both of which can't be safely fixed without implementing
prepublishing:

* Periodic root key rotation would never happen because the default
  `root_key_rotation_threshold` of 720h exceeds the 72h maximum window of the FSM
  time table. We now compare the `CreateTime` against the wall clock time instead
  of the time table. (We expect to remove the time table in future work, ref
  https://github.com/hashicorp/nomad/issues/16359)
* Root key garbage collection could GC keys that were used to sign
  identities. We now wait until `root_key_rotation_threshold` +
  `root_key_gc_threshold` before GC'ing a key.
* When rekeying a root key, the core job did not mark the key as inactive after
  the rekey was complete.

Ref: https://hashicorp.atlassian.net/browse/NET-10398
Ref: https://hashicorp.atlassian.net/browse/NET-10280
Fixes: https://github.com/hashicorp/nomad/issues/19669
Fixes: https://github.com/hashicorp/nomad/issues/23528
Fixes: https://github.com/hashicorp/nomad/issues/19368
2024-07-19 13:29:41 -04:00

98 lines
2.5 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"fmt"
"net/url"
)
// Keyring is used to access the Variables keyring.
type Keyring struct {
client *Client
}
// Keyring returns a handle to the Keyring endpoint
func (c *Client) Keyring() *Keyring {
return &Keyring{client: c}
}
// EncryptionAlgorithm chooses which algorithm is used for
// encrypting / decrypting entries with this key
type EncryptionAlgorithm string
const (
EncryptionAlgorithmAES256GCM EncryptionAlgorithm = "aes256-gcm"
)
// RootKeyMeta is the metadata used to refer to a RootKey.
type RootKeyMeta struct {
KeyID string // UUID
Algorithm EncryptionAlgorithm
CreateTime int64
CreateIndex uint64
ModifyIndex uint64
State RootKeyState
PublishTime int64
}
// RootKeyState enum describes the lifecycle of a root key.
type RootKeyState string
const (
RootKeyStateInactive RootKeyState = "inactive"
RootKeyStateActive = "active"
RootKeyStateRekeying = "rekeying"
RootKeyStateDeprecated = "deprecated"
RootKeyStatePrepublished = "prepublished"
)
// List lists all the keyring metadata
func (k *Keyring) List(q *QueryOptions) ([]*RootKeyMeta, *QueryMeta, error) {
var resp []*RootKeyMeta
qm, err := k.client.query("/v1/operator/keyring/keys", &resp, q)
if err != nil {
return nil, nil, err
}
return resp, qm, nil
}
// Delete deletes a specific inactive key from the keyring
func (k *Keyring) Delete(opts *KeyringDeleteOptions, w *WriteOptions) (*WriteMeta, error) {
wm, err := k.client.delete(fmt.Sprintf("/v1/operator/keyring/key/%v",
url.PathEscape(opts.KeyID)), nil, nil, w)
return wm, err
}
// KeyringDeleteOptions are parameters for the Delete API
type KeyringDeleteOptions struct {
KeyID string // UUID
}
// Rotate requests a key rotation
func (k *Keyring) Rotate(opts *KeyringRotateOptions, w *WriteOptions) (*RootKeyMeta, *WriteMeta, error) {
qp := url.Values{}
if opts != nil {
if opts.Algorithm != "" {
qp.Set("algo", string(opts.Algorithm))
}
if opts.Full {
qp.Set("full", "true")
}
if opts.PublishTime > 0 {
qp.Set("publish_time", fmt.Sprintf("%d", opts.PublishTime))
}
}
resp := &struct{ Key *RootKeyMeta }{}
wm, err := k.client.put("/v1/operator/keyring/rotate?"+qp.Encode(), nil, resp, w)
return resp.Key, wm, err
}
// KeyringRotateOptions are parameters for the Rotate API
type KeyringRotateOptions struct {
Full bool
Algorithm EncryptionAlgorithm
PublishTime int64
}