Merge branch 'main' into initial_ldap

This commit is contained in:
Ryan Richard
2021-05-11 11:09:37 -07:00
37 changed files with 1949 additions and 231 deletions
+18
View File
@@ -20,6 +20,7 @@ import (
"time"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/go-logr/logr"
"github.com/pkg/browser"
"golang.org/x/oauth2"
"golang.org/x/term"
@@ -58,11 +59,14 @@ const (
defaultLDAPPasswordPrompt = "Password: "
httpLocationHeaderName = "Location"
debugLogLevel = 4
)
type handlerState struct {
// Basic parameters.
ctx context.Context
logger logr.Logger
issuer string
clientID string
scopes []string
@@ -117,6 +121,15 @@ func WithContext(ctx context.Context) Option {
}
}
// WithLogger specifies a PLogger to use with the login.
// If not specified this will default to a new logger.
func WithLogger(logger logr.Logger) Option {
return func(h *handlerState) error {
h.logger = logger
return nil
}
}
// WithListenPort specifies a TCP listen port on localhost, which will be used for the redirect_uri and to handle the
// authorization code callback. By default, a random high port will be chosen which requires the authorization server
// to support wildcard port numbers as described by https://tools.ietf.org/html/rfc8252#section-7.3:
@@ -227,6 +240,7 @@ func Login(issuer string, clientID string, opts ...Option) (*oidctypes.Token, er
cache: &nopCache{},
callbackPath: "/callback",
ctx: context.Background(),
logger: logr.Discard(), // discard logs unless a logger is specified
callbacks: make(chan callbackResult),
httpClient: http.DefaultClient,
@@ -306,6 +320,7 @@ func (h *handlerState) baseLogin() (*oidctypes.Token, error) {
// If the ID token is still valid for a bit, return it immediately and skip the rest of the flow.
cached := h.cache.GetToken(cacheKey)
if cached != nil && cached.IDToken != nil && time.Until(cached.IDToken.Expiry.Time) > minIDTokenValidity {
h.logger.V(debugLogLevel).Info("Pinniped: Found unexpired cached token.")
return cached, nil
}
@@ -538,6 +553,7 @@ func (h *handlerState) initOIDCDiscovery() error {
return nil
}
h.logger.V(debugLogLevel).Info("Pinniped: Performing OIDC discovery", "issuer", h.issuer)
var err error
h.provider, err = oidc.NewProvider(h.ctx, h.issuer)
if err != nil {
@@ -554,6 +570,7 @@ func (h *handlerState) initOIDCDiscovery() error {
}
func (h *handlerState) tokenExchangeRFC8693(baseToken *oidctypes.Token) (*oidctypes.Token, error) {
h.logger.V(debugLogLevel).Info("Pinniped: Performing RFC8693 token exchange", "requestedAudience", h.requestedAudience)
// Perform OIDC discovery. This may have already been performed if there was not a cached base token.
if err := h.initOIDCDiscovery(); err != nil {
return nil, err
@@ -624,6 +641,7 @@ func (h *handlerState) tokenExchangeRFC8693(baseToken *oidctypes.Token) (*oidcty
}
func (h *handlerState) handleRefresh(ctx context.Context, refreshToken *oidctypes.RefreshToken) (*oidctypes.Token, error) {
h.logger.V(debugLogLevel).Info("Pinniped: Refreshing cached token.")
refreshSource := h.oauth2Config.TokenSource(ctx, &oauth2.Token{RefreshToken: refreshToken.Token})
refreshed, err := refreshSource.Token()
+105 -30
View File
@@ -16,18 +16,22 @@ import (
"testing"
"time"
"github.com/go-logr/stdr"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
"go.pinniped.dev/internal/httputil/httperr"
"go.pinniped.dev/internal/httputil/roundtripper"
"go.pinniped.dev/internal/mocks/mockupstreamoidcidentityprovider"
"go.pinniped.dev/internal/oidc/provider"
"go.pinniped.dev/internal/testutil"
"go.pinniped.dev/internal/testutil/testlogger"
"go.pinniped.dev/pkg/oidcclient/nonce"
"go.pinniped.dev/pkg/oidcclient/oidctypes"
"go.pinniped.dev/pkg/oidcclient/pkce"
@@ -254,6 +258,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
clientID string
wantErr string
wantToken *oidctypes.Token
wantLogs []string
}{
{
name: "option error",
@@ -318,7 +323,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return WithSessionCache(cache)(h)
}
},
wantErr: `could not perform OIDC discovery for "test-issuer": Get "test-issuer/.well-known/openid-configuration": unsupported protocol scheme ""`,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"test-issuer\""},
wantErr: `could not perform OIDC discovery for "test-issuer": Get "test-issuer/.well-known/openid-configuration": unsupported protocol scheme ""`,
},
{
name: "session cache hit with valid token",
@@ -339,6 +345,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return WithSessionCache(cache)(h)
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\""},
wantToken: &testToken,
},
{
@@ -346,8 +353,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
opt: func(t *testing.T) Option {
return func(h *handlerState) error { return nil }
},
issuer: errorServer.URL,
wantErr: fmt.Sprintf("could not perform OIDC discovery for %q: 500 Internal Server Error: some discovery error\n", errorServer.URL),
issuer: errorServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + errorServer.URL + "\""},
wantErr: fmt.Sprintf("could not perform OIDC discovery for %q: 500 Internal Server Error: some discovery error\n", errorServer.URL),
},
{
name: "session cache hit with refreshable token",
@@ -386,6 +394,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\"",
"\"level\"=4 \"msg\"=\"Pinniped: Refreshing cached token.\""},
wantToken: &testToken,
},
{
@@ -418,6 +428,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\"",
"\"level\"=4 \"msg\"=\"Pinniped: Refreshing cached token.\""},
wantErr: "some validation error",
},
{
@@ -444,6 +456,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\"",
"\"level\"=4 \"msg\"=\"Pinniped: Refreshing cached token.\""},
// Expect this to fall through to the authorization code flow, so it fails here.
wantErr: "could not open callback listener: listen tcp: address invalid-listen-address: missing port in address",
},
@@ -455,8 +469,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "could not open callback listener: listen tcp: address invalid-listen-address: missing port in address",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "could not open callback listener: listen tcp: address invalid-listen-address: missing port in address",
},
{
name: "browser open failure",
@@ -465,8 +480,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return fmt.Errorf("some browser open error")
})
},
issuer: successServer.URL,
wantErr: "could not open browser: some browser open error",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "could not open browser: some browser open error",
},
{
name: "timeout waiting for callback",
@@ -482,8 +498,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "timed out waiting for token callback: context canceled",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "timed out waiting for token callback: context canceled",
},
{
name: "callback returns error",
@@ -498,8 +515,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "error handling callback: some callback error",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "error handling callback: some callback error",
},
{
name: "callback returns success",
@@ -559,6 +577,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}
},
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantToken: &testToken,
},
{
@@ -622,6 +641,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}
},
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantToken: &testToken,
},
{
@@ -637,8 +657,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "error prompting for username: some prompt error",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "error prompting for username: some prompt error",
},
{
name: "ldap login when prompting for password returns an error",
@@ -650,8 +671,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "error prompting for password: some prompt error",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "error prompting for password: some prompt error",
},
{
name: "ldap login when there is a problem with parsing the authorize URL",
@@ -690,8 +712,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: `could not build authorize request: parse "%?access_type=offline&client_id=test-client-id&code_challenge=VVaezYqum7reIhoavCHD1n2d-piN3r_mywoYj7fCR7g&code_challenge_method=S256&nonce=test-nonce&pinniped_idp_name=some-upstream-name&pinniped_idp_type=ldap&redirect_uri=http%3A%2F%2F127.0.0.1%3A0%2Fcallback&response_type=code&scope=test-scope&state=test-state": invalid URL escape "%"`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `could not build authorize request: parse "%?access_type=offline&client_id=test-client-id&code_challenge=VVaezYqum7reIhoavCHD1n2d-piN3r_mywoYj7fCR7g&code_challenge_method=S256&nonce=test-nonce&pinniped_idp_name=some-upstream-name&pinniped_idp_type=ldap&redirect_uri=http%3A%2F%2F127.0.0.1%3A0%2Fcallback&response_type=code&scope=test-scope&state=test-state": invalid URL escape "%"`,
},
{
name: "ldap login when there is an error calling the authorization endpoint",
@@ -701,7 +724,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return defaultLDAPTestOpts(t, h, nil, errors.New("some error fetching authorize endpoint"))
}
},
issuer: successServer.URL,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `authorization response error: Get "http://` + successServer.Listener.Addr().String() +
`/authorize?access_type=offline&client_id=test-client-id&code_challenge=VVaezYqum7reIhoavCHD1n2d-piN3r_mywoYj7fCR7g&code_challenge_method=S256&nonce=test-nonce&pinniped_idp_name=some-upstream-name&pinniped_idp_type=ldap&redirect_uri=http%3A%2F%2F127.0.0.1%3A0%2Fcallback&response_type=code&scope=test-scope&state=test-state": some error fetching authorize endpoint`,
},
@@ -713,8 +737,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return defaultLDAPTestOpts(t, h, &http.Response{StatusCode: http.StatusBadGateway, Status: "502 Bad Gateway"}, nil)
}
},
issuer: successServer.URL,
wantErr: `error getting authorization: expected to be redirected, but response status was 502 Bad Gateway`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `error getting authorization: expected to be redirected, but response status was 502 Bad Gateway`,
},
{
name: "ldap login when the OIDC provider authorization endpoint redirect has an error and error description",
@@ -729,8 +754,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}, nil)
}
},
issuer: successServer.URL,
wantErr: `login failed with code "access_denied": optional-error-description`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `login failed with code "access_denied": optional-error-description`,
},
{
name: "ldap login when the OIDC provider authorization endpoint redirects us to a different server",
@@ -745,8 +771,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}, nil)
}
},
issuer: successServer.URL,
wantErr: `error getting authorization: redirected to the wrong location: http://other-server.example.com/callback?code=foo&state=test-state`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `error getting authorization: redirected to the wrong location: http://other-server.example.com/callback?code=foo&state=test-state`,
},
{
name: "ldap login when the OIDC provider authorization endpoint redirect has an error but no error description",
@@ -761,8 +788,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}, nil)
}
},
issuer: successServer.URL,
wantErr: `login failed with code "access_denied"`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `login failed with code "access_denied"`,
},
{
name: "ldap login when the OIDC provider authorization endpoint redirect has the wrong state value",
@@ -775,8 +803,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}, nil)
}
},
issuer: successServer.URL,
wantErr: `missing or invalid state parameter in authorization response: http://127.0.0.1:0/callback?code=foo&state=wrong-state`,
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `missing or invalid state parameter in authorization response: http://127.0.0.1:0/callback?code=foo&state=wrong-state`,
},
{
name: "ldap login when there is an error exchanging the authcode or validating the tokens",
@@ -801,8 +830,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
issuer: successServer.URL,
wantErr: "error during authorization code exchange: some authcode exchange or token validation error",
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: "error during authorization code exchange: some authcode exchange or token validation error",
},
{
name: "successful ldap login",
@@ -898,6 +928,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
}
},
issuer: successServer.URL,
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantToken: &testToken,
},
{
@@ -921,6 +952,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"cluster-1234\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + errorServer.URL + "\""},
wantErr: fmt.Sprintf("failed to exchange token: could not perform OIDC discovery for %q: 500 Internal Server Error: some discovery error\n", errorServer.URL),
},
{
@@ -944,6 +978,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"cluster-1234\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + brokenTokenURLServer.URL + "\""},
wantErr: `failed to exchange token: could not build RFC8693 request: parse "%": invalid URL escape "%"`,
},
{
@@ -967,6 +1004,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-http-response\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: fmt.Sprintf(`failed to exchange token: Post "%s/token": failed to parse Location header "%%": parse "%%": invalid URL escape "%%"`, successServer.URL),
},
{
@@ -990,6 +1030,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-http-400\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: unexpected HTTP response status 400`,
},
{
@@ -1013,6 +1056,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-content-type\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: failed to decode content-type header: mime: invalid media parameter`,
},
{
@@ -1036,6 +1082,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-wrong-content-type\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: unexpected HTTP response content type "invalid"`,
},
{
@@ -1059,6 +1108,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-json\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: failed to decode response: unexpected EOF`,
},
{
@@ -1082,6 +1134,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-tokentype\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: got unexpected token_type "invalid"`,
},
{
@@ -1105,6 +1160,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-issuedtokentype\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: got unexpected issued_token_type "invalid"`,
},
{
@@ -1128,6 +1186,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience-produce-invalid-jwt\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantErr: `failed to exchange token: received invalid JWT: oidc: malformed jwt: square/go-jose: compact JWS format must have three parts`,
},
{
@@ -1157,6 +1218,9 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{"\"level\"=4 \"msg\"=\"Pinniped: Found unexpired cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\""},
wantToken: &testExchangedToken,
},
{
@@ -1204,18 +1268,29 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
return nil
}
},
wantLogs: []string{
"\"level\"=4 \"msg\"=\"Pinniped: Performing OIDC discovery\" \"issuer\"=\"" + successServer.URL + "\"",
"\"level\"=4 \"msg\"=\"Pinniped: Refreshing cached token.\"",
"\"level\"=4 \"msg\"=\"Pinniped: Performing RFC8693 token exchange\" \"requestedAudience\"=\"test-audience\"",
},
wantToken: &testExchangedToken,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
testLogger := testlogger.New(t)
klog.SetLogger(testLogger)
stdr.SetVerbosity(debugLogLevel) // set stdr's global log level to debug so the test logger will send output.
tok, err := Login(tt.issuer, tt.clientID,
WithContext(context.Background()),
WithListenPort(0),
WithScopes([]string{"test-scope"}),
tt.opt(t),
WithLogger(testLogger),
)
require.Equal(t, tt.wantLogs, testLogger.Lines())
if tt.wantErr != "" {
require.EqualError(t, err, tt.wantErr)
require.Nil(t, tok)