Add Dex to our integration test environment and use it to test the CLI.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
50d80489be
commit
33fcc74417
@ -99,11 +99,12 @@ docker build .
|
|||||||
- [`tilt`](https://docs.tilt.dev/install.html)
|
- [`tilt`](https://docs.tilt.dev/install.html)
|
||||||
- [`ytt`](https://carvel.dev/#getting-started)
|
- [`ytt`](https://carvel.dev/#getting-started)
|
||||||
- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||||
|
- [`chromedriver`](https://chromedriver.chromium.org/) (and [Chrome](https://www.google.com/chrome/))
|
||||||
|
|
||||||
On macOS, these tools can be installed with [Homebrew](https://brew.sh/):
|
On macOS, these tools can be installed with [Homebrew](https://brew.sh/) (assuming you have Chrome installed already):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install kind tilt-dev/tap/tilt k14s/tap/ytt kubectl
|
brew install kind tilt-dev/tap/tilt k14s/tap/ytt kubectl chromedriver
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Create a local Kubernetes cluster using `kind`:
|
1. Create a local Kubernetes cluster using `kind`:
|
||||||
|
@ -4,4 +4,12 @@ nodes:
|
|||||||
- role: control-plane
|
- role: control-plane
|
||||||
- role: worker
|
- role: worker
|
||||||
- role: worker
|
- role: worker
|
||||||
extraPortMappings: [{containerPort: 31234, hostPort: 12345, protocol: TCP}]
|
extraPortMappings:
|
||||||
|
- protocol: TCP
|
||||||
|
containerPort: 31234
|
||||||
|
hostPort: 12345
|
||||||
|
listenAddress: 127.0.0.1
|
||||||
|
- protocol: TCP
|
||||||
|
containerPort: 31235
|
||||||
|
hostPort: 12346
|
||||||
|
listenAddress: 127.0.0.1
|
||||||
|
@ -2,4 +2,12 @@ kind: Cluster
|
|||||||
apiVersion: kind.x-k8s.io/v1alpha4
|
apiVersion: kind.x-k8s.io/v1alpha4
|
||||||
nodes:
|
nodes:
|
||||||
- role: control-plane
|
- role: control-plane
|
||||||
extraPortMappings: [{containerPort: 31234, hostPort: 12345, protocol: TCP}]
|
extraPortMappings:
|
||||||
|
- protocol: TCP
|
||||||
|
containerPort: 31234
|
||||||
|
hostPort: 12345
|
||||||
|
listenAddress: 127.0.0.1
|
||||||
|
- protocol: TCP
|
||||||
|
containerPort: 31235
|
||||||
|
hostPort: 12346
|
||||||
|
listenAddress: 127.0.0.1
|
||||||
|
@ -18,6 +18,23 @@ local_resource(
|
|||||||
deps=['../../../cmd', '../../../internal', '../../../pkg', '../../../generated'],
|
deps=['../../../cmd', '../../../internal', '../../../pkg', '../../../generated'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#####################################################################################################
|
||||||
|
# Dex
|
||||||
|
#
|
||||||
|
|
||||||
|
# Render the Dex installation manifest using ytt.
|
||||||
|
k8s_yaml(local(['ytt','--file', '../../../test/deploy/dex']))
|
||||||
|
|
||||||
|
# Collect all the deployed Dex resources under a "dex" resource tab.
|
||||||
|
k8s_resource(
|
||||||
|
workload='dex', # this is the deployment name
|
||||||
|
objects=[
|
||||||
|
# these are the objects that would otherwise appear in the "uncategorized" tab in the tilt UI
|
||||||
|
'dex:namespace',
|
||||||
|
'dex-config:configmap',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
#####################################################################################################
|
#####################################################################################################
|
||||||
# Local-user-authenticator app
|
# Local-user-authenticator app
|
||||||
#
|
#
|
||||||
|
@ -119,7 +119,7 @@ if ! tilt_mode; then
|
|||||||
log_note "Checking for running kind clusters..."
|
log_note "Checking for running kind clusters..."
|
||||||
if ! kind get clusters | grep -q -e '^pinniped$'; then
|
if ! kind get clusters | grep -q -e '^pinniped$'; then
|
||||||
log_note "Creating a kind cluster..."
|
log_note "Creating a kind cluster..."
|
||||||
# single-node.yaml exposes node port 31234 as 127.0.0.1:12345
|
# single-node.yaml exposes node port 31234 as 127.0.0.1:12345 and port 31235 as 127.0.0.1:12346
|
||||||
kind create cluster --config "$pinniped_path/hack/lib/kind-config/single-node.yaml" --name pinniped
|
kind create cluster --config "$pinniped_path/hack/lib/kind-config/single-node.yaml" --name pinniped
|
||||||
else
|
else
|
||||||
if ! kubectl cluster-info | grep master | grep -q 127.0.0.1; then
|
if ! kubectl cluster-info | grep master | grep -q 127.0.0.1; then
|
||||||
@ -176,6 +176,17 @@ if ! tilt_mode; then
|
|||||||
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
|
|
||||||
|
#
|
||||||
|
# Deploy dex
|
||||||
|
#
|
||||||
|
pushd test/deploy/dex >/dev/null
|
||||||
|
|
||||||
|
log_note "Deploying Dex to the cluster..."
|
||||||
|
ytt --file . >"$manifest"
|
||||||
|
kubectl apply --dry-run=client -f "$manifest" # Validate manifest schema.
|
||||||
|
kapp deploy --yes --app dex --diff-changes --file "$manifest"
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test_username="test-username"
|
test_username="test-username"
|
||||||
@ -261,6 +272,11 @@ export PINNIPED_TEST_WEBHOOK_CA_BUNDLE=${webhook_ca_bundle}
|
|||||||
export PINNIPED_TEST_SUPERVISOR_NAMESPACE=${supervisor_namespace}
|
export PINNIPED_TEST_SUPERVISOR_NAMESPACE=${supervisor_namespace}
|
||||||
export PINNIPED_TEST_SUPERVISOR_APP_NAME=${supervisor_app_name}
|
export PINNIPED_TEST_SUPERVISOR_APP_NAME=${supervisor_app_name}
|
||||||
export PINNIPED_TEST_SUPERVISOR_ADDRESS="127.0.0.1:12345"
|
export PINNIPED_TEST_SUPERVISOR_ADDRESS="127.0.0.1:12345"
|
||||||
|
export PINNIPED_TEST_CLI_OIDC_ISSUER=http://127.0.0.1:12346/dex
|
||||||
|
export PINNIPED_TEST_CLI_OIDC_CLIENT_ID=pinniped-cli
|
||||||
|
export PINNIPED_TEST_CLI_OIDC_LOCALHOST_PORT=48095
|
||||||
|
export PINNIPED_TEST_CLI_OIDC_USERNAME=pinny@example.com
|
||||||
|
export PINNIPED_TEST_CLI_OIDC_PASSWORD=password
|
||||||
|
|
||||||
read -r -d '' PINNIPED_TEST_CLUSTER_CAPABILITY_YAML << PINNIPED_TEST_CLUSTER_CAPABILITY_YAML_EOF || true
|
read -r -d '' PINNIPED_TEST_CLUSTER_CAPABILITY_YAML << PINNIPED_TEST_CLUSTER_CAPABILITY_YAML_EOF || true
|
||||||
${pinniped_cluster_capability_file_content}
|
${pinniped_cluster_capability_file_content}
|
||||||
|
102
test/deploy/dex/dex.yaml
Normal file
102
test/deploy/dex/dex.yaml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#! Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@ load("@ytt:data", "data")
|
||||||
|
#@ load("@ytt:sha256", "sha256")
|
||||||
|
#@ load("@ytt:yaml", "yaml")
|
||||||
|
|
||||||
|
#@ def dexConfig():
|
||||||
|
issuer: #@ "http://127.0.0.1:" + str(data.values.ports.local) + "/dex"
|
||||||
|
storage:
|
||||||
|
type: sqlite3
|
||||||
|
config:
|
||||||
|
file: ":memory:"
|
||||||
|
web:
|
||||||
|
http: 0.0.0.0:5556
|
||||||
|
oauth2:
|
||||||
|
skipApprovalScreen: true
|
||||||
|
staticClients:
|
||||||
|
- id: pinniped-cli
|
||||||
|
name: 'Pinniped CLI'
|
||||||
|
#! we can't have "public: true" until https://github.com/dexidp/dex/pull/1822 lands in Dex.
|
||||||
|
redirectURIs:
|
||||||
|
- #@ "http://127.0.0.1:" + str(data.values.ports.cli) + "/callback"
|
||||||
|
- #@ "http://[::1]:" + str(data.values.ports.cli) + "/callback"
|
||||||
|
enablePasswordDB: true
|
||||||
|
staticPasswords:
|
||||||
|
- username: "pinny"
|
||||||
|
email: "pinny@example.com"
|
||||||
|
hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" #! bcrypt("password")
|
||||||
|
userID: "061d23d1-fe1e-4777-9ae9-59cd12abeaaa"
|
||||||
|
#@ end
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: dex
|
||||||
|
labels:
|
||||||
|
name: dex
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: dex-config
|
||||||
|
namespace: dex
|
||||||
|
labels:
|
||||||
|
app: dex
|
||||||
|
data:
|
||||||
|
config.yaml: #@ yaml.encode(dexConfig())
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: dex
|
||||||
|
namespace: dex
|
||||||
|
labels:
|
||||||
|
app: dex
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: dex
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: dex
|
||||||
|
annotations:
|
||||||
|
dexConfigHash: #@ sha256.sum(yaml.encode(dexConfig()))
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: dex
|
||||||
|
image: quay.io/dexidp/dex:v2.10.0
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command:
|
||||||
|
- /usr/local/bin/dex
|
||||||
|
- serve
|
||||||
|
- /etc/dex/cfg/config.yaml
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 5556
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/dex/cfg
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: dex-config
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: dex
|
||||||
|
namespace: dex
|
||||||
|
labels:
|
||||||
|
app: dex
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: dex
|
||||||
|
ports:
|
||||||
|
- port: 5556
|
||||||
|
nodePort: #@ data.values.ports.node
|
17
test/deploy/dex/values.yaml
Normal file
17
test/deploy/dex/values.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#! Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||||
|
#! SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#@data/values
|
||||||
|
---
|
||||||
|
ports:
|
||||||
|
#! Port on which the Pinniped CLI is listening for a callback (`--listen-port` flag value)
|
||||||
|
#! Used in the Dex configuration to form the valid redirect URIs for our test client.
|
||||||
|
cli: 48095
|
||||||
|
|
||||||
|
#! Kubernetes NodePort that should be forwarded to the Dex service.
|
||||||
|
#! Used to create a Service of type: NodePort
|
||||||
|
node: 31235
|
||||||
|
|
||||||
|
#! External port where Dex ends up exposed on localhost during tests. This value comes from our
|
||||||
|
#! Kind configuration which maps 127.0.0.1:12346 to port 31235 on the Kind worker node.
|
||||||
|
local: 12346
|
@ -102,19 +102,58 @@ func runPinnipedCLIGetKubeconfig(t *testing.T, pinnipedExe, token, namespaceName
|
|||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCLILoginOIDC(t *testing.T) {
|
type loginProviderPatterns struct {
|
||||||
var (
|
Name string
|
||||||
oktaURLPattern = regexp.MustCompile(`\Ahttps://.+.okta.com/.+\z`)
|
IssuerPattern *regexp.Regexp
|
||||||
localURLPattern = regexp.MustCompile(`\Ahttp://127.0.0.1.+\z`)
|
LoginPagePattern *regexp.Regexp
|
||||||
)
|
UsernameSelector string
|
||||||
|
PasswordSelector string
|
||||||
|
LoginButtonSelector string
|
||||||
|
}
|
||||||
|
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ExternalOIDCProviderIsAvailable)
|
func getLoginProvider(t *testing.T) *loginProviderPatterns {
|
||||||
|
t.Helper()
|
||||||
|
issuer := library.IntegrationEnv(t).OIDCUpstream.Issuer
|
||||||
|
for _, p := range []loginProviderPatterns{
|
||||||
|
{
|
||||||
|
Name: "Okta",
|
||||||
|
IssuerPattern: regexp.MustCompile(`\Ahttps://.+\.okta\.com/.+\z`),
|
||||||
|
LoginPagePattern: regexp.MustCompile(`\Ahttps://.+\.okta\.com/.+\z`),
|
||||||
|
UsernameSelector: "input#okta-signin-username",
|
||||||
|
PasswordSelector: "input#okta-signin-password",
|
||||||
|
LoginButtonSelector: "input#okta-signin-submit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Dex",
|
||||||
|
IssuerPattern: regexp.MustCompile(`\Ahttp://127\.0\.0\.1.+/dex.*\z`),
|
||||||
|
LoginPagePattern: regexp.MustCompile(`\Ahttp://127\.0\.0\.1.+/dex/auth/local.+\z`),
|
||||||
|
UsernameSelector: "input#login",
|
||||||
|
PasswordSelector: "input#password",
|
||||||
|
LoginButtonSelector: "button#submit-login",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if p.IssuerPattern.MatchString(issuer) {
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.Failf(t, "could not find login provider for issuer %q", issuer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLILoginOIDC(t *testing.T) {
|
||||||
|
env := library.IntegrationEnv(t)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Find the login CSS selectors for the test issuer, or fail fast.
|
||||||
|
loginProvider := getLoginProvider(t)
|
||||||
|
|
||||||
// Build pinniped CLI.
|
// Build pinniped CLI.
|
||||||
t.Logf("building CLI binary")
|
t.Logf("building CLI binary")
|
||||||
pinnipedExe := buildPinnipedCLI(t)
|
pinnipedExe := buildPinnipedCLI(t)
|
||||||
|
|
||||||
cmd := exec.Command(pinnipedExe, "alpha", "login", "oidc",
|
cmd := exec.CommandContext(ctx, pinnipedExe, "alpha", "login", "oidc",
|
||||||
"--issuer", env.OIDCUpstream.Issuer,
|
"--issuer", env.OIDCUpstream.Issuer,
|
||||||
"--client-id", env.OIDCUpstream.ClientID,
|
"--client-id", env.OIDCUpstream.ClientID,
|
||||||
"--listen-port", strconv.Itoa(env.OIDCUpstream.LocalhostPort),
|
"--listen-port", strconv.Itoa(env.OIDCUpstream.LocalhostPort),
|
||||||
@ -123,7 +162,7 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
|
|
||||||
// Create a WaitGroup that will wait for all child goroutines to finish, so they can assert errors.
|
// Create a WaitGroup that will wait for all child goroutines to finish, so they can assert errors.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
defer wg.Wait()
|
t.Cleanup(wg.Wait)
|
||||||
|
|
||||||
// Start a background goroutine to read stderr from the CLI and parse out the login URL.
|
// Start a background goroutine to read stderr from the CLI and parse out the login URL.
|
||||||
loginURLChan := make(chan string)
|
loginURLChan := make(chan string)
|
||||||
@ -131,6 +170,7 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
r := bufio.NewReader(stderr)
|
r := bufio.NewReader(stderr)
|
||||||
line, err := r.ReadString('\n')
|
line, err := r.ReadString('\n')
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -138,9 +178,9 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
require.Truef(t, strings.HasPrefix(line, prompt), "expected %q to have prefix %q", line, prompt)
|
require.Truef(t, strings.HasPrefix(line, prompt), "expected %q to have prefix %q", line, prompt)
|
||||||
loginURLChan <- strings.TrimPrefix(line, prompt)
|
loginURLChan <- strings.TrimPrefix(line, prompt)
|
||||||
_, err = io.Copy(ioutil.Discard, r)
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
|
|
||||||
t.Logf("stderr stream closed")
|
t.Logf("stderr stream closed")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wg.Done()
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Start a background goroutine to read stdout from the CLI and parse out an ExecCredential.
|
// Start a background goroutine to read stdout from the CLI and parse out an ExecCredential.
|
||||||
@ -149,6 +189,7 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
r := bufio.NewReader(stdout)
|
r := bufio.NewReader(stdout)
|
||||||
|
|
||||||
var out clientauthenticationv1beta1.ExecCredential
|
var out clientauthenticationv1beta1.ExecCredential
|
||||||
@ -158,18 +199,15 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
_, err = io.Copy(ioutil.Discard, r)
|
_, err = io.Copy(ioutil.Discard, r)
|
||||||
t.Logf("stdout stream closed")
|
t.Logf("stdout stream closed")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wg.Done()
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
t.Logf("starting CLI subprocess")
|
t.Logf("starting CLI subprocess")
|
||||||
require.NoError(t, cmd.Start())
|
require.NoError(t, cmd.Start())
|
||||||
wg.Add(1)
|
t.Cleanup(func() {
|
||||||
defer func() {
|
|
||||||
err := cmd.Wait()
|
err := cmd.Wait()
|
||||||
t.Logf("CLI subprocess exited")
|
t.Logf("CLI subprocess exited")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wg.Done()
|
})
|
||||||
}()
|
|
||||||
|
|
||||||
// Start the browser driver.
|
// Start the browser driver.
|
||||||
t.Logf("opening browser driver")
|
t.Logf("opening browser driver")
|
||||||
@ -193,26 +231,23 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
t.Logf("navigating to login page")
|
t.Logf("navigating to login page")
|
||||||
require.NoError(t, page.Navigate(loginURL))
|
require.NoError(t, page.Navigate(loginURL))
|
||||||
|
|
||||||
// Expect to be redirected to the Okta login page.
|
// Expect to be redirected to the login page.
|
||||||
t.Logf("waiting for redirect to Okta login page")
|
t.Logf("waiting for redirect to %s login page", loginProvider.Name)
|
||||||
waitForURL(t, page, oktaURLPattern)
|
waitForURL(t, page, loginProvider.LoginPagePattern)
|
||||||
|
|
||||||
// Wait for the login page to be rendered.
|
// Wait for the login page to be rendered.
|
||||||
waitForVisibleElements(t, page,
|
waitForVisibleElements(t, page, loginProvider.UsernameSelector, loginProvider.PasswordSelector, loginProvider.LoginButtonSelector)
|
||||||
"input#okta-signin-username",
|
|
||||||
"input#okta-signin-password",
|
|
||||||
"input#okta-signin-submit",
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fill in the username and password and click "submit".
|
// Fill in the username and password and click "submit".
|
||||||
t.Logf("logging into Okta")
|
t.Logf("logging into %s", loginProvider.Name)
|
||||||
require.NoError(t, page.First("input#okta-signin-username").Fill(env.OIDCUpstream.Username))
|
require.NoError(t, page.First(loginProvider.UsernameSelector).Fill(env.OIDCUpstream.Username))
|
||||||
require.NoError(t, page.First("input#okta-signin-password").Fill(env.OIDCUpstream.Password))
|
require.NoError(t, page.First(loginProvider.PasswordSelector).Fill(env.OIDCUpstream.Password))
|
||||||
require.NoError(t, page.First("input#okta-signin-submit").Click())
|
require.NoError(t, page.First(loginProvider.LoginButtonSelector).Click())
|
||||||
|
|
||||||
// Wait for the login to happen and us be redirected back to a localhost callback.
|
// Wait for the login to happen and us be redirected back to a localhost callback.
|
||||||
t.Logf("waiting for redirect to localhost callback")
|
t.Logf("waiting for redirect to localhost callback")
|
||||||
waitForURL(t, page, localURLPattern)
|
callbackURLPattern := regexp.MustCompile(`\Ahttp://127.0.0.1:` + strconv.Itoa(env.OIDCUpstream.LocalhostPort) + `/.+\z`)
|
||||||
|
waitForURL(t, page, callbackURLPattern)
|
||||||
|
|
||||||
// Wait for the "pre" element that gets rendered for a `text/plain` page, and
|
// Wait for the "pre" element that gets rendered for a `text/plain` page, and
|
||||||
// assert that it contains the success message.
|
// assert that it contains the success message.
|
||||||
@ -221,7 +256,6 @@ func TestCLILoginOIDC(t *testing.T) {
|
|||||||
msg, err := page.First("pre").Text()
|
msg, err := page.First("pre").Text()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "you have been logged in and may now close this tab", msg)
|
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.
|
// Expect the CLI to output an ExecCredential in JSON format.
|
||||||
t.Logf("waiting for CLI to output ExecCredential JSON")
|
t.Logf("waiting for CLI to output ExecCredential JSON")
|
||||||
@ -267,7 +301,7 @@ func waitForVisibleElements(t *testing.T, page *agouti.Page, selectors ...string
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
30*time.Second,
|
10*time.Second,
|
||||||
100*time.Millisecond,
|
100*time.Millisecond,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -276,5 +310,5 @@ func waitForURL(t *testing.T, page *agouti.Page, pat *regexp.Regexp) {
|
|||||||
require.Eventually(t, func() bool {
|
require.Eventually(t, func() bool {
|
||||||
url, err := page.URL()
|
url, err := page.URL()
|
||||||
return err == nil && pat.MatchString(url)
|
return err == nil && pat.MatchString(url)
|
||||||
}, 30*time.Second, 100*time.Millisecond)
|
}, 10*time.Second, 100*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@ 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.
|
||||||
@ -90,16 +89,11 @@ func IntegrationEnv(t *testing.T) *TestEnv {
|
|||||||
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.Issuer = needEnv("PINNIPED_TEST_CLI_OIDC_ISSUER")
|
||||||
result.OIDCUpstream.ClientID = os.Getenv("PINNIPED_TEST_CLI_OIDC_CLIENT_ID")
|
result.OIDCUpstream.ClientID = needEnv("PINNIPED_TEST_CLI_OIDC_CLIENT_ID")
|
||||||
result.OIDCUpstream.LocalhostPort, _ = strconv.Atoi(os.Getenv("PINNIPED_TEST_CLI_OIDC_LOCALHOST_PORT"))
|
result.OIDCUpstream.LocalhostPort, _ = strconv.Atoi(needEnv("PINNIPED_TEST_CLI_OIDC_LOCALHOST_PORT"))
|
||||||
result.OIDCUpstream.Username = os.Getenv("PINNIPED_TEST_CLI_OIDC_USERNAME")
|
result.OIDCUpstream.Username = needEnv("PINNIPED_TEST_CLI_OIDC_USERNAME")
|
||||||
result.OIDCUpstream.Password = os.Getenv("PINNIPED_TEST_CLI_OIDC_PASSWORD")
|
result.OIDCUpstream.Password = needEnv("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