-
Notifications
You must be signed in to change notification settings - Fork 32
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
feat: configurable API Key K8s secret key name #488
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,7 @@ import ( | |
) | ||
|
||
const ( | ||
apiKeySelector = "api_key" | ||
defaultAPIKeySelector = "api_key" | ||
invalidApiKeyMsg = "the API Key provided is invalid" | ||
credentialsFetchingErrorMsg = "Something went wrong fetching the authorized credentials" | ||
) | ||
|
@@ -26,18 +26,20 @@ type APIKey struct { | |
Name string `yaml:"name"` | ||
LabelSelectors k8s_labels.Selector `yaml:"labelSelectors"` | ||
Namespace string `yaml:"namespace"` | ||
KeySelectors []string `yaml:"keySelectors"` | ||
|
||
secrets map[string]k8s.Secret | ||
mutex sync.RWMutex | ||
k8sClient k8s_client.Reader | ||
} | ||
|
||
func NewApiKeyIdentity(name string, labelSelectors k8s_labels.Selector, namespace string, authCred auth.AuthCredentials, k8sClient k8s_client.Reader, ctx context.Context) *APIKey { | ||
func NewApiKeyIdentity(name string, labelSelectors k8s_labels.Selector, namespace string, keySelectors []string, authCred auth.AuthCredentials, k8sClient k8s_client.Reader, ctx context.Context) *APIKey { | ||
apiKey := &APIKey{ | ||
AuthCredentials: authCred, | ||
Name: name, | ||
LabelSelectors: labelSelectors, | ||
Namespace: namespace, | ||
KeySelectors: append(keySelectors, defaultAPIKeySelector), | ||
secrets: make(map[string]k8s.Secret), | ||
k8sClient: k8sClient, | ||
} | ||
|
@@ -92,6 +94,7 @@ func (a *APIKey) GetK8sSecretLabelSelectors() k8s_labels.Selector { | |
return a.LabelSelectors | ||
} | ||
|
||
// Caution! This function is not thread-safe. Make sure to acquire a lock before calling it. | ||
func (a *APIKey) AddK8sSecretBasedIdentity(ctx context.Context, new k8s.Secret) { | ||
if !a.withinScope(new.GetNamespace()) { | ||
return | ||
|
@@ -103,17 +106,19 @@ func (a *APIKey) AddK8sSecretBasedIdentity(ctx context.Context, new k8s.Secret) | |
logger := log.FromContext(ctx).WithName("apikey") | ||
|
||
// updating existing | ||
newAPIKeyValue := string(new.Data[apiKeySelector]) | ||
for oldAPIKeyValue, current := range a.secrets { | ||
if current.GetNamespace() == new.GetNamespace() && current.GetName() == new.GetName() { | ||
if oldAPIKeyValue != newAPIKeyValue { | ||
a.appendK8sSecretBasedIdentity(new) | ||
delete(a.secrets, oldAPIKeyValue) | ||
logger.V(1).Info("api key updated") | ||
} else { | ||
logger.V(1).Info("api key unchanged") | ||
for _, key := range a.KeySelectors { | ||
newAPIKeyValue := string(new.Data[key]) | ||
for oldAPIKeyValue, current := range a.secrets { | ||
if current.GetNamespace() == new.GetNamespace() && current.GetName() == new.GetName() { | ||
if oldAPIKeyValue != newAPIKeyValue { | ||
a.appendK8sSecretBasedIdentity(new) | ||
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. In the issue I said:
But I guess the part of making it easier to implement key rotation is not really true, is it? In order to properly support rotation, all keys in a Secret must be accepted, otherwise at the moment a new valid key is added to the secret, the old one is automatically deleted and stop being accepted. Should we add to the |
||
delete(a.secrets, oldAPIKeyValue) | ||
KevFan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
logger.V(1).Info("api key updated") | ||
} else { | ||
logger.V(1).Info("api key unchanged") | ||
} | ||
return | ||
} | ||
return | ||
} | ||
} | ||
|
||
|
@@ -146,10 +151,13 @@ func (a *APIKey) withinScope(namespace string) bool { | |
// Appends the K8s Secret to the cache of API keys | ||
// Caution! This function is not thread-safe. Make sure to acquire a lock before calling it. | ||
func (a *APIKey) appendK8sSecretBasedIdentity(secret k8s.Secret) bool { | ||
value, isAPIKeySecret := secret.Data[apiKeySelector] | ||
if isAPIKeySecret && len(value) > 0 { | ||
a.secrets[string(value)] = secret | ||
return true | ||
for _, key := range a.KeySelectors { | ||
value, isAPIKeySecret := secret.Data[key] | ||
if isAPIKeySecret && len(value) > 0 { | ||
a.secrets[string(value)] = secret | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} |
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.
I wonder if the struct shouldn't store 2 maps –
api key value → k8s secret
andk8s secret namespaced name → api key value
. This would make this function as well asappendK8sSecretBasedIdentity
both slightly more efficient. On the other hand, updating both maps might be an atomic operation.WDYT?