feat: add nats_ca crypto_key_feature enum value (#26761)

This commit is contained in:
Callum Styan
2026-06-26 11:59:00 -07:00
committed by GitHub
parent db6e5a2a55
commit 8ff2109298
8 changed files with 49 additions and 8 deletions
+20 -1
View File
@@ -5,6 +5,7 @@ import (
"crypto/rand"
"database/sql"
"encoding/hex"
"slices"
"time"
"golang.org/x/xerrors"
@@ -27,6 +28,24 @@ const (
DefaultKeyDuration = time.Hour * 24 * 30
)
// defaultRotatedFeatures are the crypto key features the rotator manages. It
// intentionally excludes features that are gated behind an experiment or
// deployment flag so that a dormant feature's enum value does not cause the
// rotator to mint keys it has no generator for. Gated features are opted in by
// the caller that owns their generator.
var defaultRotatedFeatures = []database.CryptoKeyFeature{
database.CryptoKeyFeatureWorkspaceAppsToken,
database.CryptoKeyFeatureWorkspaceAppsAPIKey,
database.CryptoKeyFeatureOIDCConvert,
database.CryptoKeyFeatureTailnetResume,
}
// DefaultRotatedFeatures returns the crypto key features the rotator manages by
// default. It excludes experiment-gated features such as the NATS CA.
func DefaultRotatedFeatures() []database.CryptoKeyFeature {
return slices.Clone(defaultRotatedFeatures)
}
// rotator is responsible for rotating keys in the database.
type rotator struct {
db database.Store
@@ -62,7 +81,7 @@ func StartRotator(ctx context.Context, logger slog.Logger, db database.Store, op
logger: logger.Named("keyrotator"),
clock: quartz.NewReal(),
keyDuration: DefaultKeyDuration,
features: database.AllCryptoKeyFeatureValues(),
features: defaultRotatedFeatures,
}
for _, opt := range opts {
+2 -2
View File
@@ -358,7 +358,7 @@ func Test_rotateKeys(t *testing.T) {
keyDuration: keyDuration,
clock: clock,
logger: logger,
features: database.AllCryptoKeyFeatureValues(),
features: defaultRotatedFeatures,
}
now := dbnow(clock)
@@ -409,7 +409,7 @@ func Test_rotateKeys(t *testing.T) {
require.NoError(t, err)
require.Len(t, keys, 5)
kbf, err := keysByFeature(keys, database.AllCryptoKeyFeatureValues())
kbf, err := keysByFeature(keys, defaultRotatedFeatures)
require.NoError(t, err)
// No actions on OIDC convert.
+3 -3
View File
@@ -37,7 +37,7 @@ func TestRotator(t *testing.T) {
// are as expected.
dbkeys, err = db.GetCryptoKeys(ctx)
require.NoError(t, err)
require.Len(t, dbkeys, len(database.AllCryptoKeyFeatureValues()))
require.Len(t, dbkeys, len(cryptokeys.DefaultRotatedFeatures()))
requireContainsAllFeatures(t, dbkeys)
})
@@ -64,7 +64,7 @@ func TestRotator(t *testing.T) {
cryptokeys.StartRotator(ctx, logger, db, cryptokeys.WithClock(clock))
initialKeyLen := len(database.AllCryptoKeyFeatureValues())
initialKeyLen := len(cryptokeys.DefaultRotatedFeatures())
// Fetch the keys from the database and ensure they
// are as expected.
dbkeys, err := db.GetCryptoKeys(ctx)
@@ -113,7 +113,7 @@ func requireContainsAllFeatures(t *testing.T, keys []database.CryptoKey) {
for _, key := range keys {
features[key.Feature] = true
}
for _, feature := range database.AllCryptoKeyFeatureValues() {
for _, feature := range cryptokeys.DefaultRotatedFeatures() {
require.True(t, features[feature])
}
}
+2 -1
View File
@@ -374,7 +374,8 @@ CREATE TYPE crypto_key_feature AS ENUM (
'workspace_apps_token',
'workspace_apps_api_key',
'oidc_convert',
'tailnet_resume'
'tailnet_resume',
'nats_ca'
);
CREATE TYPE display_app AS ENUM (
@@ -0,0 +1,16 @@
DELETE FROM crypto_keys WHERE feature = 'nats_ca';
CREATE TYPE old_crypto_key_feature AS ENUM (
'workspace_apps_token',
'workspace_apps_api_key',
'oidc_convert',
'tailnet_resume'
);
ALTER TABLE crypto_keys
ALTER COLUMN feature TYPE old_crypto_key_feature
USING (feature::text::old_crypto_key_feature);
DROP TYPE crypto_key_feature;
ALTER TYPE old_crypto_key_feature RENAME TO crypto_key_feature;
@@ -0,0 +1 @@
ALTER TYPE crypto_key_feature ADD VALUE IF NOT EXISTS 'nats_ca';
+4 -1
View File
@@ -1887,6 +1887,7 @@ const (
CryptoKeyFeatureWorkspaceAppsAPIKey CryptoKeyFeature = "workspace_apps_api_key"
CryptoKeyFeatureOIDCConvert CryptoKeyFeature = "oidc_convert"
CryptoKeyFeatureTailnetResume CryptoKeyFeature = "tailnet_resume"
CryptoKeyFeatureNATSCA CryptoKeyFeature = "nats_ca"
)
func (e *CryptoKeyFeature) Scan(src interface{}) error {
@@ -1929,7 +1930,8 @@ func (e CryptoKeyFeature) Valid() bool {
case CryptoKeyFeatureWorkspaceAppsToken,
CryptoKeyFeatureWorkspaceAppsAPIKey,
CryptoKeyFeatureOIDCConvert,
CryptoKeyFeatureTailnetResume:
CryptoKeyFeatureTailnetResume,
CryptoKeyFeatureNATSCA:
return true
}
return false
@@ -1941,6 +1943,7 @@ func AllCryptoKeyFeatureValues() []CryptoKeyFeature {
CryptoKeyFeatureWorkspaceAppsAPIKey,
CryptoKeyFeatureOIDCConvert,
CryptoKeyFeatureTailnetResume,
CryptoKeyFeatureNATSCA,
}
}
+1
View File
@@ -254,6 +254,7 @@ sql:
login_type_oauth2_provider_app: LoginTypeOAuth2ProviderApp
crypto_key_feature_workspace_apps_api_key: CryptoKeyFeatureWorkspaceAppsAPIKey
crypto_key_feature_oidc_convert: CryptoKeyFeatureOIDCConvert
crypto_key_feature_nats_ca: CryptoKeyFeatureNATSCA
stale_interval_ms: StaleIntervalMS
has_ai_task: HasAITask
ai_task_sidebar_app_id: AITaskSidebarAppID