diff --git a/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go.tmpl b/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go.tmpl new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go.tmpl @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/cmd/pinniped/cmd/kubeconfig.go b/cmd/pinniped/cmd/kubeconfig.go index c6abc1b6..272f210d 100644 --- a/cmd/pinniped/cmd/kubeconfig.go +++ b/cmd/pinniped/cmd/kubeconfig.go @@ -32,6 +32,7 @@ import ( conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1" configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1" + idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1" conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned" "go.pinniped.dev/internal/groupsuffix" ) @@ -98,24 +99,6 @@ type getKubeconfigParams struct { credentialCachePathSet bool } -type supervisorOIDCDiscoveryResponseWithV1Alpha1 struct { - SupervisorDiscovery SupervisorDiscoveryResponseV1Alpha1 `json:"discovery.supervisor.pinniped.dev/v1alpha1"` -} - -type SupervisorDiscoveryResponseV1Alpha1 struct { - PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` -} - -type supervisorIDPsDiscoveryResponseV1Alpha1 struct { - PinnipedIDPs []pinnipedIDPResponse `json:"pinniped_identity_providers"` -} - -type pinnipedIDPResponse struct { - Name string `json:"name"` - Type string `json:"type"` - Flows []string `json:"flows,omitempty"` -} - func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command { var ( cmd = &cobra.Command{ @@ -818,7 +801,7 @@ func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpCl return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err) } - var body supervisorOIDCDiscoveryResponseWithV1Alpha1 + var body idpdiscoveryv1alpha1.SupervisorOIDCDiscoveryResponse err = discoveredProvider.Claims(&body) if err != nil { return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err) @@ -827,7 +810,7 @@ func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpCl return body.SupervisorDiscovery.PinnipedIDPsEndpoint, nil } -func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]pinnipedIDPResponse, error) { +func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]idpdiscoveryv1alpha1.SupervisorPinnipedIDP, error) { request, err := http.NewRequestWithContext(ctx, http.MethodGet, pinnipedIDPsEndpoint, nil) if err != nil { return nil, fmt.Errorf("while forming request to IDP discovery URL: %w", err) @@ -849,7 +832,7 @@ func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDP return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not read response body: %w", err) } - var body supervisorIDPsDiscoveryResponseV1Alpha1 + var body idpdiscoveryv1alpha1.SupervisorIDPDiscoveryResponse err = json.Unmarshal(rawBody, &body) if err != nil { return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not parse response JSON: %w", err) @@ -858,7 +841,7 @@ func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDP return body.PinnipedIDPs, nil } -func selectUpstreamIDPNameAndType(pinnipedIDPs []pinnipedIDPResponse, specifiedIDPName, specifiedIDPType string) (string, string, []string, error) { +func selectUpstreamIDPNameAndType(pinnipedIDPs []idpdiscoveryv1alpha1.SupervisorPinnipedIDP, specifiedIDPName, specifiedIDPType string) (string, string, []string, error) { pinnipedIDPsString, _ := json.Marshal(pinnipedIDPs) var discoveredFlows []string switch { diff --git a/generated/1.17/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go b/generated/1.17/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/generated/1.17/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/generated/1.18/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go b/generated/1.18/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/generated/1.18/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/generated/1.19/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go b/generated/1.19/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/generated/1.19/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/generated/1.20/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go b/generated/1.20/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/generated/1.20/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/generated/latest/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go b/generated/latest/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go new file mode 100644 index 00000000..1d37195f --- /dev/null +++ b/generated/latest/apis/supervisor/idpdiscovery/v1alpha1/types_supervisor_idp_discovery.go @@ -0,0 +1,29 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration +// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider +// configuration metadata and only picks out the portion related to Supervisor identity provider discovery. +type SupervisorOIDCDiscoveryResponse struct { + SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` +} + +// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint. +type SupervisorOIDCDiscoveryResponseIDPEndpoint struct { + PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` +} + +// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint. +type SupervisorIDPDiscoveryResponse struct { + PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"` +} + +// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's +// identity provider discovery endpoint. +type SupervisorPinnipedIDP struct { + Name string `json:"name"` + Type string `json:"type"` + Flows []string `json:"flows,omitempty"` +} diff --git a/internal/oidc/discovery/discovery_handler.go b/internal/oidc/discovery/discovery_handler.go index 008808b6..591a6d98 100644 --- a/internal/oidc/discovery/discovery_handler.go +++ b/internal/oidc/discovery/discovery_handler.go @@ -9,6 +9,7 @@ import ( "encoding/json" "net/http" + "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1" "go.pinniped.dev/internal/oidc" ) @@ -41,20 +42,11 @@ type Metadata struct { // vvv Custom vvv - SupervisorDiscovery SupervisorDiscoveryMetadataV1Alpha1 `json:"discovery.supervisor.pinniped.dev/v1alpha1"` + SupervisorDiscovery v1alpha1.SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"` // ^^^ Custom ^^^ } -type SupervisorDiscoveryMetadataV1Alpha1 struct { - PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"` -} - -type IdentityProviderMetadata struct { - Name string `json:"name"` - Type string `json:"type"` -} - // NewHandler returns an http.Handler that serves an OIDC discovery endpoint. func NewHandler(issuerURL string) http.Handler { oidcConfig := Metadata{ @@ -62,7 +54,7 @@ func NewHandler(issuerURL string) http.Handler { AuthorizationEndpoint: issuerURL + oidc.AuthorizationEndpointPath, TokenEndpoint: issuerURL + oidc.TokenEndpointPath, JWKSURI: issuerURL + oidc.JWKSEndpointPath, - SupervisorDiscovery: SupervisorDiscoveryMetadataV1Alpha1{PinnipedIDPsEndpoint: issuerURL + oidc.PinnipedIDPsPathV1Alpha1}, + SupervisorDiscovery: v1alpha1.SupervisorOIDCDiscoveryResponseIDPEndpoint{PinnipedIDPsEndpoint: issuerURL + oidc.PinnipedIDPsPathV1Alpha1}, ResponseTypesSupported: []string{"code"}, ResponseModesSupported: []string{"query", "form_post"}, SubjectTypesSupported: []string{"public"}, diff --git a/internal/oidc/discovery/discovery_handler_test.go b/internal/oidc/discovery/discovery_handler_test.go index b1707f77..855f830d 100644 --- a/internal/oidc/discovery/discovery_handler_test.go +++ b/internal/oidc/discovery/discovery_handler_test.go @@ -4,13 +4,13 @@ package discovery import ( - "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/require" + "go.pinniped.dev/internal/here" "go.pinniped.dev/internal/oidc" ) @@ -24,7 +24,7 @@ func TestDiscovery(t *testing.T) { wantStatus int wantContentType string - wantBodyJSON interface{} + wantBodyJSON string wantBodyString string }{ { @@ -34,22 +34,24 @@ func TestDiscovery(t *testing.T) { path: "/some/path" + oidc.WellKnownEndpointPath, wantStatus: http.StatusOK, wantContentType: "application/json", - wantBodyJSON: &Metadata{ - Issuer: "https://some-issuer.com/some/path", - AuthorizationEndpoint: "https://some-issuer.com/some/path/oauth2/authorize", - TokenEndpoint: "https://some-issuer.com/some/path/oauth2/token", - JWKSURI: "https://some-issuer.com/some/path/jwks.json", - SupervisorDiscovery: SupervisorDiscoveryMetadataV1Alpha1{ - PinnipedIDPsEndpoint: "https://some-issuer.com/some/path/v1alpha1/pinniped_identity_providers", - }, - ResponseTypesSupported: []string{"code"}, - ResponseModesSupported: []string{"query", "form_post"}, - SubjectTypesSupported: []string{"public"}, - IDTokenSigningAlgValuesSupported: []string{"ES256"}, - TokenEndpointAuthMethodsSupported: []string{"client_secret_basic"}, - ScopesSupported: []string{"openid", "offline"}, - ClaimsSupported: []string{"groups"}, - }, + wantBodyJSON: here.Doc(` + { + "issuer": "https://some-issuer.com/some/path", + "authorization_endpoint": "https://some-issuer.com/some/path/oauth2/authorize", + "token_endpoint": "https://some-issuer.com/some/path/oauth2/token", + "jwks_uri": "https://some-issuer.com/some/path/jwks.json", + "response_types_supported": ["code"], + "response_modes_supported": ["query", "form_post"], + "subject_types_supported": ["public"], + "id_token_signing_alg_values_supported": ["ES256"], + "token_endpoint_auth_methods_supported": ["client_secret_basic"], + "scopes_supported": ["openid", "offline"], + "claims_supported": ["groups"], + "discovery.supervisor.pinniped.dev/v1alpha1": { + "pinniped_identity_providers_endpoint": "https://some-issuer.com/some/path/v1alpha1/pinniped_identity_providers" + } + } + `), }, { name: "bad method", @@ -73,10 +75,8 @@ func TestDiscovery(t *testing.T) { require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type")) - if test.wantBodyJSON != nil { - wantJSON, err := json.Marshal(test.wantBodyJSON) - require.NoError(t, err) - require.JSONEq(t, string(wantJSON), rsp.Body.String()) + if test.wantBodyJSON != "" { + require.JSONEq(t, test.wantBodyJSON, rsp.Body.String()) } if test.wantBodyString != "" { diff --git a/internal/oidc/idpdiscovery/idp_discovery_handler.go b/internal/oidc/idpdiscovery/idp_discovery_handler.go index 8e4535a8..32ce187d 100644 --- a/internal/oidc/idpdiscovery/idp_discovery_handler.go +++ b/internal/oidc/idpdiscovery/idp_discovery_handler.go @@ -10,6 +10,7 @@ import ( "net/http" "sort" + "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1" "go.pinniped.dev/internal/oidc" ) @@ -21,16 +22,6 @@ const ( flowCLIPassword = "cli_password" ) -type response struct { - IDPs []identityProviderResponse `json:"pinniped_identity_providers"` -} - -type identityProviderResponse struct { - Name string `json:"name"` - Type string `json:"type"` - Flows []string `json:"flows"` -} - // NewHandler returns an http.Handler that serves the upstream IDP discovery endpoint. func NewHandler(upstreamIDPs oidc.UpstreamIdentityProvidersLister) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -54,13 +45,13 @@ func NewHandler(upstreamIDPs oidc.UpstreamIdentityProvidersLister) http.Handler } func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte, error) { - r := response{ - IDPs: []identityProviderResponse{}, + r := v1alpha1.SupervisorIDPDiscoveryResponse{ + PinnipedIDPs: []v1alpha1.SupervisorPinnipedIDP{}, } // The cache of IDPs could change at any time, so always recalculate the list. for _, provider := range upstreamIDPs.GetLDAPIdentityProviders() { - r.IDPs = append(r.IDPs, identityProviderResponse{ + r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.SupervisorPinnipedIDP{ Name: provider.GetName(), Type: idpDiscoveryTypeLDAP, Flows: []string{flowCLIPassword}, @@ -71,7 +62,7 @@ func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte, if provider.AllowsPasswordGrant() { flows = append(flows, flowCLIPassword) } - r.IDPs = append(r.IDPs, identityProviderResponse{ + r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.SupervisorPinnipedIDP{ Name: provider.GetName(), Type: idpDiscoveryTypeOIDC, Flows: flows, @@ -79,8 +70,8 @@ func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte, } // Nobody like an API that changes the results unnecessarily. :) - sort.SliceStable(r.IDPs, func(i, j int) bool { - return r.IDPs[i].Name < r.IDPs[j].Name + sort.SliceStable(r.PinnipedIDPs, func(i, j int) bool { + return r.PinnipedIDPs[i].Name < r.PinnipedIDPs[j].Name }) var b bytes.Buffer diff --git a/internal/oidc/idpdiscovery/idp_discovery_handler_test.go b/internal/oidc/idpdiscovery/idp_discovery_handler_test.go index 8f7b270a..7faf8a35 100644 --- a/internal/oidc/idpdiscovery/idp_discovery_handler_test.go +++ b/internal/oidc/idpdiscovery/idp_discovery_handler_test.go @@ -4,13 +4,13 @@ package idpdiscovery import ( - "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/require" + "go.pinniped.dev/internal/here" "go.pinniped.dev/internal/oidc" "go.pinniped.dev/internal/oidc/provider" "go.pinniped.dev/internal/testutil/oidctestutil" @@ -25,8 +25,8 @@ func TestIDPDiscovery(t *testing.T) { wantStatus int wantContentType string - wantFirstResponseBodyJSON interface{} - wantSecondResponseBodyJSON interface{} + wantFirstResponseBodyJSON string + wantSecondResponseBodyJSON string wantBodyString string }{ { @@ -35,24 +35,24 @@ func TestIDPDiscovery(t *testing.T) { path: "/some/path" + oidc.WellKnownEndpointPath, wantStatus: http.StatusOK, wantContentType: "application/json", - wantFirstResponseBodyJSON: &response{ - IDPs: []identityProviderResponse{ - {Name: "a-some-ldap-idp", Type: "ldap", Flows: []string{"cli_password"}}, - {Name: "a-some-oidc-idp", Type: "oidc", Flows: []string{"browser_authcode"}}, - {Name: "x-some-idp", Type: "ldap", Flows: []string{"cli_password"}}, - {Name: "x-some-idp", Type: "oidc", Flows: []string{"browser_authcode"}}, - {Name: "z-some-ldap-idp", Type: "ldap", Flows: []string{"cli_password"}}, - {Name: "z-some-oidc-idp", Type: "oidc", Flows: []string{"browser_authcode", "cli_password"}}, - }, - }, - wantSecondResponseBodyJSON: &response{ - IDPs: []identityProviderResponse{ - {Name: "some-other-ldap-idp-1", Type: "ldap", Flows: []string{"cli_password"}}, - {Name: "some-other-ldap-idp-2", Type: "ldap", Flows: []string{"cli_password"}}, - {Name: "some-other-oidc-idp-1", Type: "oidc", Flows: []string{"browser_authcode", "cli_password"}}, - {Name: "some-other-oidc-idp-2", Type: "oidc", Flows: []string{"browser_authcode"}}, - }, - }, + wantFirstResponseBodyJSON: here.Doc(`{ + "pinniped_identity_providers": [ + {"name": "a-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]}, + {"name": "a-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode"]}, + {"name": "x-some-idp", "type": "ldap", "flows": ["cli_password"]}, + {"name": "x-some-idp", "type": "oidc", "flows": ["browser_authcode"]}, + {"name": "z-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]}, + {"name": "z-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode", "cli_password"]} + ] + }`), + wantSecondResponseBodyJSON: here.Doc(`{ + "pinniped_identity_providers": [ + {"name": "some-other-ldap-idp-1", "type": "ldap", "flows": ["cli_password"]}, + {"name": "some-other-ldap-idp-2", "type": "ldap", "flows": ["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: "bad method", @@ -84,10 +84,8 @@ func TestIDPDiscovery(t *testing.T) { require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type")) - if test.wantFirstResponseBodyJSON != nil { - wantJSON, err := json.Marshal(test.wantFirstResponseBodyJSON) - require.NoError(t, err) - require.JSONEq(t, string(wantJSON), rsp.Body.String()) + if test.wantFirstResponseBodyJSON != "" { + require.JSONEq(t, test.wantFirstResponseBodyJSON, rsp.Body.String()) } if test.wantBodyString != "" { @@ -112,10 +110,8 @@ func TestIDPDiscovery(t *testing.T) { require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type")) - if test.wantFirstResponseBodyJSON != nil { - wantJSON, err := json.Marshal(test.wantSecondResponseBodyJSON) - require.NoError(t, err) - require.JSONEq(t, string(wantJSON), rsp.Body.String()) + if test.wantFirstResponseBodyJSON != "" { + require.JSONEq(t, test.wantSecondResponseBodyJSON, rsp.Body.String()) } if test.wantBodyString != "" {