k8s.io/client-go@v0.31.1/plugin/pkg/client/auth/oidc/oidc_test.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package oidc
    18  
    19  import (
    20  	"encoding/base64"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  	"time"
    25  )
    26  
    27  func TestJSONTime(t *testing.T) {
    28  	data := `{
    29  		"t1": 1493851263,
    30  		"t2": 1.493851263e9
    31  	}`
    32  
    33  	var v struct {
    34  		T1 jsonTime `json:"t1"`
    35  		T2 jsonTime `json:"t2"`
    36  	}
    37  	if err := json.Unmarshal([]byte(data), &v); err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	wantT1 := time.Unix(1493851263, 0)
    41  	wantT2 := time.Unix(1493851263, 0)
    42  	gotT1 := time.Time(v.T1)
    43  	gotT2 := time.Time(v.T2)
    44  
    45  	if !wantT1.Equal(gotT1) {
    46  		t.Errorf("t1 value: wanted %s got %s", wantT1, gotT1)
    47  	}
    48  	if !wantT2.Equal(gotT2) {
    49  		t.Errorf("t2 value: wanted %s got %s", wantT2, gotT2)
    50  	}
    51  }
    52  
    53  func encodeJWT(header, payload, sig string) string {
    54  	e := func(s string) string {
    55  		return base64.RawURLEncoding.EncodeToString([]byte(s))
    56  	}
    57  	return e(header) + "." + e(payload) + "." + e(sig)
    58  }
    59  
    60  func TestExpired(t *testing.T) {
    61  	now := time.Now()
    62  
    63  	nowFunc := func() time.Time { return now }
    64  
    65  	tests := []struct {
    66  		name        string
    67  		idToken     string
    68  		wantErr     bool
    69  		wantExpired bool
    70  	}{
    71  		{
    72  			name: "valid",
    73  			idToken: encodeJWT(
    74  				"{}",
    75  				fmt.Sprintf(`{"exp":%d}`, now.Add(time.Hour).Unix()),
    76  				"blah", // signature isn't veified.
    77  			),
    78  		},
    79  		{
    80  			name: "expired",
    81  			idToken: encodeJWT(
    82  				"{}",
    83  				fmt.Sprintf(`{"exp":%d}`, now.Add(-time.Hour).Unix()),
    84  				"blah", // signature isn't veified.
    85  			),
    86  			wantExpired: true,
    87  		},
    88  		{
    89  			name: "bad exp claim",
    90  			idToken: encodeJWT(
    91  				"{}",
    92  				`{"exp":"foobar"}`,
    93  				"blah", // signature isn't veified.
    94  			),
    95  			wantErr: true,
    96  		},
    97  		{
    98  			name:    "not an id token",
    99  			idToken: "notanidtoken",
   100  			wantErr: true,
   101  		},
   102  	}
   103  	for _, test := range tests {
   104  		t.Run(test.name, func(t *testing.T) {
   105  			valid, err := idTokenExpired(nowFunc, test.idToken)
   106  			if err != nil {
   107  				if !test.wantErr {
   108  					t.Errorf("parse error: %v", err)
   109  				}
   110  				return
   111  			}
   112  			if test.wantExpired == valid {
   113  				t.Errorf("wanted expired %t, got %t", test.wantExpired, !valid)
   114  			}
   115  		})
   116  	}
   117  }
   118  
   119  func TestClientCache(t *testing.T) {
   120  	cache := newClientCache()
   121  
   122  	if _, ok := cache.getClient("cluster1", "issuer1", "id1"); ok {
   123  		t.Fatalf("got client before putting one in the cache")
   124  	}
   125  	assertCacheLen(t, cache, 0)
   126  
   127  	cli1 := new(oidcAuthProvider)
   128  	cli2 := new(oidcAuthProvider)
   129  	cli3 := new(oidcAuthProvider)
   130  
   131  	gotcli := cache.setClient("cluster1", "issuer1", "id1", cli1)
   132  	if cli1 != gotcli {
   133  		t.Fatalf("set first client and got a different one")
   134  	}
   135  	assertCacheLen(t, cache, 1)
   136  
   137  	gotcli = cache.setClient("cluster1", "issuer1", "id1", cli2)
   138  	if cli1 != gotcli {
   139  		t.Fatalf("set a second client and didn't get the first")
   140  	}
   141  	assertCacheLen(t, cache, 1)
   142  
   143  	gotcli = cache.setClient("cluster2", "issuer1", "id1", cli3)
   144  	if cli1 == gotcli {
   145  		t.Fatalf("set a third client and got the first")
   146  	}
   147  	if cli3 != gotcli {
   148  		t.Fatalf("set third client and got a different one")
   149  	}
   150  	assertCacheLen(t, cache, 2)
   151  }
   152  
   153  func assertCacheLen(t *testing.T, cache *clientCache, length int) {
   154  	t.Helper()
   155  	if len(cache.cache) != length {
   156  		t.Errorf("expected cache length %d got %d", length, len(cache.cache))
   157  	}
   158  }