-
Notifications
You must be signed in to change notification settings - Fork 38
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
Oidc autoregistration #152
Conversation
# | ||
# Optional: To skip TLS certificate checking with the provider, specify insecureTLS as true. Default is false. | ||
# insecureTLS: dHJ1ZQ== | ||
---- |
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.
can we also add what the corresponding RuntimeComponent
CR would be, and how it references this Secret? It would be good to visualize a working sample of what fields are needed in this auto-registration flow. Is there a specific naming convention that one must follow for this Secret to be auto discovered, or it can be named whatever we want as long as we reference it from the CR?
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.
The secret is an attribute of the OpenLibertyApplication, sso.oidc[].autoRegisterSecret
, so it's not usable from the RuntimeComponent CR. It can be named whatever we want. I've updated the user guide to make the flow and who needs what (RedHat SSO vs. IBM Cloud Identity) more clear.
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.
my bad - I meant to say the corresponding OpenLibertyApplication
CR sample, that shows a complete CR using autoRegisterSecret
. I really like the Secret
example, I think we just need the corresponding olapp CR.
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.
ah, got it. Added an example.
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.
@brutif Added some initial comments. Yet to review some code. Thanks.
secretName := instance.GetName() + ssoSecretNameSuffix | ||
ssoSecret := &corev1.Secret{} | ||
err := r.GetClient().Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: instance.GetNamespace()}, ssoSecret) | ||
err = lutils.CustomizeEnvSSO(&deploy.Spec.Template, instance, r.GetClient(), r.IsOpenShift()) |
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 reference statefulSet's template
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.
will be fixed
if err != nil { | ||
return errors.Wrapf(err, "Secret for Single sign-on (SSO) was not found. Create a secret named %q in namespace %q with the credentials for the login providers you selected in application image.", secretName, instance.GetNamespace()) | ||
reqLogger.Error(err, "Failed to reconcile Single sign-on configuration") | ||
return err |
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.
Use ManageError to handle error:
r.ManageError(err, common.StatusConditionTypeReconciled, instance)
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 inside the mutator function, the enclosing createOrUpdate call returns it, it's then handled with a call to r.ManageError outside of that around line 666, so ManageError is getting called.
doc/user-guide.adoc
Outdated
| `sso.github.hostname` | Specifies the host name of your enterprise GitHub, such as _github.mycompany.com_. The default is _github.com_, which is the public Github. | ||
| `sso.oidc` | The list of OpenID Connect (OIDC) providers to authenticate with. Required fields: _discoveryEndpoint_. Specify sensitive fields, such as _clientId_ and _clientSecret_, by using the `Secret`. | ||
| `sso.oidc[].autoRegisterSecret` | Specifies name of secret containing information to automatically register Liberty with the OIDC provider. See link:++#Using-automatic-registration-with-OIDC-providers++[Using automatic registration with OIDC providers]. |
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 it be "Liberty application"?
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.
fixed
doc/user-guide.adoc
Outdated
@@ -315,6 +318,66 @@ spec: | |||
name: self-signed | |||
termination: reencrypt | |||
---- | |||
==== Using automatic registration with OIDC providers | |||
|
|||
The operator can request a client Id and client Secret from providers, rather than requiring them in advance. This can simplify deployment, as the provider's administrator can supply the information needed for registration once, instead of supplying clientIds and secrets repetitively. An additional secret specified by `sso.oidc[].autoRegisterSecret` contains additional information necessary to perform the registration. First the operator will make an https request to the `sso.oidc[].discoveryEndpoint` to obtain URLs for subsequent REST calls. Next it will make additional REST calls to the provider and obtain a client Id and client Secret. Automatic registration takes precedence over the values in the sso secret. The name of this secret should end with `-olapp-sso` for it to be monitored for changes. This is tested with Red Hat Single Sign-on (RHSSO). |
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.
"The name of this secret should end with -olapp-sso
for it to be monitored for changes."
With the current implementation you have in place, I don't think the auto-register secret is monitored.
Instead of users always having to explicitly specify the auto-register secret name, by default we could automatically find it (only while reconciling providers) using a naming convention: <CR_name>-olapp-sso-<provider_id>
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 will look into auto-detecting off of the name, to make it consistent with the way we handle the other sso secret. I can't think of any disadvantage to that.
pkg/utils/utils.go
Outdated
ssoEnv = append(ssoEnv, *createEnvVarSSO(id, "_CLIENTID", clientId)) | ||
ssoEnv = append(ssoEnv, *createEnvVarSSO(id, "_CLIENTSECRET", clientSecret)) | ||
} else { | ||
if !haveSsoSecret { // if we don't have an autoreg secret, we need an sso secret. |
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.
A similar error is needed for OAuth2 providers below and GitHub above (when Github.Hostname is specified).
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.
fixed
pkg/utils/utils.go
Outdated
} | ||
clientId, clientSecret, err = RegisterWithOidcProvider(regData, regSecret) | ||
if err != nil { | ||
return errors.Wrapf(err, "Error occured during registration with OIDC provider") |
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.
It'll be good to add the provider ID here.
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.
fixed
pkg/utils/utils.go
Outdated
return errors.Wrapf(err, "Registration Data Secret for Single sign-on (SSO) of name %q was not found. Create a secret in namespace %q with the credentials for the login providers you selected in application image.", secretName, instance.GetNamespace()) | ||
} | ||
// if no clientId specified for this provider, try auto-registration | ||
clientId := string(ssoSecret.Data[strings.ToLower(id) + "-clientId"]) |
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.
There could be mismatch due to converting to lower case. oidcClient.ID
should be used as is here.
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.
fixed
pkg/utils/utils.go
Outdated
return errors.Wrapf(err, "Error occured during registration with OIDC for provider " + providerId) | ||
} | ||
|
||
_, err = controllerutil.CreateOrUpdate(context.TODO(), client, ssoSecret, func() error { |
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.
Updating the secret for each provider will cause many reconciliations unnecessarily. It'll be good to collect the data to add to the secret and then update the secret just once at the end. That way it'll have to reconcile only once.
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.
fixed
pkg/utils/utils.go
Outdated
ssoSecret.Data[strings.ToLower(id) + autoregFragment + "RegisteredOidcClientId"] = []byte(clientId) | ||
ssoSecret.Data[strings.ToLower(id) + autoregFragment + "RegisteredOidcSecret"] = []byte(clientSecret) | ||
ssoSecret.Data[strings.ToLower(id) + "-clientId"] = []byte(clientId) | ||
ssoSecret.Data[strings.ToLower(id) + "-clientSecret"] = []byte(clientSecret) |
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.
is the clientSecret already base64 encoded at this point? or will it be automatically converted when adding to secret?
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.
kube appears to decode on read and encode on write, so we don't have to.
"github.com/OpenLiberty/open-liberty-operator/pkg/apis/openliberty/v1beta1.ServiceBindingConsumes": schema_pkg_apis_openliberty_v1beta1_ServiceBindingConsumes(ref), | ||
"github.com/OpenLiberty/open-liberty-operator/pkg/apis/openliberty/v1beta1.ServiceBindingProvides": schema_pkg_apis_openliberty_v1beta1_ServiceBindingProvides(ref), | ||
"github.com/OpenLiberty/open-liberty-operator/pkg/apis/openliberty/v1beta1.StatusCondition": schema_pkg_apis_openliberty_v1beta1_StatusCondition(ref), | ||
"github.com/open-liberty-operator/pkg/apis/openliberty/v1beta1.GithubLogin": schema_pkg_apis_openliberty_v1beta1_GithubLogin(ref), |
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.
The path changed for some reason. Likely due to go path setting on your machine.
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.
@brutif Looks good. We can merge this now. Thank you!
* update userguide for auto registration * add registration code * update types * clean up format * propagate error * interim updates * rework route logic * clean up * merge with integration * fix user-guide table * remove commented out code * minor doc clarifications * improve rhsso secret explanation * add liberty cr usage example * move registration results from status to the secret * update for code review comments * add updated crd * remove refs to autoreg secret that is no longer used * adjust registratiton json for IBM Cloud Verify * fix setting env var twice * updates for code review, change client name registered at provider * resolve merge conflict
What this PR does / why we need it?:
Adds ability for oidc sso clients to automatically register with RedHat Single Sign-On
Does this PR introduce a user-facing change? yes
CHANGELOG.md
Which issue(s) this PR fixes:
Addresses kabanero-io/kabanero-security#71