-
Notifications
You must be signed in to change notification settings - Fork 265
[WIP] CNTRLPLANE-3236: Kms plugin lifecycle #2169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
5221c82
407f682
3b48c83
793d171
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,15 +2,24 @@ package kms | |
|
|
||
| import ( | ||
| "fmt" | ||
| "path/filepath" | ||
| "regexp" | ||
| "strconv" | ||
| "strings" | ||
|
|
||
| configv1 "github.com/openshift/api/config/v1" | ||
| "github.com/openshift/api/features" | ||
| "github.com/openshift/library-go/pkg/operator/configobserver/featuregates" | ||
| "github.com/openshift/library-go/pkg/operator/encryption/encoding" | ||
| corev1 "k8s.io/api/core/v1" | ||
| apiserverv1 "k8s.io/apiserver/pkg/apis/apiserver/v1" | ||
| ) | ||
|
|
||
| var kmsEndpointRegexp = regexp.MustCompile(`^unix:///var/run/kmsplugin/kms-(\d+)\.sock$`) | ||
|
|
||
| const providerConfigDataKeyPrefix = "kms-provider-config-" | ||
| const credentialDataKeyPrefix = "kms-secret-data-" | ||
| const credentialsDir = "/etc/kubernetes/static-pod-resources/secrets/encryption-config" | ||
|
|
||
| // ToProviderConfigSecretDataKeyFor constructs the data key for storing a KMS provider config in the encryption-config Secret. | ||
| // The keyID must be a valid non-negative integer string. | ||
|
|
@@ -34,6 +43,28 @@ func KeyIDFromProviderConfigSecretDataKey(dataKey string) (string, bool, error) | |
| return keyID, true, nil | ||
| } | ||
|
|
||
| // ToCredentialSecretDataKeyFor constructs the data key for storing KMS credentials in the encryption-config Secret. | ||
| // The keyID must be a valid non-negative integer string. | ||
| func ToCredentialSecretDataKeyFor(keyID string) (string, error) { | ||
| if _, err := strconv.ParseUint(keyID, 10, 64); err != nil { | ||
| return "", fmt.Errorf("invalid keyID %q: must be a non-negative integer", keyID) | ||
| } | ||
| return credentialDataKeyPrefix + keyID, nil | ||
| } | ||
|
|
||
| // KeyIDFromCredentialSecretDataKey extracts the keyID from a kms-secret-data data key. | ||
| // Returns the keyID and true if the key matches the "kms-secret-data-<keyID>" pattern. | ||
| func KeyIDFromCredentialSecretDataKey(dataKey string) (string, bool, error) { | ||
| keyID, found := strings.CutPrefix(dataKey, credentialDataKeyPrefix) | ||
| if !found || len(keyID) == 0 { | ||
| return "", false, nil | ||
| } | ||
| if _, err := strconv.ParseUint(keyID, 10, 64); err != nil { | ||
| return "", false, fmt.Errorf("invalid keyID %q: must be a non-negative integer", keyID) | ||
| } | ||
| return keyID, true, nil | ||
| } | ||
|
|
||
| // AddKMSPluginVolumeAndMountToPodSpec conditionally adds the KMS plugin volume mount to the specified container. | ||
| // It assumes the pod spec does not already contain the KMS volume or mount; no deduplication is performed. | ||
| // Deprecated: this is a temporary solution to get KMS TP v1 out. We should come up with a different approach afterwards. | ||
|
|
@@ -90,3 +121,50 @@ func AddKMSPluginVolumeAndMountToPodSpec(podSpec *corev1.PodSpec, containerName | |
|
|
||
| return nil | ||
| } | ||
|
|
||
| func findFirstKMSConfiguration(config *apiserverv1.EncryptionConfiguration) *apiserverv1.KMSConfiguration { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don't need to wire the first config anymore. kms-plugin-configs are coming from encryption-config Secret already. So it is just a matter of a loop over the keys.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ack, I can get the key ids from the secret's keys. The plugin also needs the endpoint path, do you suggest I reconstruct it using the information from the kms-plugin-config? Or is it better to plumb that information thru?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. encryption-config key contains uds path keyed by secret_KEYID, oauth_KEYID, etc. format. |
||
| for _, resource := range config.Resources { | ||
| for _, provider := range resource.Providers { | ||
| if provider.KMS != nil { | ||
| return provider.KMS | ||
| } | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func parseKeyIDFromEndpoint(endpoint string) (string, error) { | ||
| matches := kmsEndpointRegexp.FindStringSubmatch(endpoint) | ||
| if matches == nil { | ||
| return "", fmt.Errorf("unexpected KMS endpoint format: %s", endpoint) | ||
| } | ||
| return matches[1], nil | ||
| } | ||
|
|
||
| func parseProviderConfig(secret *corev1.Secret, kmsConfiguration *apiserverv1.KMSConfiguration) (*configv1.KMSConfig, error) { | ||
| keyID, err := parseKeyIDFromEndpoint(kmsConfiguration.Endpoint) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to parse key ID from endpoint: %w", err) | ||
| } | ||
| providerConfigKey, err := ToProviderConfigSecretDataKeyFor(keyID) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to create provider config secret key ID from endpoint: %w", err) | ||
| } | ||
| providerConfigData, ok := secret.Data[providerConfigKey] | ||
| if !ok { | ||
| return nil, fmt.Errorf("missing provider config key %s in encryption-config secret", providerConfigKey) | ||
| } | ||
| kmsConfig, err := encoding.DecodeKMSConfig(providerConfigData) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to decode provider config: %w", err) | ||
| } | ||
| return kmsConfig, nil | ||
| } | ||
|
|
||
| func parseSecretDataPath(kmsConfiguration *apiserverv1.KMSConfiguration) (string, error) { | ||
| keyID, err := parseKeyIDFromEndpoint(kmsConfiguration.Endpoint) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to parse key ID from endpoint: %w", err) | ||
| } | ||
| return filepath.Join(credentialsDir, credentialDataKeyPrefix+keyID), nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that we should move this
library-go/pkg/operator/encryption/controllers/key_controller.go
Line 43 in 6769d5f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I didn't recall this existed before. Are you suggesting I remove the one in key_controller.go and keep this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we can remove the one from key_controller. I think kms/helpers.go is better place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, so that one is a string fmt, and this one is a regex