Advertise browser_authcode flow in ldap idp discovery
To keep this backwards compatible, this PR changes how the cli deals with ambiguous flows. Previously, if there was more than one flow advertised, the cli would require users to set the flag --upstream-identity-provider-flow. Now it chooses the first one in the list. Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
parent
24b0ddf600
commit
694e4d6df6
@ -233,7 +233,7 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
|||||||
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input. Maybe they know something
|
// When all the upstream IDP flags are set by the user, then skip discovery and don't validate their input. Maybe they know something
|
||||||
// that we can't know, like the name of an IDP that they are going to define in the future.
|
// that we can't know, like the name of an IDP that they are going to define in the future.
|
||||||
if len(flags.oidc.issuer) > 0 && (flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "") {
|
if len(flags.oidc.issuer) > 0 && (flags.oidc.upstreamIDPType == "" || flags.oidc.upstreamIDPName == "" || flags.oidc.upstreamIDPFlow == "") {
|
||||||
if err := discoverSupervisorUpstreamIDP(ctx, &flags); err != nil {
|
if err := discoverSupervisorUpstreamIDP(ctx, &flags, deps.log); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,7 +726,7 @@ func hasPendingStrategy(credentialIssuer *configv1alpha1.CredentialIssuer) bool
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigParams) error {
|
func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigParams, log logr.Logger) error {
|
||||||
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
httpClient, err := newDiscoveryHTTPClient(flags.oidc.caBundle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -758,7 +758,7 @@ func discoverSupervisorUpstreamIDP(ctx context.Context, flags *getKubeconfigPara
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedIDPFlow, err := selectUpstreamIDPFlow(discoveredIDPFlows, selectedIDPName, selectedIDPType, flags.oidc.upstreamIDPFlow)
|
selectedIDPFlow, err := selectUpstreamIDPFlow(discoveredIDPFlows, selectedIDPName, selectedIDPType, flags.oidc.upstreamIDPFlow, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -898,7 +898,7 @@ func selectUpstreamIDPNameAndType(pinnipedIDPs []idpdiscoveryv1alpha1.PinnipedID
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectUpstreamIDPFlow(discoveredIDPFlows []idpdiscoveryv1alpha1.IDPFlow, selectedIDPName string, selectedIDPType idpdiscoveryv1alpha1.IDPType, specifiedFlow string) (idpdiscoveryv1alpha1.IDPFlow, error) {
|
func selectUpstreamIDPFlow(discoveredIDPFlows []idpdiscoveryv1alpha1.IDPFlow, selectedIDPName string, selectedIDPType idpdiscoveryv1alpha1.IDPType, specifiedFlow string, log logr.Logger) (idpdiscoveryv1alpha1.IDPFlow, error) {
|
||||||
switch {
|
switch {
|
||||||
case len(discoveredIDPFlows) == 0:
|
case len(discoveredIDPFlows) == 0:
|
||||||
// No flows listed by discovery means that we are talking to an old Supervisor from before this feature existed.
|
// No flows listed by discovery means that we are talking to an old Supervisor from before this feature existed.
|
||||||
@ -922,10 +922,7 @@ func selectUpstreamIDPFlow(discoveredIDPFlows []idpdiscoveryv1alpha1.IDPFlow, se
|
|||||||
return discoveredIDPFlows[0], nil
|
return discoveredIDPFlows[0], nil
|
||||||
default:
|
default:
|
||||||
// The user did not specify a flow, and more than one was found.
|
// The user did not specify a flow, and more than one was found.
|
||||||
return "", fmt.Errorf(
|
log.Info("multiple client flows found, selecting first value as default: "+discoveredIDPFlows[0].String(), "idpName", selectedIDPName, "idpType", selectedIDPType)
|
||||||
"multiple client flows for Supervisor upstream identity provider %q of type %q were found, "+
|
return discoveredIDPFlows[0], nil
|
||||||
"so the --upstream-identity-provider-flow flag must be specified. "+
|
|
||||||
"Found these flows: %v",
|
|
||||||
selectedIDPName, selectedIDPType, discoveredIDPFlows)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1261,13 +1261,51 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
oidcDiscoveryResponse: happyOIDCDiscoveryResponse,
|
oidcDiscoveryResponse: happyOIDCDiscoveryResponse,
|
||||||
idpsDiscoveryResponse: here.Docf(`{
|
idpsDiscoveryResponse: here.Docf(`{
|
||||||
"pinniped_identity_providers": [
|
"pinniped_identity_providers": [
|
||||||
{"name": "some-oidc-idp", "type": "oidc", "flows": ["flow1", "flow2"]}
|
{"name": "some-ldap-idp", "type": "ldap", "flows": ["cli_password", "flow2"]}
|
||||||
]
|
]
|
||||||
}`),
|
}`),
|
||||||
wantError: true,
|
wantStdout: func(issuerCABundle string, issuerURL string) string {
|
||||||
wantStderr: func(issuerCABundle string, issuerURL string) string {
|
return here.Docf(`
|
||||||
return `Error: multiple client flows for Supervisor upstream identity provider "some-oidc-idp" of type "oidc" were found, so the --upstream-identity-provider-flow flag must be specified.` +
|
apiVersion: v1
|
||||||
` Found these flows: [flow1 flow2]` + "\n"
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
||||||
|
server: https://fake-server-url-value
|
||||||
|
name: kind-cluster-pinniped
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: kind-cluster-pinniped
|
||||||
|
user: kind-user-pinniped
|
||||||
|
name: kind-context-pinniped
|
||||||
|
current-context: kind-context-pinniped
|
||||||
|
kind: Config
|
||||||
|
preferences: {}
|
||||||
|
users:
|
||||||
|
- name: kind-user-pinniped
|
||||||
|
user:
|
||||||
|
exec:
|
||||||
|
apiVersion: client.authentication.k8s.io/v1beta1
|
||||||
|
args:
|
||||||
|
- login
|
||||||
|
- oidc
|
||||||
|
- --issuer=%s
|
||||||
|
- --client-id=pinniped-cli
|
||||||
|
- --scopes=offline_access,openid,pinniped:request-audience
|
||||||
|
- --ca-bundle-data=%s
|
||||||
|
- --upstream-identity-provider-name=some-ldap-idp
|
||||||
|
- --upstream-identity-provider-type=ldap
|
||||||
|
- --upstream-identity-provider-flow=cli_password
|
||||||
|
command: '.../path/to/pinniped'
|
||||||
|
env: []
|
||||||
|
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
|
||||||
|
for more details
|
||||||
|
provideClusterInfo: true
|
||||||
|
`,
|
||||||
|
issuerURL,
|
||||||
|
base64.StdEncoding.EncodeToString([]byte(issuerCABundle)))
|
||||||
|
},
|
||||||
|
wantLogs: func(_ string, _ string) []string {
|
||||||
|
return []string{"\"level\"=0 \"msg\"=\"multiple client flows found, selecting first value as default: cli_password\" \"idpName\"=\"some-ldap-idp\" \"idpType\"=\"ldap\""}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package idpdiscovery provides a handler for the upstream IDP discovery endpoint.
|
// Package idpdiscovery provides a handler for the upstream IDP discovery endpoint.
|
||||||
@ -44,14 +44,14 @@ func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte,
|
|||||||
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.PinnipedIDP{
|
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.PinnipedIDP{
|
||||||
Name: provider.GetName(),
|
Name: provider.GetName(),
|
||||||
Type: v1alpha1.IDPTypeLDAP,
|
Type: v1alpha1.IDPTypeLDAP,
|
||||||
Flows: []v1alpha1.IDPFlow{v1alpha1.IDPFlowCLIPassword},
|
Flows: []v1alpha1.IDPFlow{v1alpha1.IDPFlowCLIPassword, v1alpha1.IDPFlowBrowserAuthcode},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, provider := range upstreamIDPs.GetActiveDirectoryIdentityProviders() {
|
for _, provider := range upstreamIDPs.GetActiveDirectoryIdentityProviders() {
|
||||||
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.PinnipedIDP{
|
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.PinnipedIDP{
|
||||||
Name: provider.GetName(),
|
Name: provider.GetName(),
|
||||||
Type: v1alpha1.IDPTypeActiveDirectory,
|
Type: v1alpha1.IDPTypeActiveDirectory,
|
||||||
Flows: []v1alpha1.IDPFlow{v1alpha1.IDPFlowCLIPassword},
|
Flows: []v1alpha1.IDPFlow{v1alpha1.IDPFlowCLIPassword, v1alpha1.IDPFlowBrowserAuthcode},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, provider := range upstreamIDPs.GetOIDCIdentityProviders() {
|
for _, provider := range upstreamIDPs.GetOIDCIdentityProviders() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package idpdiscovery
|
package idpdiscovery
|
||||||
@ -37,22 +37,22 @@ func TestIDPDiscovery(t *testing.T) {
|
|||||||
wantContentType: "application/json",
|
wantContentType: "application/json",
|
||||||
wantFirstResponseBodyJSON: here.Doc(`{
|
wantFirstResponseBodyJSON: here.Doc(`{
|
||||||
"pinniped_identity_providers": [
|
"pinniped_identity_providers": [
|
||||||
{"name": "a-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]},
|
{"name": "a-some-ldap-idp", "type": "ldap", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "a-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode"]},
|
{"name": "a-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode"]},
|
||||||
{"name": "x-some-idp", "type": "ldap", "flows": ["cli_password"]},
|
{"name": "x-some-idp", "type": "ldap", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "x-some-idp", "type": "oidc", "flows": ["browser_authcode"]},
|
{"name": "x-some-idp", "type": "oidc", "flows": ["browser_authcode"]},
|
||||||
{"name": "y-some-ad-idp", "type": "activedirectory", "flows": ["cli_password"]},
|
{"name": "y-some-ad-idp", "type": "activedirectory", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "z-some-ad-idp", "type": "activedirectory", "flows": ["cli_password"]},
|
{"name": "z-some-ad-idp", "type": "activedirectory", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "z-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]},
|
{"name": "z-some-ldap-idp", "type": "ldap", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "z-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode", "cli_password"]}
|
{"name": "z-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode", "cli_password"]}
|
||||||
]
|
]
|
||||||
}`),
|
}`),
|
||||||
wantSecondResponseBodyJSON: here.Doc(`{
|
wantSecondResponseBodyJSON: here.Doc(`{
|
||||||
"pinniped_identity_providers": [
|
"pinniped_identity_providers": [
|
||||||
{"name": "some-other-ad-idp-1", "type": "activedirectory", "flows": ["cli_password"]},
|
{"name": "some-other-ad-idp-1", "type": "activedirectory", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "some-other-ad-idp-2", "type": "activedirectory", "flows": ["cli_password"]},
|
{"name": "some-other-ad-idp-2", "type": "activedirectory", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "some-other-ldap-idp-1", "type": "ldap", "flows": ["cli_password"]},
|
{"name": "some-other-ldap-idp-1", "type": "ldap", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "some-other-ldap-idp-2", "type": "ldap", "flows": ["cli_password"]},
|
{"name": "some-other-ldap-idp-2", "type": "ldap", "flows": ["cli_password", "browser_authcode"]},
|
||||||
{"name": "some-other-oidc-idp-1", "type": "oidc", "flows": ["browser_authcode", "cli_password"]},
|
{"name": "some-other-oidc-idp-1", "type": "oidc", "flows": ["browser_authcode", "cli_password"]},
|
||||||
{"name": "some-other-oidc-idp-2", "type": "oidc", "flows": ["browser_authcode"]}
|
{"name": "some-other-oidc-idp-2", "type": "oidc", "flows": ["browser_authcode"]}
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user