diff --git a/go.mod b/go.mod index 6167333fe..17a49c65b 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/openshift/api v0.0.0-20260521125114-09730f85d883 github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af github.com/openshift/client-go v0.0.0-20260512113608-deb4dc54551a - github.com/openshift/library-go v0.0.0-20260604143514-ba2b9a3a3499 + github.com/openshift/library-go v0.0.0-20260603103329-d8750ed2813e github.com/spf13/cobra v1.10.0 github.com/stretchr/testify v1.11.1 go.etcd.io/etcd/client/v3 v3.6.5 diff --git a/go.sum b/go.sum index aac04c8ea..a01d1f8de 100644 --- a/go.sum +++ b/go.sum @@ -174,8 +174,8 @@ github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af h1:Ui github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20260512113608-deb4dc54551a h1:EKx2XhOKehd1C5ptY7IrLl4WV35E8kP0pRPnG5BUZXk= github.com/openshift/client-go v0.0.0-20260512113608-deb4dc54551a/go.mod h1:V933kvY/cb/Un7UCEOhXHUySNX327u7Epe8g9KNqg2Q= -github.com/openshift/library-go v0.0.0-20260604143514-ba2b9a3a3499 h1:Ff5OLOVD1Kj5RYEUHaBCOWGzqdEjygIGvReaj7uIxpc= -github.com/openshift/library-go v0.0.0-20260604143514-ba2b9a3a3499/go.mod h1:/HBhy6jm/igWI3Y1vYFwFG3ZCcXmnNsKUT6VBpPyM9A= +github.com/openshift/library-go v0.0.0-20260603103329-d8750ed2813e h1:YZwznqixO2lJa3eNSghZiKCgYbdk5IRvqDf7k6NKFZ4= +github.com/openshift/library-go v0.0.0-20260603103329-d8750ed2813e/go.mod h1:/HBhy6jm/igWI3Y1vYFwFG3ZCcXmnNsKUT6VBpPyM9A= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20260303184444-1cc650aa0565 h1:3/q8qM4HbFa+Een8wgzpwO8W6mO7Po+MwY6uxiXi/ac= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20260303184444-1cc650aa0565/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= diff --git a/test/e2e-encryption-kms/encryption_kms.go b/test/e2e-encryption-kms/encryption_kms.go index 29c21f9cb..8ba566271 100644 --- a/test/e2e-encryption-kms/encryption_kms.go +++ b/test/e2e-encryption-kms/encryption_kms.go @@ -30,7 +30,7 @@ var _ = g.Describe("[sig-openshift-apiserver] cluster-openshift-apiserver-operat // testKMSEncryptionOnOff tests KMS encryption on/off cycle. // This test: -// 1. Deploys the real Vault KMS plugin +// 1. Deploys the mock KMS plugin // 2. Creates a test OAuth access token (TokenOfLife) // 3. Enables KMS encryption // 4. Verifies token is encrypted @@ -65,13 +65,13 @@ func testKMSEncryptionOnOff(ctx context.Context, t testing.TB) { AssertResourceNotEncryptedFunc: operatorencryption.AssertRouteOfLifeNotEncrypted, ResourceFunc: func(t testing.TB, _ string) runtime.Object { return operatorencryption.RouteOfLife(t, ns) }, ResourceName: "TokenOfLife", - EncryptionProvider: librarykms.DefaultVaultEncryptionProvider(ctx, t), + EncryptionProvider: librarykms.DefaultFakeVaultEncryptionProvider, }) } // testKMSEncryptionProvidersMigration tests migration between KMS and AES encryption providers. // This test: -// 1. Deploys the real Vault KMS plugin +// 1. Deploys the mock KMS plugin // 2. Creates a test OAuth access token (TokenOfLife) // 3. Randomly picks one AES encryption provider (AESGCM or AESCBC) // 4. Shuffles the selected AES provider with KMS to create a randomized migration order @@ -103,7 +103,7 @@ func testKMSEncryptionProvidersMigration(ctx context.Context, t testing.TB) { ResourceFunc: func(t testing.TB, _ string) runtime.Object { return operatorencryption.RouteOfLife(t, ns) }, ResourceName: "TokenOfLife", EncryptionProviders: library.ShuffleEncryptionProviders([]library.EncryptionProvider{ - librarykms.DefaultVaultEncryptionProvider(ctx, t), + librarykms.DefaultFakeVaultEncryptionProvider, library.SupportedStaticEncryptionProviders[rand.IntN(len(library.SupportedStaticEncryptionProviders))], }), }) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/config.go index 666f07a33..9317acc17 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/config.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/config.go @@ -32,34 +32,34 @@ type Config struct { KMSPlugins map[string]configv1.KMSPluginConfig // KMSPluginsSecretData maps keyID to secret data carried from // Key Secrets into the encryption-config Secret. - // Structure: keyID → referenceName → dataKey → value. - KMSPluginsSecretData KMSPluginsReferenceData + // Structure: keyID → secretName → dataKey → value. + KMSPluginsSecretData KMSPluginsSecretData } -// KMSPluginsReferenceData maps keyID to reference data carried from Key Secrets into -// the encryption-config Secret. Structure: keyID → referenceName → dataKey → value. -type KMSPluginsReferenceData struct { - byKeyID map[string]state.KMSReferenceData +// KMSPluginsSecretData maps keyID to secret data carried from Key Secrets into +// the encryption-config Secret. Structure: keyID → secretName → dataKey → value. +type KMSPluginsSecretData struct { + byKeyID map[string]state.KMSSecretData } -// Get returns the KMSReferenceData for the given keyID and true if it exists, +// Get returns the KMSSecretData for the given keyID and true if it exists, // or a zero value and false otherwise. It is safe to call on a nil map. -func (d *KMSPluginsReferenceData) Get(keyID string) (state.KMSReferenceData, bool) { +func (d *KMSPluginsSecretData) Get(keyID string) (state.KMSSecretData, bool) { if d.byKeyID == nil { - return state.KMSReferenceData{}, false + return state.KMSSecretData{}, false } sd, ok := d.byKeyID[keyID] return sd, ok } // SetFromRawKey stores a value for the given keyID, splitting rawKey -// on "_" into referenceName and dataKey. -func (d *KMSPluginsReferenceData) SetFromRawKey(keyID, rawKey string, value []byte) error { +// on "_" into secretName and dataKey. +func (d *KMSPluginsSecretData) SetFromRawKey(keyID, rawKey string, value []byte) error { if len(keyID) == 0 { return fmt.Errorf("keyID must not be empty") } if d.byKeyID == nil { - d.byKeyID = map[string]state.KMSReferenceData{} + d.byKeyID = map[string]state.KMSSecretData{} } sd := d.byKeyID[keyID] if err := sd.SetFromRawKey(rawKey, value); err != nil { @@ -70,8 +70,8 @@ func (d *KMSPluginsReferenceData) SetFromRawKey(keyID, rawKey string, value []by } // FlatEntriesByKeyID returns the stored data as a map of keyID to flat entries, -// where each flat entry is keyed by "referenceName_dataKey". -func (d *KMSPluginsReferenceData) FlatEntriesByKeyID() map[string]map[string][]byte { +// where each flat entry is keyed by "secretName_dataKey". +func (d *KMSPluginsSecretData) FlatEntriesByKeyID() map[string]map[string][]byte { if d.byKeyID == nil { return nil } @@ -92,7 +92,7 @@ func (c *Config) HasEncryptionConfiguration() bool { func FromEncryptionState(encryptionState map[schema.GroupResource]state.GroupResourceState) (*Config, error) { resourceConfigs := make([]apiserverconfigv1.ResourceConfiguration, 0, len(encryptionState)) var kmsPlugins map[string]configv1.KMSPluginConfig - var kmsPluginsSecretData KMSPluginsReferenceData + var kmsPluginsSecretData KMSPluginsSecretData for gr, grKeys := range encryptionState { resourceConfigs = append(resourceConfigs, apiserverconfigv1.ResourceConfiguration{ diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/secret.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/secret.go index 9a386ff17..9daffad08 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/secret.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptiondata/secret.go @@ -89,7 +89,7 @@ func FromSecret(encryptionConfigSecret *corev1.Secret) (*Config, error) { // (e.g. "kms-plugin-secret-app-role_role-id-1"). keyIDFromSecretDataKey // returns the keyID (e.g. "1") and the combined key (e.g. "app-role_role-id"), // which is then split on "_" to recover secretName and dataKey. - var kmsPluginsSecretData KMSPluginsReferenceData + var kmsPluginsSecretData KMSPluginsSecretData for key, value := range encryptionConfigSecret.Data { keyID, rawKey, found, err := parseKMSSecretDataKey(key) if err != nil { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/credentials.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/credentials.go deleted file mode 100644 index f4abd1d8f..000000000 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/credentials.go +++ /dev/null @@ -1,43 +0,0 @@ -package pluginlifecycle - -import ( - "fmt" - "path/filepath" - - "github.com/openshift/library-go/pkg/operator/encryption/encryptiondata" -) - -// credentialResolver resolves KMS plugin credentials for a specific keyID -// by looking up secret data and mapping it to values or file paths on disk. -type credentialResolver struct { - keyID string - credentialsDir string - pluginsSecretData encryptiondata.KMSPluginsReferenceData -} - -// Value returns the credential value for the given secret name and data key. -func (r *credentialResolver) Value(secretName, dataKey string) (string, error) { - sd, ok := r.pluginsSecretData.Get(r.keyID) - if !ok { - return "", fmt.Errorf("missing secret data for keyID %s", r.keyID) - } - v, ok := sd.Get(secretName, dataKey) - if !ok { - return "", fmt.Errorf("missing %s in secret %s for keyID %s", dataKey, secretName, r.keyID) - } - return string(v), nil -} - -// FilePath returns the on-disk path where the credential for the given secret name and data key is mounted. -func (r *credentialResolver) FilePath(secretName, dataKey string) (string, error) { - sd, ok := r.pluginsSecretData.Get(r.keyID) - if !ok { - return "", fmt.Errorf("missing secret data for keyID %s", r.keyID) - } - rawKey, ok := sd.FlatEntry(secretName, dataKey) - if !ok { - return "", fmt.Errorf("missing %s in secret %s for keyID %s", dataKey, secretName, r.keyID) - } - secretDataKey := encryptiondata.FormatKMSSecretDataKey(rawKey, r.keyID) - return filepath.Join(r.credentialsDir, secretDataKey), nil -} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/sidecar.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/sidecar.go index 4bdfd26cb..66590eaae 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/sidecar.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/sidecar.go @@ -3,7 +3,6 @@ package pluginlifecycle import ( "context" "fmt" - "path/filepath" configv1 "github.com/openshift/api/config/v1" "github.com/openshift/api/features" @@ -15,14 +14,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corev1client "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/klog/v2" - "k8s.io/utils/ptr" -) - -const ( - resourceDirVolumeName = "resource-dir" - credentialsVolumeName = "kms-plugin-credentials" - credentialsMountPath = "/var/run/secrets/kms-plugin" - resourcesDir = "/etc/kubernetes/static-pod-resources" ) const ( @@ -38,134 +29,66 @@ type sidecarProvider interface { BuildSidecarContainer() (corev1.Container, error) } -// newSidecarProvider creates a provider-specific sidecarProvider for the given keyID and plugin configuration, -// wiring in credentials via the credentialResolver. -func newSidecarProvider(keyID string, udsPath string, pluginConfig configv1.KMSPluginConfig, creds *credentialResolver) (sidecarProvider, error) { +// newSidecarProvider creates a provider-specific SidecarProvider for the given keyID, UDS endpoint, and plugin configuration. +func newSidecarProvider(keyID string, udsPath string, pluginConfig configv1.KMSPluginConfig) (sidecarProvider, error) { switch pluginConfig.Type { case configv1.VaultKMSProvider: - return newVaultSidecarProvider("vault-kms-plugin", keyID, udsPath, pluginConfig.Vault, creds) + return newVaultSidecarProvider("vault-kms-plugin", keyID, udsPath, pluginConfig.Vault) default: return nil, fmt.Errorf("unsupported KMS plugin configuration") } } -// AddKMSPluginSidecarToStaticPodSpec injects KMS plugin sidecar containers into a kube-apiserver static pod spec. -// -// Static pods access credentials through the resource-dir volume, which the static pod revision controller -// populates on disk from the encryption-config Secret. Because those files are owned by root, each sidecar -// is configured to run as UID 0. -// +// AddKMSPluginSidecarToPodSpec discovers KMS plugins from the encryption-config secret and injects a sidecar container for each one into the pod spec. // It is a no-op when the KMSEncryption feature gate is not enabled or the encryption-config secret does not exist. -// The secretClient should be uncached to avoid injecting sidecars based on a stale encryption configuration. -func AddKMSPluginSidecarToStaticPodSpec(ctx context.Context, podSpec *corev1.PodSpec, containerName string, encryptionConfigNamespace string, encryptionConfigSecretName string, secretClient corev1client.SecretsGetter, featureGateAccessor featuregates.FeatureGateAccess) error { - // The static pod revision controller copies secret data to disk under resourcesDir/secrets//. - credentialsDir := filepath.Join(resourcesDir, "secrets", encryptionConfigSecretName) - - sidecarNames, err := addKMSPluginSidecars(ctx, podSpec, containerName, encryptionConfigNamespace, encryptionConfigSecretName, secretClient, featureGateAccessor, credentialsDir) - if err != nil { - return err - } - - // Don't touch the pod spec further when there are no sidecars. - if len(sidecarNames) == 0 { - return nil - } - - for _, name := range sidecarNames { - volumeMount := corev1.VolumeMount{Name: resourceDirVolumeName, MountPath: resourcesDir, ReadOnly: true} - if err := ensureVolumeMountInContainer(podSpec.InitContainers, name, volumeMount); err != nil { - return err - } - // The resource-dir files are owned by root, so the sidecar needs root to read credential files. - if err := setRunAsUser(podSpec.InitContainers, name, 0); err != nil { - return err - } - } - - return nil -} - -// AddKMSPluginSidecarToPodSpec injects KMS plugin sidecar containers into an aggregated API server pod spec (e.g., openshift-apiserver, oauth-apiserver). -// -// It is a no-op when the KMSEncryption feature gate is not enabled or the encryption-config secret does not exist. -// The secretClient should be uncached to avoid injecting sidecars based on a stale encryption configuration. +// It uses an uncached client to avoid injecting sidecars based on a stale encryption configuration. func AddKMSPluginSidecarToPodSpec(ctx context.Context, podSpec *corev1.PodSpec, containerName string, encryptionConfigNamespace string, encryptionConfigSecretName string, secretClient corev1client.SecretsGetter, featureGateAccessor featuregates.FeatureGateAccess) error { - sidecarNames, err := addKMSPluginSidecars(ctx, podSpec, containerName, encryptionConfigNamespace, encryptionConfigSecretName, secretClient, featureGateAccessor, credentialsMountPath) - if err != nil { - return err - } - - // Don't touch the pod spec further when there are no sidecars. - if len(sidecarNames) == 0 { - return nil - } - - for _, name := range sidecarNames { - volumeMount := corev1.VolumeMount{Name: credentialsVolumeName, MountPath: credentialsMountPath, ReadOnly: true} - if err := ensureVolumeMountInContainer(podSpec.InitContainers, name, volumeMount); err != nil { - return err - } - } - - // Unlike static pods, aggregated API servers access credentials by mounting the encryption-config Secret directly as a volume. - // Callers include the revision number in encryptionConfigSecretName (e.g. "encryption-config-7"), so each revision maps to a distinct Secret and volume. - if err := ensureCredentialsVolume(podSpec, encryptionConfigSecretName); err != nil { - return err - } - - return nil -} - -// addKMSPluginSidecars contains the shared logic for discovering KMS plugins and injecting sidecar containers. -// It returns the names of the sidecar containers that were injected, so callers can add deployment-mode-specific volume mounts. -func addKMSPluginSidecars(ctx context.Context, podSpec *corev1.PodSpec, containerName string, encryptionConfigNamespace string, encryptionConfigSecretName string, secretClient corev1client.SecretsGetter, featureGateAccessor featuregates.FeatureGateAccess, credentialsDir string) ([]string, error) { if podSpec == nil { - return nil, fmt.Errorf("pod spec cannot be nil") + return fmt.Errorf("pod spec cannot be nil") } if containerName == "" { - return nil, fmt.Errorf("container name cannot be empty") + return fmt.Errorf("container name cannot be empty") } if !featureGateAccessor.AreInitialFeatureGatesObserved() { - return nil, nil + return nil } featureGates, err := featureGateAccessor.CurrentFeatureGates() if err != nil { - return nil, fmt.Errorf("failed to get feature gates: %w", err) + return fmt.Errorf("failed to get feature gates: %w", err) } if !featureGates.Enabled(features.FeatureGateKMSEncryption) { - return nil, nil + return nil } encryptionConfigurationSecret, err := secretClient.Secrets(encryptionConfigNamespace).Get(ctx, encryptionConfigSecretName, metav1.GetOptions{}) if apierrors.IsNotFound(err) { klog.V(4).Infof("skipping KMS sidecar injection: %s/%s secret not found", encryptionConfigNamespace, encryptionConfigSecretName) - return nil, nil + return nil } if err != nil { - return nil, fmt.Errorf("failed to get %s/%s secret: %w", encryptionConfigNamespace, encryptionConfigSecretName, err) + return fmt.Errorf("failed to get %s/%s secret: %w", encryptionConfigNamespace, encryptionConfigSecretName, err) } encryptionConfig, err := encryptiondata.FromSecret(encryptionConfigurationSecret) if err != nil { - return nil, fmt.Errorf("failed to extract encryption config from %s/%s secret: %w", encryptionConfigNamespace, encryptionConfigSecretName, err) + return fmt.Errorf("failed to extract encryption config from %s/%s secret: %w", encryptionConfigNamespace, encryptionConfigSecretName, err) } kmsConfigurations, err := encryptiondata.ExtractUniqueAndSortedKMSConfigurations(encryptionConfig) if err != nil { - return nil, fmt.Errorf("failed to get KMS configurations: %w", err) + return fmt.Errorf("failed to get KMS configurations: %w", err) } if len(kmsConfigurations) == 0 { klog.V(4).Infof("skipping KMS sidecar injection: no KMS plugins found in EncryptionConfiguration") - return nil, nil + return nil } klog.V(4).Infof("injecting %d KMS sidecar(s)", len(kmsConfigurations)) - var sidecarNames []string socketVolumeMount := corev1.VolumeMount{Name: kmsPluginSocketVolumeName, MountPath: kmsPluginSocketMountPath, ReadOnly: false} for _, kmsConfiguration := range kmsConfigurations { // ExtractUniqueAndSortedKMSConfigurations function rewrites the .Name field to include only the key ID @@ -174,41 +97,31 @@ func addKMSPluginSidecars(ctx context.Context, podSpec *corev1.PodSpec, containe pluginConfig, ok := encryptionConfig.KMSPlugins[keyID] if !ok { - return nil, fmt.Errorf("missing plugin config for keyID %s", keyID) - } - - creds := &credentialResolver{ - pluginsSecretData: encryptionConfig.KMSPluginsSecretData, - credentialsDir: credentialsDir, - keyID: keyID, + return fmt.Errorf("missing plugin config for keyID %s", keyID) } - provider, err := newSidecarProvider(keyID, udsPath, pluginConfig, creds) + sidecarProvider, err := newSidecarProvider(keyID, udsPath, pluginConfig) if err != nil { - return nil, fmt.Errorf("failed to create a sidecar provider for keyID %s: %w", keyID, err) + return fmt.Errorf("failed to create a sidecar provider for keyID %s: %w", keyID, err) } - if err := ensureSidecarContainer(podSpec, provider); err != nil { - return nil, err + if err := ensureSidecarContainer(podSpec, sidecarProvider); err != nil { + return err } - if err := ensureVolumeMountInContainer(podSpec.InitContainers, provider.Name(), socketVolumeMount); err != nil { - return nil, err + if err := ensureVolumeMountInContainer(podSpec.InitContainers, sidecarProvider.Name(), socketVolumeMount); err != nil { + return err } - - sidecarNames = append(sidecarNames, provider.Name()) } if err := ensureVolumeMountInContainer(podSpec.Containers, containerName, socketVolumeMount); err != nil { - return nil, err + return err } // The volume mount in the kube-apiserver and KMS plugin containers requires a volume in the podSpec - if err := ensureSocketVolume(podSpec); err != nil { - return nil, err - } + ensureSocketVolume(podSpec) - return sidecarNames, nil + return nil } func ensureSidecarContainer(podSpec *corev1.PodSpec, provider sidecarProvider) error { @@ -254,50 +167,19 @@ func ensureVolumeMountInContainer(containers []corev1.Container, containerName s return nil } -func ensureVolume(podSpec *corev1.PodSpec, volume corev1.Volume) error { - for _, v := range podSpec.Volumes { - if v.Name == volume.Name { - if !equality.Semantic.DeepEqual(v, volume) { - return fmt.Errorf("pod already has volume %s with different settings", v.Name) - } - return nil +func ensureSocketVolume(podSpec *corev1.PodSpec) { + for _, volume := range podSpec.Volumes { + if volume.Name == kmsPluginSocketVolumeName { + return } } - podSpec.Volumes = append(podSpec.Volumes, volume) - return nil -} - -func ensureSocketVolume(podSpec *corev1.PodSpec) error { - volume := corev1.Volume{ - Name: kmsPluginSocketVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - } - return ensureVolume(podSpec, volume) -} -func ensureCredentialsVolume(podSpec *corev1.PodSpec, secretName string) error { - volume := corev1.Volume{ - Name: credentialsVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, + podSpec.Volumes = append(podSpec.Volumes, + corev1.Volume{ + Name: kmsPluginSocketVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, - } - return ensureVolume(podSpec, volume) -} - -func setRunAsUser(containers []corev1.Container, containerName string, uid int64) error { - for i, c := range containers { - if c.Name == containerName { - if c.SecurityContext == nil { - containers[i].SecurityContext = &corev1.SecurityContext{} - } - containers[i].SecurityContext.RunAsUser = ptr.To(uid) - return nil - } - } - return fmt.Errorf("container %s not found", containerName) + ) } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/vault.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/vault.go index f628c49d0..234041674 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/vault.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle/vault.go @@ -9,39 +9,22 @@ import ( "k8s.io/utils/ptr" ) -// newVaultSidecarProvider creates a Vault sidecar provider from the given KMS plugin data. -// It assumes the input data has been already been validated. -func newVaultSidecarProvider(name, keyID, udsPath string, vaultConfig configv1.VaultKMSPluginConfig, creds *credentialResolver) (*vault, error) { - secretName := vaultConfig.Authentication.AppRole.Secret.Name - - roleID, err := creds.Value(secretName, "role-id") - if err != nil { - return nil, err - } - - secretIDPath, err := creds.FilePath(secretName, "secret-id") - if err != nil { - return nil, err - } - +// newVaultSidecarProvider creates a Vault sidecar provider from the given KMS plugin configuration. +func newVaultSidecarProvider(name, keyID, udsPath string, vaultConfig configv1.VaultKMSPluginConfig) (*vault, error) { return &vault{ - name: name, - keyID: keyID, - udsPath: udsPath, - config: vaultConfig, - roleID: roleID, - secretIDPath: secretIDPath, + name: name, + keyID: keyID, + udsPath: udsPath, + config: vaultConfig, }, nil } // vault implements SidecarProvider for HashiCorp Vault KMS. type vault struct { - name string - keyID string - udsPath string - config configv1.VaultKMSPluginConfig - roleID string - secretIDPath string + name string + keyID string + udsPath string + config configv1.VaultKMSPluginConfig } // Name returns the sidecar name appended by the key id. @@ -58,8 +41,10 @@ func (v *vault) BuildSidecarContainer() (corev1.Container, error) { fmt.Sprintf("-vault-address=%s", v.config.VaultAddress), fmt.Sprintf("-transit-mount=%s", v.config.TransitMount), fmt.Sprintf("-transit-key=%s", v.config.TransitKey), - fmt.Sprintf("-approle-role-id=%s", v.roleID), - fmt.Sprintf("-approle-secret-id-path=%s", v.secretIDPath), + // TODO(bertinatto): dummy value for the Vault mock plugin; will come from the encryption-config secret. + fmt.Sprintf("-approle-role-id=dummy-role-id-%s", v.keyID), + // TODO(bertinatto): placeholder path for the Vault mock plugin; will differ per operator (KASO vs. aggregated apiserver operators). + fmt.Sprintf("-approle-secret-id-path=/var/run/secrets/vault-kms/secret-id-%s", v.keyID), } // Optional fields: only pass non-empty values. @@ -82,7 +67,6 @@ func (v *vault) BuildSidecarContainer() (corev1.Container, error) { TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, // Vault team recommendation based on single-node OCP cluster measurements: // ~10 mCPU / 32-64 MiB steady state, memory peaked at ~60 MiB under 400 KEK rotations. - // Slack discussion: https://redhat-external.slack.com/archives/C09KZ5QCBUH/p1779134070543079 Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceMemory: resource.MustParse("64Mi"), 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 6121935a1..dbb5a12c6 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 @@ -18,10 +18,10 @@ const ( Altering of the encryption secrets will render you cluster inaccessible. Catastrophic data loss can occur from the most minor changes.` - // referenceDataKeySeparator separates the reference name from the data key. + // secretDataKeySeparator separates the secret name from the data key. // Underscore is used because it is forbidden in Kubernetes secret/configmap // names, preventing collisions. - referenceDataKeySeparator = "_" + secretDataKeySeparator = "_" ) // GroupResourceState represents, for a single group resource, the write and read keys in a @@ -73,25 +73,25 @@ type KMSState struct { Plugin configv1.KMSPluginConfig // PluginSecretData stores data key-value pairs fetched from referenced secrets. - PluginSecretData KMSReferenceData + PluginSecretData KMSSecretData } -// KMSReferenceData stores data key-value pairs fetched from referenced secrets or configmaps. -// entries maps reference names (secret or configmap) to their data key-value pairs. -type KMSReferenceData struct { +// KMSSecretData stores data key-value pairs fetched from referenced secrets. +// entries maps secret names to their data key-value pairs. +type KMSSecretData struct { entries map[string]map[string][]byte } -// Get returns the value for the given referenceName and dataKey. It returns false if -// referenceName or dataKey is empty, if Entries is nil, or if the key does not exist. -func (d *KMSReferenceData) Get(referenceName, dataKey string) ([]byte, bool) { - if len(referenceName) == 0 || len(dataKey) == 0 { +// Get returns the value for the given secretName and dataKey. It returns false if +// secretName or dataKey is empty, if Entries is nil, or if the key does not exist. +func (d *KMSSecretData) Get(secretName, dataKey string) ([]byte, bool) { + if len(secretName) == 0 || len(dataKey) == 0 { return nil, false } if d.entries == nil { return nil, false } - secretEntries, ok := d.entries[referenceName] + secretEntries, ok := d.entries[secretName] if !ok { return nil, false } @@ -99,61 +99,54 @@ func (d *KMSReferenceData) Get(referenceName, dataKey string) ([]byte, bool) { return value, ok } -func (d *KMSReferenceData) Set(referenceName, dataKey string, value []byte) error { - if len(referenceName) == 0 || len(dataKey) == 0 || len(value) == 0 { - return fmt.Errorf("referenceName, dataKey, and value must not be empty") +func (d *KMSSecretData) Set(secretName, dataKey string, value []byte) error { + if len(secretName) == 0 || len(dataKey) == 0 || len(value) == 0 { + return fmt.Errorf("secretName, dataKey, and value must not be empty") } - if strings.Contains(referenceName, "_") { - return fmt.Errorf("referenceName name %q must not contain underscores", referenceName) + if strings.Contains(secretName, "_") { + return fmt.Errorf("secret name %q must not contain underscores", secretName) } if d.entries == nil { d.entries = map[string]map[string][]byte{} } - if d.entries[referenceName] == nil { - d.entries[referenceName] = map[string][]byte{} + if d.entries[secretName] == nil { + d.entries[secretName] = map[string][]byte{} } - d.entries[referenceName][dataKey] = value + d.entries[secretName][dataKey] = value return nil } -// SetFromRawKey splits a combined key of the form "referenceName_dataKey" +// SetFromRawKey splits a combined key of the form "secretName_dataKey" // and stores the value. -func (d *KMSReferenceData) SetFromRawKey(rawKey string, value []byte) error { - parts := strings.SplitN(rawKey, referenceDataKeySeparator, 2) +func (d *KMSSecretData) SetFromRawKey(rawKey string, value []byte) error { + parts := strings.SplitN(rawKey, secretDataKeySeparator, 2) if len(parts) != 2 { - return fmt.Errorf("invalid combined key %q: expected format {referenceName}%s{dataKey}", rawKey, referenceDataKeySeparator) + return fmt.Errorf("invalid combined key %q: expected format {secretName}%s{dataKey}", rawKey, secretDataKeySeparator) } return d.Set(parts[0], parts[1], value) } -// FlatEntry returns the combined key "referenceName_dataKey" used in flat representations. +// FlatEntry returns the combined key "secretName_dataKey" used in flat representations. // // Note: // // It does not validate inputs. The callers are expected to use Set, -// which rejects empty values and underscores in referenceName. -func (d *KMSReferenceData) FlatEntry(referenceName, dataKey string) (string, bool) { - if _, ok := d.Get(referenceName, dataKey); !ok { - return "", false - } - return d.flatEntry(referenceName, dataKey), true -} - -func (d *KMSReferenceData) flatEntry(referenceName, dataKey string) string { - return referenceName + referenceDataKeySeparator + dataKey +// which rejects empty values and underscores in secretName. +func (d *KMSSecretData) FlatEntry(secretName, dataKey string) string { + return secretName + secretDataKeySeparator + dataKey } -// FlatEntries returns the stored data as a flat map keyed by "referenceName_dataKey". -// "_" separates referenceName from dataKey because "_" is forbidden in -// Kubernetes secret/configmap names, making the split unambiguous. -func (d *KMSReferenceData) FlatEntries() map[string][]byte { +// FlatEntries returns the stored data as a flat map keyed by "secretName_dataKey". +// "_" separates secretName from dataKey because "_" is forbidden in +// Kubernetes secret names, making the split unambiguous. +func (d *KMSSecretData) FlatEntries() map[string][]byte { if d.entries == nil { return nil } result := map[string][]byte{} for secretName, keys := range d.entries { for dataKey, value := range keys { - result[d.flatEntry(secretName, dataKey)] = value + result[d.FlatEntry(secretName, dataKey)] = value } } return result diff --git a/vendor/github.com/openshift/library-go/test/library/encryption/kms/vault.go b/vendor/github.com/openshift/library-go/test/library/encryption/kms/vault.go index c3c265370..0c268449c 100644 --- a/vendor/github.com/openshift/library-go/test/library/encryption/kms/vault.go +++ b/vendor/github.com/openshift/library-go/test/library/encryption/kms/vault.go @@ -23,18 +23,17 @@ import ( ) const ( - defaultVaultNamespace = "vault-kms" - defaultVaultPodName = "vault-0" - defaultVaultCredentialsSecret = "vault-credentials" - defaultVaultAppRoleSecretName = "vault-approle-secret" - defaultFAKEVaultKMSPluginImage = "quay.io/openshifttest/mock-kms-plugin@sha256:958a2f8276037468aa47dc2137d3c30dfcd96489455eddb2fe655f8168a57622" - defaultVaultKMSPluginImage = "registry.ci.openshift.org/control-plane-custom-builds/vault-kube-kms@sha256:33599dd6eee61dcf9a60138759fafda3d88593a3c2072585156882c6b5bd3fa5" - defaultVaultAddress = "https://vault.vault-kms.svc:8200" - defaultVaultEnterpriseNS = "admin" - defaultVaultTransitMount = "transit" - defaultVaultTransitKey = "kms-key" - defaultAppRoleTargetNamespace = "openshift-config" - vaultCommandTimeout = 30 * time.Second + defaultVaultNamespace = "vault-kms" + defaultVaultPodName = "vault-0" + defaultVaultCredentialsSecret = "vault-credentials" + defaultVaultAppRoleSecretName = "vault-approle-secret" + defaultVaultKMSPluginImage = "quay.io/openshifttest/mock-kms-plugin@sha256:958a2f8276037468aa47dc2137d3c30dfcd96489455eddb2fe655f8168a57622" + defaultVaultAddress = "https://vault.vault-kms.svc:8200" + defaultVaultEnterpriseNS = "admin" + defaultVaultTransitMount = "transit" + defaultVaultTransitKey = "kms-key" + defaultAppRoleTargetNamespace = "openshift-config" + vaultCommandTimeout = 30 * time.Second ) // DefaultVaultEncryptionProvider returns a ready-to-use Vault KMS EncryptionProvider for e2e tests. @@ -84,7 +83,7 @@ var DefaultFakeKMSPluginConfig = configv1.APIServerEncryption{ KMS: configv1.KMSPluginConfig{ Type: configv1.VaultKMSProvider, Vault: configv1.VaultKMSPluginConfig{ - KMSPluginImage: defaultFAKEVaultKMSPluginImage, + KMSPluginImage: defaultVaultKMSPluginImage, VaultAddress: "https://vault.example.com", Authentication: configv1.VaultAuthentication{ Type: configv1.VaultAuthenticationTypeAppRole, diff --git a/vendor/modules.txt b/vendor/modules.txt index 3da037079..0ccbe1daf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -405,7 +405,7 @@ github.com/openshift/client-go/route/applyconfigurations/internal github.com/openshift/client-go/route/applyconfigurations/route/v1 github.com/openshift/client-go/route/clientset/versioned/scheme github.com/openshift/client-go/route/clientset/versioned/typed/route/v1 -# github.com/openshift/library-go v0.0.0-20260604143514-ba2b9a3a3499 +# github.com/openshift/library-go v0.0.0-20260603103329-d8750ed2813e ## explicit; go 1.25.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/apps/deployment