...

Source file src/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap_test.go

Documentation: k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap

     1  /*
     2  Copyright 2017 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 bootstrap
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	corev1 "k8s.io/api/core/v1"
    25  	"k8s.io/apimachinery/pkg/api/errors"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/labels"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  	"k8s.io/apiserver/pkg/authentication/user"
    30  	bootstrapapi "k8s.io/cluster-bootstrap/token/api"
    31  )
    32  
    33  type lister struct {
    34  	secrets []*corev1.Secret
    35  }
    36  
    37  func (l *lister) List(selector labels.Selector) (ret []*corev1.Secret, err error) {
    38  	return l.secrets, nil
    39  }
    40  
    41  func (l *lister) Get(name string) (*corev1.Secret, error) {
    42  	for _, s := range l.secrets {
    43  		if s.Name == name {
    44  			return s, nil
    45  		}
    46  	}
    47  	return nil, errors.NewNotFound(schema.GroupResource{}, name)
    48  }
    49  
    50  const (
    51  	// Fake values for testing.
    52  	tokenID     = "foobar"           // 6 letters
    53  	tokenSecret = "circumnavigation" // 16 letters
    54  )
    55  
    56  func TestTokenAuthenticator(t *testing.T) {
    57  	now := metav1.Now()
    58  
    59  	tests := []struct {
    60  		name string
    61  
    62  		secrets []*corev1.Secret
    63  		token   string
    64  
    65  		wantNotFound bool
    66  		wantUser     *user.DefaultInfo
    67  	}{
    68  		{
    69  			name: "valid token",
    70  			secrets: []*corev1.Secret{
    71  				{
    72  					ObjectMeta: metav1.ObjectMeta{
    73  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
    74  					},
    75  					Data: map[string][]byte{
    76  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
    77  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
    78  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
    79  					},
    80  					Type: "bootstrap.kubernetes.io/token",
    81  				},
    82  			},
    83  			token: tokenID + "." + tokenSecret,
    84  			wantUser: &user.DefaultInfo{
    85  				Name:   "system:bootstrap:" + tokenID,
    86  				Groups: []string{"system:bootstrappers"},
    87  			},
    88  		},
    89  		{
    90  			name: "valid token with extra group",
    91  			secrets: []*corev1.Secret{
    92  				{
    93  					ObjectMeta: metav1.ObjectMeta{
    94  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
    95  					},
    96  					Data: map[string][]byte{
    97  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
    98  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
    99  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   100  						bootstrapapi.BootstrapTokenExtraGroupsKey:      []byte("system:bootstrappers:foo"),
   101  					},
   102  					Type: "bootstrap.kubernetes.io/token",
   103  				},
   104  			},
   105  			token: tokenID + "." + tokenSecret,
   106  			wantUser: &user.DefaultInfo{
   107  				Name:   "system:bootstrap:" + tokenID,
   108  				Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
   109  			},
   110  		},
   111  		{
   112  			name: "invalid group",
   113  			secrets: []*corev1.Secret{
   114  				{
   115  					ObjectMeta: metav1.ObjectMeta{
   116  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   117  					},
   118  					Data: map[string][]byte{
   119  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   120  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   121  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   122  						bootstrapapi.BootstrapTokenExtraGroupsKey:      []byte("foo"),
   123  					},
   124  					Type: "bootstrap.kubernetes.io/token",
   125  				},
   126  			},
   127  			token:        tokenID + "." + tokenSecret,
   128  			wantNotFound: true,
   129  		},
   130  		{
   131  			name: "invalid secret name",
   132  			secrets: []*corev1.Secret{
   133  				{
   134  					ObjectMeta: metav1.ObjectMeta{
   135  						Name: "bad-name",
   136  					},
   137  					Data: map[string][]byte{
   138  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   139  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   140  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   141  					},
   142  					Type: "bootstrap.kubernetes.io/token",
   143  				},
   144  			},
   145  			token:        tokenID + "." + tokenSecret,
   146  			wantNotFound: true,
   147  		},
   148  		{
   149  			name: "no usage",
   150  			secrets: []*corev1.Secret{
   151  				{
   152  					ObjectMeta: metav1.ObjectMeta{
   153  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   154  					},
   155  					Data: map[string][]byte{
   156  						bootstrapapi.BootstrapTokenIDKey:     []byte(tokenID),
   157  						bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret),
   158  					},
   159  					Type: "bootstrap.kubernetes.io/token",
   160  				},
   161  			},
   162  			token:        tokenID + "." + tokenSecret,
   163  			wantNotFound: true,
   164  		},
   165  		{
   166  			name: "wrong token",
   167  			secrets: []*corev1.Secret{
   168  				{
   169  					ObjectMeta: metav1.ObjectMeta{
   170  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   171  					},
   172  					Data: map[string][]byte{
   173  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   174  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   175  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   176  					},
   177  					Type: "bootstrap.kubernetes.io/token",
   178  				},
   179  			},
   180  			token:        "barfoo" + "." + tokenSecret,
   181  			wantNotFound: true,
   182  		},
   183  		{
   184  			name: "deleted token",
   185  			secrets: []*corev1.Secret{
   186  				{
   187  					ObjectMeta: metav1.ObjectMeta{
   188  						Name:              bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   189  						DeletionTimestamp: &now,
   190  					},
   191  					Data: map[string][]byte{
   192  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   193  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   194  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   195  					},
   196  					Type: "bootstrap.kubernetes.io/token",
   197  				},
   198  			},
   199  			token:        tokenID + "." + tokenSecret,
   200  			wantNotFound: true,
   201  		},
   202  		{
   203  			name: "expired token",
   204  			secrets: []*corev1.Secret{
   205  				{
   206  					ObjectMeta: metav1.ObjectMeta{
   207  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   208  					},
   209  					Data: map[string][]byte{
   210  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   211  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   212  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   213  						bootstrapapi.BootstrapTokenExpirationKey:       []byte("2009-11-10T23:00:00Z"),
   214  					},
   215  					Type: "bootstrap.kubernetes.io/token",
   216  				},
   217  			},
   218  			token:        tokenID + "." + tokenSecret,
   219  			wantNotFound: true,
   220  		},
   221  		{
   222  			name: "not expired token",
   223  			secrets: []*corev1.Secret{
   224  				{
   225  					ObjectMeta: metav1.ObjectMeta{
   226  						Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
   227  					},
   228  					Data: map[string][]byte{
   229  						bootstrapapi.BootstrapTokenIDKey:               []byte(tokenID),
   230  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   231  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   232  						bootstrapapi.BootstrapTokenExpirationKey:       []byte("2109-11-10T23:00:00Z"),
   233  					},
   234  					Type: "bootstrap.kubernetes.io/token",
   235  				},
   236  			},
   237  			token: tokenID + "." + tokenSecret,
   238  			wantUser: &user.DefaultInfo{
   239  				Name:   "system:bootstrap:" + tokenID,
   240  				Groups: []string{"system:bootstrappers"},
   241  			},
   242  		},
   243  		{
   244  			name: "token id wrong length",
   245  			secrets: []*corev1.Secret{
   246  				{
   247  					ObjectMeta: metav1.ObjectMeta{
   248  						Name: bootstrapapi.BootstrapTokenSecretPrefix + "foo",
   249  					},
   250  					Data: map[string][]byte{
   251  						bootstrapapi.BootstrapTokenIDKey:               []byte("foo"),
   252  						bootstrapapi.BootstrapTokenSecretKey:           []byte(tokenSecret),
   253  						bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
   254  					},
   255  					Type: "bootstrap.kubernetes.io/token",
   256  				},
   257  			},
   258  			// Token ID must be 6 characters.
   259  			token:        "foo" + "." + tokenSecret,
   260  			wantNotFound: true,
   261  		},
   262  	}
   263  
   264  	for _, test := range tests {
   265  		func() {
   266  			a := NewTokenAuthenticator(&lister{test.secrets})
   267  			resp, found, err := a.AuthenticateToken(context.Background(), test.token)
   268  			if err != nil {
   269  				t.Errorf("test %q returned an error: %v", test.name, err)
   270  				return
   271  			}
   272  
   273  			if !found {
   274  				if !test.wantNotFound {
   275  					t.Errorf("test %q expected to get user", test.name)
   276  				}
   277  				return
   278  			}
   279  
   280  			if test.wantNotFound {
   281  				t.Errorf("test %q expected to not get a user", test.name)
   282  				return
   283  			}
   284  
   285  			gotUser := resp.User.(*user.DefaultInfo)
   286  			if !reflect.DeepEqual(gotUser, test.wantUser) {
   287  				t.Errorf("test %q want user=%#v, got=%#v", test.name, test.wantUser, gotUser)
   288  			}
   289  		}()
   290  	}
   291  }
   292  

View as plain text