...

Source file src/k8s.io/kubernetes/plugin/pkg/admission/certificates/subjectrestriction/admission_test.go

Documentation: k8s.io/kubernetes/plugin/pkg/admission/certificates/subjectrestriction

     1  /*
     2  Copyright 2020 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 subjectrestriction
    18  
    19  import (
    20  	"context"
    21  	"crypto/ed25519"
    22  	"crypto/rand"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/pem"
    26  	"testing"
    27  
    28  	certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
    29  	"k8s.io/apimachinery/pkg/runtime"
    30  	"k8s.io/apimachinery/pkg/runtime/schema"
    31  	"k8s.io/apiserver/pkg/admission"
    32  	certificatesapi "k8s.io/kubernetes/pkg/apis/certificates"
    33  )
    34  
    35  func TestPlugin_Validate(t *testing.T) {
    36  	tests := []struct {
    37  		name    string
    38  		a       admission.Attributes
    39  		wantErr string
    40  	}{
    41  		{
    42  			name: "ignored resource",
    43  			a: &testAttributes{
    44  				resource: schema.GroupResource{
    45  					Group:    "foo",
    46  					Resource: "bar",
    47  				},
    48  			},
    49  			wantErr: "",
    50  		},
    51  		{
    52  			name: "ignored subresource",
    53  			a: &testAttributes{
    54  				resource:    certificatesapi.Resource("certificatesigningrequests"),
    55  				subresource: "approve",
    56  			},
    57  			wantErr: "",
    58  		},
    59  		{
    60  			name: "wrong type",
    61  			a: &testAttributes{
    62  				resource: certificatesapi.Resource("certificatesigningrequests"),
    63  				obj:      &certificatesapi.CertificateSigningRequestList{},
    64  				name:     "panda",
    65  			},
    66  			wantErr: `certificatesigningrequests.certificates.k8s.io "panda" is forbidden: expected type CertificateSigningRequest, got: *certificates.CertificateSigningRequestList`,
    67  		},
    68  		{
    69  			name: "some other signer",
    70  			a: &testAttributes{
    71  				resource: certificatesapi.Resource("certificatesigningrequests"),
    72  				obj: &certificatesapi.CertificateSigningRequest{Spec: certificatesapi.CertificateSigningRequestSpec{
    73  					Request:    pemWithGroup("system:masters"),
    74  					SignerName: certificatesv1beta1.KubeAPIServerClientKubeletSignerName,
    75  				}},
    76  			},
    77  			wantErr: "",
    78  		},
    79  		{
    80  			name: "invalid request",
    81  			a: &testAttributes{
    82  				resource: certificatesapi.Resource("certificatesigningrequests"),
    83  				obj: &certificatesapi.CertificateSigningRequest{Spec: certificatesapi.CertificateSigningRequestSpec{
    84  					Request:    []byte("this is not a CSR"),
    85  					SignerName: certificatesv1beta1.KubeAPIServerClientSignerName,
    86  				}},
    87  				name: "bear",
    88  			},
    89  			wantErr: `certificatesigningrequests.certificates.k8s.io "bear" is forbidden: failed to parse CSR: PEM block type must be CERTIFICATE REQUEST`,
    90  		},
    91  		{
    92  			name: "some other group",
    93  			a: &testAttributes{
    94  				resource: certificatesapi.Resource("certificatesigningrequests"),
    95  				obj: &certificatesapi.CertificateSigningRequest{Spec: certificatesapi.CertificateSigningRequestSpec{
    96  					Request:    pemWithGroup("system:admin"),
    97  					SignerName: certificatesv1beta1.KubeAPIServerClientSignerName,
    98  				}},
    99  			},
   100  			wantErr: "",
   101  		},
   102  		{
   103  			name: "request for system:masters",
   104  			a: &testAttributes{
   105  				resource: certificatesapi.Resource("certificatesigningrequests"),
   106  				obj: &certificatesapi.CertificateSigningRequest{Spec: certificatesapi.CertificateSigningRequestSpec{
   107  					Request:    pemWithGroup("system:masters"),
   108  					SignerName: certificatesv1beta1.KubeAPIServerClientSignerName,
   109  				}},
   110  				name: "pooh",
   111  			},
   112  			wantErr: `certificatesigningrequests.certificates.k8s.io "pooh" is forbidden: use of kubernetes.io/kube-apiserver-client signer with system:masters group is not allowed`,
   113  		},
   114  	}
   115  	for _, tt := range tests {
   116  		t.Run(tt.name, func(t *testing.T) {
   117  			p := &Plugin{}
   118  			if err := p.Validate(context.TODO(), tt.a, nil); errStr(err) != tt.wantErr {
   119  				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
   120  			}
   121  		})
   122  	}
   123  }
   124  
   125  type testAttributes struct {
   126  	resource    schema.GroupResource
   127  	subresource string
   128  	obj         runtime.Object
   129  	name        string
   130  
   131  	admission.Attributes // nil panic if any other methods called
   132  }
   133  
   134  func (t *testAttributes) GetResource() schema.GroupVersionResource {
   135  	return t.resource.WithVersion("ignored")
   136  }
   137  
   138  func (t *testAttributes) GetSubresource() string {
   139  	return t.subresource
   140  }
   141  
   142  func (t *testAttributes) GetObject() runtime.Object {
   143  	return t.obj
   144  }
   145  
   146  func (t *testAttributes) GetName() string {
   147  	return t.name
   148  }
   149  
   150  func errStr(err error) string {
   151  	if err == nil {
   152  		return ""
   153  	}
   154  	es := err.Error()
   155  	if len(es) == 0 {
   156  		panic("invalid empty error")
   157  	}
   158  	return es
   159  }
   160  
   161  func pemWithGroup(group string) []byte {
   162  	template := &x509.CertificateRequest{
   163  		Subject: pkix.Name{
   164  			Organization: []string{group},
   165  		},
   166  	}
   167  
   168  	_, key, err := ed25519.GenerateKey(rand.Reader)
   169  	if err != nil {
   170  		panic(err)
   171  	}
   172  
   173  	csrDER, err := x509.CreateCertificateRequest(rand.Reader, template, key)
   174  	if err != nil {
   175  		panic(err)
   176  	}
   177  
   178  	csrPemBlock := &pem.Block{
   179  		Type:  "CERTIFICATE REQUEST",
   180  		Bytes: csrDER,
   181  	}
   182  
   183  	p := pem.EncodeToMemory(csrPemBlock)
   184  	if p == nil {
   185  		panic("invalid pem block")
   186  	}
   187  
   188  	return p
   189  }
   190  

View as plain text