2020-09-16 14:19:51 +00:00
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
2020-08-25 15:48:14 +00:00
package client
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/require"
2020-09-17 22:11:47 +00:00
corev1 "k8s.io/api/core/v1"
2020-08-25 15:48:14 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
2020-10-30 14:34:43 +00:00
loginv1alpha1 "go.pinniped.dev/generated/1.19/apis/concierge/login/v1alpha1"
2020-09-17 22:11:47 +00:00
idpv1alpha1 "go.pinniped.dev/generated/1.19/apis/idp/v1alpha1"
2020-09-18 19:56:24 +00:00
"go.pinniped.dev/internal/testutil"
2020-08-25 15:48:14 +00:00
)
func TestExchangeToken ( t * testing . T ) {
t . Parallel ( )
ctx := context . Background ( )
2020-09-17 22:11:47 +00:00
testIDP := corev1 . TypedLocalObjectReference {
APIGroup : & idpv1alpha1 . SchemeGroupVersion . Group ,
Kind : "WebhookIdentityProvider" ,
Name : "test-webhook" ,
}
2020-08-25 15:48:14 +00:00
t . Run ( "invalid configuration" , func ( t * testing . T ) {
t . Parallel ( )
2020-09-17 22:11:47 +00:00
got , err := ExchangeToken ( ctx , "test-namespace" , testIDP , "" , "" , "" )
2020-08-25 15:48:14 +00:00
require . EqualError ( t , err , "could not get API client: invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable" )
require . Nil ( t , got )
} )
t . Run ( "server error" , func ( t * testing . T ) {
t . Parallel ( )
// Start a test server that returns only 500 errors.
2020-09-14 15:34:41 +00:00
caBundle , endpoint := testutil . TLSTestServer ( t , func ( w http . ResponseWriter , r * http . Request ) {
2020-08-25 15:48:14 +00:00
w . WriteHeader ( http . StatusInternalServerError )
_ , _ = w . Write ( [ ] byte ( "some server error" ) )
} )
2020-09-17 22:11:47 +00:00
got , err := ExchangeToken ( ctx , "test-namespace" , testIDP , "" , caBundle , endpoint )
2020-10-30 14:34:43 +00:00
require . EqualError ( t , err , ` could not login: an error on the server ("some server error") has prevented the request from succeeding (post tokencredentialrequests.login.concierge.pinniped.dev) ` )
2020-08-25 15:48:14 +00:00
require . Nil ( t , got )
} )
t . Run ( "login failure" , func ( t * testing . T ) {
t . Parallel ( )
// Start a test server that returns success but with an error message
errorMessage := "some login failure"
2020-09-14 15:34:41 +00:00
caBundle , endpoint := testutil . TLSTestServer ( t , func ( w http . ResponseWriter , r * http . Request ) {
2020-08-25 15:48:14 +00:00
w . Header ( ) . Set ( "content-type" , "application/json" )
2020-09-17 22:11:47 +00:00
_ = json . NewEncoder ( w ) . Encode ( & loginv1alpha1 . TokenCredentialRequest {
2020-10-30 14:34:43 +00:00
TypeMeta : metav1 . TypeMeta { APIVersion : "login.concierge.pinniped.dev/v1alpha1" , Kind : "TokenCredentialRequest" } ,
2020-09-17 22:11:47 +00:00
Status : loginv1alpha1 . TokenCredentialRequestStatus { Message : & errorMessage } ,
2020-08-25 15:48:14 +00:00
} )
} )
2020-09-17 22:11:47 +00:00
got , err := ExchangeToken ( ctx , "test-namespace" , testIDP , "" , caBundle , endpoint )
2020-08-25 15:48:14 +00:00
require . EqualError ( t , err , ` login failed: some login failure ` )
require . Nil ( t , got )
} )
2020-09-16 20:03:54 +00:00
t . Run ( "login failure unknown error" , func ( t * testing . T ) {
t . Parallel ( )
// Start a test server that returns without any error message but also without valid credentials
caBundle , endpoint := testutil . TLSTestServer ( t , func ( w http . ResponseWriter , r * http . Request ) {
w . Header ( ) . Set ( "content-type" , "application/json" )
2020-09-17 22:11:47 +00:00
_ = json . NewEncoder ( w ) . Encode ( & loginv1alpha1 . TokenCredentialRequest {
2020-10-30 14:34:43 +00:00
TypeMeta : metav1 . TypeMeta { APIVersion : "login.concierge.pinniped.dev/v1alpha1" , Kind : "TokenCredentialRequest" } ,
2020-09-16 20:03:54 +00:00
} )
} )
2020-09-17 22:11:47 +00:00
got , err := ExchangeToken ( ctx , "test-namespace" , testIDP , "" , caBundle , endpoint )
2020-09-16 20:03:54 +00:00
require . EqualError ( t , err , ` login failed: unknown ` )
require . Nil ( t , got )
} )
2020-08-25 15:48:14 +00:00
t . Run ( "success" , func ( t * testing . T ) {
t . Parallel ( )
expires := metav1 . NewTime ( time . Now ( ) . Truncate ( time . Second ) )
// Start a test server that returns successfully and asserts various properties of the request.
2020-09-14 15:34:41 +00:00
caBundle , endpoint := testutil . TLSTestServer ( t , func ( w http . ResponseWriter , r * http . Request ) {
2020-08-25 15:48:14 +00:00
require . Equal ( t , http . MethodPost , r . Method )
2020-10-30 14:34:43 +00:00
require . Equal ( t , "/apis/login.concierge.pinniped.dev/v1alpha1/namespaces/test-namespace/tokencredentialrequests" , r . URL . Path )
2020-08-25 15:48:14 +00:00
require . Equal ( t , "application/json" , r . Header . Get ( "content-type" ) )
body , err := ioutil . ReadAll ( r . Body )
require . NoError ( t , err )
require . JSONEq ( t ,
` {
2020-09-16 20:03:54 +00:00
"kind" : "TokenCredentialRequest" ,
2020-10-30 14:34:43 +00:00
"apiVersion" : "login.concierge.pinniped.dev/v1alpha1" ,
2020-08-25 15:48:14 +00:00
"metadata" : {
2020-09-21 22:31:07 +00:00
"creationTimestamp" : null ,
"namespace" : "test-namespace"
2020-08-25 15:48:14 +00:00
} ,
"spec" : {
2020-09-17 22:11:47 +00:00
"token" : "test-token" ,
"identityProvider" : {
"apiGroup" : "idp.pinniped.dev" ,
"kind" : "WebhookIdentityProvider" ,
"name" : "test-webhook"
}
2020-08-25 15:48:14 +00:00
} ,
"status" : { }
} ` ,
string ( body ) ,
)
w . Header ( ) . Set ( "content-type" , "application/json" )
2020-09-17 22:11:47 +00:00
_ = json . NewEncoder ( w ) . Encode ( & loginv1alpha1 . TokenCredentialRequest {
2020-10-30 14:34:43 +00:00
TypeMeta : metav1 . TypeMeta { APIVersion : "login.concierge.pinniped.dev/v1alpha1" , Kind : "TokenCredentialRequest" } ,
2020-09-17 22:11:47 +00:00
Status : loginv1alpha1 . TokenCredentialRequestStatus {
Credential : & loginv1alpha1 . ClusterCredential {
2020-08-25 15:48:14 +00:00
ExpirationTimestamp : expires ,
ClientCertificateData : "test-certificate" ,
ClientKeyData : "test-key" ,
} ,
} ,
} )
} )
2020-09-17 22:11:47 +00:00
got , err := ExchangeToken ( ctx , "test-namespace" , testIDP , "test-token" , caBundle , endpoint )
2020-08-25 15:48:14 +00:00
require . NoError ( t , err )
require . Equal ( t , & clientauthenticationv1beta1 . ExecCredential {
TypeMeta : metav1 . TypeMeta {
Kind : "ExecCredential" ,
APIVersion : "client.authentication.k8s.io/v1beta1" ,
} ,
Status : & clientauthenticationv1beta1 . ExecCredentialStatus {
ClientCertificateData : "test-certificate" ,
ClientKeyData : "test-key" ,
ExpirationTimestamp : & expires ,
} ,
} , got )
} )
}