Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Add ability to provide oidc configuration #182

Merged
merged 7 commits into from
May 27, 2020

Conversation

invidian
Copy link
Member

@invidian invidian commented Mar 17, 2020

This PR adds the ability to provide oidc configuration for Lokomotive supported platforms in the form of oidc block inside the cluster block of Lokomotive configuration.

This feature can then be used to remove the manual step of adding extra flags to apiserver when configuring dex and gangway and also the manual changes were not persistent during cluster upgrade.

Closes #279

Signed-off-by: Mateusz Gozdek mateusz@kinvolk.io
Signed-off-by: Imran Pochi imran@kinvolk.io

TODO:

  • Add some tests? I was thinking about adding following snippet to CI configuration for smoke tests:
    kube_apiserver_extra_flags = [
      "-v=1",
    ]
    

UPDATE - Removed the kube_apiserver_extra_flags from tests as mentioned above since we are exposing oidc block. I have added an empty oidc block in ci configuration so that apiserver starts with oidc configured with default values.

TODO:

  • Add an http test to the dex/gangway endpoint to see if the endpoints are returning HTTP 200 status

Signed-off-by: Mateusz Gozdek mateusz@kinvolk.io
Signed-off-by: Imran Pochi imran@kinvolk.io

Copy link
Contributor

@iaguis iaguis left a comment

Choose a reason for hiding this comment

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

Small nits. I think adding a smoke test like described makes sense.

pkg/platform/aws/aws.go Outdated Show resolved Hide resolved
pkg/platform/baremetal/baremetal.go Outdated Show resolved Hide resolved
@invidian invidian force-pushed the invidian/kube-apiserver-extra-flags branch from be060ea to 363cf28 Compare March 17, 2020 18:28
@invidian invidian requested a review from pothos as a code owner March 17, 2020 18:28
@invidian
Copy link
Member Author

Small nits. I think adding a smoke test like described makes sense.

All right, added then.

iaguis
iaguis previously approved these changes Mar 17, 2020
Copy link
Contributor

@iaguis iaguis left a comment

Choose a reason for hiding this comment

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

lgtm if it works.

@invidian invidian requested review from ipochi and rata March 17, 2020 20:08
@invidian
Copy link
Member Author

Pulled some additional reviewers for one more approval before merging.

@surajssd
Copy link
Member

@invidian Why not expose the variables needed for dex, rather than allowing user to specify any apiserver flag? Are there any unforeseen issues with being so much flexible?

Here I don't feel there is a lot of control over what is allowed and what is not. If you look at the hosted K8s providers they have control over what is allowed and what is not.

@invidian
Copy link
Member Author

@surajssd we discussed that in original issue #122. TL;DR this is the simplest approach for now and we want to ship it with 0.1.0 release.

@surajssd
Copy link
Member

I see. But IMHO adding things is easier vs removing them/changing them in backwards incompatible way. So I still think adding specific dex related flags/parameters is the right way to go!

@iaguis
Copy link
Contributor

iaguis commented Mar 18, 2020

I think @surajssd has a point here, if we add freeform extra flags we might create a support burden, increase the feature matrix and expose the user to unnecessary complexity. This is Typhoon's reasoning.

OTOH projects like kubeadm do offer this kind of flexibility, but one can argue that they're a "building block" technology and need to be more flexible for that reason.

After thinking about it, maybe our best option for now is allowing extra flags but doing some validation them so we only support the ones we need and error out if others are passed. In this way we restrict what's possible, we don't need to change the implementation too much, and we don't expose tons of flags which be confusing. If in the future we support automatic generation of OIDC parameters for dex+gangway we can just tell users to remove the snippet, if we move to separate OIDC parameters we can tell them to switch to those.

I'd like to get some more opinions though.

@invidian
Copy link
Member Author

I like the following approach, as it gives user freedom for adding any kind of parameters they need, which would be super useful in cases, where we don't have dedicated parameter for some flags. I do agree, that we shouldn't support setups, which use this flag, as user can put anything in there. Perhaps we could document, that one should use it at their own risk?

After thinking about it, maybe our best option for now is allowing extra flags but doing some validation them so we only support the ones we need and error out if others are passed.

That doesn't seem right to me. I'd rather change the implementation to only accept data we need then.

