-
Notifications
You must be signed in to change notification settings - Fork 37
feat: configurable API Key K8s secret key name #488
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: main
Are you sure you want to change the base?
Conversation
guicassolato
left a comment
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.
Thank you so much for taking the time to address this issue, @KevFan!
I've left a few comments. Nothing that invalidates the change, but mainly to double check on the design we want for the feature and some implementation detail.
One general wondering I have though is whether we want to allow this change into v1beta2 or v1beta3 (addressing #480 first). Although the keySelectors field not being backwards compatible with v1beta1 is not much of a concern (since #483 was merged), it feels like breaking a promise (internal agreement maybe?) that all changes to the API now would go into v1beta3.
Do you have an opinion on this, @alexsnaps?
So... @guicassolato, you'd bump the version with this change, is that it? I'm growing concerned I won't get the CEL stuff done by the EOW tho... So the question becomes more of when would |
| if secret.GetNamespace() == deleted.Namespace && secret.GetName() == deleted.Name { | ||
| delete(a.secrets, key) | ||
| log.FromContext(ctx).WithName("apikey").V(1).Info("api key deleted") | ||
| return |
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.
Should no longer return early since the change now allows for the possibility of multiple keys pointing to the same secret
api/v1beta3/auth_config_types.go
Outdated
| // Authorino will attempt to authenticate using any matching key, including "api-key". | ||
| // If no match is found, the Kubernetes secret is not considered a valid Authorino API Key secret and is ignored. | ||
| // +optional | ||
| KeySelectors []string `json:"keySelectors,omitempty"` |
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.
Do we want to define the kubebuilder default here also? 🤔
// +kubebuilder:default:={"api_key"}
Do we want to set a maximum?
+kubebuilder:validation:MaxItems
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.
This is a good question. I guess the only reason I can think of to do that is to help users not to shoot themselves in the foot when tempted to add hundreds, thousands of valid keys as a workaround to store multiple valid API keys inside of a same Kubernetes secret.
If we ignore performance (and let users figure that out by themselves), arguably storing multiple valid identities in the same Secret may not be necessarily such a bad idea-even though it isn't how this feature was originally designed to work and users would lose capabilities in the process (e.g. storing one identity's metadata in the secret's metadata).
Say we do want to let users store multiple API keys in a Secret (now that it will be technically possible anyway). Probably, having to come up with a different key name for each identity would be a PITA. I can see requests of extending the key selector to support things like regexes, globs, etc coming up.
So I wonder, should we embrace that we make the key selector to be a CEL expression?
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 think that is a good point, moving to CEL expression would make a more consistent experience while giving users more capabilities to how they want to select the secret keys 👍
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've a working implementation based on how it's currently done for the AuthJSON and implementing
authorino/pkg/expressions/types.go
Lines 3 to 5 in b2bde91
| type Value interface { | |
| ResolveFor(jsonData string) (interface{}, error) | |
| } |
Interested in @alexsnaps opinions on this
cc84bee to
faec0db
Compare
guicassolato
left a comment
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.
Verification steps work.
nit: we may want to fix perhaps only where it says:
- Curling with api_key_2 should succeed
curl -H 'Authorization: APIKEY key_2' http://talker-api.127.0.0.1.nip.io:8000/hello -v # HTTP/1.1 401 Unauthorized
Last line (commented) should probably read # HTTP/1.1 200 OK.
Let's just make sure we're all in agreement regarding https://github.com/Kuadrant/authorino/pull/488/files#r1958525812 before merging this (or making the proper adjustments.)
Nice job, @KevFan!
|
I wondered if binding the |
| assert.Equal(t, apiKey.LabelSelectors.String(), "planet=coruscant") | ||
| assert.Equal(t, apiKey.Namespace, "ns1") | ||
| assert.Equal(t, len(apiKey.secrets), 1) | ||
| _, exists := apiKey.secrets["ObiWanKenobiLightSaber"] |
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.
<3
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Signed-off-by: KevFan <chfan@redhat.com>
Thanks @alexsnaps for raising this. Yes, I believe its always a unique set of keys also. Agreed, I'm in favour of possibly exposing more of the secret as needed in any future work 👍 |
Let me start by saying that API key authentication, without proper guardrails set by a cluster admin beforehand, can easily be the least secure feature of Authorino. On one hand, giving access to the entire secret by binding to the root of the object instead of Only this change could make label selectors obsolete (if it wasn't for the optimisation aspect involved when querying the API server of course). On the other hand, such change marginally increases an existing known vulnerability of unsafe Authorino deployments, that allow malicious users to elevate privileges and get access to Kubernetes secrets otherwise out of reach. While checking the listed secrets for valid API keys stored in it, this line could be exploited to leak sensitive data to the logs, such as other values stored in the secret that are unrelated to API key authn. Combined with I say "marginally", however, because arguably such vulnerability already exists. It exists in 2 levels. First, because any secret deemed to contain a valid API key secret already gets a root binding at The second level is enabled by this PR. One who can guess the value of any key stored in a secret-it doesn't have to be necessarily the value of the |
Signed-off-by: KevFan <chfan@redhat.com>
Description
Closes: #360
Adds Key Selectors support for API Key k8s secret
Verification
api_keykey (default key as not key selector was defined) should succeedapi_key_2andkey 3key should fail with401 Unauthorizedapi_key_2api_key_2should succeedapi_keyandkey 3key should fail with401 Unauthorizedapi_key*api_keyandapi_key_2should succeedkey_3key should fail with401 Unauthorizedcurl -H 'Authorization: APIKEY key_3' http://talker-api.127.0.0.1.nip.io:8000/hello -vapi_key_2kubectl patch secret api-key-1 -p '{"data":{"api_key_2": null}}'api_key_2should failapi_keyshould still succeedapi_key_2from second secret should succeedapi_key,api_key_2andapi_key_3should failapi_key_2andapi_key_3should succeed