mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add nats_ca crypto_key_feature enum value (#26761)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+2
-1
@@ -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';
|
||||
Generated
+4
-1
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user