@ipochi
Copy link
Member

ipochi commented Mar 18, 2020

I too agree with Suraj here that we should be careful what with we add just because its the easiest step right now.

Can we not put the oidc related flags as optional fields in the cluster configuration ?

@invidian invidian force-pushed the invidian/kube-apiserver-extra-flags branch from 363cf28 to af9f0c2 Compare March 18, 2020 12:14
@rata
Copy link
Member

rata commented Mar 18, 2020

I mostly agree with @invidian here, specially on this: if we are going to allow only some things (like validate only some flags are exposed), let's expose them nicely instead of that very hacky approach (and probably more complex because of checking that those strings are what we "allow").

Regarding what @surajssd mentions about managed service having that kind of control, I want to add THAT is one of the biggest complains for managed services: users can't add flags (for auth and others). And this is not a managed service, so why not allow the user to take the risks he wants? (I don't have a source for this, just my mem from mailing list and reddit).

I think in general there are two approaches for this: "abstract" as much as possible for the users and provide a nice and clean interface, doing kind of a "whitelist" of params user can tune, or abstract some things but allow any random flags they want to use.

Envoy is quite complex, so for example contour is only exposing very simple things and it hides the envoy complexity. That has the overhead of every single change needs to be properly integrated and is blocked until it is. And the positive thing that everything you configure is properly integrated in contour (like in it's CRD).

While nice, I'm not sure the trade-off is good for kubernetes. Specially if you think in alpha features: kubernetes is constantly adding them, for example. You are already managing your cluster, why wouldn't you be able to enable an alpha feature you may benefit from? An alpha feature I guess some will need is IPv4/IPv6 dual-stack. Or a feature we currently don't support but needs api flag is Kubernetes Auditing. I don't think we want to prevent people from using them, though.

As long as this doesn't expand our test matrix and we warn the user that it may cause instability and, even if we want say it is not supported (like, open a bug report only if you can reproduce without that)... I don't see why not do it. I see the Typhoon decision against this: "can create reliance on alpha features/behaviors that get canned, and can cause instability that lowers the quality bar". Maybe we can reconsider if it causes lot of bug reports?

Also, in my experience when using kubernetes, I really needed to change flags some times. There was a bug in the linux kernel for CFS and another in Kubernetes in the way that configured CPU limits, that made latency sensitive apps impossible to run and one of the ways to make it work (this bug took more than an year to be solved in k8s) was adding a flag to the kubelet. Hopefully, in kops I couls specify that flag very easily (in the yaml) for compoenents, it would have been a deal breaker in that case that kops didn't allow that. So, IMHO, I'd even go further and suggest to consider adding an extra_flags params to all k8s components in the future (another discussion for another time :)).

Kubernetes has TON of features, and even more flags... I don't think we plan to provide a nice interface for ALL of them (and it expands quite fast). And one of the biggest disadvantage of managed services I've read people complain is the restriction to control flags (again, no sources, just what I've read in mailing list and reddit). Therefore, I lean towards allowing users to take risk, by having a "extra_flags" param, and warn that is not supported/tainted or something.

What do others think?

rata
rata previously approved these changes Mar 18, 2020
Copy link
Member

@rata rata left a comment

Choose a reason for hiding this comment

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

Code-wise, LGTM (we definitely need that refactor!). Some small comments/questions.

Of course, let's wait to agree/disagree on the general approach for merge/close the PR.

Thanks in any case @invidian for the PR! :)

@invidian invidian force-pushed the invidian/kube-apiserver-extra-flags branch 2 times, most recently from 2c2bd03 to bd5fe0b Compare March 19, 2020 08:12
@invidian
Copy link
Member Author

If we decide to expose only parameters required for OIDC, which parameters should we expose exactly? Just 'issuer URL' or all of them? And if so, how do we expose them? as oidc_issuer_url parameter? Or maybe it would be better to use a block:

oidc {
  issuer_url = ...
}

Then, if we use block, should we put it in inside cluster block, or maybe move towards more generic solution and put it in root config, so it's platform-agnostic then (as suggested in #123.

I think Terraform implementation can stay generic as it is right now. We only need to change user-facing interface.

@ipochi
Copy link
Member

ipochi commented Mar 20, 2020

If we decide to expose only parameters required for OIDC, which parameters should we expose exactly? Just 'issuer URL' or all of them? And if so, how do we expose them? as oidc_issuer_url parameter? Or maybe it would be better to use a block:

oidc {
  issuer_url = ...
}

Then, if we use block, should we put it in inside cluster block, or maybe move towards more generic solution and put it in root config, so it's platform-agnostic then (as suggested in #123.

I think Terraform implementation can stay generic as it is right now. We only need to change user-facing interface.

oidc block seems like a reasonable tradeoff between not giving user an option to pass all sorts of api server flags and lokomotive controlling what flags can be provided.

@invidian
Copy link
Member Author

oidc block seems like a reasonable tradeoff between not giving user an option to pass all sorts of api server flags and lokomotive controlling what flags can be provided.

And which parameters should be exposed then via the block? All of them or only issuer_url?

@rata
Copy link
Member

rata commented Mar 20, 2020

IMHO, all of them. We can't force users to use this auth method or nothing. If we want to expose those, we should expose them all so they can configure other OIDC providers.

And use sensible defaults (like for the other params use the values we will use for our auth by default) for the others, IMHO.

We have an interface that for users using the component is as easy as possible, but with flexibility for other params to be tuned if users don't want this auth.

Does it make sense?

@invidian
Copy link
Member Author

Does it make sense?

Yes, thanks.

Then, do you think I can implement it in the following way:

cluster "packet" {
  ...
}

oidc {
  issuer_url = "..."
}

I would like to start build more reusable blocks and not duplicate the parameters across platforms.

@rata
Copy link
Member

rata commented Mar 20, 2020

Duplication can be a little bit reduced by using a embedding a common struct in the platform struct, and reusing parsing functions, probably. But there will be some boilerplate code per platform.

I think this impacts on how syntax will be for multi-cluster. But, trying to be pragmatic, I think we are already doing this with other fields (at least backend) and as long as we don't add many more, it should be easy to move them back into cluster config if we decide that is the path (not sure).

So, IMHO, both options are fine. The big warning for embedding in cluster block would be to not duplicate all code (i.e. using common structs and parsing functions, if the end code is not a PITA to work with or some other smarter trick. I don't know, maybe in any case there is too much boilerplate?).

@ipochi ipochi force-pushed the invidian/kube-apiserver-extra-flags branch 2 times, most recently from a3e5b5e to 8d74b26 Compare May 22, 2020 10:57
iaguis
iaguis previously requested changes May 25, 2020
Copy link
Contributor

@iaguis iaguis left a comment

Choose a reason for hiding this comment

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

One issue I found during testing.

pkg/oidc/oidc.go Outdated Show resolved Hide resolved
@ipochi ipochi force-pushed the invidian/kube-apiserver-extra-flags branch from 8d74b26 to 5681bf8 Compare May 26, 2020 05:33
@ipochi ipochi requested a review from iaguis May 26, 2020 06:44
@ipochi ipochi dismissed iaguis’s stale review May 26, 2020 09:34

Fixed. Please re-review.

iaguis
iaguis previously approved these changes May 26, 2020
Copy link
Contributor

@iaguis iaguis left a comment

Choose a reason for hiding this comment

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

LGTM

ipochi
ipochi previously approved these changes May 26, 2020
Copy link
Member

@ipochi ipochi left a comment

Choose a reason for hiding this comment

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

Approving. Since the policy is for two approvers. I cannot merge despite being the second person to approve as I am the co-author.

@ipochi ipochi requested a review from rata May 26, 2020 09:55
Copy link
Member

@surajssd surajssd left a comment

Choose a reason for hiding this comment

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

Few nits otherwise LGTM.

pkg/oidc/oidc.go Show resolved Hide resolved
@@ -105,6 +107,10 @@ func NewConfig() *config {
}
}

func (c *config) clusterDomain() string {
return fmt.Sprintf("%s.%s", c.ClusterName, c.DNSZone)
Copy link
Member

Choose a reason for hiding this comment

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

Does this not take into account the variable cluster_domain_suffix? What if user provides some other cluster_domain_suffix?

Correct me if I am wrong, I am just trying to identify potential discrepancy between variables.

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 think cluster_domain_suffix is needed here

@invidian

Copy link
Member Author

Choose a reason for hiding this comment

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

cluster_domain_suffix is for cluster internal DNS, no?

Copy link
Member

Choose a reason for hiding this comment

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

yes.

docs/how-to-guides/authentication-with-dex-gangway.md Outdated Show resolved Hide resolved
@ipochi ipochi dismissed stale reviews from iaguis and themself via 86dd93e May 26, 2020 12:21
@ipochi ipochi force-pushed the invidian/kube-apiserver-extra-flags branch from 5681bf8 to 86dd93e Compare May 26, 2020 12:21
@ipochi ipochi requested a review from surajssd May 26, 2020 12:21
@ipochi ipochi force-pushed the invidian/kube-apiserver-extra-flags branch 2 times, most recently from 560af76 to 84ebae9 Compare May 26, 2020 13:47
invidian and others added 7 commits May 27, 2020 10:30
This commit adds an ability to provide extra flags for self-hosted
kube-apiserver, so this feature can be used when configuring dex and
gangway for OIDC authentication to the cluster, as currently any manual
changes to kube-apiserver pods will be overwritten during cluster
upgrade.

Update generated-assets.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>

Signed-off-by: Imran Pochi <imran@kinvolk.io>
With 'terraform fmt'.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
- To configure an OIDC based authentication for Lokomotive, oidc block
  is added to the Lokomotive configuration.

  Currently 4 fields are added as part of the oidc block with defaults
    - issuer_url (default is "https://dex.<CLUSTER_DOMAIN>")
    - client_id (default is "gangway")
    - username_claim (default is "email")
    - groups_claim (default is "groups")

  `ConfigureOIDCFlags` sets the defaults if not provided by user and returns
  the list of flags that should be appened to the Kubernetes API Server
  extra flags (KubeAPIServerExtraFlags)

  `Validate` validates on two conditions:
    - issuer_url is a valid url
    - url scheme is https.

Signed-off-by: Imran Pochi <imran@kinvolk.io>
- Add `oidc` block to aws cluster config for configuring oidc based
  authentication on aws.

- configures the KubeAPIServerExtraFlags that needs to be configured, in
  this case we need to configure the oidc block and add oidc related flags
  to KubeAPIServerExtraFlags.

- configure the oidc block, only if present in the configuration.

- Update documentation regarding same.

- Update ci configuration to make use of the same.

- Update example configuration for production use.

Signed-off-by: Imran Pochi <imran@kinvolk.io>
- Add `oidc` block to packet cluster config for configuring oidc based
  authentication on packet.

- configures the KubeAPIServerExtraFlags that needs to be configured, in
  this case we need to configure the oidc block and add oidc related flags
  to KubeAPIServerExtraFlags.

- configure the oidc block, only if present in the configuration.

- Update documentation regarding same.

- Update ci configuration(packet and packet-arm) to make use of the same.

- Update example configuration for production use.

Signed-off-by: Imran Pochi <imran@kinvolk.io>
- Add `oidc` block to baremetal cluster config for configuring oidc based
  authentication on baremetal.

- Enables validation of the configuration with `checkValidConfig`.

- configures the KubeAPIServerExtraFlags that needs to be configured, in
  this case we need to configure the oidc block and add oidc related flags
  to KubeAPIServerExtraFlags.

- configure the oidc block, only if present in the configuration.

- Update documentation regarding same.

- Update ci configuration to make use of the same.

Signed-off-by: Imran Pochi <imran@kinvolk.io>
- Update how-to guide with oidc block configuration.

Signed-off-by: Imran Pochi <imran@kinvolk.io>
@ipochi ipochi force-pushed the invidian/kube-apiserver-extra-flags branch from 84ebae9 to a728b1a Compare May 27, 2020 05:00
@ipochi
Copy link
Member

ipochi commented May 27, 2020

@surajssd please re-review.

Copy link
Contributor

@iaguis iaguis left a comment

Choose a reason for hiding this comment

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

lgtm

@ipochi ipochi merged commit b671bcb into master May 27, 2020
@ipochi ipochi deleted the invidian/kube-apiserver-extra-flags branch May 27, 2020 11:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose OIDC parameters
5 participants