OIDC Policy - #1356
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1356 +/- ##
==========================================
- Coverage 80.58% 78.46% -2.13%
==========================================
Files 93 98 +5
Lines 8815 9574 +759
==========================================
+ Hits 7104 7512 +408
- Misses 1420 1744 +324
- Partials 291 318 +27
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
710f359 to
992e1e3
Compare
1d7dba8 to
35ca303
Compare
2f286cd to
36ee7b0
Compare
32d4ff2 to
4f6c8d1
Compare
ddef298 to
c23e47d
Compare
2be83a8 to
5d02772
Compare
5d02772 to
c12a67d
Compare
86ec0fd to
27dfbb2
Compare
| // DiscoveryEndpoint is Currently not supported by Authorino. | ||
| // The DiscoveryEndpoint path (i.e. "/.well-known/openid-configuration") is appended to the IssuerURL to fetch the OIDC configuration. | ||
| // +optional | ||
| // DiscoveryEndpoint string `json:"discoveryEndpoint,omitempty"` |
There was a problem hiding this comment.
Commented because currently is not supported by Authorino
|
|
||
| // OIDC OAuth 2.0 request parameters, such as `scope`, `response_type`, `client_id`, `redirect_uri`, `state`, etc. | ||
| // +optional | ||
| // AuthorizationEndpointQuery map[string]string `json:"authorizationEndpointQuery,omitempty"` |
There was a problem hiding this comment.
Commented because of lacking definition: Kuadrant/architecture#114 (comment)
adam-cattermole
left a comment
There was a problem hiding this comment.
So far looking good.
I'm a little lost on the one-of for IssuerURL and JWKSURL, I don't see any uses of the JWKS variant and all the rest of the logic heavily depends on Issuer being present? I guess this is a TODO?
Only other bits I see would be handling updates for the callback policy (and maybe route) in the case the gateway hostname changes. What about deletion?
|
|
||
| // Provider defines the settings related to the Identity Provider (IDP) | ||
| // | ||
| // +kubebuilder:validation:XValidation:rule="!(has(self.jwksURL) && self.jwksURL != '' && has(self.issuerURL) && self.issuerURL != '')",message="Use one of: jwksURL, issuerURL" |
There was a problem hiding this comment.
This kubebuilder validation seems confusing; if jwksURL is configured as omitempty, won't it always be a non-empty string if it is set, and has(self.jwksURL) and self.jwksURL != '' are equivalent?
Maybe instead we could set both fields to omitempty and just check that one of them is not empty and both are not set has(self.jwksURL) != has(self.issuerURL)
There was a problem hiding this comment.
I wanted to match how it was defined in Authorino. And yes, kind of confusing since is not implemented because we haven't replicated the AuthConfig changes in the AuthPolicy. TODO
There was a problem hiding this comment.
Gotcha, if we're not going to support the JWKSURL field in the OIDCPolicy in this PR, perhaps we should comment it out/remove and have the validation ensure the issuer is set to a non-empty string, as that's required for most of the flow?
Then a follow up can add it back in when it's supported, wdyt?
| "context" | ||
| "encoding/json" | ||
| "fmt" | ||
| "net/url" | ||
| "reflect" | ||
| "strings" | ||
|
|
||
| "github.com/kuadrant/limitador-operator/pkg/helpers" | ||
| "k8s.io/apimachinery/pkg/api/meta" | ||
|
|
||
| extcontroller "github.com/kuadrant/kuadrant-operator/pkg/extension/controller" | ||
|
|
||
| "k8s.io/apimachinery/pkg/runtime" | ||
|
|
||
| "github.com/kuadrant/policy-machinery/machinery" | ||
| "k8s.io/utils/ptr" | ||
| ctrl "sigs.k8s.io/controller-runtime" | ||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
| "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||
| gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" | ||
| gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" | ||
|
|
||
| "github.com/kuadrant/kuadrant-operator/internal/reconcilers" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| authorinov1beta3 "github.com/kuadrant/authorino/api/v1beta3" | ||
| "k8s.io/apimachinery/pkg/api/errors" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
|
||
| kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1" | ||
| kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" | ||
| "github.com/kuadrant/kuadrant-operator/pkg/extension/types" | ||
| "github.com/kuadrant/kuadrant-operator/pkg/extension/utils" | ||
|
|
||
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
| ) |
There was a problem hiding this comment.
I think what @Boomatang means is to re-order to have local, external, kuadrant-operator imports:
The import checker only ensures things are separate logical groups but not formatted nicely overall.
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "net/url" | |
| "reflect" | |
| "strings" | |
| "github.com/kuadrant/limitador-operator/pkg/helpers" | |
| "k8s.io/apimachinery/pkg/api/meta" | |
| extcontroller "github.com/kuadrant/kuadrant-operator/pkg/extension/controller" | |
| "k8s.io/apimachinery/pkg/runtime" | |
| "github.com/kuadrant/policy-machinery/machinery" | |
| "k8s.io/utils/ptr" | |
| ctrl "sigs.k8s.io/controller-runtime" | |
| "sigs.k8s.io/controller-runtime/pkg/client" | |
| "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | |
| gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" | |
| gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" | |
| "github.com/kuadrant/kuadrant-operator/internal/reconcilers" | |
| "github.com/go-logr/logr" | |
| authorinov1beta3 "github.com/kuadrant/authorino/api/v1beta3" | |
| "k8s.io/apimachinery/pkg/api/errors" | |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
| kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1" | |
| kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" | |
| "github.com/kuadrant/kuadrant-operator/pkg/extension/types" | |
| "github.com/kuadrant/kuadrant-operator/pkg/extension/utils" | |
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | |
| ) | |
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "net/url" | |
| "reflect" | |
| "strings" | |
| "github.com/go-logr/logr" | |
| authorinov1beta3 "github.com/kuadrant/authorino/api/v1beta3" | |
| "github.com/kuadrant/limitador-operator/pkg/helpers" | |
| "github.com/kuadrant/policy-machinery/machinery" | |
| "k8s.io/apimachinery/pkg/api/errors" | |
| "k8s.io/apimachinery/pkg/api/meta" | |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
| "k8s.io/apimachinery/pkg/runtime" | |
| "k8s.io/utils/ptr" | |
| ctrl "sigs.k8s.io/controller-runtime" | |
| "sigs.k8s.io/controller-runtime/pkg/client" | |
| "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | |
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | |
| gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" | |
| gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" | |
| kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1" | |
| kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" | |
| "github.com/kuadrant/kuadrant-operator/internal/reconcilers" | |
| extcontroller "github.com/kuadrant/kuadrant-operator/pkg/extension/controller" | |
| "github.com/kuadrant/kuadrant-operator/pkg/extension/types" | |
| "github.com/kuadrant/kuadrant-operator/pkg/extension/utils" | |
| ) |
2d37be4 to
b9f2e15
Compare
Signed-off-by: dd di cesare <didi@posteo.net>
Both needed for OIDC Policy build * BaseReconciler: Lazy initialization and setup with manager * ExtensionsController: Exposing its Manager Signed-off-by: dd di cesare <didi@posteo.net>
Signed-off-by: dd di cesare <didi@posteo.net>
* API: Added as `v1alpha` * Refactor of `cmd/extension` to `cmd/extensions` in order to provide multiple Signed-off-by: dd di cesare <didi@posteo.net>
* `AuthPolicies` and `HTTPRoute` need create permissions for the `OIDCReconciler` Signed-off-by: dd di cesare <didi@posteo.net>
Signed-off-by: dd di cesare <didi@posteo.net>
b9f2e15 to
a24507a
Compare
| // Not implemented in AuthPolicy yet | ||
| // URL of the JSON Web Key Set (JWKS) endpoint. | ||
| // Use it for non-OpenID Connect (OIDC) JWT authentication, where the JWKS URL is known beforehand. | ||
| // The JSON Web Keys (JWK) obtained from this endpoint are automatically cached and the caching updated whenever the kid of a JWT does not match any of the cached JWKs (https://openid.net/specs/openid-connect-core-1_0.html#RotateSigKeys). | ||
| // One of: jwksURL, issuerURL | ||
| // +optional | ||
| //JWKSURL string `json:"jwksURL,omitempty"` |
There was a problem hiding this comment.
Should we first bump the version of the AuthConfig the Kuadrant Operator depends upon?
There was a problem hiding this comment.
Yes, that's the idea, so then we can implement it here
| ClientID string `json:"clientID"` | ||
| // OAuth2 Client Secret. | ||
| // +optional | ||
| ClientSecret string `json:"clientSecret,omitempty"` |
There was a problem hiding this comment.
Ideally this would be a reference to a Kubernetes Secret.
There was a problem hiding this comment.
I'll leave it as a TODO for the next iteration if that's OK with you
| r.logger.Info("Reconciling OIDCPolicy") | ||
|
|
||
| oidcPolicy := &kuadrantv1alpha1.OIDCPolicy{} | ||
| if err := r.Client().Get(ctx, request.NamespacedName, oidcPolicy); err != nil { |
There was a problem hiding this comment.
Are we back to reading directly from the cluster in the middle of a reconciliation call? It feels like breaking the state of the world principle.
There was a problem hiding this comment.
that's is not the Kuadrant controller, that's just a "regular" reconciler, with some magic from our end. This wouldn't even have access to the SotW.
There was a problem hiding this comment.
Problem is the pattern. There's no guarantee this Get will return the generation of the resource as it was when reconciliation was triggered. More importantly, a second Get further ahead could introduce yet another state, while decisions have been possibly made already in the same reconciliation call. This is the main motivation of SOTW and a problem the Policy Machinery offers tools to solve. That's why, IMO, new policy controllers should adopt that pattern, not this one.
There was a problem hiding this comment.
This is targeted at "any other k8s developer", that uses Kuadrant. "The pattern" here is: you get your resource (your metapolicy) once and use the Kuadrant Context to interact with the SotW (which would go thru the kuadrant controller over gRPC, to use the policy machinery and "a DAG"). The Context then also takes care of the subscription part to what you care about (and restart the reconciliation for you).
It might be confusing, but this isn't one or the other, it's "the good ol' way" for the metapolicy itself (which the SotW knows nothing about), alongside SotW querying/subscription model for the "Gateway API target objects".
| os.Exit(1) | ||
| } | ||
|
|
||
| oidcPolicyReconciler.SetupWithManager(extController.Manager()) |
There was a problem hiding this comment.
I need to educate myself in the whole policy extension mechanism, but this smells a lot how we use to do reconciliation in the past and I do not like it. I want to make sure we are not making concurrent calls to a reconcile func that reads again directly from the cluster, that touches so many other resources, based on events centred in the policy object. I bet the next step here is adding mapping functions from target objects to policies ones, and that could be the final breaking of the state of the world principle. Sorry. Not happy with it.
There was a problem hiding this comment.
This only reads user defined CRs from the cluster, not targets or anything else, those are read from the SotW, through the "kuadrant context", as CEL expression e.g. self.findGateways()[0].metadata.name (or whatever it was/is), which is resolved by the Kuadrant controller (and for which then follow up updates are sent to this controller).
| @@ -0,0 +1,287 @@ | |||
| /* | |||
There was a problem hiding this comment.
Can we get these files to be under cmd/extension/ or somewhere specific? Wondering if we could get all files related to a single extension under one single directory?
There was a problem hiding this comment.
It's not quite possible without adding specific targets to use the build tools from kustomize/operator-sdk
alexsnaps
left a comment
There was a problem hiding this comment.
Probably will be slightly iterated further as we go, but this seems like a reasonable starting place.
Closes #1148
Based on Kuadrant/architecture#114
This PR introduces the Meta Policy
OIDCPolicyusing the extensions "framework" and consuming the Kuadrant context for the subscriptions to particular DAG object props changes. Mind that at the moment is a basic implementation of the OIDC flow, following heuristics and definitely open to change :)Notes
v1alpha1tokenSourceother than cookie, the storage of the token should be stored by the clientVerification Steps
WITH_EXTENSIONSset to true5.1 . (optional) Check for connectivity
curl http://bakery.$INGRESS_IP.nip.io/baker -ihttp://bakery.$INGRESS_IP.nip.io/bakerin browser and login to gitlabVerifying Authorization:
Share with me your Gitlab username, and I'll add it to the group. Then you can apply the following OIDCPolicy:
TODO
ResolveDAGAuthPoliciescreated by theOIDCPolicyingressGatewayInfofor the protocol, and addSecureif it'shttpsNext: