Skip to content

Add OIDC to bootstrap CLI #3399

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

Merged
merged 235 commits into from
Oct 26, 2023
Merged

Add OIDC to bootstrap CLI #3399

merged 235 commits into from
Oct 26, 2023

Conversation

Samra10
Copy link
Member

@Samra10 Samra10 commented Sep 25, 2023

Closes #3275

What changed?

  • Add bootstrap command for gitops bootstrap to add OIDC configs

Why was this change made?

  • To help the user to configure OIDC settings after WGE installation

How was this change implemented?

How did you validate the change?

  • Manual testing
  • Unit tests

How to test: #3399 (comment)

Release notes

Documentation Changes

Other follow ups

@waleedhammam waleedhammam requested a review from enekofb October 22, 2023 08:34
Copy link
Contributor

@enekofb enekofb left a comment

Choose a reason for hiding this comment

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

if feels that we are closer here. I have added some more comments on the code.

I would like to test it to understand the user experience. However, i could not find indications in the PR on how to do that (please see here https://github.com/weaveworks/weave-gitops-enterprise/blob/main/.github/pull_request_template.md?plain=1#L36)

I could not see higher level testing for the scenario of bootstrapping wge with oidc as flow nor as a single. please let me know your expectations here.

Regarding testing: please, let me know how should i verify that it works and the strategy for having automated testing for both bootstrap command and bootstrap auth. i could not find them in the PR.

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

given that you are configuring oidc, i think that you dont need passing steps.AuthOIDC,

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

given that you are passing flags.discoveryURL let me know why PromptedForDiscoveryURL is required?

Copy link
Contributor

Choose a reason for hiding this comment

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

PromptedForDiscoveryURL is to differentiate for the step method where it's called, from the separate command or from within the setup flow. it's responsibe for asking Do you want to setup OIDC to access Weave GitOps Dashboard

if err != nil {
return []StepOutput{}, err
}
c.Logger.Actionf("retrieved issure url: %s", issuerUrl)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
c.Logger.Actionf("retrieved issure url: %s", issuerUrl)
c.Logger.Actionf("retrieved issuer url: %s", issuerUrl)

c.IssuerURL = issuerUrl

if c.DomainType == domainTypeLocalhost {
c.RedirectURL = "http://localhost:8000/oauth2/callback"
Copy link
Contributor

Choose a reason for hiding this comment

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

what would happen if we are exposing SSL server on 8000 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

the localhost installation is only HTTP, otherwise it'll require setting up local certificate and a lot of things could go wrong here

if c.DomainType == domainTypeLocalhost {
c.RedirectURL = "http://localhost:8000/oauth2/callback"
} else {
c.RedirectURL = fmt.Sprintf("https://%s/oauth2/callback", c.UserDomain)
Copy link
Contributor

Choose a reason for hiding this comment

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

what about if the user exposes non https domain?

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 for majority of users exposing https is a must ?, what do you think ?

return []StepOutput{}, err
}
c.Logger.Actionf("rendered HelmRelease file")
c.Logger.Successf(oidcConfirmationMsg)
Copy link
Contributor

Choose a reason for hiding this comment

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

c.Logger.Successf(oidcConfirmationMsg) given this message if I was a user, I would understand that oidc is ready to use at this stage but actually will be after the reconciliation happens, correct? if that is the case, we could revisit this msg

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Member Author

@Samra10 Samra10 Oct 24, 2023

Choose a reason for hiding this comment

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

OIDC can be tested by using the following parameters:-

bootstrap  --discovery-url https://dex-01.wge.dev.weave.works/.well-known/openid-configu0ration --client-id weave-gitops-enterprise
  • These configs are configured on WW dex setup here
  • We have added two redirect URLs under weave-gitops-enterprise static-client, one to be used if we choose the domain type to be local here and another if external DNS has been chosen here, so if you need to test with a different external DNS you need to add it under one of the static-clients.

cc: @enekofb @waleedhammam

Copy link
Contributor

Choose a reason for hiding this comment

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

adding this to the PR description

Copy link
Contributor

Choose a reason for hiding this comment

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

removed client-secret from the description to do not leak it

Copy link
Contributor

Choose a reason for hiding this comment

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

Acceptance scenarios based on the configuration

scenarios: happy path without previous

  • As user without existing oidc, I could setup odic with valid arguments via interactive session
  • As user without existing oidc, I could setup odic with valid arguments via non-interactive flags

scenarios: happy path with previous oidc configuration

  • As user with existing oidc, I could overwrite odic with valid arguments via interactive session
  • As user with existing oidc, I could overwrite odic with valid arguments via non-interactive session

scenarios: happy path with previous oidc configuration

  • As user with existing oidc, I could reuse odic via interactive session
  • As user with existing oidc, I could reuse odic via non-interactive session

scenarios: unhappy path

  • As user with existing oidc, I could not setup odic with invalid arguments via interactive session
  • As user with existing oidc, I could not setup odic with invalid arguments via non-interactive session

Copy link
Contributor

Choose a reason for hiding this comment

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

Testing Scenario:

As user without existing oidc, I could setup odic with valid arguments via non-interactive flags
Run with the following args

cmd_acceptance_test.go:152: "level"=0 "msg"="execute cmd" "args"=["bootstrap","--kubeconfig=/var/folders/9b/bkrspzws5xgd7x_ldtc880pr0000gn/T/kubeconfig1556281884","--version=0.33.0","--private-key=/Users/enekofb/.ssh/id_ed25519","--private-key-password=""","--username=admin","--password=admin123","--domain-type=localhost","--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configu0ration --client-id=weave-gitops-enterprise --client-secret="]

and got the following output

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
? Do you want to setup OIDC to access Weave GitOps Dashboards? [y/N] █

✗ Please enter OIDC clientID: █

    cmd_acceptance_test.go:159: 
        Expected
            <*errors.errorString | 0x14000c63510>: 
            cannot execute bootstrap: cannot process input 'OIDC Configuration': ^D
            {
                s: "cannot execute bootstrap: cannot process input 'OIDC Configuration': ^D",
            }
        to be nil
    cmd_acceptance_test.go:260: "level"=0 "msg"="deleted object" "name"="weave-gitops-enterprise-credentials" "ns"="flux-system" "kind"="Secret"
    cmd_acceptance_test.go:260: "level"=0 "msg"="deleted object" "name"="cluster-user-auth" "ns"="flux-system" "kind"="Secret"

Copy link
Contributor

Choose a reason for hiding this comment

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

Testing Scenario: As user without existing oidc, I could setup odic with valid arguments via interactive session

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
Do you want to setup OIDC to access Weave GitOps Dashboards: y
Please enter OIDC clientSecret: ******************************
► retrieved issuer url: https://dex-01.wge.dev.weave.works
► setting redirect url: http://localhost:8000/oauth2/callback
◎ Configuring OIDC
► configuring oidc values
► rendered HelmRelease file
✔ OIDC has been configured successfully! It will be ready to use after reconcillation
► updating HelmRelease file
► creating secret: flux-system/oidc-auth
✔ created secret flux-system/oidc-auth
► write file to repo: wge-hrelease.yaml
► cloning flux git repo: flux-system/flux-system
✔ cloned flux git repo: flux-system/flux-system
✔ file committed to repo: wge-hrelease.yaml
◎ reconciling changes
✔ changes are reconciled successfully!
◎ preparing dashboard domain
✔ WGE v0.33.0 is installed successfully. To access the dashboard, run the following command to create portforward to the dasboard local domain http://localhost:8000
kubectl -n flux-system port-forward svc/clusters-service 8000:8000

after that i could login:

Screenshot 2023-10-25 at 09 17 20

but could not see anything:

Screenshot 2023-10-25 at 09 17 35

Copy link
Contributor

Choose a reason for hiding this comment

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

scenarios: happy path with previous oidc configuration

As user with existing oidc, I could overwrite odic with valid arguments via interactive session

does not finish with both yes

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
Do you want to setup OIDC to access Weave GitOps Dashboards: y
◎ preparing dashboard domain

does not finish with yes/no-selection

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
? Do you want to setup OIDC to access Weave GitOps Dashboards? [y/N] █
◎ preparing dashboard domain

it finishes with yes and no

✔ file committed to repo: wge-hrelease.yaml
◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
✗ Do you want to setup OIDC to access Weave GitOps Dashboards:
◎ preparing dashboard domain
✔ WGE v0.33.0 is installed successfully. To access the dashboard, run the following command to create portforward to the dasboard local domain http://localhost:8000
kubectl -n flux-system port-forward svc/clusters-service 8000:8000
➜

As user with existing oidc, I could overwrite odic with valid arguments via non-interactive session

we cannot

✔ selected version 0.33.0
◎ user authentication
⚠️ admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system', then try again
do you want to continue using existing credentials: y
◎ dashboard access

@waleedhammam waleedhammam requested a review from enekofb October 24, 2023 12:41
Copy link
Contributor

@enekofb enekofb left a comment

Choose a reason for hiding this comment

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

tested the journeys here: lets discuss it with our session

to add:

  • support for oidc with acceptance test started here

to follow up:


func OIDCConfigStep(config Config) BootstrapStep {

inputs := []StepInput{
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 is the case

in case of non-interactive. he should see that anyway

it breaks the contract, a non-interactive user wont be able to use it.

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

Acceptance scenarios based on the configuration

scenarios: happy path without previous

  • As user without existing oidc, I could setup odic with valid arguments via interactive session
  • As user without existing oidc, I could setup odic with valid arguments via non-interactive flags

scenarios: happy path with previous oidc configuration

  • As user with existing oidc, I could overwrite odic with valid arguments via interactive session
  • As user with existing oidc, I could overwrite odic with valid arguments via non-interactive session

scenarios: happy path with previous oidc configuration

  • As user with existing oidc, I could reuse odic via interactive session
  • As user with existing oidc, I could reuse odic via non-interactive session

scenarios: unhappy path

  • As user with existing oidc, I could not setup odic with invalid arguments via interactive session
  • As user with existing oidc, I could not setup odic with invalid arguments via non-interactive session

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

Testing Scenario:

As user without existing oidc, I could setup odic with valid arguments via non-interactive flags
Run with the following args

cmd_acceptance_test.go:152: "level"=0 "msg"="execute cmd" "args"=["bootstrap","--kubeconfig=/var/folders/9b/bkrspzws5xgd7x_ldtc880pr0000gn/T/kubeconfig1556281884","--version=0.33.0","--private-key=/Users/enekofb/.ssh/id_ed25519","--private-key-password=""","--username=admin","--password=admin123","--domain-type=localhost","--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configu0ration --client-id=weave-gitops-enterprise --client-secret="]

and got the following output

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
? Do you want to setup OIDC to access Weave GitOps Dashboards? [y/N] █

✗ Please enter OIDC clientID: █

    cmd_acceptance_test.go:159: 
        Expected
            <*errors.errorString | 0x14000c63510>: 
            cannot execute bootstrap: cannot process input 'OIDC Configuration': ^D
            {
                s: "cannot execute bootstrap: cannot process input 'OIDC Configuration': ^D",
            }
        to be nil
    cmd_acceptance_test.go:260: "level"=0 "msg"="deleted object" "name"="weave-gitops-enterprise-credentials" "ns"="flux-system" "kind"="Secret"
    cmd_acceptance_test.go:260: "level"=0 "msg"="deleted object" "name"="cluster-user-auth" "ns"="flux-system" "kind"="Secret"

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

Testing Scenario: As user without existing oidc, I could setup odic with valid arguments via interactive session

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
Do you want to setup OIDC to access Weave GitOps Dashboards: y
Please enter OIDC clientSecret: ******************************
► retrieved issuer url: https://dex-01.wge.dev.weave.works
► setting redirect url: http://localhost:8000/oauth2/callback
◎ Configuring OIDC
► configuring oidc values
► rendered HelmRelease file
✔ OIDC has been configured successfully! It will be ready to use after reconcillation
► updating HelmRelease file
► creating secret: flux-system/oidc-auth
✔ created secret flux-system/oidc-auth
► write file to repo: wge-hrelease.yaml
► cloning flux git repo: flux-system/flux-system
✔ cloned flux git repo: flux-system/flux-system
✔ file committed to repo: wge-hrelease.yaml
◎ reconciling changes
✔ changes are reconciled successfully!
◎ preparing dashboard domain
✔ WGE v0.33.0 is installed successfully. To access the dashboard, run the following command to create portforward to the dasboard local domain http://localhost:8000
kubectl -n flux-system port-forward svc/clusters-service 8000:8000

after that i could login:

Screenshot 2023-10-25 at 09 17 20

but could not see anything:

Screenshot 2023-10-25 at 09 17 35

WithVersion(flags.version).
WithDomainType(flags.domainType).
WithDomain(flags.domain).
WithPrivateKey(flags.privateKeyPath, flags.privateKeyPassword).
WithOIDCConfig(steps.AuthOIDC, flags.discoveryURL, flags.clientID, flags.clientSecret, true).
Copy link
Contributor

Choose a reason for hiding this comment

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

scenarios: happy path with previous oidc configuration

As user with existing oidc, I could overwrite odic with valid arguments via interactive session

does not finish with both yes

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
Do you want to setup OIDC to access Weave GitOps Dashboards: y
◎ preparing dashboard domain

does not finish with yes/no-selection

◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
? Do you want to setup OIDC to access Weave GitOps Dashboards? [y/N] █
◎ preparing dashboard domain

it finishes with yes and no

✔ file committed to repo: wge-hrelease.yaml
◎ reconciling changes
✔ changes are reconciled successfully!
◎ OIDC Configuration
⚠️ OIDC is already configured on the cluster. To reset configurations please remove secret 'oidc-auth' in namespace 'flux-system' and run 'bootstrap auth --type=oidc' command again
Do you want to continue using existing OIDC configurations: y
✗ Do you want to setup OIDC to access Weave GitOps Dashboards:
◎ preparing dashboard domain
✔ WGE v0.33.0 is installed successfully. To access the dashboard, run the following command to create portforward to the dasboard local domain http://localhost:8000
kubectl -n flux-system port-forward svc/clusters-service 8000:8000
➜

As user with existing oidc, I could overwrite odic with valid arguments via non-interactive session

we cannot

✔ selected version 0.33.0
◎ user authentication
⚠️ admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system', then try again
do you want to continue using existing credentials: y
◎ dashboard access

@waleedhammam
Copy link
Contributor

fixed the OIDC prompt
start using default flag for continue with existing data shall be in the followup

@waleedhammam waleedhammam requested a review from enekofb October 25, 2023 12:10
Copy link
Contributor

@enekofb enekofb left a comment

Choose a reason for hiding this comment

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

🚀

Followups

@@ -97,6 +112,18 @@ func (c *ConfigBuilder) WithPrivateKey(privateKeyPath string, privateKeyPassword
return c
}

func (c *ConfigBuilder) WithOIDCConfig(discoveryURL string, clientID string, clientSecret string, prompted bool) *ConfigBuilder {
Copy link
Contributor

Choose a reason for hiding this comment

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

followup: add testing for this logic as we setup expectations that if arguments are passed means that we want to install oidc which is an implicit contract

@@ -97,6 +112,18 @@ func (c *ConfigBuilder) WithPrivateKey(privateKeyPath string, privateKeyPassword
return c
}

func (c *ConfigBuilder) WithOIDCConfig(discoveryURL string, clientID string, clientSecret string, prompted bool) *ConfigBuilder {
c.authType = AuthOIDC
Copy link
Contributor

Choose a reason for hiding this comment

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

followup: add this as argument

@enekofb enekofb dismissed waleedhammam’s stale review October 26, 2023 11:07

no longer relevant

@waleedhammam waleedhammam merged commit 6912a53 into main Oct 26, 2023
@waleedhammam waleedhammam deleted the oidc-flow-update branch October 26, 2023 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Onboarding CLI | Implement OIDC setup
4 participants