Skip to content

Conversation

@jhadvig
Copy link
Member

@jhadvig jhadvig commented Mar 11, 2020

Story: https://issues.redhat.com/browse/CONSOLE-2036

Will run the generator script by the end of the review.

/assign @benjaminapetersen @spadgett

@openshift-ci-robot openshift-ci-robot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Mar 11, 2020
Host string `json:host:omitempty`
// servingCert references to ConfigMap in the openshift-config namespace that
// contains custom certificate.
ServingCert ConfigMapNameReference `json:servingCert:omitempty`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't really sure about this name, but didn't want to duplicate the custom* prefix in every field...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given it also needs to contain the private key (you can't serve a cert without a private key) shouldn't this reference a secret?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just update the PR with the SecretReference. Thanks !

// customization is used to optionally provide a small set of
// customization options to the web console.
// +optional
Customization ConsoleCustomization `json:"customization,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this as customization really. Maybe route? Something like

spec:
  route:
    hostname: my-hostname
    servingCert: my-secret

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We spoke with @benjaminapetersen that it might be good to follow the patter that we have in our operator config

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mean to bikeshed, but this isn't customization imo. It's basic serving info. I wouldn't think to look there to set these values.

(Technically, any config is a customization I guess, but then it starts to lose meaning.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I like both approaches. Since there already is a Authentication field on the ConsoleSpec I kinda incline to go with:

...
Route   ConsoleRoute   `json:"route,omitempty"`
...

@benjaminapetersen thoughts ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can roll with this. We have Customization on the operator config which contains a URL, but its an override to a default. Agree, this is a different kind of thing.

I'm good with Route { URL, ServingCert } type of struct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/openshift/api/blob/master/config/v1/types_infrastructure.go#L58 for an example of documentation verbiage.

URL is a valid URI with scheme(http/https)....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want just hostname here, not URL. That matches what Route API, and we don't want the user to set a scheme, port, or path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hostname is good, I've been meaning to look up what would be consistent, was thinkging URL isn't quite right.

CustomURL `json:customURL,omitempty`
}

// CustomURL replaces the default console URL under which console will be available.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to make sure we're documenting the default behavior when these values aren't specified.

Host string `json:host:omitempty`
// servingCert references to Secret in the openshift-config namespace that
// contains custom certificate and key.
ServingCert corev1.SecretReference `json:servingCert:omitempty`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably doesn't need to be required. If you pick a hostname that uses the default routing suffix, you shouldn't need to specify a certificate and key.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we document that that's a reasonable thing to do?

// host is the desired custom URL under which console will be available.
Host string `json:host:omitempty`
// servingCert references to Secret in the openshift-config namespace that
// contains custom certificate and key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document the fields in the referenced secret that contain the certificate and key.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spadgett you mean the fields on the Secret itself - tls.crtand tls.key
Or the Name and the Namespace and where they should point to ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the keys in the secret, tls.crt and tls.key. That needs to be documented somewhere, otherwise the user has no way to know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah as the Operator will have to pluck them out by this. Unless we let the user configure the keys, but that seems unnecessary.

@spadgett
Copy link
Member

/cc @bparees

@jhadvig
Copy link
Member Author

jhadvig commented Mar 13, 2020

@spadgett @benjaminapetersen I've update the PR based on your comments

// CustomRoute replaces the default console hostname under which console will be available.
type CustomRoute struct {
// hostname is the desired custom address under which console will be available.
Hostname string `json:hostname`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I wasn't sure if we dont wanna follow the Route naming, which would be Host

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably create ConsoleConfigRoute and do the same as https://github.com/openshift/api/blob/master/imageregistry/v1/types.go#L302. Three fields, include Name. Consistency is good.

Provided we don't go the central config route that is currently being discussed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// ConsoleConfigRoute holds information on external route access to console
type ConsoleConfigRoute struct {
	// name of the route to be created.
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// hostname for the route.
	// +optional
	Hostname string `json:"hostname,omitempty" protobuf:"bytes,2,opt,name=hostname"`
	// secretName points to secret containing the certificates to be used
	// by the route.
	// +optional
	SecretName string `json:"secretName,omitempty" protobuf:"bytes,3,opt,name=secretName"`
}

Authentication ConsoleAuthentication `json:"authentication"`
// route contains hostname and serving certificate for replacing the default hostname,
// under which is console available.
// If not specified, default route will be created by the console-operator.
Copy link
Member Author

@jhadvig jhadvig Mar 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spadgett @benjaminapetersen would be good to align on the default behaviour, that means if we wanna keep the default route or not, when the custom hostname will be specified.
Not sure if it makes sense to have two urls for console, if the custom one is defined.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do want to keep it, for the squatting reason stated before.
It probably doesn't affect this PR, aside from documentation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could update to something like:

If a custom route is specified, a new route will be created with the provided URL.  The default route will be maintained but will no longer access the console.

@deads2k
Copy link
Contributor

deads2k commented Mar 16, 2020

/hold

This approach doesn't seem to address the larger issue of needing to provide custom certificates for all of our components exposed via routes. How about placing this in the ingress config and using an API similar to

type APIServerNamedServingCert struct {
to describe them. The individual operators would then be able to select the name for their route.

We could even rename the struct type for inclusion. The kube-apiserver configuration remains separate because it is externally managed and not necessarily exposed via route.

@ironcladlou I was hoping that network-edge would produce something that could be re-used across all exposed routes, like authentication, console, metrics, etc. Does the approach I sketched sound reasonable?

@openshift-ci-robot openshift-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 16, 2020
@jhadvig
Copy link
Member Author

jhadvig commented Mar 16, 2020

@deads2k wasnt aware the other components are trying to solve this issue.

Which component (besides the apiserver) is dealing with this issue ?

We could even rename the struct type for inclusion

To solve it uniformly would make sense, but not sure how that would fit into our story where besides the ServingCertificate a specific hostname, under which the console will be available, needs to be specified. Not sure if it would make sense to add the hostname to the mantioned APIServerNamedServingCert struct after inclusion.

@benjaminapetersen @spadgett thoughts ?

@deads2k
Copy link
Contributor

deads2k commented Mar 16, 2020

@deads2k wasnt aware the other components are trying to solve this issue.

Everything we expose today with a route has this issue and knows what name its looking for.
This includes authentication, console, downloads (currently owned by console), alertmanager, grafana, prometheus, and thanos.

A solution should resolve certs for these route based endpoints in a unified way. Removing wildcard certs requires resolving all of these.

@bparees
Copy link
Contributor

bparees commented Mar 16, 2020

@deads2k are you suggesting a central location for all external certs, mapped to hostnames, which ingress would automatically configure matching routes to use?

@deads2k
Copy link
Contributor

deads2k commented Mar 16, 2020

@deads2k are you suggesting a central location for all external certs, mapped to hostnames, which ingress would automatically configure matching routes to use?

I think it would go in the other direction. Ingress cannot rewrite the operands, but providing hostname/certificate tuples in a central spot in ingresses.config.openshift.io|spec makes sense since it's a general ingress problem. From there, each individual operand has sufficient information to configure the routes.

@bparees
Copy link
Contributor

bparees commented Mar 16, 2020

followed up with @deads2k on slack. what he's proposing is a central config api for "map these hostnames to these certs".

individual operators would be responsible for looking at that config and deciding what cert, if any, they needed to configure their operand's routes to use.

I think there's a usability/obviousness/risk-of-breakage tradeoff between central config for this vs having an operator fully own the config in its own resource, but i guess fundamentally i'm ok either way. But i'm also worried about the console team getting blocked on this if the central store api isn't finalized+introduced rapidly.

@benjaminapetersen
Copy link
Contributor

It seems like the central list approach is an advantage if components need to share, having them all in one place ensures a uniform API, helps an admin do the right thing.

Would this config have to be named keys, or can it be in a list form? IE, for authentication, console, downloads, alertmanager, grafana, prometheus, and thanos... and foo,bar,baz, can additional items be added w/o PRs to add new keys?

@bparees
Copy link
Contributor

bparees commented Mar 16, 2020

Would this config have to be named keys, or can it be in a list form? IE, for authentication, console, downloads, alertmanager, grafana, prometheus, and thanos... and foo,bar,baz, can additional items be added w/o PRs to add new keys?

i would have guessed it would be a hostname/cert pairing and anyone who wants to create a route for a given hostname could look at the config to see if a cert existed for that hostname, and use it.

Though that seems to present another problem w/ the central config (if i understand the idea correctly) which is that all components are going to have to be able to read all the certs for everything. Just getting the cert isn't sufficient to MITM something, but it's a big step.

@jhadvig
Copy link
Member Author

jhadvig commented Mar 16, 2020

Though that seems to present another problem w/ the central config (if i understand the idea correctly) which is that all components are going to have to be able to read all the certs for everything. Just getting the cert isn't sufficient to MITM something, but it's a big step.

In that case, should the openshift-config namespace be used for the Secrets that will be used for storing the certs ?

Also other question is, who will be responsible for the API changes ? Since this change would have bigger impact, than the one the story Im working on is about.

@deads2k
Copy link
Contributor

deads2k commented Mar 16, 2020

In that case, should the openshift-config namespace be used for the Secrets that will be used for storing the certs ?

Yes.

Also other question is, who will be responsible for the API changes ? Since this change would have bigger impact, than the one the story Im working on is about.

Good APIs can originate from anyone. You probably want to talk with @openshift/sig-network-edge and the other impacted teams

@jhadvig
Copy link
Member Author

jhadvig commented Mar 16, 2020

Good APIs can originate from anyone. You probably want to talk with @openshift/sig-network-edge and the other impacted teams

makes sense

Are there any guesses where the hostname and servingCert will be located ? since I doubt that we will read those from console config (as the current PR suggests)

@ironcladlou
Copy link
Contributor

I must be misunderstanding the proposal because I'm not clear how it impacts ingress operator or the router. It sounds like you're talking about centralizing cert data and making changes to (non-ingress) operators to drive how they create routes and inject cert config into the routes they create.

What specific impact would that have to the ingress operator or ingress controller (router)?

@bparees
Copy link
Contributor

bparees commented Mar 17, 2020

What specific impact would that have to the ingress operator or ingress controller (router)?

i think none, other than you'd own the CRD that contained the central config that @deads2k is proposing. So your operator would probably include the resource yaml for that CRD.

but i'm still interested in the answer to this, also:

Though that seems to present another problem w/ the central config (if i understand the idea correctly) which is that all components are going to have to be able to read all the certs for everything. Just getting the cert isn't sufficient to MITM something, but it's a big step.

@deads2k
Copy link
Contributor

deads2k commented Mar 17, 2020

Though that seems to present another problem w/ the central config (if i understand the idea correctly) which is that all components are going to have to be able to read all the certs for everything. Just getting the cert isn't sufficient to MITM something, but it's a big step.

It doesn't have to be all certs, a cluster-admin could choose to limit the access and operators could watch a named item (server supports this), but at least a couple of these components an already read secret content from openshift-config since it is the canonical source.

My one reservation would be a future move to OLM, but I think that migration would be straightforward

@jhadvig jhadvig changed the title Add CustomURL fields for console Add Route for consoles custom hostname Mar 18, 2020
@jhadvig
Copy link
Member Author

jhadvig commented Mar 19, 2020

/test verify

type ConsoleSpec struct {
// +optional
Authentication ConsoleAuthentication `json:"authentication"`
// route contains hostname and serving certificate for replacing the default hostname,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor tweaks, I'll just inline in your original text:

// route contains hostname and serving certificate for replacing the default route for the console.
// If a custom route is specified, a new route will be created with the provided hostname.
// The default console route will be maintained to reserve the default hostname for console if the custom route is removed.

// If hostname that uses default routing suffix of the given cluster, the
// servignCert specification will not be needed.
// +optional
SecretName string `json:"secretName,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guessing this should really be a SecretNameReference rather than a string.
Not a lot to it:

// SecretNameReference references a secret in a specific namespace.
// The namespace must be specified at the point of use.
type SecretNameReference struct {
	// name is the metadata.name of the referenced secret
	// +kubebuilder:validation:Required
	// +required
	Name string `json:"name"`
}

// The default console route will be maintained to reserve the default hostname for console if the custom route is removed.
// If not specified, default route will be used.
// +optional
Route ConsoleConfigRoute `json:"route,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not in this group. Put it on your operator resource.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason why it can live on the console config ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's more that it shouldn't. this is config that's only consumed by your operator, it's not global config that's consumed by others. (the console operator publishes the public route hostname back to this resource under status, which is global information that's consumed by others, or can be)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our logic has been a custom route is a normal thing a cluster-admin may configure, thus it should exist on the top-level config.

That said, we can move it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How "normal" it is is not the right deciding factor for where it should go, the things l listed above are

// ConsoleConfigRoute holds information on external route access to console.
type ConsoleConfigRoute struct {
// name of the route to be created.
Name string `json:"name"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this configurable

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have been pointed to https://github.com/openshift/api/blob/master/imageregistry/v1/types.go#L304-L314 so wanted to align with what we already use

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to improve on what was done in imageregistry. I don't think we had a good reason to make the route name configurable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can drop the name.
@jhadvig since we likely want to keep the default route (squat on it) in case the custom route is removed, we can just hard code console-custom as name for the new route.

Name string `json:"name"`
// hostname is the desired custom address under which console will be available.
// +optional
Hostname string `json:"hostname,omitempty"`
Copy link
Contributor

@deads2k deads2k Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given a different hostname, couldn't they simply point to your service today and configure an unmanaged route as they wish. This could make your API contract on the service name, but nothing else. No new API and no conflict with resources you manage. What is the value of you having them program this API to program a route instead of simply creating the route?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update our OAuth client with the console callback URL. Also the OAuth server whitelists console URL for kubeadmin logout.

We also use cookies and localStorage. Multiple routes for console could be problematic since the cookies won't be shared.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console also needs to know its own public URL for various reasons (for instance, to build the OAuth callback URL). Maybe we can read the host from the HTTP request, but I'm not sure that's always reliable.

@jhadvig
Copy link
Member Author

jhadvig commented Mar 23, 2020

@spadgett @benjaminapetersen PR updated. PTAL

// Referenced Secret is required to contain following key value pairs:
// - "tls.crt" - to specifies custom certificate
// - "tls.key" - to specifies private key of the custom certificate
// If hostname that uses default routing suffix of the given cluster, the servignCert specification will not be needed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor tweak:
If the custom hostname uses the default routing suffix of the cluster, the Secret specification for a serving cert will not be needed.

@jhadvig jhadvig force-pushed the customURL branch 2 times, most recently from e573d14 to fb1e57d Compare March 24, 2020 11:41
// ConsoleConfigRoute holds information on external route access to console.
type ConsoleConfigRoute struct {
// hostname is the desired custom address under which console will be available.
Hostname string `json:"hostname,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this hostname is not a subdomain of the default ingress domain, seems like the admin would have to manually configure DNS to point at the ingress controller. Maybe I'm misunderstanding something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just update the PR adding notification regarding that case

// for console if the custom route is removed.
// If not specified, default route will be used.
// +optional
Route *ConsoleConfigRoute `json:"route,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if empty strings in this struct are the same as not present (I would expect them to be), then this doesn't need to be a pointer

@jhadvig
Copy link
Member Author

jhadvig commented Mar 26, 2020

@deads2k update the PR. Removed the omitempty form the added field since we are not serializing them.
PTAL

@bparees
Copy link
Contributor

bparees commented Mar 31, 2020

/lgtm

@bparees
Copy link
Contributor

bparees commented Mar 31, 2020

/hold cancel

@openshift-ci-robot openshift-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 31, 2020
@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Mar 31, 2020
@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bparees, jhadvig

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 31, 2020
@openshift-merge-robot openshift-merge-robot merged commit 585af27 into openshift:master Mar 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants