From 71962d8ae7f456a349e02a8d7342b4c28a847cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Mon, 27 Oct 2025 12:11:27 +0300 Subject: [PATCH 1/9] Fake import to verify KMS integration --- go.mod | 2 + go.sum | 4 +- .../encryption/controllers/key_controller.go | 86 +++++++++-- .../pkg/operator/encryption/crypto/keys.go | 1 + .../encryption/encryptionconfig/config.go | 22 +++ .../pkg/operator/encryption/kms/kms.go | 139 ++++++++++++++++++ .../pkg/operator/encryption/kms/kms_client.go | 85 +++++++++++ .../operator/encryption/secrets/secrets.go | 18 ++- .../pkg/operator/encryption/secrets/types.go | 8 + .../pkg/operator/encryption/state/helpers.go | 15 +- .../pkg/operator/encryption/state/types.go | 7 +- .../resourceapply/admissionregistration.go | 48 ++++++ .../resource/resourceapply/generic.go | 24 +++ .../controller/guard/manifests/guard-pod.yaml | 1 + vendor/modules.txt | 4 +- 15 files changed, 445 insertions(+), 19 deletions(-) create mode 100644 vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go create mode 100644 vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms_client.go diff --git a/go.mod b/go.mod index 6af3cd018d..b3a54a32a3 100644 --- a/go.mod +++ b/go.mod @@ -135,3 +135,5 @@ require ( ) replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 + +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 diff --git a/go.sum b/go.sum index f4e011ae46..4cb21bb8fc 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= +github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 h1:7eLZXasJOdmkb6AmIBHoL4a/4vVYVRCQxWUoKiB1LSA= +github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -165,8 +167,6 @@ github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee h1:+S github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 h1:9JBeIXmnHlpXTQPi7LPmu1jdxznBhAE7bb1K+3D8gxY= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235/go.mod h1:L49W6pfrZkfOE5iC1PqEkuLkXG4W0BX4w8b+L2Bv7fM= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 h1:bANtDc8SgetSK4nQehf59x3+H9FqVJCprgjs49/OTg0= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5/go.mod h1:OlFFws1AO51uzfc48MsStGE4SFMWlMZD0+f5a/zCtKI= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 h1:AKx/w1qpS8We43bsRgf8Nll3CGlDHpr/WAXvuedTNZI= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go index c999f140f0..229ec75d14 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/openshift/library-go/pkg/operator/encryption/kms" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -20,6 +21,7 @@ import ( "k8s.io/klog/v2" "k8s.io/utils/ptr" + configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" @@ -39,6 +41,9 @@ import ( // greater than the last key's ID (the first key has a key ID of 1). const encryptionSecretMigrationInterval = time.Hour * 24 * 7 // one week +// kmsHashesGetter is a function type for getting KMS config and key ID hashes +var kmsHashesGetterFunc func(ctx context.Context, kmsConfig *configv1.KMSConfig) (configHash string, keyIDHash string, err error) + // keyController creates new keys if necessary. It // * watches // - secrets in openshift-config-managed @@ -104,6 +109,8 @@ func NewKeyController( secretClient: secretClient, } + kmsHashesGetterFunc = defaultGetKMSHashes + return factory.New(). WithSync(c.sync). WithControllerInstanceName(c.controllerInstanceName). @@ -159,11 +166,20 @@ func (c *keyController) sync(ctx context.Context, syncCtx factory.SyncContext) ( } func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext factory.SyncContext, encryptedGRs []schema.GroupResource) error { - currentMode, externalReason, err := c.getCurrentModeAndExternalReason(ctx) + currentMode, externalReason, kmsConfig, err := c.getCurrentModeAndExternalReason(ctx) if err != nil { return err } + // Compute KMS hashes if using KMS mode + var kmsConfigHash, kmsKeyIDHash string + if currentMode == state.KMS && kmsConfig != nil { + kmsConfigHash, kmsKeyIDHash, err = kmsHashesGetterFunc(ctx, kmsConfig) + if err != nil { + return err + } + } + currentConfig, desiredEncryptionState, secrets, isProgressingReason, err := statemachine.GetEncryptionConfigAndState(ctx, c.deployer, c.secretClient, c.encryptionSecretSelector, encryptedGRs) if err != nil { return err @@ -191,7 +207,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact var commonReason *string for gr, grKeys := range desiredEncryptionState { - latestKeyID, internalReason, needed := needsNewKey(grKeys, currentMode, externalReason, encryptedGRs) + latestKeyID, internalReason, needed := needsNewKey(grKeys, currentMode, externalReason, encryptedGRs, kmsConfigHash, kmsKeyIDHash) if !needed { continue } @@ -218,7 +234,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact sort.Sort(sort.StringSlice(reasons)) internalReason := strings.Join(reasons, ", ") - keySecret, err := c.generateKeySecret(newKeyID, currentMode, internalReason, externalReason) + keySecret, err := c.generateKeySecret(newKeyID, currentMode, internalReason, externalReason, kmsConfigHash, kmsKeyIDHash) if err != nil { return fmt.Errorf("failed to create key: %v", err) } @@ -255,7 +271,7 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c return nil // we made this key earlier } -func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason string) (*corev1.Secret, error) { +func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason, kmsConfigHash, kmsKeyIDHash string) (*corev1.Secret, error) { bs := crypto.ModeToNewKeyFunc[currentMode]() ks := state.KeyState{ Key: apiserverv1.Key{ @@ -265,40 +281,71 @@ func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, Mode: currentMode, InternalReason: internalReason, ExternalReason: externalReason, + KMSConfigHash: kmsConfigHash, + KMSKeyIDHash: kmsKeyIDHash, } return secrets.FromKeyState(c.instanceName, ks) } -func (c *keyController) getCurrentModeAndExternalReason(ctx context.Context) (state.Mode, string, error) { +func (c *keyController) getCurrentModeAndExternalReason(ctx context.Context) (state.Mode, string, *configv1.KMSConfig, error) { apiServer, err := c.apiServerClient.Get(ctx, "cluster", metav1.GetOptions{}) if err != nil { - return "", "", err + return "", "", nil, err } operatorSpec, _, _, err := c.operatorClient.GetOperatorState() if err != nil { - return "", "", err + return "", "", nil, err } encryptionConfig, err := structuredUnsupportedConfigFrom(operatorSpec.UnsupportedConfigOverrides.Raw, c.unsupportedConfigPrefix) if err != nil { - return "", "", err + return "", "", nil, err } reason := encryptionConfig.Encryption.Reason switch currentMode := state.Mode(apiServer.Spec.Encryption.Type); currentMode { case state.AESCBC, state.AESGCM, state.Identity: // secretbox is disabled for now - return currentMode, reason, nil + return currentMode, reason, nil, nil + case state.KMS: + return currentMode, reason, apiServer.Spec.Encryption.KMS, nil case "": // unspecified means use the default (which can change over time) - return state.DefaultMode, reason, nil + return state.DefaultMode, reason, nil, nil default: - return "", "", fmt.Errorf("unknown encryption mode configured: %s", currentMode) + return "", "", nil, fmt.Errorf("unknown encryption mode configured: %s", currentMode) + } +} + +// defaultGetKMSHashes is the default implementation of getting KMS hashes +// It calls the real KMS client to get the status and compute hashes +func defaultGetKMSHashes(ctx context.Context, kmsConfig *configv1.KMSConfig) (string, string, error) { + // Generate unix socket path from KMS config and get the hash + socketPath, configHash, err := kms.GenerateUnixSocketPath(kmsConfig) + if err != nil { + return "", "", fmt.Errorf("failed to generate KMS unix socket path: %w", err) + } + + kmsClient, err := kms.NewKMSClient(socketPath) + if err != nil { + return "", "", fmt.Errorf("failed to create KMS client: %w", err) } + defer kmsClient.Close() + + statusResp, err := kmsClient.Status(ctx) + if err != nil { + return "", "", fmt.Errorf("failed to call KMS Status endpoint: %w", err) + } + + if statusResp.Healthz != "ok" { + return "", "", fmt.Errorf("KMS plugin is unhealthy: %s", statusResp.Healthz) + } + + return configHash, kms.ComputeKMSKeyIDHash(statusResp.KeyID), nil } // needsNewKey checks whether a new key must be created for the given resource. If true, it also returns the latest // used key ID and a reason string. -func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, externalReason string, encryptedGRs []schema.GroupResource) (uint64, string, bool) { +func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, externalReason string, encryptedGRs []schema.GroupResource, kmsConfigHash, kmsKeyIDHash string) (uint64, string, bool) { // we always need to have some encryption keys unless we are turned off if len(grKeys.ReadKeys) == 0 { return 0, "key-does-not-exist", currentMode != state.Identity @@ -346,6 +393,21 @@ func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, extern return latestKeyID, "external-reason-changed", true } + // if we are using KMS, check if the KMS configuration or key ID hash has changed + if currentMode == state.KMS { + if latestKey.KMSConfigHash != kmsConfigHash && len(kmsConfigHash) != 0 { + return latestKeyID, "kms-config-changed", true + } + + if latestKey.KMSKeyIDHash != kmsKeyIDHash && len(kmsKeyIDHash) != 0 { + return latestKeyID, "kms-key-id-changed", true + } + + // For KMS mode, we don't do time-based rotation + // KMS keys are rotated externally by the KMS system + return 0, "", false + } + // we check for encryptionSecretMigratedTimestamp set by migration controller to determine when migration completed // this also generates back pressure for key rotation when migration takes a long time or was recently completed return latestKeyID, "rotation-interval-has-passed", time.Since(latestKey.Migrated.Timestamp) > encryptionSecretMigrationInterval diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go index a623d30f79..b9393ece66 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go @@ -12,6 +12,7 @@ var ( state.AESGCM: NewAES256Key, state.SecretBox: NewAES256Key, // secretbox requires a 32 byte key so we can reuse the same function here state.Identity: NewIdentityKey, + state.KMS: NewIdentityKey, // this is not used in KMS } ) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go index 3082aa653f..1a8b130b9d 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "sort" + "github.com/openshift/library-go/pkg/operator/encryption/kms" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" apiserverconfigv1 "k8s.io/apiserver/pkg/apis/apiserver/v1" @@ -106,6 +107,25 @@ func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfigurati Mode: s, } + case provider.KMS != nil: + configHash, keyIDHash, keyName, err := kms.ExtractKMSHashAndKeyName(provider) + if err != nil { + klog.Warningf("skipping invalid encryption KMS config for resource %v", provider) + continue // should never happen + } + + ks = state.KeyState{ + Key: apiserverconfigv1.Key{ + Name: keyName, + // We set this unused secret just to align with what we set initially. + // This is unused. + Secret: base64.StdEncoding.EncodeToString(crypto.ModeToNewKeyFunc[state.KMS]()), + }, + Mode: state.KMS, + KMSConfigHash: configHash, + KMSKeyIDHash: keyIDHash, + } + default: klog.Infof("skipping invalid provider index %d for resource %s", i, resourceConfig.Resources[0]) continue // should never happen @@ -192,6 +212,8 @@ func stateToProviders(desired state.GroupResourceState) []apiserverconfigv1.Prov Keys: []apiserverconfigv1.Key{key.Key}, }, }) + case state.KMS: + providers = append(providers, kms.GenerateKMSProviderConfigurationFromKey(key)) default: // this should never happen because our input should always be valid klog.Infof("skipping key %s as it has invalid mode %s", key.Key.Name, key.Mode) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go new file mode 100644 index 0000000000..4f73f9bb6b --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go @@ -0,0 +1,139 @@ +package kms + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "regexp" + "time" + + configv1 "github.com/openshift/api/config/v1" + "github.com/openshift/library-go/pkg/operator/encryption/state" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apiserver/pkg/apis/apiserver/v1" +) + +const ( + // unixSocketBaseDir is the base directory for KMS unix sockets + unixSocketBaseDir = "unix://var/run/kms" +) + +// GenerateUnixSocketPath generates a unique unix socket path from KMS configuration +// by hashing the provider-specific configuration. +// Returns the socket path and the hash value (first 16 characters). +func GenerateUnixSocketPath(kmsConfig *configv1.KMSConfig) (socketPath string, hash string, err error) { + if kmsConfig == nil { + return "", "", fmt.Errorf("kmsConfig cannot be nil") + } + + // Determine KMS type and generate path accordingly + switch kmsConfig.Type { + case configv1.AWSKMSProvider: + if kmsConfig.AWS == nil { + return "", "", fmt.Errorf("AWS KMS config cannot be nil for AWS provider type") + } + return generateAWSUnixSocketPath(kmsConfig.AWS) + default: + return "", "", fmt.Errorf("unsupported KMS provider type: %s", kmsConfig.Type) + } +} + +// generateAWSUnixSocketPath generates a unique unix socket path from AWS KMS configuration +// by hashing the ARN and region. Returns the socket path and the hash (first 16 characters). +func generateAWSUnixSocketPath(awsConfig *configv1.AWSKMSConfig) (string, string, error) { + if awsConfig.KeyARN == "" { + return "", "", fmt.Errorf("AWS KMS KeyARN cannot be empty") + } + + if awsConfig.Region == "" { + return "", "", fmt.Errorf("AWS region cannot be empty") + } + + // Combine KeyARN and region for hashing + combined := awsConfig.KeyARN + ":" + awsConfig.Region + + // Compute SHA256 hash + hash := sha256.Sum256([]byte(combined)) + hashStr := hex.EncodeToString(hash[:]) + + // Take first 16 characters of hash for shorter path + shortHash := hashStr[:16] + + socketPath := fmt.Sprintf("%s/kms-%s.sock", unixSocketBaseDir, shortHash) + + return socketPath, shortHash, nil +} + +// ComputeKMSKeyIDHash computes a hash of the KMS key ID returned from the Status endpoint. +// Returns the first 16 characters of the SHA256 hash. +func ComputeKMSKeyIDHash(keyID string) string { + if keyID == "" { + return "" + } + + // Compute SHA256 hash + hash := sha256.Sum256([]byte(keyID)) + hashStr := hex.EncodeToString(hash[:]) + + return hashStr[:16] +} + +var ( + // endpointHashRegex matches the config hash in endpoint path: unix://var/run/kms/kms-{configHash16}.sock + endpointHashRegex = regexp.MustCompile(`kms-([a-f0-9]{16})\.sock$`) + // providerNameRegex matches the key ID hash and key ID in provider name: kms-provider-{keyIDHash16}-{keyID} + // Example: kms-provider-abcdef1234567890-1 + providerNameRegex = regexp.MustCompile(`^kms-provider-([a-f0-9]{16})-(.+)$`) +) + +// ExtractKMSHashAndKeyName extracts the KMSConfigHash, KMSKeyIDHash, and key.Name embedded into provider +// name and socket path. Returns (configHash, keyIDHash, keyName, error) +func ExtractKMSHashAndKeyName(provider v1.ProviderConfiguration) (string, string, string, error) { + // Extract the config hash from the endpoint path: unix://var/run/kms/kms-{configHash}.sock + endpoint := provider.KMS.Endpoint + var configHash string + if matches := endpointHashRegex.FindStringSubmatch(endpoint); len(matches) == 2 { + configHash = matches[1] + } else { + return "", "", "", fmt.Errorf("invalid KMS endpoint format: %s", endpoint) + } + + // Extract the key ID hash and key ID from the provider name: kms-provider-{keyIDHash16}-{keyID} + // Example: kms-provider-abcdef1234567890-1 + var keyIDHash, keyName string + providerName := provider.KMS.Name + if matches := providerNameRegex.FindStringSubmatch(providerName); len(matches) == 3 { + keyIDHash = matches[1] + keyName = matches[2] + } else { + return "", "", "", fmt.Errorf("invalid KMS provider name format: %s", providerName) + } + + return configHash, keyIDHash, keyName, nil +} + +// GenerateKMSProviderConfigurationFromKey generates the compatible ProviderConfiguration with +// opinionated and extractable fields. We embed: +// - KMSConfigHash in the socket path (endpoint) +// - KMSKeyIDHash and key.Name in the provider name +// This allows us to extract all three values and detect both config changes and key rotations. +func GenerateKMSProviderConfigurationFromKey(key state.KeyState) v1.ProviderConfiguration { + // Embed KMSConfigHash in the endpoint so we can extract it + // This must generate the same format as GenerateUnixSocketPath + socketPath := fmt.Sprintf("%s/kms-%s.sock", unixSocketBaseDir, key.KMSConfigHash) + // Embed KMSKeyIDHash and key ID in the provider name so we can extract them when reading back + // Format: kms-provider-{keyIDHash16}-{keyID} + // This must match the providerNameRegex + providerName := fmt.Sprintf("kms-provider-%s-%s", key.KMSKeyIDHash, key.Key.Name) + + return v1.ProviderConfiguration{ + KMS: &v1.KMSConfiguration{ + APIVersion: "v2", + Name: providerName, + Endpoint: socketPath, + Timeout: &metav1.Duration{ + Duration: 10 * time.Second, + }, + }, + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms_client.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms_client.go new file mode 100644 index 0000000000..c0aa86e1b0 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms_client.go @@ -0,0 +1,85 @@ +package kms + +import ( + "context" + "fmt" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + kmsv2 "k8s.io/kms/apis/v2" +) + +const ( + // defaultTimeout is the default timeout for KMS operations + defaultTimeout = 30 * time.Second +) + +// KMSClient is an interface for interacting with KMS plugins +type KMSClient interface { + // Status calls the KMS plugin's Status endpoint and returns the response + Status(ctx context.Context) (*StatusResponse, error) + // Close closes the connection to the KMS plugin + Close() error +} + +// StatusResponse represents the response from a KMS Status call +type StatusResponse struct { + Version string + Healthz string + KeyID string +} + +// kmsClient implements the KMSClient interface +type kmsClient struct { + conn *grpc.ClientConn + kmsClient kmsv2.KeyManagementServiceClient + endpoint string +} + +func NewKMSClient(endpoint string) (KMSClient, error) { + if endpoint == "" { + return nil, fmt.Errorf("kms endpoint cannot be empty") + } + + options := []grpc.DialOption{ + grpc.WithTransportCredentials(insecure.NewCredentials()), + } + + conn, err := grpc.NewClient(endpoint, options...) + if err != nil { + return nil, fmt.Errorf("failed to connect to KMS plugin at %s: %w", endpoint, err) + } + + return &kmsClient{ + conn: conn, + kmsClient: kmsv2.NewKeyManagementServiceClient(conn), + endpoint: endpoint, + }, nil +} + +// Status calls the KMS plugin's Status endpoint +func (c *kmsClient) Status(ctx context.Context) (*StatusResponse, error) { + timeoutCtx, cancel := context.WithTimeout(ctx, defaultTimeout) + defer cancel() + + // Call the Status endpoint + resp, err := c.kmsClient.Status(timeoutCtx, &kmsv2.StatusRequest{}) + if err != nil { + return nil, fmt.Errorf("failed to call KMS Status endpoint at %s: %w", c.endpoint, err) + } + + return &StatusResponse{ + Version: resp.GetVersion(), + Healthz: resp.GetHealthz(), + KeyID: resp.GetKeyId(), + }, nil +} + +// Close closes the connection to the KMS plugin +func (c *kmsClient) Close() error { + if c.conn != nil { + return c.conn.Close() + } + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go index 4e54317c7d..e33f9fc6af 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go @@ -58,14 +58,21 @@ func ToKeyState(s *corev1.Secret) (state.KeyState, error) { key.ExternalReason = v } + if v, ok := s.Annotations[EncryptionSecretKMSConfigHash]; ok && len(v) > 0 { + key.KMSConfigHash = v + } + if v, ok := s.Annotations[EncryptionSecretKMSKeyIDHash]; ok && len(v) > 0 { + key.KMSKeyIDHash = v + } + keyMode := state.Mode(s.Annotations[encryptionSecretMode]) switch keyMode { - case state.AESCBC, state.AESGCM, state.SecretBox, state.Identity: + case state.AESCBC, state.AESGCM, state.SecretBox, state.Identity, state.KMS: key.Mode = keyMode default: return state.KeyState{}, fmt.Errorf("secret %s/%s has invalid mode: %s", s.Namespace, s.Name, keyMode) } - if keyMode != state.Identity && len(data) == 0 { + if keyMode != state.Identity && keyMode != state.KMS && len(data) == 0 { return state.KeyState{}, fmt.Errorf("secret %s/%s of mode %q must have non-empty key", s.Namespace, s.Name, keyMode) } @@ -113,6 +120,13 @@ func FromKeyState(component string, ks state.KeyState) (*corev1.Secret, error) { s.Annotations[EncryptionSecretMigratedResources] = string(bs) } + if len(ks.KMSConfigHash) > 0 { + s.Annotations[EncryptionSecretKMSConfigHash] = ks.KMSConfigHash + } + if len(ks.KMSKeyIDHash) > 0 { + s.Annotations[EncryptionSecretKMSKeyIDHash] = ks.KMSKeyIDHash + } + return s, nil } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go index 7161e4a124..5b6be9574f 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go @@ -41,6 +41,14 @@ const ( // determine if a new key should be created even if encryptionSecretMigrationInterval has not been reached. encryptionSecretExternalReason = "encryption.apiserver.operator.openshift.io/external-reason" + // EncryptionSecretKMSConfigHash is the annotation that stores the hash of the KMS configuration. + // This is used to detect changes in the KMS configuration that would require a new key. + EncryptionSecretKMSConfigHash = "encryption.apiserver.operator.openshift.io/kms-config-hash" + + // EncryptionSecretKMSKeyIDHash is the annotation that stores the hash of the KMS key ID. + // This is used to detect changes in the KMS key ID (e.g., after key rotation in the KMS system). + EncryptionSecretKMSKeyIDHash = "encryption.apiserver.operator.openshift.io/kms-key-id-hash" + // In the data field of the secret API object, this (map) key is used to hold the actual encryption key // (i.e. for AES-CBC mode the value associated with this map key is 32 bytes of random noise). EncryptionSecretKeyDataKey = "encryption.apiserver.operator.openshift.io-key" diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go index 656aeafef6..6dde64f8e6 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go @@ -74,10 +74,23 @@ func NameToKeyID(name string) (uint64, bool) { } func EqualKeyAndEqualID(s1, s2 *KeyState) bool { - if s1.Mode != s2.Mode || s1.Key.Secret != s2.Key.Secret { + if s1.Mode != s2.Mode { return false } + // For KMS mode, compare both KMSConfigHash and KMSKeyIDHash to detect config or key rotation + if s1.Mode == KMS { + if s1.KMSConfigHash != s2.KMSConfigHash { + return false + } + if s1.KMSKeyIDHash != s2.KMSKeyIDHash { + return false + } + } else if s1.Key.Secret != s2.Key.Secret { + return false + } + + // Verify key IDs match (for both KMS and non-KMS modes) id1, valid1 := NameToKeyID(s1.Key.Name) id2, valid2 := NameToKeyID(s2.Key.Name) return valid1 && valid2 && id1 == id2 diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go index 460c21bfa2..9ec37aa118 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go @@ -26,7 +26,7 @@ type GroupResourceState struct { } func (k GroupResourceState) HasWriteKey() bool { - return len(k.WriteKey.Key.Name) > 0 && len(k.WriteKey.Key.Secret) > 0 + return (len(k.WriteKey.Key.Name) > 0 && len(k.WriteKey.Key.Secret) > 0) || k.WriteKey.KMSConfigHash != "" } type KeyState struct { @@ -40,6 +40,10 @@ type KeyState struct { InternalReason string // the user via unsupportConfigOverrides.encryption.reason triggered this key. ExternalReason string + // hash of the KMS configuration to detect changes + KMSConfigHash string + // hash of the KMS key ID to detect changes + KMSKeyIDHash string } type MigrationState struct { @@ -60,6 +64,7 @@ const ( AESGCM Mode = "aesgcm" SecretBox Mode = "secretbox" // available from the first release, see defaultMode below Identity Mode = "identity" // available from the first release, see defaultMode below + KMS Mode = "kms" // Changing this value requires caution to not break downgrades. // Specifically, if some new Mode is released in version X, that new Mode cannot diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go index 88bd00b251..0b52c3a324 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go @@ -415,3 +415,51 @@ func ApplyValidatingAdmissionPolicyBindingV1(ctx context.Context, client admissi cache.UpdateCachedResourceMetadata(requiredOriginal, actual) return actual, true, nil } + +func DeleteValidatingAdmissionPolicyV1beta1(ctx context.Context, client admissionregistrationclientv1beta1.ValidatingAdmissionPoliciesGetter, recorder events.Recorder, required *admissionregistrationv1beta1.ValidatingAdmissionPolicy) (*admissionregistrationv1beta1.ValidatingAdmissionPolicy, bool, error) { + err := client.ValidatingAdmissionPolicies().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyBindingV1beta1(ctx context.Context, client admissionregistrationclientv1beta1.ValidatingAdmissionPolicyBindingsGetter, recorder events.Recorder, required *admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding) (*admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding, bool, error) { + err := client.ValidatingAdmissionPolicyBindings().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyV1(ctx context.Context, client admissionregistrationclientv1.ValidatingAdmissionPoliciesGetter, recorder events.Recorder, required *admissionregistrationv1.ValidatingAdmissionPolicy) (*admissionregistrationv1.ValidatingAdmissionPolicy, bool, error) { + err := client.ValidatingAdmissionPolicies().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyBindingV1(ctx context.Context, client admissionregistrationclientv1.ValidatingAdmissionPolicyBindingsGetter, recorder events.Recorder, required *admissionregistrationv1.ValidatingAdmissionPolicyBinding) (*admissionregistrationv1.ValidatingAdmissionPolicyBinding, bool, error) { + err := client.ValidatingAdmissionPolicyBindings().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go index 9105464bd0..471f1bb2f2 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go @@ -380,6 +380,30 @@ func DeleteAll(ctx context.Context, clients *ClientHolder, recorder events.Recor } else { _, result.Changed, result.Error = DeleteValidatingWebhookConfiguration(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) } + case *admissionregistrationv1beta1.ValidatingAdmissionPolicy: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyV1beta1(ctx, clients.kubeClient.AdmissionregistrationV1beta1(), recorder, t) + } + case *admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyBindingV1beta1(ctx, clients.kubeClient.AdmissionregistrationV1beta1(), recorder, t) + } + case *admissionregistrationv1.ValidatingAdmissionPolicy: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyV1(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + } + case *admissionregistrationv1.ValidatingAdmissionPolicyBinding: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyBindingV1(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + } case *storagev1.CSIDriver: if clients.kubeClient == nil { result.Error = fmt.Errorf("missing kubeClient") diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/manifests/guard-pod.yaml b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/manifests/guard-pod.yaml index 657c87ec8b..29d4a345b3 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/manifests/guard-pod.yaml +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/manifests/guard-pod.yaml @@ -14,6 +14,7 @@ spec: terminationGracePeriodSeconds: 3 tolerations: - operator: Exists + hostUsers: false containers: - name: guard image: # Value set by operator diff --git a/vendor/modules.txt b/vendor/modules.txt index 24a45fcdf7..630261d1fa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -440,6 +440,7 @@ github.com/openshift/library-go/pkg/operator/encryption/controllers/migrators github.com/openshift/library-go/pkg/operator/encryption/crypto github.com/openshift/library-go/pkg/operator/encryption/deployer github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig +github.com/openshift/library-go/pkg/operator/encryption/kms github.com/openshift/library-go/pkg/operator/encryption/observer github.com/openshift/library-go/pkg/operator/encryption/secrets github.com/openshift/library-go/pkg/operator/encryption/state @@ -1681,3 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 From eefd6e0c5955a444e35fb9db9a61999e8f904c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Mon, 27 Oct 2025 19:47:05 +0300 Subject: [PATCH 2/9] Update based on latest changes --- go.mod | 2 +- go.sum | 4 +- .../encryption/controllers/key_controller.go | 38 +++++++++---------- .../pkg/operator/encryption/crypto/keys.go | 12 ++++-- .../encryption/encryptionconfig/config.go | 11 ++---- .../pkg/operator/encryption/kms/kms.go | 35 +++++++++-------- .../operator/encryption/secrets/secrets.go | 6 --- .../pkg/operator/encryption/secrets/types.go | 4 -- .../pkg/operator/encryption/state/helpers.go | 15 +------- .../pkg/operator/encryption/state/types.go | 4 +- vendor/modules.txt | 4 +- 11 files changed, 55 insertions(+), 80 deletions(-) diff --git a/go.mod b/go.mod index b3a54a32a3..fa94e8294b 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 diff --git a/go.sum b/go.sum index 4cb21bb8fc..d6f1c298c6 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 h1:7eLZXasJOdmkb6AmIBHoL4a/4vVYVRCQxWUoKiB1LSA= -github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 h1:6MQ2HefcbiOp9EKxIFbyfmO0xUiOU/+TqP8/ZlHLTAs= +github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go index 229ec75d14..4dfcef0080 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go @@ -42,7 +42,7 @@ import ( const encryptionSecretMigrationInterval = time.Hour * 24 * 7 // one week // kmsHashesGetter is a function type for getting KMS config and key ID hashes -var kmsHashesGetterFunc func(ctx context.Context, kmsConfig *configv1.KMSConfig) (configHash string, keyIDHash string, err error) +var kmsHashesGetterFunc func(ctx context.Context, kmsConfig *configv1.KMSConfig) (configHash string, keyIDHash []byte, err error) // keyController creates new keys if necessary. It // * watches @@ -172,9 +172,10 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact } // Compute KMS hashes if using KMS mode - var kmsConfigHash, kmsKeyIDHash string + var kmsConfigHash string + var kmsKeyHash []byte if currentMode == state.KMS && kmsConfig != nil { - kmsConfigHash, kmsKeyIDHash, err = kmsHashesGetterFunc(ctx, kmsConfig) + kmsConfigHash, kmsKeyHash, err = kmsHashesGetterFunc(ctx, kmsConfig) if err != nil { return err } @@ -207,7 +208,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact var commonReason *string for gr, grKeys := range desiredEncryptionState { - latestKeyID, internalReason, needed := needsNewKey(grKeys, currentMode, externalReason, encryptedGRs, kmsConfigHash, kmsKeyIDHash) + latestKeyID, internalReason, needed := needsNewKey(grKeys, currentMode, externalReason, encryptedGRs, kmsKeyHash) if !needed { continue } @@ -234,7 +235,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact sort.Sort(sort.StringSlice(reasons)) internalReason := strings.Join(reasons, ", ") - keySecret, err := c.generateKeySecret(newKeyID, currentMode, internalReason, externalReason, kmsConfigHash, kmsKeyIDHash) + keySecret, err := c.generateKeySecret(newKeyID, currentMode, internalReason, externalReason, kmsConfigHash, kmsKeyHash) if err != nil { return fmt.Errorf("failed to create key: %v", err) } @@ -271,8 +272,8 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c return nil // we made this key earlier } -func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason, kmsConfigHash, kmsKeyIDHash string) (*corev1.Secret, error) { - bs := crypto.ModeToNewKeyFunc[currentMode]() +func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason, kmsConfigHash string, kmsKeyIDHash []byte) (*corev1.Secret, error) { + bs := crypto.ModeToNewKeyFunc[currentMode](kmsKeyIDHash) ks := state.KeyState{ Key: apiserverv1.Key{ Name: fmt.Sprintf("%d", keyID), @@ -282,7 +283,6 @@ func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, InternalReason: internalReason, ExternalReason: externalReason, KMSConfigHash: kmsConfigHash, - KMSKeyIDHash: kmsKeyIDHash, } return secrets.FromKeyState(c.instanceName, ks) } @@ -318,34 +318,34 @@ func (c *keyController) getCurrentModeAndExternalReason(ctx context.Context) (st // defaultGetKMSHashes is the default implementation of getting KMS hashes // It calls the real KMS client to get the status and compute hashes -func defaultGetKMSHashes(ctx context.Context, kmsConfig *configv1.KMSConfig) (string, string, error) { +func defaultGetKMSHashes(ctx context.Context, kmsConfig *configv1.KMSConfig) (string, []byte, error) { // Generate unix socket path from KMS config and get the hash socketPath, configHash, err := kms.GenerateUnixSocketPath(kmsConfig) if err != nil { - return "", "", fmt.Errorf("failed to generate KMS unix socket path: %w", err) + return "", nil, fmt.Errorf("failed to generate KMS unix socket path: %w", err) } kmsClient, err := kms.NewKMSClient(socketPath) if err != nil { - return "", "", fmt.Errorf("failed to create KMS client: %w", err) + return "", nil, fmt.Errorf("failed to create KMS client: %w", err) } defer kmsClient.Close() statusResp, err := kmsClient.Status(ctx) if err != nil { - return "", "", fmt.Errorf("failed to call KMS Status endpoint: %w", err) + return "", nil, fmt.Errorf("failed to call KMS Status endpoint: %w", err) } if statusResp.Healthz != "ok" { - return "", "", fmt.Errorf("KMS plugin is unhealthy: %s", statusResp.Healthz) + return "", nil, fmt.Errorf("KMS plugin is unhealthy: %s", statusResp.Healthz) } - return configHash, kms.ComputeKMSKeyIDHash(statusResp.KeyID), nil + return configHash, kms.ComputeKMSKeyHash(configHash, statusResp.KeyID), nil } // needsNewKey checks whether a new key must be created for the given resource. If true, it also returns the latest // used key ID and a reason string. -func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, externalReason string, encryptedGRs []schema.GroupResource, kmsConfigHash, kmsKeyIDHash string) (uint64, string, bool) { +func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, externalReason string, encryptedGRs []schema.GroupResource, kmsKeyHash []byte) (uint64, string, bool) { // we always need to have some encryption keys unless we are turned off if len(grKeys.ReadKeys) == 0 { return 0, "key-does-not-exist", currentMode != state.Identity @@ -395,12 +395,8 @@ func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, extern // if we are using KMS, check if the KMS configuration or key ID hash has changed if currentMode == state.KMS { - if latestKey.KMSConfigHash != kmsConfigHash && len(kmsConfigHash) != 0 { - return latestKeyID, "kms-config-changed", true - } - - if latestKey.KMSKeyIDHash != kmsKeyIDHash && len(kmsKeyIDHash) != 0 { - return latestKeyID, "kms-key-id-changed", true + if latestKey.Key.Secret != base64.StdEncoding.EncodeToString(kmsKeyHash) { + return latestKeyID, "kms-key-changed", true } // For KMS mode, we don't do time-based rotation diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go index b9393ece66..76c67763bf 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go @@ -7,16 +7,16 @@ import ( ) var ( - ModeToNewKeyFunc = map[state.Mode]func() []byte{ + ModeToNewKeyFunc = map[state.Mode]func(externalKey []byte) []byte{ state.AESCBC: NewAES256Key, state.AESGCM: NewAES256Key, state.SecretBox: NewAES256Key, // secretbox requires a 32 byte key so we can reuse the same function here state.Identity: NewIdentityKey, - state.KMS: NewIdentityKey, // this is not used in KMS + state.KMS: NewKMSKey, } ) -func NewAES256Key() []byte { +func NewAES256Key(_ []byte) []byte { b := make([]byte, 32) // AES-256 == 32 byte key if _, err := rand.Read(b); err != nil { panic(err) // rand should never fail @@ -24,6 +24,10 @@ func NewAES256Key() []byte { return b } -func NewIdentityKey() []byte { +func NewIdentityKey(_ []byte) []byte { return make([]byte, 16) // the key is not used to perform encryption but must be a valid AES key } + +func NewKMSKey(externalKey []byte) []byte { + return externalKey +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go index 1a8b130b9d..a39968650d 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go @@ -16,7 +16,7 @@ import ( ) var ( - emptyStaticIdentityKey = base64.StdEncoding.EncodeToString(crypto.NewIdentityKey()) + emptyStaticIdentityKey = base64.StdEncoding.EncodeToString(crypto.NewIdentityKey(nil)) ) // FromEncryptionState converts state to config. @@ -108,7 +108,7 @@ func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfigurati } case provider.KMS != nil: - configHash, keyIDHash, keyName, err := kms.ExtractKMSHashAndKeyName(provider) + configHash, keyHash, keyName, err := kms.ExtractKMSHashAndKeyName(provider) if err != nil { klog.Warningf("skipping invalid encryption KMS config for resource %v", provider) continue // should never happen @@ -116,14 +116,11 @@ func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfigurati ks = state.KeyState{ Key: apiserverconfigv1.Key{ - Name: keyName, - // We set this unused secret just to align with what we set initially. - // This is unused. - Secret: base64.StdEncoding.EncodeToString(crypto.ModeToNewKeyFunc[state.KMS]()), + Name: keyName, + Secret: keyHash, }, Mode: state.KMS, KMSConfigHash: configHash, - KMSKeyIDHash: keyIDHash, } default: diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go index 4f73f9bb6b..8560cade3b 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go @@ -2,6 +2,7 @@ package kms import ( "crypto/sha256" + "encoding/base64" "encoding/hex" "fmt" "regexp" @@ -21,7 +22,7 @@ const ( // GenerateUnixSocketPath generates a unique unix socket path from KMS configuration // by hashing the provider-specific configuration. // Returns the socket path and the hash value (first 16 characters). -func GenerateUnixSocketPath(kmsConfig *configv1.KMSConfig) (socketPath string, hash string, err error) { +func GenerateUnixSocketPath(kmsConfig *configv1.KMSConfig) (string, string, error) { if kmsConfig == nil { return "", "", fmt.Errorf("kmsConfig cannot be nil") } @@ -64,26 +65,27 @@ func generateAWSUnixSocketPath(awsConfig *configv1.AWSKMSConfig) (string, string return socketPath, shortHash, nil } -// ComputeKMSKeyIDHash computes a hash of the KMS key ID returned from the Status endpoint. -// Returns the first 16 characters of the SHA256 hash. -func ComputeKMSKeyIDHash(keyID string) string { +// ComputeKMSKeyHash computes a hash of the KMS key ID returned from the Status endpoint. +// Returns the first 32 characters of the SHA256 hash. +func ComputeKMSKeyHash(configHash, keyID string) []byte { if keyID == "" { - return "" + return nil } + combined := configHash + ":" + keyID // Compute SHA256 hash - hash := sha256.Sum256([]byte(keyID)) + hash := sha256.Sum256([]byte(combined)) hashStr := hex.EncodeToString(hash[:]) - return hashStr[:16] + return []byte(hashStr[:32]) } var ( // endpointHashRegex matches the config hash in endpoint path: unix://var/run/kms/kms-{configHash16}.sock endpointHashRegex = regexp.MustCompile(`kms-([a-f0-9]{16})\.sock$`) - // providerNameRegex matches the key ID hash and key ID in provider name: kms-provider-{keyIDHash16}-{keyID} - // Example: kms-provider-abcdef1234567890-1 - providerNameRegex = regexp.MustCompile(`^kms-provider-([a-f0-9]{16})-(.+)$`) + // providerNameRegex matches the key ID hash and key ID in provider name: kms-provider-{keyIDHash32}-{keyID} + // Example: kms-provider-abcdef1234567890abcdef1234567890-1 + providerNameRegex = regexp.MustCompile(`^kms-provider-([a-f0-9]{32})-(.+)$`) ) // ExtractKMSHashAndKeyName extracts the KMSConfigHash, KMSKeyIDHash, and key.Name embedded into provider @@ -99,17 +101,17 @@ func ExtractKMSHashAndKeyName(provider v1.ProviderConfiguration) (string, string } // Extract the key ID hash and key ID from the provider name: kms-provider-{keyIDHash16}-{keyID} - // Example: kms-provider-abcdef1234567890-1 - var keyIDHash, keyName string + // Example: kms-provider-abcdef1234567890abcdef1234567890-1 + var keyHash, keyName string providerName := provider.KMS.Name if matches := providerNameRegex.FindStringSubmatch(providerName); len(matches) == 3 { - keyIDHash = matches[1] + keyHash = matches[1] keyName = matches[2] } else { return "", "", "", fmt.Errorf("invalid KMS provider name format: %s", providerName) } - return configHash, keyIDHash, keyName, nil + return configHash, base64.StdEncoding.EncodeToString([]byte(keyHash)), keyName, nil } // GenerateKMSProviderConfigurationFromKey generates the compatible ProviderConfiguration with @@ -122,9 +124,10 @@ func GenerateKMSProviderConfigurationFromKey(key state.KeyState) v1.ProviderConf // This must generate the same format as GenerateUnixSocketPath socketPath := fmt.Sprintf("%s/kms-%s.sock", unixSocketBaseDir, key.KMSConfigHash) // Embed KMSKeyIDHash and key ID in the provider name so we can extract them when reading back - // Format: kms-provider-{keyIDHash16}-{keyID} + // Format: kms-provider-{keyIDHash32}-{keyID} // This must match the providerNameRegex - providerName := fmt.Sprintf("kms-provider-%s-%s", key.KMSKeyIDHash, key.Key.Name) + decoded, _ := base64.StdEncoding.DecodeString(key.Key.Secret) + providerName := fmt.Sprintf("kms-provider-%s-%s", decoded, key.Key.Name) return v1.ProviderConfiguration{ KMS: &v1.KMSConfiguration{ diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go index e33f9fc6af..f814d153d9 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go @@ -61,9 +61,6 @@ func ToKeyState(s *corev1.Secret) (state.KeyState, error) { if v, ok := s.Annotations[EncryptionSecretKMSConfigHash]; ok && len(v) > 0 { key.KMSConfigHash = v } - if v, ok := s.Annotations[EncryptionSecretKMSKeyIDHash]; ok && len(v) > 0 { - key.KMSKeyIDHash = v - } keyMode := state.Mode(s.Annotations[encryptionSecretMode]) switch keyMode { @@ -123,9 +120,6 @@ func FromKeyState(component string, ks state.KeyState) (*corev1.Secret, error) { if len(ks.KMSConfigHash) > 0 { s.Annotations[EncryptionSecretKMSConfigHash] = ks.KMSConfigHash } - if len(ks.KMSKeyIDHash) > 0 { - s.Annotations[EncryptionSecretKMSKeyIDHash] = ks.KMSKeyIDHash - } return s, nil } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go index 5b6be9574f..32a576dea2 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go @@ -45,10 +45,6 @@ const ( // This is used to detect changes in the KMS configuration that would require a new key. EncryptionSecretKMSConfigHash = "encryption.apiserver.operator.openshift.io/kms-config-hash" - // EncryptionSecretKMSKeyIDHash is the annotation that stores the hash of the KMS key ID. - // This is used to detect changes in the KMS key ID (e.g., after key rotation in the KMS system). - EncryptionSecretKMSKeyIDHash = "encryption.apiserver.operator.openshift.io/kms-key-id-hash" - // In the data field of the secret API object, this (map) key is used to hold the actual encryption key // (i.e. for AES-CBC mode the value associated with this map key is 32 bytes of random noise). EncryptionSecretKeyDataKey = "encryption.apiserver.operator.openshift.io-key" diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go index 6dde64f8e6..656aeafef6 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go @@ -74,23 +74,10 @@ func NameToKeyID(name string) (uint64, bool) { } func EqualKeyAndEqualID(s1, s2 *KeyState) bool { - if s1.Mode != s2.Mode { + if s1.Mode != s2.Mode || s1.Key.Secret != s2.Key.Secret { return false } - // For KMS mode, compare both KMSConfigHash and KMSKeyIDHash to detect config or key rotation - if s1.Mode == KMS { - if s1.KMSConfigHash != s2.KMSConfigHash { - return false - } - if s1.KMSKeyIDHash != s2.KMSKeyIDHash { - return false - } - } else if s1.Key.Secret != s2.Key.Secret { - return false - } - - // Verify key IDs match (for both KMS and non-KMS modes) id1, valid1 := NameToKeyID(s1.Key.Name) id2, valid2 := NameToKeyID(s2.Key.Name) return valid1 && valid2 && id1 == id2 diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go index 9ec37aa118..5ec7ae35f9 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go @@ -26,7 +26,7 @@ type GroupResourceState struct { } func (k GroupResourceState) HasWriteKey() bool { - return (len(k.WriteKey.Key.Name) > 0 && len(k.WriteKey.Key.Secret) > 0) || k.WriteKey.KMSConfigHash != "" + return len(k.WriteKey.Key.Name) > 0 && len(k.WriteKey.Key.Secret) > 0 } type KeyState struct { @@ -42,8 +42,6 @@ type KeyState struct { ExternalReason string // hash of the KMS configuration to detect changes KMSConfigHash string - // hash of the KMS key ID to detect changes - KMSKeyIDHash string } type MigrationState struct { diff --git a/vendor/modules.txt b/vendor/modules.txt index 630261d1fa..4b66f55438 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027081946-196d70f9eaa6 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 From df55e9493e305dc5cb5beb685c74cef1d4bc352c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Thu, 30 Oct 2025 11:24:44 +0300 Subject: [PATCH 3/9] fix encryption type --- go.mod | 2 +- go.sum | 4 ++-- .../library-go/pkg/operator/encryption/state/types.go | 2 +- vendor/modules.txt | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index fa94e8294b..6ddabecbb6 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 diff --git a/go.sum b/go.sum index d6f1c298c6..116a07a51f 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 h1:6MQ2HefcbiOp9EKxIFbyfmO0xUiOU/+TqP8/ZlHLTAs= -github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 h1:sPnpxKDNN/dv6s835RVL/t+Y2752N4+ZNmxwjTh/Znk= +github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go index 5ec7ae35f9..8d2c621f5e 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go @@ -62,7 +62,7 @@ const ( AESGCM Mode = "aesgcm" SecretBox Mode = "secretbox" // available from the first release, see defaultMode below Identity Mode = "identity" // available from the first release, see defaultMode below - KMS Mode = "kms" + KMS Mode = "KMS" // Changing this value requires caution to not break downgrades. // Specifically, if some new Mode is released in version X, that new Mode cannot diff --git a/vendor/modules.txt b/vendor/modules.txt index 4b66f55438..1f9a672ec8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251027150451-6d2bd1a42054 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 From 01ed3d1b8c0e6276066cd6578ac6f84b12205ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Thu, 30 Oct 2025 14:57:56 +0300 Subject: [PATCH 4/9] Temporarily disable KMS plugin access --- go.mod | 2 +- go.sum | 4 ++-- .../operator/encryption/controllers/key_controller.go | 9 +++++---- vendor/modules.txt | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 6ddabecbb6..fd18cdec1c 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 diff --git a/go.sum b/go.sum index 116a07a51f..c06f36b3fb 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 h1:sPnpxKDNN/dv6s835RVL/t+Y2752N4+ZNmxwjTh/Znk= -github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 h1:HP6YRlc+IAuXrXSks2439bZG1vYywRn56mjXDRu0a3Q= +github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go index 4dfcef0080..9e6d947b75 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go @@ -320,12 +320,12 @@ func (c *keyController) getCurrentModeAndExternalReason(ctx context.Context) (st // It calls the real KMS client to get the status and compute hashes func defaultGetKMSHashes(ctx context.Context, kmsConfig *configv1.KMSConfig) (string, []byte, error) { // Generate unix socket path from KMS config and get the hash - socketPath, configHash, err := kms.GenerateUnixSocketPath(kmsConfig) + _, configHash, err := kms.GenerateUnixSocketPath(kmsConfig) if err != nil { return "", nil, fmt.Errorf("failed to generate KMS unix socket path: %w", err) } - kmsClient, err := kms.NewKMSClient(socketPath) + /*kmsClient, err := kms.NewKMSClient(socketPath) if err != nil { return "", nil, fmt.Errorf("failed to create KMS client: %w", err) } @@ -338,9 +338,10 @@ func defaultGetKMSHashes(ctx context.Context, kmsConfig *configv1.KMSConfig) (st if statusResp.Healthz != "ok" { return "", nil, fmt.Errorf("KMS plugin is unhealthy: %s", statusResp.Healthz) - } + }*/ - return configHash, kms.ComputeKMSKeyHash(configHash, statusResp.KeyID), nil + keyId := "kms" + return configHash, kms.ComputeKMSKeyHash(configHash, keyId), nil } // needsNewKey checks whether a new key must be created for the given resource. If true, it also returns the latest diff --git a/vendor/modules.txt b/vendor/modules.txt index 1f9a672ec8..3a86af0390 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030082339-71699d34e967 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 From 2afae7dfdd18304bc6032ecd2aa3f756f40a305a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Fri, 31 Oct 2025 10:32:06 +0300 Subject: [PATCH 5/9] Mount hostPath --- .../bootkube/bootstrap-manifests/kube-apiserver-pod.yaml | 6 ++++++ go.mod | 2 +- go.sum | 4 ++-- .../openshift/library-go/pkg/operator/encryption/kms/kms.go | 2 +- vendor/modules.txt | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml b/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml index b8607a250d..956d95acf5 100644 --- a/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml +++ b/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml @@ -67,6 +67,8 @@ spec: name: logs - mountPath: /var/log/kube-apiserver name: audit-dir + - mountPath: /var/run/kms + name: kms-dir livenessProbe: httpGet: scheme: HTTPS @@ -138,3 +140,7 @@ spec: - hostPath: path: /var/log/kube-apiserver name: audit-dir + - hostPath: + path: /var/run/kms + type: DirectoryOrCreate + name: kms-dir diff --git a/go.mod b/go.mod index fd18cdec1c..391043da84 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 diff --git a/go.sum b/go.sum index c06f36b3fb..e1edd1be8b 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 h1:HP6YRlc+IAuXrXSks2439bZG1vYywRn56mjXDRu0a3Q= -github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 h1:JGwxHhq5eTkAyU5p3Un3a91EGfgevlZwwTIZQmoaS4k= +github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go index 8560cade3b..becec7bec6 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go @@ -16,7 +16,7 @@ import ( const ( // unixSocketBaseDir is the base directory for KMS unix sockets - unixSocketBaseDir = "unix://var/run/kms" + unixSocketBaseDir = "unix:///var/run/kms" ) // GenerateUnixSocketPath generates a unique unix socket path from KMS configuration diff --git a/vendor/modules.txt b/vendor/modules.txt index 3a86af0390..32b85488a8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251030115626-ea8e6aa29848 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 From a11ec650d29e704609693f0cb8ef4160c6ea3cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Mon, 3 Nov 2025 17:12:26 +0300 Subject: [PATCH 6/9] Get library-go changes --- go.mod | 2 +- go.sum | 4 ++-- .../encryption/encryptionconfig/config.go | 6 ++--- .../pkg/operator/encryption/kms/kms.go | 24 ++++++++++--------- vendor/modules.txt | 4 ++-- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 391043da84..d5f32e64c4 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c diff --git a/go.sum b/go.sum index e1edd1be8b..c081c9082f 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 h1:JGwxHhq5eTkAyU5p3Un3a91EGfgevlZwwTIZQmoaS4k= -github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c h1:F/3WHB083Ik/2oL0xcvGkioQkLVqjxS2+wO1PWvIbi4= +github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go index a39968650d..467cac1488 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go @@ -26,7 +26,7 @@ func FromEncryptionState(encryptionState map[schema.GroupResource]state.GroupRes for gr, grKeys := range encryptionState { resourceConfigs = append(resourceConfigs, apiserverconfigv1.ResourceConfiguration{ Resources: []string{gr.String()}, // we are forced to lose data here because this API is broken - Providers: stateToProviders(grKeys), + Providers: stateToProviders(gr.Resource, grKeys), }) } @@ -156,7 +156,7 @@ func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfigurati // it primarily handles the conversion of KeyState to the appropriate provider config. // the identity mode is transformed into a custom aesgcm provider that simply exists to // curry the associated null key secret through the encryption state machine. -func stateToProviders(desired state.GroupResourceState) []apiserverconfigv1.ProviderConfiguration { +func stateToProviders(resource string, desired state.GroupResourceState) []apiserverconfigv1.ProviderConfiguration { allKeys := desired.ReadKeys providers := make([]apiserverconfigv1.ProviderConfiguration, 0, len(allKeys)+1) // one extra for identity @@ -210,7 +210,7 @@ func stateToProviders(desired state.GroupResourceState) []apiserverconfigv1.Prov }, }) case state.KMS: - providers = append(providers, kms.GenerateKMSProviderConfigurationFromKey(key)) + providers = append(providers, kms.GenerateKMSProviderConfigurationFromKey(resource, key)) default: // this should never happen because our input should always be valid klog.Infof("skipping key %s as it has invalid mode %s", key.Key.Name, key.Mode) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go index becec7bec6..1c9339cd44 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/kms.go @@ -83,9 +83,9 @@ func ComputeKMSKeyHash(configHash, keyID string) []byte { var ( // endpointHashRegex matches the config hash in endpoint path: unix://var/run/kms/kms-{configHash16}.sock endpointHashRegex = regexp.MustCompile(`kms-([a-f0-9]{16})\.sock$`) - // providerNameRegex matches the key ID hash and key ID in provider name: kms-provider-{keyIDHash32}-{keyID} - // Example: kms-provider-abcdef1234567890abcdef1234567890-1 - providerNameRegex = regexp.MustCompile(`^kms-provider-([a-f0-9]{32})-(.+)$`) + // providerNameRegex matches the key ID hash, key ID, and resource in provider name: kms-provider-{keyIDHash32}-{keyID}-{resource} + // Example: kms-provider-abcdef1234567890abcdef1234567890-1-secrets + providerNameRegex = regexp.MustCompile(`^kms-provider-([a-f0-9]{32})-([^-]+)-(.+)$`) ) // ExtractKMSHashAndKeyName extracts the KMSConfigHash, KMSKeyIDHash, and key.Name embedded into provider @@ -100,13 +100,14 @@ func ExtractKMSHashAndKeyName(provider v1.ProviderConfiguration) (string, string return "", "", "", fmt.Errorf("invalid KMS endpoint format: %s", endpoint) } - // Extract the key ID hash and key ID from the provider name: kms-provider-{keyIDHash16}-{keyID} - // Example: kms-provider-abcdef1234567890abcdef1234567890-1 + // Extract the key ID hash, key ID, and resource from the provider name: kms-provider-{keyIDHash32}-{keyID}-{resource} + // Example: kms-provider-abcdef1234567890abcdef1234567890-1-secrets var keyHash, keyName string providerName := provider.KMS.Name - if matches := providerNameRegex.FindStringSubmatch(providerName); len(matches) == 3 { + if matches := providerNameRegex.FindStringSubmatch(providerName); len(matches) == 4 { keyHash = matches[1] keyName = matches[2] + // matches[3] is the resource, but we don't need to return it } else { return "", "", "", fmt.Errorf("invalid KMS provider name format: %s", providerName) } @@ -117,17 +118,18 @@ func ExtractKMSHashAndKeyName(provider v1.ProviderConfiguration) (string, string // GenerateKMSProviderConfigurationFromKey generates the compatible ProviderConfiguration with // opinionated and extractable fields. We embed: // - KMSConfigHash in the socket path (endpoint) -// - KMSKeyIDHash and key.Name in the provider name +// - KMSKeyIDHash, key.Name, and resource in the provider name // This allows us to extract all three values and detect both config changes and key rotations. -func GenerateKMSProviderConfigurationFromKey(key state.KeyState) v1.ProviderConfiguration { +// The resource parameter ensures uniqueness when the same KMS config is used for multiple resources. +func GenerateKMSProviderConfigurationFromKey(resource string, key state.KeyState) v1.ProviderConfiguration { // Embed KMSConfigHash in the endpoint so we can extract it // This must generate the same format as GenerateUnixSocketPath socketPath := fmt.Sprintf("%s/kms-%s.sock", unixSocketBaseDir, key.KMSConfigHash) - // Embed KMSKeyIDHash and key ID in the provider name so we can extract them when reading back - // Format: kms-provider-{keyIDHash32}-{keyID} + // Embed KMSKeyIDHash, key ID, and resource in the provider name so we can extract them when reading back + // Format: kms-provider-{keyIDHash32}-{keyID}-{resource} // This must match the providerNameRegex decoded, _ := base64.StdEncoding.DecodeString(key.Key.Secret) - providerName := fmt.Sprintf("kms-provider-%s-%s", decoded, key.Key.Name) + providerName := fmt.Sprintf("kms-provider-%s-%s-%s", decoded, key.Key.Name, resource) return v1.ProviderConfiguration{ KMS: &v1.KMSConfiguration{ diff --git a/vendor/modules.txt b/vendor/modules.txt index 32b85488a8..18e227e6d3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251031073000-2da49addafa4 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c From e603a1abc892273f054f59deb17c9fcd0c64579e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Tue, 4 Nov 2025 12:43:46 +0300 Subject: [PATCH 7/9] Add PoC plugin lifecycle --- .../kube-apiserver-pod.yaml | 7 +- go.mod | 2 +- go.sum | 4 +- pkg/operator/starter.go | 2 + .../targetconfigcontroller/kms_plugin.go | 96 ++++++ .../targetconfigcontroller.go | 44 ++- .../pkg/operator/encryption/kms/plugin.go | 294 ++++++++++++++++++ vendor/modules.txt | 4 +- 8 files changed, 435 insertions(+), 18 deletions(-) create mode 100644 pkg/operator/targetconfigcontroller/kms_plugin.go create mode 100644 vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go diff --git a/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml b/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml index 956d95acf5..70c8d3453e 100644 --- a/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml +++ b/bindata/bootkube/bootstrap-manifests/kube-apiserver-pod.yaml @@ -67,8 +67,6 @@ spec: name: logs - mountPath: /var/log/kube-apiserver name: audit-dir - - mountPath: /var/run/kms - name: kms-dir livenessProbe: httpGet: scheme: HTTPS @@ -140,7 +138,4 @@ spec: - hostPath: path: /var/log/kube-apiserver name: audit-dir - - hostPath: - path: /var/run/kms - type: DirectoryOrCreate - name: kms-dir + diff --git a/go.mod b/go.mod index d5f32e64c4..eeee3d6d58 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 diff --git a/go.sum b/go.sum index c081c9082f..0c9855f488 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c h1:F/3WHB083Ik/2oL0xcvGkioQkLVqjxS2+wO1PWvIbi4= -github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 h1:YuYNUuQRR0n9VPg7C+mXgyHoanBUB2Db/48PqQNPDeI= +github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/pkg/operator/starter.go b/pkg/operator/starter.go index 1e0551cff8..50ea63d6f6 100644 --- a/pkg/operator/starter.go +++ b/pkg/operator/starter.go @@ -281,9 +281,11 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle os.Getenv("IMAGE"), os.Getenv("OPERATOR_IMAGE"), os.Getenv("OPERATOR_IMAGE_VERSION"), + os.Getenv("KMS_PLUGIN_IMAGE"), operatorClient, kubeInformersForNamespaces.InformersFor(operatorclient.TargetNamespace), kubeInformersForNamespaces, + configInformers.Config().V1().APIServers(), kubeClient, startupmonitorreadiness.IsStartupMonitorEnabledFunction(configInformers.Config().V1().Infrastructures().Lister(), operatorClient), requireMultipleEtcdEndpoints, diff --git a/pkg/operator/targetconfigcontroller/kms_plugin.go b/pkg/operator/targetconfigcontroller/kms_plugin.go new file mode 100644 index 0000000000..27a14c83a3 --- /dev/null +++ b/pkg/operator/targetconfigcontroller/kms_plugin.go @@ -0,0 +1,96 @@ +package targetconfigcontroller + +import ( + "context" + "fmt" + + configv1 "github.com/openshift/api/config/v1" + configv1listers "github.com/openshift/client-go/config/listers/config/v1" + "github.com/openshift/library-go/pkg/operator/encryption/kms" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/klog/v2" +) + +// copied from https://github.com/flavianmissi/cluster-kube-apiserver-operator/tree/kms-plugin-sidecars + +const ( + // KMSPluginImageEnvVar is the environment variable that specifies the KMS plugin container image + // This should be set by the operator deployment + KMSPluginImageEnvVar = "KMS_PLUGIN_IMAGE" + + // DefaultKMSPluginImage is the fallback image if KMS_PLUGIN_IMAGE is not set + DefaultKMSPluginImage = "registry.k8s.io/kms-plugin/aws-encryption-provider:v1.0.0" +) + +// getKMSEncryptionConfig checks if KMS encryption is enabled and returns the configuration +// Returns: +// - kmsConfig: the KMS configuration if enabled, nil otherwise +// - enabled: true if KMS encryption is enabled +// - error: any error encountered while reading the config +func getKMSEncryptionConfig(ctx context.Context, apiserverLister configv1listers.APIServerLister) (*configv1.KMSConfig, bool, error) { + apiserver, err := apiserverLister.Get("cluster") + if err != nil { + if apierrors.IsNotFound(err) { + klog.V(4).Info("APIServer config.openshift.io/cluster not found, KMS encryption not enabled") + return nil, false, nil + } + return nil, false, fmt.Errorf("failed to get APIServer config: %w", err) + } + + // Check if encryption is configured + if apiserver.Spec.Encryption.Type != configv1.EncryptionTypeKMS { + klog.V(4).Infof("Encryption type is %q, not KMS - skipping KMS plugin injection", apiserver.Spec.Encryption.Type) + return nil, false, nil + } + + // KMS type is set, must have KMS config + if apiserver.Spec.Encryption.KMS == nil { + return nil, false, fmt.Errorf("encryption type is KMS but kms config is nil") + } + + klog.Infof("KMS encryption enabled with type=%s, region=%s, keyARN=%s", + apiserver.Spec.Encryption.KMS.Type, + apiserver.Spec.Encryption.KMS.AWS.Region, + apiserver.Spec.Encryption.KMS.AWS.KeyARN) + + return apiserver.Spec.Encryption.KMS, true, nil +} + +// injectKMSPlugin adds the KMS plugin sidecar container to the kube-apiserver pod +// if KMS encryption is enabled in the cluster APIServer config +func injectKMSPlugin(ctx context.Context, pod *corev1.Pod, apiserverLister configv1listers.APIServerLister, kmsPluginImage string) error { + // Check if KMS encryption is enabled + kmsConfig, enabled, err := getKMSEncryptionConfig(ctx, apiserverLister) + if err != nil { + return fmt.Errorf("failed to check KMS encryption config: %w", err) + } + + if !enabled { + klog.V(4).Info("KMS encryption not enabled, skipping sidecar injection") + return nil + } + + // Validate the image is set + if kmsPluginImage == "" { + return fmt.Errorf("KMS plugin image is required when KMS encryption is enabled") + } + + klog.Infof("Injecting KMS plugin sidecar container (image: %s)", kmsPluginImage) + + // Create container config for kube-apiserver + // kube-apiserver uses hostNetwork: true, so it accesses AWS credentials via IMDS + containerConfig := &kms.ContainerConfig{ + Image: kmsPluginImage, + UseHostNetwork: true, // Static pod with hostNetwork uses EC2 IMDS for AWS credentials + KMSConfig: kmsConfig, + } + + // Inject the KMS plugin sidecar container and volumes into the pod spec + if err := kms.AddKMSPluginToPodSpec(&pod.Spec, kmsConfig, containerConfig, true); err != nil { + return fmt.Errorf("failed to inject KMS plugin sidecar: %w", err) + } + + klog.Infof("Successfully injected KMS plugin sidecar container") + return nil +} diff --git a/pkg/operator/targetconfigcontroller/targetconfigcontroller.go b/pkg/operator/targetconfigcontroller/targetconfigcontroller.go index 7a4406f670..94cc012e08 100644 --- a/pkg/operator/targetconfigcontroller/targetconfigcontroller.go +++ b/pkg/operator/targetconfigcontroller/targetconfigcontroller.go @@ -15,6 +15,8 @@ import ( kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1" operatorv1 "github.com/openshift/api/operator/v1" + configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" + configv1listers "github.com/openshift/client-go/config/listers/config/v1" "github.com/openshift/cluster-kube-apiserver-operator/bindata" "github.com/openshift/cluster-kube-apiserver-operator/pkg/operator/configobservation/node" "github.com/openshift/cluster-kube-apiserver-operator/pkg/operator/operatorclient" @@ -51,21 +53,24 @@ type TargetConfigController struct { targetImagePullSpec string operatorImagePullSpec string operatorImageVersion string + kmsPluginImage string operatorClient v1helpers.StaticPodOperatorClient kubeClient kubernetes.Interface configMapLister corev1listers.ConfigMapLister + apiserverLister configv1listers.APIServerLister isStartupMonitorEnabledFn func() (bool, error) requireMultipleEtcdEndpointsFn func() bool } func NewTargetConfigController( - targetImagePullSpec, operatorImagePullSpec, operatorImageVersion string, + targetImagePullSpec, operatorImagePullSpec, operatorImageVersion, kmsPluginImage string, operatorClient v1helpers.StaticPodOperatorClient, kubeInformersForOpenshiftKubeAPIServerNamespace informers.SharedInformerFactory, kubeInformersForNamespaces v1helpers.KubeInformersForNamespaces, + apiserverInformer configv1informers.APIServerInformer, kubeClient kubernetes.Interface, isStartupMonitorEnabledFn func() (bool, error), requireMultipleEtcdEndpointsFn func() bool, @@ -75,9 +80,11 @@ func NewTargetConfigController( targetImagePullSpec: targetImagePullSpec, operatorImagePullSpec: operatorImagePullSpec, operatorImageVersion: operatorImageVersion, + kmsPluginImage: kmsPluginImage, operatorClient: operatorClient, kubeClient: kubeClient, configMapLister: kubeInformersForNamespaces.ConfigMapLister(), + apiserverLister: apiserverInformer.Lister(), isStartupMonitorEnabledFn: isStartupMonitorEnabledFn, requireMultipleEtcdEndpointsFn: requireMultipleEtcdEndpointsFn, } @@ -91,6 +98,7 @@ func NewTargetConfigController( kubeInformersForNamespaces.InformersFor(operatorclient.GlobalMachineSpecifiedConfigNamespace).Core().V1().ConfigMaps().Informer(), kubeInformersForNamespaces.InformersFor(operatorclient.OperatorNamespace).Core().V1().ConfigMaps().Informer(), kubeInformersForNamespaces.InformersFor(operatorclient.TargetNamespace).Core().V1().ConfigMaps().Informer(), + apiserverInformer.Informer(), ).WithSync(c.sync).ResyncEvery(time.Minute).ToController("TargetConfigController", eventRecorder.WithComponentSuffix("target-config-controller")) } @@ -219,7 +227,18 @@ func createTargetConfig(ctx context.Context, c TargetConfigController, recorder if err != nil { errors = append(errors, fmt.Errorf("%q: %v", "configmap/config", err)) } - _, _, err = managePods(ctx, c.kubeClient.CoreV1(), c.isStartupMonitorEnabledFn, recorder, operatorSpec, c.targetImagePullSpec, c.operatorImagePullSpec, c.operatorImageVersion) + _, _, err = managePods( + ctx, + c.kubeClient.CoreV1(), + c.apiserverLister, + c.isStartupMonitorEnabledFn, + recorder, + operatorSpec, + c.targetImagePullSpec, + c.operatorImagePullSpec, + c.operatorImageVersion, + c.kmsPluginImage, + ) if err != nil { errors = append(errors, fmt.Errorf("%q: %v", "configmap/kube-apiserver-pod", err)) } @@ -303,11 +322,17 @@ func manageKubeAPIServerConfig(ctx context.Context, client coreclientv1.ConfigMa return resourceapply.ApplyConfigMap(ctx, client, recorder, requiredConfigMap) } -func managePods(ctx context.Context, client coreclientv1.ConfigMapsGetter, isStartupMonitorEnabledFn func() (bool, error), recorder events.Recorder, operatorSpec *operatorv1.StaticPodOperatorSpec, imagePullSpec, operatorImagePullSpec, operatorImageVersion string) (*corev1.ConfigMap, bool, error) { - appliedPodTemplate, err := manageTemplate(string(bindata.MustAsset("assets/kube-apiserver/pod.yaml")), imagePullSpec, operatorImagePullSpec, operatorImageVersion, operatorSpec) - if err != nil { - return nil, false, err - } +func managePods( + ctx context.Context, + client coreclientv1.ConfigMapsGetter, + apiserverLister configv1listers.APIServerLister, + isStartupMonitorEnabledFn func() (bool, error), + recorder events.Recorder, + operatorSpec *operatorv1.StaticPodOperatorSpec, + imagePullSpec, operatorImagePullSpec, operatorImageVersion, kmsPluginImage string, +) (*corev1.ConfigMap, bool, error) { + appliedPodTemplate, err := manageTemplate( + string(bindata.MustAsset("assets/kube-apiserver/pod.yaml")), imagePullSpec, operatorImagePullSpec, operatorImageVersion, operatorSpec) required := resourceread.ReadPodV1OrDie([]byte(appliedPodTemplate)) var observedConfig map[string]interface{} @@ -324,6 +349,11 @@ func managePods(ctx context.Context, client coreclientv1.ConfigMapsGetter, isSta required.Spec.Containers[i].Env = append(container.Env, proxyEnvVars...) } + // Inject KMS plugin sidecar if KMS encryption is enabled + if err := injectKMSPlugin(ctx, required, apiserverLister, kmsPluginImage); err != nil { + return nil, false, fmt.Errorf("failed to inject KMS plugin: %v", err) + } + configMap := resourceread.ReadConfigMapV1OrDie(bindata.MustAsset("assets/kube-apiserver/pod-cm.yaml")) configMap.Data["pod.yaml"] = resourceread.WritePodV1OrDie(required) configMap.Data["forceRedeploymentReason"] = operatorSpec.ForceRedeploymentReason diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go new file mode 100644 index 0000000000..ce777cf0af --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go @@ -0,0 +1,294 @@ +package kms + +import ( + "fmt" + + configv1 "github.com/openshift/api/config/v1" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" +) + +// from https://github.com/flavianmissi/library-go/tree/kms-plugin-sidecars + +const ( + // defaultKMSPluginImage is the default AWS KMS plugin image + // This should be overridden by the operator with the actual image reference + defaultKMSPluginImage = "registry.k8s.io/kms-plugin-aws:latest" + + // defaultHealthPort is the default port for the KMS plugin health endpoint + defaultHealthPort = 8080 + + // KMSContainerName is the standard name for the KMS plugin sidecar container + KMSContainerName = "kms-plugin" + + // KMSSocketVolumeName is the standard name for the socket volume + KMSSocketVolumeName = "kms-socket" + + // KMSCredentialsVolumeName is the standard name for the credentials volume + KMSCredentialsVolumeName = "aws-credentials" +) + +// ContainerConfig holds additional configuration beyond what's in configv1.KMSConfig +// for building the KMS plugin sidecar container +type ContainerConfig struct { + // KMSConfig is the desired configv1.KMSConfig + // Required + KMSConfig *configv1.KMSConfig + + // Image is the container image for the KMS plugin + // Required + Image string + + // UseHostNetwork indicates if the pod uses hostNetwork: true + // If true, the container will access AWS credentials via EC2 IMDS + // If false, credentials must be provided via CredentialsSecretName + UseHostNetwork bool + + // CredentialsSecretName is the name of the secret containing AWS credentials + // Only required when UseHostNetwork is false + // The secret should contain a key "credentials" in AWS shared credentials file format + CredentialsSecretName string + + // SocketPath is the Unix socket path where the KMS plugin listens + // Optional - defaults to defaultSocketPath + SocketPath string + + // HealthPort is the port for the KMS plugin health endpoint + // Optional - defaults to defaultHealthPort + HealthPort int32 + + // CPURequest is the CPU request for the container + // Optional - defaults to "10m" + CPURequest string + + // MemoryRequest is the memory request for the container + // Optional - defaults to "50Mi" + MemoryRequest string +} + +// Validate ensures the ContainerConfig is valid +func (c *ContainerConfig) Validate() error { + if c.Image == "" { + return fmt.Errorf("Image is required") + } + if !c.UseHostNetwork && c.CredentialsSecretName == "" { + return fmt.Errorf("CredentialsSecretName is required when UseHostNetwork is false") + } + return nil +} + +// setDefaults sets default values for unspecified fields +func (c *ContainerConfig) setDefaults() { + if c.SocketPath == "" { + socket, _, err := GenerateUnixSocketPath(c.KMSConfig) + if err != nil { + panic(err) + } + c.SocketPath = socket + } + if c.HealthPort == 0 { + c.HealthPort = defaultHealthPort + } + if c.CPURequest == "" { + c.CPURequest = "10m" + } + if c.MemoryRequest == "" { + c.MemoryRequest = "50Mi" + } +} + +// buildPluginContainer creates a corev1.Container spec for the KMS plugin sidecar +// based on the KMS configuration from openshift/api and container-specific config +func buildPluginContainer(kmsConfig *configv1.KMSConfig, containerConfig *ContainerConfig) (*corev1.Container, error) { + if kmsConfig == nil { + return nil, fmt.Errorf("kmsConfig cannot be nil") + } + if containerConfig == nil { + return nil, fmt.Errorf("containerConfig cannot be nil") + } + + // Validate inputs + if err := containerConfig.Validate(); err != nil { + return nil, fmt.Errorf("invalid container config: %w", err) + } + + // Set defaults + containerConfig.setDefaults() + + // Currently only AWS is supported + if kmsConfig.Type != configv1.AWSKMSProvider { + return nil, fmt.Errorf("unsupported KMS provider type: %s (only %s is supported)", kmsConfig.Type, configv1.AWSKMSProvider) + } + if kmsConfig.AWS == nil { + return nil, fmt.Errorf("AWS KMS config is required when type is AWS") + } + + container := &corev1.Container{ + Name: KMSContainerName, + Image: containerConfig.Image, + Command: []string{ + "/aws-encryption-provider", + }, + Args: []string{ + fmt.Sprintf("--key=%s", kmsConfig.AWS.KeyARN), + fmt.Sprintf("--region=%s", kmsConfig.AWS.Region), + fmt.Sprintf("--listen=%s", containerConfig.SocketPath), + }, + Ports: []corev1.ContainerPort{ + { + Name: "healthz", + ContainerPort: containerConfig.HealthPort, + Protocol: corev1.ProtocolTCP, + }, + }, + SecurityContext: &corev1.SecurityContext{ + AllowPrivilegeEscalation: ptr.To(false), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + ReadOnlyRootFilesystem: ptr.To(true), + RunAsUser: ptr.To(int64(0)), // Required for AWS SDK credential chain + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: KMSSocketVolumeName, + MountPath: "/var/run/kms", + }, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: "/healthz", + Port: intstr.FromInt32(containerConfig.HealthPort), + }, + }, + InitialDelaySeconds: 10, + PeriodSeconds: 10, + TimeoutSeconds: 3, + FailureThreshold: 3, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: "/healthz", + Port: intstr.FromInt32(containerConfig.HealthPort), + }, + }, + InitialDelaySeconds: 5, + PeriodSeconds: 5, + TimeoutSeconds: 3, + FailureThreshold: 3, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse(containerConfig.CPURequest), + corev1.ResourceMemory: resource.MustParse(containerConfig.MemoryRequest), + }, + }, + TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, + } + + // Add credentials mount if not using hostNetwork + if !containerConfig.UseHostNetwork { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "AWS_SHARED_CREDENTIALS_FILE", + Value: "/var/run/secrets/aws/credentials", + }) + container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{ + Name: KMSCredentialsVolumeName, + MountPath: "/var/run/secrets/aws", + ReadOnly: true, + }) + } + + return container, nil +} + +// buildPluginVolumes creates the required volumes for the KMS plugin +func buildPluginVolumes(useHostNetwork bool, credentialsSecretName string, hostPath bool) []corev1.Volume { + volumes := []corev1.Volume{ + { + Name: KMSSocketVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + } + + // For static pods using hostPath, override the socket volume + if hostPath { + volumes[0].VolumeSource = corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/var/run/kms", + Type: ptr.To(corev1.HostPathDirectoryOrCreate), + }, + } + } + + // Add credentials volume if not using hostNetwork + if !useHostNetwork && credentialsSecretName != "" { + volumes = append(volumes, corev1.Volume{ + Name: KMSCredentialsVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: credentialsSecretName, + Items: []corev1.KeyToPath{ + { + Key: "credentials", + Path: "credentials", + }, + }, + }, + }, + }) + } + + return volumes +} + +// AddKMSPluginToPodSpec injects the KMS plugin container and volumes into a PodSpec +// This is a convenience function that combines buildPluginContainer() and buildPluginVolumes() +func AddKMSPluginToPodSpec( + podSpec *corev1.PodSpec, + kmsConfig *configv1.KMSConfig, + containerConfig *ContainerConfig, + useHostPathForSocket bool, +) error { + if podSpec == nil { + return fmt.Errorf("podSpec cannot be nil") + } + + // Create the KMS plugin container + kmsContainer, err := buildPluginContainer(kmsConfig, containerConfig) + if err != nil { + return fmt.Errorf("failed to create KMS plugin container: %w", err) + } + + // Add the container to the pod spec + podSpec.Containers = append(podSpec.Containers, *kmsContainer) + + // Add required volumes + volumes := buildPluginVolumes(containerConfig.UseHostNetwork, containerConfig.CredentialsSecretName, useHostPathForSocket) + podSpec.Volumes = append(podSpec.Volumes, volumes...) + + // Mount the KMS socket in the API server container + // Find the main API server container and add the socket mount + for i := range podSpec.Containers { + // Look for common API server container names + if podSpec.Containers[i].Name == "kube-apiserver" || + podSpec.Containers[i].Name == "openshift-apiserver" || + podSpec.Containers[i].Name == "oauth-apiserver" { + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ + Name: KMSSocketVolumeName, + MountPath: "/var/run/kms", + ReadOnly: true, + }) + break + } + } + + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 18e227e6d3..bdb237badf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251103141116-4a45d508098c +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 From 071e7940f9665aec6afbb221b8a34af09543d853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Tue, 4 Nov 2025 12:46:23 +0300 Subject: [PATCH 8/9] Use custom plugin image --- pkg/operator/targetconfigcontroller/kms_plugin.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/operator/targetconfigcontroller/kms_plugin.go b/pkg/operator/targetconfigcontroller/kms_plugin.go index 27a14c83a3..3c0ee2e864 100644 --- a/pkg/operator/targetconfigcontroller/kms_plugin.go +++ b/pkg/operator/targetconfigcontroller/kms_plugin.go @@ -20,7 +20,7 @@ const ( KMSPluginImageEnvVar = "KMS_PLUGIN_IMAGE" // DefaultKMSPluginImage is the fallback image if KMS_PLUGIN_IMAGE is not set - DefaultKMSPluginImage = "registry.k8s.io/kms-plugin/aws-encryption-provider:v1.0.0" + DefaultKMSPluginImage = "quay.io/fmissi/aws-kms-plugin:0.1.0" ) // getKMSEncryptionConfig checks if KMS encryption is enabled and returns the configuration @@ -73,7 +73,7 @@ func injectKMSPlugin(ctx context.Context, pod *corev1.Pod, apiserverLister confi // Validate the image is set if kmsPluginImage == "" { - return fmt.Errorf("KMS plugin image is required when KMS encryption is enabled") + kmsPluginImage = DefaultKMSPluginImage } klog.Infof("Injecting KMS plugin sidecar container (image: %s)", kmsPluginImage) From 23f52816acde5f98a7204acbd2fe91ccfd2de0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 5 Nov 2025 09:20:13 +0300 Subject: [PATCH 9/9] Revendor library-go --- go.mod | 2 +- go.sum | 4 ++-- .../library-go/pkg/operator/encryption/kms/plugin.go | 3 ++- vendor/modules.txt | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index eeee3d6d58..dac82bb6dc 100644 --- a/go.mod +++ b/go.mod @@ -136,4 +136,4 @@ require ( replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 +replace github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251105061910-519a2c27c78d diff --git a/go.sum b/go.sum index 0c9855f488..4ba96ccb90 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U= github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 h1:YuYNUuQRR0n9VPg7C+mXgyHoanBUB2Db/48PqQNPDeI= -github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= +github.com/ardaguclu/library-go v0.0.0-20251105061910-519a2c27c78d h1:nLyySCXMIChM6B3mcIIoErpirIvKZDvR+yCIR+p28Mc= +github.com/ardaguclu/library-go v0.0.0-20251105061910-519a2c27c78d/go.mod h1:UdWv/P+Rw/TrLB6qpwLsUIf5urKlbAqEoK9qnP1NVmQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go index ce777cf0af..8b85a0cc7f 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/plugin.go @@ -2,6 +2,7 @@ package kms import ( "fmt" + "strings" configv1 "github.com/openshift/api/config/v1" @@ -87,7 +88,7 @@ func (c *ContainerConfig) setDefaults() { if err != nil { panic(err) } - c.SocketPath = socket + c.SocketPath = strings.Replace(socket, "unix://", "", 1) } if c.HealthPort == 0 { c.HealthPort = defaultHealthPort diff --git a/vendor/modules.txt b/vendor/modules.txt index bdb237badf..7d6ebb2fd4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,7 +403,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 +# github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 => github.com/ardaguclu/library-go v0.0.0-20251105061910-519a2c27c78d ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -1682,4 +1682,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 -# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251104093549-31496363b7d7 +# github.com/openshift/library-go => github.com/ardaguclu/library-go v0.0.0-20251105061910-519a2c27c78d