Add initial CLI integration test for OIDC login.
This is our first test using a real browser to interact with an upstream provider. Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
8a16a92c01
commit
50d80489be
2
go.mod
2
go.mod
@ -4,6 +4,7 @@ go 1.14
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/MakeNowJust/heredoc/v2 v2.0.1
|
github.com/MakeNowJust/heredoc/v2 v2.0.1
|
||||||
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
@ -13,6 +14,7 @@ require (
|
|||||||
github.com/golangci/golangci-lint v1.31.0
|
github.com/golangci/golangci-lint v1.31.0
|
||||||
github.com/google/go-cmp v0.5.2
|
github.com/google/go-cmp v0.5.2
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
||||||
|
github.com/sclevine/agouti v3.0.0+incompatible
|
||||||
github.com/sclevine/spec v1.4.0
|
github.com/sclevine/spec v1.4.0
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
|
3
go.sum
3
go.sum
@ -71,6 +71,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
|
|||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
|
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
|
||||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
|
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||||
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bombsimon/wsl/v3 v3.1.0 h1:E5SRssoBgtVFPcYWUOFJEcgaySgdtTNYzsSKDOY7ss8=
|
github.com/bombsimon/wsl/v3 v3.1.0 h1:E5SRssoBgtVFPcYWUOFJEcgaySgdtTNYzsSKDOY7ss8=
|
||||||
github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
@ -498,6 +500,7 @@ github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUcc
|
|||||||
github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
|
github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
|
||||||
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
|
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/sclevine/agouti v3.0.0+incompatible h1:8IBJS6PWz3uTlMP3YBIR5f+KAldcGuOeFkFbUWfBgK4=
|
||||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||||
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
||||||
|
@ -3,15 +3,25 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sclevine/agouti"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/library"
|
||||||
)
|
)
|
||||||
@ -26,8 +36,7 @@ func TestCLIGetKubeconfig(t *testing.T) {
|
|||||||
idp := library.CreateTestWebhookIDP(ctx, t)
|
idp := library.CreateTestWebhookIDP(ctx, t)
|
||||||
|
|
||||||
// Build pinniped CLI.
|
// Build pinniped CLI.
|
||||||
pinnipedExe, cleanupFunc := buildPinnipedCLI(t)
|
pinnipedExe := buildPinnipedCLI(t)
|
||||||
defer cleanupFunc()
|
|
||||||
|
|
||||||
// Run pinniped CLI to get kubeconfig.
|
// Run pinniped CLI to get kubeconfig.
|
||||||
kubeConfigYAML := runPinnipedCLIGetKubeconfig(t, pinnipedExe, env.TestUser.Token, env.ConciergeNamespace, "webhook", idp.Name)
|
kubeConfigYAML := runPinnipedCLIGetKubeconfig(t, pinnipedExe, env.TestUser.Token, env.ConciergeNamespace, "webhook", idp.Name)
|
||||||
@ -58,11 +67,12 @@ func TestCLIGetKubeconfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPinnipedCLI(t *testing.T) (string, func()) {
|
func buildPinnipedCLI(t *testing.T) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
pinnipedExeDir, err := ioutil.TempDir("", "pinniped-cli-test-*")
|
pinnipedExeDir, err := ioutil.TempDir("", "pinniped-cli-test-*")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() { require.NoError(t, os.RemoveAll(pinnipedExeDir)) })
|
||||||
|
|
||||||
pinnipedExe := filepath.Join(pinnipedExeDir, "pinniped")
|
pinnipedExe := filepath.Join(pinnipedExeDir, "pinniped")
|
||||||
output, err := exec.Command(
|
output, err := exec.Command(
|
||||||
@ -73,10 +83,7 @@ func buildPinnipedCLI(t *testing.T) (string, func()) {
|
|||||||
"go.pinniped.dev/cmd/pinniped",
|
"go.pinniped.dev/cmd/pinniped",
|
||||||
).CombinedOutput()
|
).CombinedOutput()
|
||||||
require.NoError(t, err, string(output))
|
require.NoError(t, err, string(output))
|
||||||
|
return pinnipedExe
|
||||||
return pinnipedExe, func() {
|
|
||||||
require.NoError(t, os.RemoveAll(pinnipedExeDir))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPinnipedCLIGetKubeconfig(t *testing.T, pinnipedExe, token, namespaceName, idpType, idpName string) string {
|
func runPinnipedCLIGetKubeconfig(t *testing.T, pinnipedExe, token, namespaceName, idpType, idpName string) string {
|
||||||
@ -94,3 +101,180 @@ func runPinnipedCLIGetKubeconfig(t *testing.T, pinnipedExe, token, namespaceName
|
|||||||
|
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCLILoginOIDC(t *testing.T) {
|
||||||
|
var (
|
||||||
|
oktaURLPattern = regexp.MustCompile(`\Ahttps://.+.okta.com/.+\z`)
|
||||||
|
localURLPattern = regexp.MustCompile(`\Ahttp://127.0.0.1.+\z`)
|
||||||
|
)
|
||||||
|
|
||||||
|
env := library.IntegrationEnv(t).WithCapability(library.ExternalOIDCProviderIsAvailable)
|
||||||
|
|
||||||
|
// Build pinniped CLI.
|
||||||
|
t.Logf("building CLI binary")
|
||||||
|
pinnipedExe := buildPinnipedCLI(t)
|
||||||
|
|
||||||
|
cmd := exec.Command(pinnipedExe, "alpha", "login", "oidc",
|
||||||
|
"--issuer", env.OIDCUpstream.Issuer,
|
||||||
|
"--client-id", env.OIDCUpstream.ClientID,
|
||||||
|
"--listen-port", strconv.Itoa(env.OIDCUpstream.LocalhostPort),
|
||||||
|
"--skip-browser",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create a WaitGroup that will wait for all child goroutines to finish, so they can assert errors.
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
defer wg.Wait()
|
||||||
|
|
||||||
|
// Start a background goroutine to read stderr from the CLI and parse out the login URL.
|
||||||
|
loginURLChan := make(chan string)
|
||||||
|
stderr, err := cmd.StderrPipe()
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
r := bufio.NewReader(stderr)
|
||||||
|
line, err := r.ReadString('\n')
|
||||||
|
require.NoError(t, err)
|
||||||
|
const prompt = "Please log in: "
|
||||||
|
require.Truef(t, strings.HasPrefix(line, prompt), "expected %q to have prefix %q", line, prompt)
|
||||||
|
loginURLChan <- strings.TrimPrefix(line, prompt)
|
||||||
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
|
t.Logf("stderr stream closed")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Start a background goroutine to read stdout from the CLI and parse out an ExecCredential.
|
||||||
|
credOutputChan := make(chan clientauthenticationv1beta1.ExecCredential)
|
||||||
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
r := bufio.NewReader(stdout)
|
||||||
|
|
||||||
|
var out clientauthenticationv1beta1.ExecCredential
|
||||||
|
require.NoError(t, json.NewDecoder(r).Decode(&out))
|
||||||
|
credOutputChan <- out
|
||||||
|
|
||||||
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
|
t.Logf("stdout stream closed")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Logf("starting CLI subprocess")
|
||||||
|
require.NoError(t, cmd.Start())
|
||||||
|
wg.Add(1)
|
||||||
|
defer func() {
|
||||||
|
err := cmd.Wait()
|
||||||
|
t.Logf("CLI subprocess exited")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Start the browser driver.
|
||||||
|
t.Logf("opening browser driver")
|
||||||
|
agoutiDriver := agouti.ChromeDriver(
|
||||||
|
// Comment out this line to see the tests happen in a visible browser window.
|
||||||
|
agouti.ChromeOptions("args", []string{"--headless"}),
|
||||||
|
)
|
||||||
|
require.NoError(t, agoutiDriver.Start())
|
||||||
|
t.Cleanup(func() { require.NoError(t, agoutiDriver.Stop()) })
|
||||||
|
page, err := agoutiDriver.NewPage(agouti.Browser("chrome"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Wait for the CLI to print out the login URL and open the browser to it.
|
||||||
|
t.Logf("waiting for CLI to output login URL")
|
||||||
|
var loginURL string
|
||||||
|
select {
|
||||||
|
case <-time.After(1 * time.Minute):
|
||||||
|
require.Fail(t, "timed out waiting for login URL")
|
||||||
|
case loginURL = <-loginURLChan:
|
||||||
|
}
|
||||||
|
t.Logf("navigating to login page")
|
||||||
|
require.NoError(t, page.Navigate(loginURL))
|
||||||
|
|
||||||
|
// Expect to be redirected to the Okta login page.
|
||||||
|
t.Logf("waiting for redirect to Okta login page")
|
||||||
|
waitForURL(t, page, oktaURLPattern)
|
||||||
|
|
||||||
|
// Wait for the login page to be rendered.
|
||||||
|
waitForVisibleElements(t, page,
|
||||||
|
"input#okta-signin-username",
|
||||||
|
"input#okta-signin-password",
|
||||||
|
"input#okta-signin-submit",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fill in the username and password and click "submit".
|
||||||
|
t.Logf("logging into Okta")
|
||||||
|
require.NoError(t, page.First("input#okta-signin-username").Fill(env.OIDCUpstream.Username))
|
||||||
|
require.NoError(t, page.First("input#okta-signin-password").Fill(env.OIDCUpstream.Password))
|
||||||
|
require.NoError(t, page.First("input#okta-signin-submit").Click())
|
||||||
|
|
||||||
|
// Wait for the login to happen and us be redirected back to a localhost callback.
|
||||||
|
t.Logf("waiting for redirect to localhost callback")
|
||||||
|
waitForURL(t, page, localURLPattern)
|
||||||
|
|
||||||
|
// Wait for the "pre" element that gets rendered for a `text/plain` page, and
|
||||||
|
// assert that it contains the success message.
|
||||||
|
t.Logf("verifying success page")
|
||||||
|
waitForVisibleElements(t, page, "pre")
|
||||||
|
msg, err := page.First("pre").Text()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "you have been logged in and may now close this tab", msg)
|
||||||
|
require.NoError(t, page.CloseWindow())
|
||||||
|
|
||||||
|
// Expect the CLI to output an ExecCredential in JSON format.
|
||||||
|
t.Logf("waiting for CLI to output ExecCredential JSON")
|
||||||
|
var credOutput clientauthenticationv1beta1.ExecCredential
|
||||||
|
select {
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
require.Fail(t, "timed out waiting for exec credential output")
|
||||||
|
case credOutput = <-credOutputChan:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert some properties of the ExecCredential.
|
||||||
|
t.Logf("validating ExecCredential")
|
||||||
|
require.NotNil(t, credOutput.Status)
|
||||||
|
require.Empty(t, credOutput.Status.ClientKeyData)
|
||||||
|
require.Empty(t, credOutput.Status.ClientCertificateData)
|
||||||
|
|
||||||
|
// There should be at least 1 minute of remaining expiration (probably more).
|
||||||
|
require.NotNil(t, credOutput.Status.ExpirationTimestamp)
|
||||||
|
ttl := time.Until(credOutput.Status.ExpirationTimestamp.Time)
|
||||||
|
require.Greater(t, ttl.Milliseconds(), (1 * time.Minute).Milliseconds())
|
||||||
|
|
||||||
|
// Assert some properties about the token, which should be a valid JWT.
|
||||||
|
require.NotEmpty(t, credOutput.Status.Token)
|
||||||
|
jws, err := jose.ParseSigned(credOutput.Status.Token)
|
||||||
|
require.NoError(t, err)
|
||||||
|
claims := map[string]interface{}{}
|
||||||
|
require.NoError(t, json.Unmarshal(jws.UnsafePayloadWithoutVerification(), &claims))
|
||||||
|
require.Equal(t, env.OIDCUpstream.Issuer, claims["iss"])
|
||||||
|
require.Equal(t, env.OIDCUpstream.ClientID, claims["aud"])
|
||||||
|
require.Equal(t, env.OIDCUpstream.Username, claims["email"])
|
||||||
|
require.NotEmpty(t, claims["nonce"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForVisibleElements(t *testing.T, page *agouti.Page, selectors ...string) {
|
||||||
|
t.Helper()
|
||||||
|
require.Eventually(t,
|
||||||
|
func() bool {
|
||||||
|
for _, sel := range selectors {
|
||||||
|
vis, err := page.First(sel).Visible()
|
||||||
|
if !(err == nil && vis) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
30*time.Second,
|
||||||
|
100*time.Millisecond,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForURL(t *testing.T, page *agouti.Page, pat *regexp.Regexp) {
|
||||||
|
require.Eventually(t, func() bool {
|
||||||
|
url, err := page.URL()
|
||||||
|
return err == nil && pat.MatchString(url)
|
||||||
|
}, 30*time.Second, 100*time.Millisecond)
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ package library
|
|||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -18,7 +19,8 @@ import (
|
|||||||
type Capability string
|
type Capability string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClusterSigningKeyIsAvailable = Capability("clusterSigningKeyIsAvailable")
|
ClusterSigningKeyIsAvailable Capability = "clusterSigningKeyIsAvailable"
|
||||||
|
ExternalOIDCProviderIsAvailable Capability = "externalOIDCProviderIsAvailable"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestEnv captures all the external parameters consumed by our integration tests.
|
// TestEnv captures all the external parameters consumed by our integration tests.
|
||||||
@ -38,9 +40,17 @@ type TestEnv struct {
|
|||||||
ExpectedUsername string `json:"expectedUsername"`
|
ExpectedUsername string `json:"expectedUsername"`
|
||||||
ExpectedGroups []string `json:"expectedGroups"`
|
ExpectedGroups []string `json:"expectedGroups"`
|
||||||
} `json:"testUser"`
|
} `json:"testUser"`
|
||||||
|
|
||||||
|
OIDCUpstream struct {
|
||||||
|
Issuer string `json:"issuer"`
|
||||||
|
ClientID string `json:"clientID"`
|
||||||
|
LocalhostPort int `json:"localhostPort"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
} `json:"oidcUpstream"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntegrationEnv gets the integration test environment from a Kubernetes Secret in the test cluster. This
|
// IntegrationEnv gets the integration test environment from OS environment variables. This
|
||||||
// method also implies SkipUnlessIntegration().
|
// method also implies SkipUnlessIntegration().
|
||||||
func IntegrationEnv(t *testing.T) *TestEnv {
|
func IntegrationEnv(t *testing.T) *TestEnv {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@ -79,6 +89,17 @@ func IntegrationEnv(t *testing.T) *TestEnv {
|
|||||||
result.SupervisorAppName = needEnv("PINNIPED_TEST_SUPERVISOR_APP_NAME")
|
result.SupervisorAppName = needEnv("PINNIPED_TEST_SUPERVISOR_APP_NAME")
|
||||||
result.SupervisorAddress = needEnv("PINNIPED_TEST_SUPERVISOR_ADDRESS")
|
result.SupervisorAddress = needEnv("PINNIPED_TEST_SUPERVISOR_ADDRESS")
|
||||||
result.TestWebhook.TLS = &idpv1alpha1.TLSSpec{CertificateAuthorityData: needEnv("PINNIPED_TEST_WEBHOOK_CA_BUNDLE")}
|
result.TestWebhook.TLS = &idpv1alpha1.TLSSpec{CertificateAuthorityData: needEnv("PINNIPED_TEST_WEBHOOK_CA_BUNDLE")}
|
||||||
|
|
||||||
|
result.OIDCUpstream.Issuer = os.Getenv("PINNIPED_TEST_CLI_OIDC_ISSUER")
|
||||||
|
result.OIDCUpstream.ClientID = os.Getenv("PINNIPED_TEST_CLI_OIDC_CLIENT_ID")
|
||||||
|
result.OIDCUpstream.LocalhostPort, _ = strconv.Atoi(os.Getenv("PINNIPED_TEST_CLI_OIDC_LOCALHOST_PORT"))
|
||||||
|
result.OIDCUpstream.Username = os.Getenv("PINNIPED_TEST_CLI_OIDC_USERNAME")
|
||||||
|
result.OIDCUpstream.Password = os.Getenv("PINNIPED_TEST_CLI_OIDC_PASSWORD")
|
||||||
|
|
||||||
|
result.Capabilities[ExternalOIDCProviderIsAvailable] = !(result.OIDCUpstream.Issuer == "" ||
|
||||||
|
result.OIDCUpstream.ClientID == "" ||
|
||||||
|
result.OIDCUpstream.Username == "" ||
|
||||||
|
result.OIDCUpstream.Password == "")
|
||||||
result.t = t
|
result.t = t
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user