diff --git a/config/v1/tests/apiservers.config.openshift.io/KMSEncryption.yaml b/config/v1/tests/apiservers.config.openshift.io/KMSEncryption.yaml index b0e0e05cf5c..f8f04a65e19 100644 --- a/config/v1/tests/apiservers.config.openshift.io/KMSEncryption.yaml +++ b/config/v1/tests/apiservers.config.openshift.io/KMSEncryption.yaml @@ -68,13 +68,8 @@ tests: type: aescbc kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: VaultKMSConfig + name: my-vault-kms expectedError: "kms config is required when encryption type is KMS, and forbidden otherwise" diff --git a/config/v1/tests/apiservers.config.openshift.io/VaultKMS.yaml b/config/v1/tests/apiservers.config.openshift.io/VaultKMS.yaml index b37f2841a19..ed744631d74 100644 --- a/config/v1/tests/apiservers.config.openshift.io/VaultKMS.yaml +++ b/config/v1/tests/apiservers.config.openshift.io/VaultKMS.yaml @@ -5,8 +5,7 @@ featureGates: - KMSEncryption tests: onCreate: - # Valid Vault configuration tests - - name: Should be able to create with valid minimal Vault KMS Plugin config + - name: Should be able to create with valid Vault KMS pluginConfig reference initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -15,15 +14,10 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: VaultKMSConfig + name: my-vault-kms expected: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -34,17 +28,12 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: VaultKMSConfig + name: my-vault-kms - - name: Should accept kmsPluginImage with simple two-level path like quay.io/vault/kms-plugin + - name: Should reject Vault KMS config without pluginConfig initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -53,278 +42,9 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: quay.io/vault/kms-plugin@sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: quay.io/vault/kms-plugin@sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - - - name: Should be able to create with full Vault KMS Plugin config including all optional fields - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/hashicorp/vault-plugin@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 - vaultAddress: https://vault.prod.example.com:8200 - vaultNamespace: my-team - vaultAuthNamespace: central-auth - tls: - caBundle: - name: vault-ca-bundle - serverName: vault.example.com - authentication: - type: AppRole - appRole: - secret: - name: vault-approle-credentials - vaultKeyPath: custom/transit/path/keys/production-encryption-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/hashicorp/vault-plugin@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 - vaultAddress: https://vault.prod.example.com:8200 - vaultNamespace: my-team - vaultAuthNamespace: central-auth - tls: - caBundle: - name: vault-ca-bundle - serverName: vault.example.com - authentication: - type: AppRole - appRole: - secret: - name: vault-approle-credentials - vaultKeyPath: custom/transit/path/keys/production-encryption-key - - # Multi-level namespace path tests - - name: Should accept kmsPluginImage with multi-level namespace path - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/org/team/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/org/team/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - - - name: Should accept kmsPluginImage with deep multi-level namespace path - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.io/org_name/team.name/project/subproject/vault_plugin@sha256:abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234 - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.io/org_name/team.name/project/subproject/vault_plugin@sha256:abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234 - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-encryption-key - - # vaultKeyPath valid tests - - name: Should accept vaultKeyPath with multi-segment mount - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/test/keys/my-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/test/keys/my-key - - - name: Should accept vaultKeyPath with mount containing period - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit.v1/keys/my-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit.v1/keys/my-key - - - name: Should accept vaultKeyPath with mount containing tilde - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit~backup/keys/my-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit~backup/keys/my-key + expectedError: "pluginConfig" - - name: Should accept vaultKeyPath with key containing period + - name: Should be able to create with arbitrary provider pluginConfig reference GVK initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -333,15 +53,10 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/encryption.key.v1 + pluginConfig: + apiVersion: example.com/v1 + kind: ExampleKMSConfig + name: my-kms-config expected: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -352,178 +67,12 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/encryption.key.v1 - - # vaultKeyPath invalid tests - - name: Should reject vaultKeyPath without /keys/ separator - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/my-key - expectedError: "vaultKeyPath must follow the format /keys/" - - - name: Should reject vaultKeyPath starting with forward slash - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: /transit/keys/my-key - expectedError: "vaultKeyPath cannot start with a forward slash" - - - name: Should reject vaultKeyPath ending with forward slash - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key/ - expectedError: "vaultKeyPath cannot end with a forward slash" - - - name: Should reject vaultKeyPath with consecutive forward slashes - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit//keys/my-key - expectedError: "vaultKeyPath cannot contain consecutive forward slashes" - - - name: Should reject vaultKeyPath with dot path segment - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/./keys/my-key - expectedError: "vaultKeyPath must not contain '.' or '..' path segments" - - - name: Should reject vaultKeyPath with double-dot path segment - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/../keys/my-key - expectedError: "vaultKeyPath must not contain '.' or '..' path segments" - - - name: Should reject vaultKeyPath with special characters in mount - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit@test/keys/my-key - expectedError: "vaultKeyPath must only contain RFC 3986 unreserved characters" - - - name: Should reject vaultKeyPath with key name starting with hyphen - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/-bad - expectedError: "vaultKeyPath must follow the format /keys/" + pluginConfig: + apiVersion: example.com/v1 + kind: ExampleKMSConfig + name: my-kms-config - - name: Should reject vaultKeyPath with key name ending with hyphen + - name: Should reject invalid pluginConfig apiVersion format initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -532,18 +81,13 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/bad- - expectedError: "vaultKeyPath must follow the format /keys/" + pluginConfig: + apiVersion: not-a-valid-api-version + kind: VaultKMSConfig + name: my-vault-kms + expectedError: "apiVersion must be in the format /" - - name: Should reject vaultKeyPath with key containing tilde + - name: Should reject invalid pluginConfig kind format initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -552,19 +96,13 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/key~backup - expectedError: "vaultKeyPath must follow the format /keys/" + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: invalid-kind + name: my-vault-kms + expectedError: "kind must be a valid Kubernetes kind name" - # vaultKeyPath required field validation - - name: Should reject Vault KMS config without vaultKeyPath + - name: Should reject invalid pluginConfig name initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -573,506 +111,13 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - expectedError: "Required value" - - # Type validation - vault field must be set when type is Vault - - name: Should reject KMS type Vault without vault config - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - expectedError: "vault config is required when kms provider type is Vault" - - # authentication type validation - appRole field must be set when type is AppRole - - name: Should reject authentication type AppRole without appRole config - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - vaultKeyPath: transit/keys/my-key - expectedError: "appRole config is required when authentication type is AppRole" - - # kmsPluginImage validation tests - - name: Should reject kmsPluginImage with tag instead of digest - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin:latest - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "the OCI Image reference must end with a valid '@sha256:' suffix" - - - name: Should reject kmsPluginImage without registry hostname - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "the OCI Image name should follow the host[:port][/namespace]/name format" - - - name: Should reject kmsPluginImage with invalid digest length - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault@sha256:abc123 - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "the OCI Image reference must end with a valid '@sha256:' suffix, where '' is 64 characters long" - - # vaultAddress validation tests - - name: Should reject vaultAddress with http scheme - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: http://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "must use the 'https' scheme" - - - name: Should reject vaultAddress with path - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200/v1 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "must not contain a path" - - - name: Should reject vaultAddress with query parameters - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200?key=value - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "must not have a query" - - - name: Should reject vaultAddress with fragment - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200#fragment - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "must not have a fragment" - - - name: Should reject vaultAddress with user info - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://user:password@vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "must not have user info" - - # vaultNamespace validation tests - - name: Should reject vaultNamespace ending with forward slash - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: my-namespace/ - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot end with a forward slash" - - - name: Should reject vaultNamespace containing spaces - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: my namespace - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot contain spaces" - - - name: Should reject vaultNamespace with reserved name root - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: root - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - - name: Should reject vaultNamespace with reserved name sys - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: sys - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - - name: Should reject vaultNamespace with reserved name audit - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: audit - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - - name: Should reject vaultNamespace with reserved name auth - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: auth - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - - name: Should reject vaultNamespace with reserved name cubbyhole - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: cubbyhole - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - - name: Should reject vaultNamespace with reserved name identity - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: identity - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultNamespace cannot be a reserved string" - - # vaultAuthNamespace validation tests - - name: Should accept vaultAuthNamespace with both namespace fields set - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: transit-ns - vaultAuthNamespace: auth-ns - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expected: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - audit: - profile: Default - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultNamespace: transit-ns - vaultAuthNamespace: auth-ns - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - - - name: Should reject vaultAuthNamespace ending with forward slash - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultAuthNamespace: my-auth-ns/ - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultAuthNamespace cannot end with a forward slash" - - - name: Should reject vaultAuthNamespace containing spaces - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultAuthNamespace: my auth ns - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultAuthNamespace cannot contain spaces" - - - name: Should reject vaultAuthNamespace with reserved name root - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultAuthNamespace: root - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultAuthNamespace cannot be a reserved string" - - - name: Should reject vaultAuthNamespace with reserved name identity - initial: | - apiVersion: config.openshift.io/v1 - kind: APIServer - spec: - encryption: - type: KMS - kms: - type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - vaultAuthNamespace: identity - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "vaultAuthNamespace cannot be a reserved string" + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: VaultKMSConfig + name: invalid_name! + expectedError: "name must be a valid DNS subdomain name" - # serverName validation tests - - name: Should reject invalid serverName + - name: Should reject pluginConfig with empty apiVersion initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -1081,21 +126,13 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - tls: - serverName: invalid_hostname! - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "serverName must be a valid DNS hostname" + pluginConfig: + apiVersion: "" + kind: VaultKMSConfig + name: my-vault-kms + expectedError: "apiVersion" - # authentication secret and caBundle name validation tests - - name: Should reject invalid authentication secret name + - name: Should reject pluginConfig with empty kind initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -1104,18 +141,13 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - authentication: - type: AppRole - appRole: - secret: - name: invalid_secret_name! - vaultKeyPath: transit/keys/my-key - expectedError: "name must be a valid DNS subdomain name" + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: "" + name: my-vault-kms + expectedError: "kind" - - name: Should reject invalid caBundle name + - name: Should reject pluginConfig with empty name initial: | apiVersion: config.openshift.io/v1 kind: APIServer @@ -1124,16 +156,8 @@ tests: type: KMS kms: type: Vault - vault: - kmsPluginImage: registry.example.com/vault-plugin@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - vaultAddress: https://vault.example.com:8200 - tls: - caBundle: - name: invalid_configmap! - authentication: - type: AppRole - appRole: - secret: - name: vault-approle - vaultKeyPath: transit/keys/my-key - expectedError: "name must be a valid DNS subdomain name" \ No newline at end of file + pluginConfig: + apiVersion: vault.hashicorp.io/v1 + kind: VaultKMSConfig + name: "" + expectedError: "name" diff --git a/config/v1/types_kmsencryption.go b/config/v1/types_kmsencryption.go index e2f94ae1f37..b2b9e89cc5e 100644 --- a/config/v1/types_kmsencryption.go +++ b/config/v1/types_kmsencryption.go @@ -2,25 +2,31 @@ package v1 // KMSPluginConfig defines the configuration for the KMS instance // that will be used with KMS encryption -// +kubebuilder:validation:XValidation:rule="self.type == 'Vault' ? has(self.vault) : !has(self.vault)",message="vault config is required when kms provider type is Vault, and forbidden otherwise" -// +union type KMSPluginConfig struct { // type defines the kind of platform for the KMS provider. // Allowed values are Vault. - // When set to Vault, the plugin connects to a HashiCorp Vault server for key management. + // The encryption controllers read the resolved plugin configuration from the status + // of the custom resource referenced in pluginConfig. // - // +unionDiscriminator // +required Type KMSProviderType `json:"type"` - // vault defines the configuration for the Vault KMS plugin. - // The plugin connects to a Vault Enterprise server that is managed - // by the user outside the purview of the control plane. - // This field must be set when type is Vault, and must be unset otherwise. + // pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + // The referenced resource is reconciled by an OLM operator that publishes the resolved + // plugin configuration, including the container image, in the resource status. + // It references a provider-specific cluster-scoped custom resource. + // + // +required + PluginConfig KMSPluginConfigReference `json:"pluginConfig,omitzero"` + + // --- TOMBSTONE --- + // vault defined inline Vault-specific KMS plugin configuration. + // It has been replaced by pluginConfig which references a provider-managed custom resource. + // The field name is reserved to prevent reuse. // // +unionMember // +optional - Vault VaultKMSPluginConfig `json:"vault,omitempty,omitzero"` + // Vault VaultKMSPluginConfig `json:"vault,omitempty,omitzero"` // --- TOMBSTONE --- // aws was a field that allowed configuring AWS KMS. @@ -31,6 +37,40 @@ type KMSPluginConfig struct { // AWS *AWSKMSConfig `json:"aws,omitempty"` } +// KMSPluginConfigReference identifies a cluster-scoped KMS plugin configuration custom resource. +type KMSPluginConfigReference struct { + // apiVersion is the API version of the referenced KMS plugin configuration resource. + // The value must be in the format /, where group is a DNS subdomain + // and version is a Kubernetes API version (for example, v1 or v1alpha1). + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + // +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$')",message="apiVersion must be in the format /" + // +required + APIVersion string `json:"apiVersion,omitempty"` + + // kind is the kind of the referenced KMS plugin configuration resource. + // The value must be a valid Kubernetes kind name: it must be between 1 and 63 + // characters, start with an uppercase letter, and contain only alphanumeric characters. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:XValidation:rule="self.matches('^[A-Z][a-zA-Z0-9]*$')",message="kind must be a valid Kubernetes kind name" + // +required + Kind string `json:"kind,omitempty"` + + // name is the metadata.name of the referenced KMS plugin configuration resource. + // The referenced resource must be cluster-scoped. + // The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + // contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([a-z0-9\\\\-]*[a-z0-9])?(\\\\.[a-z0-9]([a-z0-9\\\\-]*[a-z0-9])?)*$')",message="name must be a valid DNS subdomain name: contain no more than 253 characters, contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character" + // +required + Name string `json:"name,omitempty"` +} + // --- TOMBSTONE --- // AWSKMSConfig was a type for AWS KMS configuration that was never implemented. // The type name is reserved to prevent reuse. diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml index f3793fac61d..e2e98d6f1c1 100644 --- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml +++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml index d06cd26ca79..37dc8c67540 100644 --- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml +++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml index cce33594546..9dcec95edef 100644 --- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml +++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/config/v1/zz_generated.deepcopy.go b/config/v1/zz_generated.deepcopy.go index 4b194b226a4..f2e5c84ea1c 100644 --- a/config/v1/zz_generated.deepcopy.go +++ b/config/v1/zz_generated.deepcopy.go @@ -4065,7 +4065,7 @@ func (in *IntermediateTLSProfile) DeepCopy() *IntermediateTLSProfile { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KMSPluginConfig) DeepCopyInto(out *KMSPluginConfig) { *out = *in - out.Vault = in.Vault + out.PluginConfig = in.PluginConfig return } @@ -4079,6 +4079,22 @@ func (in *KMSPluginConfig) DeepCopy() *KMSPluginConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KMSPluginConfigReference) DeepCopyInto(out *KMSPluginConfigReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSPluginConfigReference. +func (in *KMSPluginConfigReference) DeepCopy() *KMSPluginConfigReference { + if in == nil { + return nil + } + out := new(KMSPluginConfigReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KeystoneIdentityProvider) DeepCopyInto(out *KeystoneIdentityProvider) { *out = *in diff --git a/config/v1/zz_generated.featuregated-crd-manifests/apiservers.config.openshift.io/KMSEncryption.yaml b/config/v1/zz_generated.featuregated-crd-manifests/apiservers.config.openshift.io/KMSEncryption.yaml index 22c41067598..553b5aaf79b 100644 --- a/config/v1/zz_generated.featuregated-crd-manifests/apiservers.config.openshift.io/KMSEncryption.yaml +++ b/config/v1/zz_generated.featuregated-crd-manifests/apiservers.config.openshift.io/KMSEncryption.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: + pluginConfig: description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: - description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: - description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: + apiVersion: description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: - description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/config/v1/zz_generated.model_name.go b/config/v1/zz_generated.model_name.go index 043c03ef5ef..19d821fd71f 100644 --- a/config/v1/zz_generated.model_name.go +++ b/config/v1/zz_generated.model_name.go @@ -870,6 +870,11 @@ func (in KMSPluginConfig) OpenAPIModelName() string { return "com.github.openshift.api.config.v1.KMSPluginConfig" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in KMSPluginConfigReference) OpenAPIModelName() string { + return "com.github.openshift.api.config.v1.KMSPluginConfigReference" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in KeystoneIdentityProvider) OpenAPIModelName() string { return "com.github.openshift.api.config.v1.KeystoneIdentityProvider" diff --git a/config/v1/zz_generated.swagger_doc_generated.go b/config/v1/zz_generated.swagger_doc_generated.go index 0f4605ef380..f31faf0c57d 100644 --- a/config/v1/zz_generated.swagger_doc_generated.go +++ b/config/v1/zz_generated.swagger_doc_generated.go @@ -2465,15 +2465,26 @@ func (Storage) SwaggerDoc() map[string]string { } var map_KMSPluginConfig = map[string]string{ - "": "KMSPluginConfig defines the configuration for the KMS instance that will be used with KMS encryption", - "type": "type defines the kind of platform for the KMS provider. Allowed values are Vault. When set to Vault, the plugin connects to a HashiCorp Vault server for key management.", - "vault": "vault defines the configuration for the Vault KMS plugin. The plugin connects to a Vault Enterprise server that is managed by the user outside the purview of the control plane. This field must be set when type is Vault, and must be unset otherwise.", + "": "KMSPluginConfig defines the configuration for the KMS instance that will be used with KMS encryption", + "type": "type defines the kind of platform for the KMS provider. Allowed values are Vault. The encryption controllers read the resolved plugin configuration from the status of the custom resource referenced in pluginConfig.", + "pluginConfig": "pluginConfig references a cluster-scoped KMS plugin configuration custom resource. The referenced resource is reconciled by an OLM operator that publishes the resolved plugin configuration, including the container image, in the resource status. It references a provider-specific cluster-scoped custom resource.", } func (KMSPluginConfig) SwaggerDoc() map[string]string { return map_KMSPluginConfig } +var map_KMSPluginConfigReference = map[string]string{ + "": "KMSPluginConfigReference identifies a cluster-scoped KMS plugin configuration custom resource.", + "apiVersion": "apiVersion is the API version of the referenced KMS plugin configuration resource. The value must be in the format /, where group is a DNS subdomain and version is a Kubernetes API version (for example, v1 or v1alpha1).", + "kind": "kind is the kind of the referenced KMS plugin configuration resource. The value must be a valid Kubernetes kind name: it must be between 1 and 63 characters, start with an uppercase letter, and contain only alphanumeric characters.", + "name": "name is the metadata.name of the referenced KMS plugin configuration resource. The referenced resource must be cluster-scoped. The name must be a valid DNS subdomain name: it must contain no more than 253 characters, contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character.", +} + +func (KMSPluginConfigReference) SwaggerDoc() map[string]string { + return map_KMSPluginConfigReference +} + var map_VaultAppRoleAuthentication = map[string]string{ "": "VaultAppRoleAuthentication defines the configuration for AppRole authentication with Vault.", "secret": "secret references a secret in the openshift-config namespace containing the AppRole credentials used to authenticate with Vault. The referenced Secret must contain two keys: \"role-id\" for the AppRole Role ID and \"secret-id\" for the AppRole Secret ID.", diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 16f4728a9ae..dc1582dc9e2 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -375,6 +375,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA configv1.InsightsDataGatherSpec{}.OpenAPIModelName(): schema_openshift_api_config_v1_InsightsDataGatherSpec(ref), configv1.IntermediateTLSProfile{}.OpenAPIModelName(): schema_openshift_api_config_v1_IntermediateTLSProfile(ref), configv1.KMSPluginConfig{}.OpenAPIModelName(): schema_openshift_api_config_v1_KMSPluginConfig(ref), + configv1.KMSPluginConfigReference{}.OpenAPIModelName(): schema_openshift_api_config_v1_KMSPluginConfigReference(ref), configv1.KeystoneIdentityProvider{}.OpenAPIModelName(): schema_openshift_api_config_v1_KeystoneIdentityProvider(ref), configv1.KubeClientConfig{}.OpenAPIModelName(): schema_openshift_api_config_v1_KubeClientConfig(ref), configv1.KubevirtPlatformSpec{}.OpenAPIModelName(): schema_openshift_api_config_v1_KubevirtPlatformSpec(ref), @@ -16817,37 +16818,60 @@ func schema_openshift_api_config_v1_KMSPluginConfig(ref common.ReferenceCallback Properties: map[string]spec.Schema{ "type": { SchemaProps: spec.SchemaProps{ - Description: "type defines the kind of platform for the KMS provider. Allowed values are Vault. When set to Vault, the plugin connects to a HashiCorp Vault server for key management.", + Description: "type defines the kind of platform for the KMS provider. Allowed values are Vault. The encryption controllers read the resolved plugin configuration from the status of the custom resource referenced in pluginConfig.", Default: "", Type: []string{"string"}, Format: "", }, }, - "vault": { + "pluginConfig": { SchemaProps: spec.SchemaProps{ - Description: "vault defines the configuration for the Vault KMS plugin. The plugin connects to a Vault Enterprise server that is managed by the user outside the purview of the control plane. This field must be set when type is Vault, and must be unset otherwise.", + Description: "pluginConfig references a cluster-scoped KMS plugin configuration custom resource. The referenced resource is reconciled by an OLM operator that publishes the resolved plugin configuration, including the container image, in the resource status. It references a provider-specific cluster-scoped custom resource.", Default: map[string]interface{}{}, - Ref: ref(configv1.VaultKMSPluginConfig{}.OpenAPIModelName()), + Ref: ref(configv1.KMSPluginConfigReference{}.OpenAPIModelName()), }, }, }, - Required: []string{"type"}, + Required: []string{"type", "pluginConfig"}, }, - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-unions": []interface{}{ - map[string]interface{}{ - "discriminator": "type", - "fields-to-discriminateBy": map[string]interface{}{ - "vault": "Vault", - }, + }, + Dependencies: []string{ + configv1.KMSPluginConfigReference{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_config_v1_KMSPluginConfigReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KMSPluginConfigReference identifies a cluster-scoped KMS plugin configuration custom resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "apiVersion is the API version of the referenced KMS plugin configuration resource. The value must be in the format /, where group is a DNS subdomain and version is a Kubernetes API version (for example, v1 or v1alpha1).", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "kind is the kind of the referenced KMS plugin configuration resource. The value must be a valid Kubernetes kind name: it must be between 1 and 63 characters, start with an uppercase letter, and contain only alphanumeric characters.", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the metadata.name of the referenced KMS plugin configuration resource. The referenced resource must be cluster-scoped. The name must be a valid DNS subdomain name: it must contain no more than 253 characters, contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character.", + Type: []string{"string"}, + Format: "", }, }, }, + Required: []string{"apiVersion", "kind", "name"}, }, }, - Dependencies: []string{ - configv1.VaultKMSPluginConfig{}.OpenAPIModelName()}, } } diff --git a/openapi/openapi.json b/openapi/openapi.json index 99f806ce8fe..da1a568f378 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -8839,28 +8839,44 @@ "description": "KMSPluginConfig defines the configuration for the KMS instance that will be used with KMS encryption", "type": "object", "required": [ - "type" + "type", + "pluginConfig" ], "properties": { + "pluginConfig": { + "description": "pluginConfig references a cluster-scoped KMS plugin configuration custom resource. The referenced resource is reconciled by an OLM operator that publishes the resolved plugin configuration, including the container image, in the resource status. It references a provider-specific cluster-scoped custom resource.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.config.v1.KMSPluginConfigReference" + }, "type": { - "description": "type defines the kind of platform for the KMS provider. Allowed values are Vault. When set to Vault, the plugin connects to a HashiCorp Vault server for key management.", + "description": "type defines the kind of platform for the KMS provider. Allowed values are Vault. The encryption controllers read the resolved plugin configuration from the status of the custom resource referenced in pluginConfig.", "type": "string", "default": "" - }, - "vault": { - "description": "vault defines the configuration for the Vault KMS plugin. The plugin connects to a Vault Enterprise server that is managed by the user outside the purview of the control plane. This field must be set when type is Vault, and must be unset otherwise.", - "default": {}, - "$ref": "#/definitions/com.github.openshift.api.config.v1.VaultKMSPluginConfig" } - }, - "x-kubernetes-unions": [ - { - "discriminator": "type", - "fields-to-discriminateBy": { - "vault": "Vault" - } + } + }, + "com.github.openshift.api.config.v1.KMSPluginConfigReference": { + "description": "KMSPluginConfigReference identifies a cluster-scoped KMS plugin configuration custom resource.", + "type": "object", + "required": [ + "apiVersion", + "kind", + "name" + ], + "properties": { + "apiVersion": { + "description": "apiVersion is the API version of the referenced KMS plugin configuration resource. The value must be in the format /, where group is a DNS subdomain and version is a Kubernetes API version (for example, v1 or v1alpha1).", + "type": "string" + }, + "kind": { + "description": "kind is the kind of the referenced KMS plugin configuration resource. The value must be a valid Kubernetes kind name: it must be between 1 and 63 characters, start with an uppercase letter, and contain only alphanumeric characters.", + "type": "string" + }, + "name": { + "description": "name is the metadata.name of the referenced KMS plugin configuration resource. The referenced resource must be cluster-scoped. The name must be a valid DNS subdomain name: it must contain no more than 253 characters, contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character.", + "type": "string" } - ] + } }, "com.github.openshift.api.config.v1.KeystoneIdentityProvider": { "description": "KeystonePasswordIdentityProvider provides identities for users authenticating using keystone password credentials", diff --git a/payload-manifests/crds/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml index f3793fac61d..e2e98d6f1c1 100644 --- a/payload-manifests/crds/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml +++ b/payload-manifests/crds/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/payload-manifests/crds/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml index d06cd26ca79..37dc8c67540 100644 --- a/payload-manifests/crds/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml +++ b/payload-manifests/crds/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer. diff --git a/payload-manifests/crds/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml index cce33594546..9dcec95edef 100644 --- a/payload-manifests/crds/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml +++ b/payload-manifests/crds/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml @@ -168,286 +168,68 @@ spec: managing the lifecyle of the encryption keys outside of the control plane. This allows integration with an external provider to manage the data encryption keys securely. properties: - type: - description: |- - type defines the kind of platform for the KMS provider. - Allowed values are Vault. - When set to Vault, the plugin connects to a HashiCorp Vault server for key management. - enum: - - Vault - type: string - vault: + pluginConfig: description: |- - vault defines the configuration for the Vault KMS plugin. - The plugin connects to a Vault Enterprise server that is managed - by the user outside the purview of the control plane. - This field must be set when type is Vault, and must be unset otherwise. + pluginConfig references a cluster-scoped KMS plugin configuration custom resource. + The referenced resource is reconciled by an OLM operator that publishes the resolved + plugin configuration, including the container image, in the resource status. + It references a provider-specific cluster-scoped custom resource. properties: - authentication: - description: authentication defines the authentication - method used to authenticate with Vault. - properties: - appRole: - description: |- - appRole defines the configuration for AppRole authentication. - This field must be set when type is AppRole, and must be unset otherwise. - properties: - secret: - description: |- - secret references a secret in the openshift-config namespace containing - the AppRole credentials used to authenticate with Vault. - The referenced Secret must contain two keys: "role-id" for the AppRole Role ID and "secret-id" for the AppRole Secret ID. - properties: - name: - description: |- - name is the metadata.name of the referenced secret in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with - an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - required: - - secret - type: object - type: - description: |- - type defines the authentication method used to authenticate with Vault. - Allowed values are AppRole. - When set to AppRole, the plugin uses AppRole credentials to authenticate with Vault. - enum: - - AppRole - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: appRole config is required when authentication - type is AppRole, and forbidden otherwise - rule: 'self.type == ''AppRole'' ? has(self.appRole) - : !has(self.appRole)' - kmsPluginImage: - description: |- - kmsPluginImage specifies the container image for the HashiCorp Vault KMS plugin. - - The image must be a fully qualified OCI image pull spec with a SHA256 digest. - The format is: host[:port][/namespace]/name@sha256: - where the digest must be 64 characters long and consist only of lowercase hexadecimal characters, a-f and 0-9. - The total length must be between 75 and 447 characters. - - Short names (e.g., "vault-plugin" or "hashicorp/vault-plugin") are not allowed. - The registry hostname must be included and must contain at least one dot. - Image tags (e.g., ":latest", ":v1.0.0") are not allowed. - - Consult the OpenShift documentation for compatible plugin versions with your cluster version, - then obtain the image digest for that version from HashiCorp's container registry. - - For disconnected environments, mirror the plugin image to an accessible registry - and reference the mirrored location with its digest. - maxLength: 447 - minLength: 75 - type: string - x-kubernetes-validations: - - message: the OCI Image reference must end with a valid - '@sha256:' suffix, where '' is 64 - characters long - rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) - - message: the OCI Image name should follow the host[:port][/namespace]/name - format, resembling a valid URL without the scheme. - Short names are not allowed, the registry hostname - must be included. - rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?(/[a-zA-Z0-9-_.]+)+$')) - tls: + apiVersion: description: |- - tls contains the TLS configuration for connecting to the Vault server. - When this field is not set, system default TLS settings are used. - minProperties: 1 - properties: - caBundle: - description: |- - caBundle references a ConfigMap in the openshift-config namespace containing - the CA certificate bundle used to verify the TLS connection to the Vault server. - The referenced ConfigMap must contain the CA bundle in the key "ca-bundle.crt". - When this field is not set, the system's trusted CA certificates are used. - - The namespace for the ConfigMap is openshift-config. - - Example ConfigMap: - apiVersion: v1 - kind: ConfigMap - metadata: - name: vault-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - properties: - name: - description: |- - name is the metadata.name of the referenced ConfigMap in the openshift-config namespace. - The name must be a valid DNS subdomain name: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'name must be a valid DNS subdomain - name: contain no more than 253 characters, - contain only lowercase alphanumeric characters, - ''-'' or ''.'', and start and end with an - alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - required: - - name - type: object - serverName: - description: |- - serverName specifies the Server Name Indication (SNI) to use when connecting to Vault via TLS. - This is useful when the Vault server's hostname doesn't match its TLS certificate. - When this field is not set, the hostname from vaultAddress is used for SNI. - - The value must be a valid DNS hostname: it must contain no more than 253 characters, - contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. - maxLength: 253 - minLength: 1 - type: string - x-kubernetes-validations: - - message: 'serverName must be a valid DNS hostname: - contain no more than 253 characters, contain only - lowercase alphanumeric characters, ''-'' or ''.'', - and start and end with an alphanumeric character' - rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') - type: object - vaultAddress: - description: |- - vaultAddress specifies the address of the HashiCorp Vault instance. - The value must be a valid HTTPS URL containing only scheme, host, and optional port. - Paths, user info, query parameters, and fragments are not allowed. - - Format: https://hostname[:port] - Example: https://vault.example.com:8200 - - The value must be between 1 and 512 characters. - maxLength: 512 + apiVersion is the API version of the referenced KMS plugin configuration resource. + The value must be in the format /, where group is a DNS subdomain + and version is a Kubernetes API version (for example, v1 or v1alpha1). + maxLength: 64 minLength: 1 type: string x-kubernetes-validations: - - message: must be a valid URL - rule: isURL(self) - - message: must use the 'https' scheme - rule: isURL(self) && url(self).getScheme() == 'https' - - message: must not contain a path - rule: isURL(self) && (url(self).getEscapedPath() == - '' || url(self).getEscapedPath() == '/') - - message: must not have a query - rule: isURL(self) && url(self).getQuery() == {} - - message: must not have a fragment - rule: self.find('#(.+)$') == '' - - message: must not have user info - rule: self.find('@') == '' - vaultAuthNamespace: + - message: apiVersion must be in the format / + rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+/v[0-9]+([a-z0-9]+)*$') + kind: description: |- - vaultAuthNamespace specifies the Vault namespace to use for authentication. - This is only applicable for Vault Enterprise installations where authentication - and Transit operations may be in different namespaces. - When this field is not set, the value of vaultNamespace is used for both - authentication and Transit key operations. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + kind is the kind of the referenced KMS plugin configuration resource. + The value must be a valid Kubernetes kind name: it must be between 1 and 63 + characters, start with an uppercase letter, and contain only alphanumeric characters. + maxLength: 63 minLength: 1 type: string x-kubernetes-validations: - - message: vaultAuthNamespace cannot end with a forward - slash - rule: '!self.endsWith(''/'')' - - message: vaultAuthNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultAuthNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' - vaultKeyPath: + - message: kind must be a valid Kubernetes kind name + rule: self.matches('^[A-Z][a-zA-Z0-9]*$') + name: description: |- - vaultKeyPath specifies the full path to the encryption key in Vault's Transit secrets engine, - combining the Transit engine mount path and the key name separated by "/keys/". - Format: /keys/ (e.g., transit/keys/my-key, myteam/transit/keys/production-key). - - The total path length must be between 8 and 1542 characters. - The path cannot start or end with a forward slash, cannot contain consecutive forward slashes, - must only contain RFC 3986 unreserved characters (alphanumeric, hyphen, period, underscore, tilde) - and forward slashes as path separators, and must not contain "." or ".." path segments. - The key name must start and end with an alphanumeric character or underscore, and may contain - alphanumeric characters, underscores, hyphens, and periods in the middle. - maxLength: 1542 - minLength: 8 - type: string - x-kubernetes-validations: - - message: vaultKeyPath cannot start with a forward slash - rule: '!self.startsWith(''/'')' - - message: vaultKeyPath cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultKeyPath cannot contain consecutive forward - slashes - rule: '!self.contains(''//'')' - - message: vaultKeyPath must only contain RFC 3986 unreserved - characters (alphanumeric, hyphen, period, underscore, - tilde) and forward slashes - rule: self.matches('^[a-zA-Z0-9._~/-]+$') - - message: vaultKeyPath must not contain '.' or '..' path - segments - rule: self.split('/').filter(s, s == '.' || s == '..').size() - == 0 - - message: vaultKeyPath must follow the format /keys/ - where the key name starts and ends with an alphanumeric - character or underscore and may contain alphanumeric - characters, underscores, hyphens, and periods - rule: self.matches('^[a-zA-Z0-9._~-]+(/[a-zA-Z0-9._~-]+)*/keys/[a-zA-Z0-9_]([a-zA-Z0-9_.-]*[a-zA-Z0-9_])?$') - vaultNamespace: - description: |- - vaultNamespace specifies the Vault namespace where the Transit secrets engine is mounted. - This is only applicable for Vault Enterprise installations. - When this field is not set, no namespace is used. - - The value must be between 1 and 4096 characters. - The namespace cannot end with a forward slash, cannot contain spaces, and cannot be one of the reserved strings: root, sys, audit, auth, cubbyhole, or identity. - maxLength: 4096 + name is the metadata.name of the referenced KMS plugin configuration resource. + The referenced resource must be cluster-scoped. + The name must be a valid DNS subdomain name: it must contain no more than 253 characters, + contain only lowercase alphanumeric characters, '-' or '.', and start and end with an alphanumeric character. + maxLength: 253 minLength: 1 type: string x-kubernetes-validations: - - message: vaultNamespace cannot end with a forward slash - rule: '!self.endsWith(''/'')' - - message: vaultNamespace cannot contain spaces - rule: '!self.contains('' '')' - - message: vaultNamespace cannot be a reserved string - (root, sys, audit, auth, cubbyhole, identity) - rule: '!(self in [''root'', ''sys'', ''audit'', ''auth'', - ''cubbyhole'', ''identity''])' + - message: 'name must be a valid DNS subdomain name: contain + no more than 253 characters, contain only lowercase + alphanumeric characters, ''-'' or ''.'', and start + and end with an alphanumeric character' + rule: self.matches('^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$') required: - - authentication - - kmsPluginImage - - vaultAddress - - vaultKeyPath + - apiVersion + - kind + - name type: object + type: + description: |- + type defines the kind of platform for the KMS provider. + Allowed values are Vault. + The encryption controllers read the resolved plugin configuration from the status + of the custom resource referenced in pluginConfig. + enum: + - Vault + type: string required: + - pluginConfig - type type: object - x-kubernetes-validations: - - message: vault config is required when kms provider type is - Vault, and forbidden otherwise - rule: 'self.type == ''Vault'' ? has(self.vault) : !has(self.vault)' type: description: |- type defines what encryption type should be used to encrypt resources at the datastore layer.