mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #99657 from deads2k/beta-csr-01
remove csr v1beta1 usage in integration tests
This commit is contained in:
commit
f19f8fd18a
@ -20,7 +20,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
certv1beta1 "k8s.io/api/certificates/v1beta1"
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -64,7 +65,7 @@ func TestCSRSignerNameApprovalPlugin(t *testing.T) {
|
|||||||
const username = "test-user"
|
const username = "test-user"
|
||||||
grantUserPermissionToApproveFor(t, client, username, test.allowedSignerName)
|
grantUserPermissionToApproveFor(t, client, username, test.allowedSignerName)
|
||||||
// Create a CSR to attempt to approve.
|
// Create a CSR to attempt to approve.
|
||||||
csr := createTestingCSR(t, client.CertificatesV1beta1().CertificateSigningRequests(), "csr", test.signerName, "")
|
csr := createTestingCSR(t, client.CertificatesV1().CertificateSigningRequests(), "csr", test.signerName, "")
|
||||||
|
|
||||||
// Create a second client, impersonating the 'test-user' for us to test with.
|
// Create a second client, impersonating the 'test-user' for us to test with.
|
||||||
testuserConfig := restclient.CopyConfig(s.ClientConfig)
|
testuserConfig := restclient.CopyConfig(s.ClientConfig)
|
||||||
@ -72,12 +73,13 @@ func TestCSRSignerNameApprovalPlugin(t *testing.T) {
|
|||||||
testuserClient := clientset.NewForConfigOrDie(testuserConfig)
|
testuserClient := clientset.NewForConfigOrDie(testuserConfig)
|
||||||
|
|
||||||
// Attempt to update the Approved condition.
|
// Attempt to update the Approved condition.
|
||||||
csr.Status.Conditions = append(csr.Status.Conditions, certv1beta1.CertificateSigningRequestCondition{
|
csr.Status.Conditions = append(csr.Status.Conditions, certv1.CertificateSigningRequestCondition{
|
||||||
Type: certv1beta1.CertificateApproved,
|
Type: certv1.CertificateApproved,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
Reason: "AutoApproved",
|
Reason: "AutoApproved",
|
||||||
Message: "Approved during integration test",
|
Message: "Approved during integration test",
|
||||||
})
|
})
|
||||||
_, err := testuserClient.CertificatesV1beta1().CertificateSigningRequests().UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{})
|
_, err := testuserClient.CertificatesV1().CertificateSigningRequests().UpdateApproval(context.TODO(), csr.Name, csr, metav1.UpdateOptions{})
|
||||||
if err != nil && test.error != err.Error() {
|
if err != nil && test.error != err.Error() {
|
||||||
t.Errorf("expected error %q but got: %v", test.error, err)
|
t.Errorf("expected error %q but got: %v", test.error, err)
|
||||||
}
|
}
|
||||||
@ -114,13 +116,13 @@ func buildApprovalClusterRoleForSigners(name string, signerNames ...string) *rba
|
|||||||
// 'signerName' to approve CSRs with the given signerName.
|
// 'signerName' to approve CSRs with the given signerName.
|
||||||
{
|
{
|
||||||
Verbs: []string{"approve"},
|
Verbs: []string{"approve"},
|
||||||
APIGroups: []string{certv1beta1.SchemeGroupVersion.Group},
|
APIGroups: []string{certv1.SchemeGroupVersion.Group},
|
||||||
Resources: []string{"signers"},
|
Resources: []string{"signers"},
|
||||||
ResourceNames: signerNames,
|
ResourceNames: signerNames,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Verbs: []string{"update"},
|
Verbs: []string{"update"},
|
||||||
APIGroups: []string{certv1beta1.SchemeGroupVersion.Group},
|
APIGroups: []string{certv1.SchemeGroupVersion.Group},
|
||||||
Resources: []string{"certificatesigningrequests/approval"},
|
Resources: []string{"certificatesigningrequests/approval"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
certv1beta1 "k8s.io/api/certificates/v1beta1"
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -64,7 +64,7 @@ func TestCSRSignerNameSigningPlugin(t *testing.T) {
|
|||||||
const username = "test-user"
|
const username = "test-user"
|
||||||
grantUserPermissionToSignFor(t, client, username, test.allowedSignerName)
|
grantUserPermissionToSignFor(t, client, username, test.allowedSignerName)
|
||||||
// Create a CSR to attempt to sign.
|
// Create a CSR to attempt to sign.
|
||||||
csr := createTestingCSR(t, client.CertificatesV1beta1().CertificateSigningRequests(), "csr", test.signerName, "")
|
csr := createTestingCSR(t, client.CertificatesV1().CertificateSigningRequests(), "csr", test.signerName, "")
|
||||||
|
|
||||||
// Create a second client, impersonating the 'test-user' for us to test with.
|
// Create a second client, impersonating the 'test-user' for us to test with.
|
||||||
testuserConfig := restclient.CopyConfig(s.ClientConfig)
|
testuserConfig := restclient.CopyConfig(s.ClientConfig)
|
||||||
@ -72,8 +72,35 @@ func TestCSRSignerNameSigningPlugin(t *testing.T) {
|
|||||||
testuserClient := clientset.NewForConfigOrDie(testuserConfig)
|
testuserClient := clientset.NewForConfigOrDie(testuserConfig)
|
||||||
|
|
||||||
// Attempt to 'sign' the certificate.
|
// Attempt to 'sign' the certificate.
|
||||||
csr.Status.Certificate = []byte("dummy data")
|
// random valid pem
|
||||||
_, err := testuserClient.CertificatesV1beta1().CertificateSigningRequests().UpdateStatus(context.TODO(), csr, metav1.UpdateOptions{})
|
csr.Status.Certificate = []byte(`
|
||||||
|
Leading non-PEM content
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBqDCCAU2gAwIBAgIUfbqeieihh/oERbfvRm38XvS/xHAwCgYIKoZIzj0EAwIw
|
||||||
|
GjEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlLUNBMCAXDTE2MTAxMTA1MDYwMFoYDzIx
|
||||||
|
MTYwOTE3MDUwNjAwWjAUMRIwEAYDVQQDEwlNeSBDbGllbnQwWTATBgcqhkjOPQIB
|
||||||
|
BggqhkjOPQMBBwNCAARv6N4R/sjMR65iMFGNLN1GC/vd7WhDW6J4X/iAjkRLLnNb
|
||||||
|
KbRG/AtOUZ+7upJ3BWIRKYbOabbQGQe2BbKFiap4o3UwczAOBgNVHQ8BAf8EBAMC
|
||||||
|
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
|
||||||
|
K/pZOWpNcYai6eHFpmJEeFpeQlEwHwYDVR0jBBgwFoAUX6nQlxjfWnP6aM1meO/Q
|
||||||
|
a6b3a9kwCgYIKoZIzj0EAwIDSQAwRgIhAIWTKw/sjJITqeuNzJDAKU4xo1zL+xJ5
|
||||||
|
MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
Intermediate non-PEM content
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBqDCCAU6gAwIBAgIUfqZtjoFgczZ+oQZbEC/BDSS2J6wwCgYIKoZIzj0EAwIw
|
||||||
|
EjEQMA4GA1UEAxMHUm9vdC1DQTAgFw0xNjEwMTEwNTA2MDBaGA8yMTE2MDkxNzA1
|
||||||
|
MDYwMFowGjEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlLUNBMFkwEwYHKoZIzj0CAQYI
|
||||||
|
KoZIzj0DAQcDQgAEyWHEMMCctJg8Xa5YWLqaCPbk3MjB+uvXac42JM9pj4k9jedD
|
||||||
|
kpUJRkWIPzgJI8Zk/3cSzluUTixP6JBSDKtwwaN4MHYwDgYDVR0PAQH/BAQDAgGm
|
||||||
|
MBMGA1UdJQQMMAoGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
|
||||||
|
FF+p0JcY31pz+mjNZnjv0Gum92vZMB8GA1UdIwQYMBaAFB7P6+i4/pfNjqZgJv/b
|
||||||
|
dgA7Fe4tMAoGCCqGSM49BAMCA0gAMEUCIQCTT1YWQZaAqfQ2oBxzOkJE2BqLFxhz
|
||||||
|
3smQlrZ5gCHddwIgcvT7puhYOzAgcvMn9+SZ1JOyZ7edODjshCVCRnuHK2c=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
Trailing non-PEM content
|
||||||
|
`)
|
||||||
|
_, err := testuserClient.CertificatesV1().CertificateSigningRequests().UpdateStatus(context.TODO(), csr, metav1.UpdateOptions{})
|
||||||
if err != nil && test.error != err.Error() {
|
if err != nil && test.error != err.Error() {
|
||||||
t.Errorf("expected error %q but got: %v", test.error, err)
|
t.Errorf("expected error %q but got: %v", test.error, err)
|
||||||
}
|
}
|
||||||
@ -110,13 +137,13 @@ func buildSigningClusterRoleForSigners(name string, signerNames ...string) *rbac
|
|||||||
// 'signerName' to approve CSRs with the given signerName.
|
// 'signerName' to approve CSRs with the given signerName.
|
||||||
{
|
{
|
||||||
Verbs: []string{"sign"},
|
Verbs: []string{"sign"},
|
||||||
APIGroups: []string{certv1beta1.SchemeGroupVersion.Group},
|
APIGroups: []string{certv1.SchemeGroupVersion.Group},
|
||||||
Resources: []string{"signers"},
|
Resources: []string{"signers"},
|
||||||
ResourceNames: signerNames,
|
ResourceNames: signerNames,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Verbs: []string{"update"},
|
Verbs: []string{"update"},
|
||||||
APIGroups: []string{certv1beta1.SchemeGroupVersion.Group},
|
APIGroups: []string{certv1.SchemeGroupVersion.Group},
|
||||||
Resources: []string{"certificatesigningrequests/status"},
|
Resources: []string{"certificatesigningrequests/status"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
certv1beta1 "k8s.io/api/certificates/v1beta1"
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
@ -36,16 +36,12 @@ func TestCertificateSubjectRestrictionPlugin(t *testing.T) {
|
|||||||
error string
|
error string
|
||||||
}{
|
}{
|
||||||
"should reject a request if signerName is kube-apiserver-client and group is system:masters": {
|
"should reject a request if signerName is kube-apiserver-client and group is system:masters": {
|
||||||
signerName: certv1beta1.KubeAPIServerClientSignerName,
|
signerName: certv1.KubeAPIServerClientSignerName,
|
||||||
group: "system:masters",
|
group: "system:masters",
|
||||||
error: `certificatesigningrequests.certificates.k8s.io "csr" is forbidden: use of kubernetes.io/kube-apiserver-client signer with system:masters group is not allowed`,
|
error: `certificatesigningrequests.certificates.k8s.io "csr" is forbidden: use of kubernetes.io/kube-apiserver-client signer with system:masters group is not allowed`,
|
||||||
},
|
},
|
||||||
"should admit a request if signerName is NOT kube-apiserver-client and org is system:masters": {
|
|
||||||
signerName: certv1beta1.LegacyUnknownSignerName,
|
|
||||||
group: "system:masters",
|
|
||||||
},
|
|
||||||
"should admit a request if signerName is kube-apiserver-client and group is NOT system:masters": {
|
"should admit a request if signerName is kube-apiserver-client and group is NOT system:masters": {
|
||||||
signerName: certv1beta1.KubeAPIServerClientSignerName,
|
signerName: certv1.KubeAPIServerClientSignerName,
|
||||||
group: "system:notmasters",
|
group: "system:notmasters",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -58,7 +54,7 @@ func TestCertificateSubjectRestrictionPlugin(t *testing.T) {
|
|||||||
|
|
||||||
// Attempt to create the CSR resource.
|
// Attempt to create the CSR resource.
|
||||||
csr := buildTestingCSR("csr", test.signerName, test.group)
|
csr := buildTestingCSR("csr", test.signerName, test.group)
|
||||||
_, err := client.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
_, err := client.CertificatesV1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
||||||
if err != nil && test.error != err.Error() {
|
if err != nil && test.error != err.Error() {
|
||||||
t.Errorf("expected error %q but got: %v", test.error, err)
|
t.Errorf("expected error %q but got: %v", test.error, err)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
certv1beta1 "k8s.io/api/certificates/v1beta1"
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -49,22 +49,22 @@ func TestController_AutoApproval(t *testing.T) {
|
|||||||
Organization: []string{"system:nodes"},
|
Organization: []string{"system:nodes"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
validKubeAPIServerClientKubeletUsages := []certv1beta1.KeyUsage{
|
validKubeAPIServerClientKubeletUsages := []certv1.KeyUsage{
|
||||||
certv1beta1.UsageDigitalSignature,
|
certv1.UsageDigitalSignature,
|
||||||
certv1beta1.UsageKeyEncipherment,
|
certv1.UsageKeyEncipherment,
|
||||||
certv1beta1.UsageClientAuth,
|
certv1.UsageClientAuth,
|
||||||
}
|
}
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
signerName string
|
signerName string
|
||||||
request []byte
|
request []byte
|
||||||
usages []certv1beta1.KeyUsage
|
usages []certv1.KeyUsage
|
||||||
username string
|
username string
|
||||||
autoApproved bool
|
autoApproved bool
|
||||||
grantNodeClient bool
|
grantNodeClient bool
|
||||||
grantSelfNodeClient bool
|
grantSelfNodeClient bool
|
||||||
}{
|
}{
|
||||||
"should auto-approve CSR that has kube-apiserver-client-kubelet signerName and matches requirements": {
|
"should auto-approve CSR that has kube-apiserver-client-kubelet signerName and matches requirements": {
|
||||||
signerName: certv1beta1.KubeAPIServerClientKubeletSignerName,
|
signerName: certv1.KubeAPIServerClientKubeletSignerName,
|
||||||
request: validKubeAPIServerClientKubeletCSR,
|
request: validKubeAPIServerClientKubeletCSR,
|
||||||
usages: validKubeAPIServerClientKubeletUsages,
|
usages: validKubeAPIServerClientKubeletUsages,
|
||||||
username: validKubeAPIServerClientKubeletUsername,
|
username: validKubeAPIServerClientKubeletUsername,
|
||||||
@ -72,20 +72,15 @@ func TestController_AutoApproval(t *testing.T) {
|
|||||||
autoApproved: true,
|
autoApproved: true,
|
||||||
},
|
},
|
||||||
"should auto-approve CSR that has kube-apiserver-client-kubelet signerName and matches requirements despite missing username if nodeclient permissions are granted": {
|
"should auto-approve CSR that has kube-apiserver-client-kubelet signerName and matches requirements despite missing username if nodeclient permissions are granted": {
|
||||||
signerName: certv1beta1.KubeAPIServerClientKubeletSignerName,
|
signerName: certv1.KubeAPIServerClientKubeletSignerName,
|
||||||
request: validKubeAPIServerClientKubeletCSR,
|
request: validKubeAPIServerClientKubeletCSR,
|
||||||
usages: validKubeAPIServerClientKubeletUsages,
|
usages: validKubeAPIServerClientKubeletUsages,
|
||||||
username: "does-not-match-cn",
|
username: "does-not-match-cn",
|
||||||
grantNodeClient: true,
|
grantNodeClient: true,
|
||||||
autoApproved: true,
|
autoApproved: true,
|
||||||
},
|
},
|
||||||
"should not auto-approve CSR that has kube-apiserver-client-kubelet signerName that does not match requirements": {
|
|
||||||
signerName: certv1beta1.KubeAPIServerClientKubeletSignerName,
|
|
||||||
request: pemWithGroup("system:notnodes"),
|
|
||||||
autoApproved: false,
|
|
||||||
},
|
|
||||||
"should not auto-approve CSR that has kube-apiserver-client signerName that DOES match kubelet CSR requirements": {
|
"should not auto-approve CSR that has kube-apiserver-client signerName that DOES match kubelet CSR requirements": {
|
||||||
signerName: certv1beta1.KubeAPIServerClientSignerName,
|
signerName: certv1.KubeAPIServerClientSignerName,
|
||||||
request: validKubeAPIServerClientKubeletCSR,
|
request: validKubeAPIServerClientKubeletCSR,
|
||||||
usages: validKubeAPIServerClientKubeletUsages,
|
usages: validKubeAPIServerClientKubeletUsages,
|
||||||
username: validKubeAPIServerClientKubeletUsername,
|
username: validKubeAPIServerClientKubeletUsername,
|
||||||
@ -124,17 +119,17 @@ func TestController_AutoApproval(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error in create clientset: %v", err)
|
t.Fatalf("Error in create clientset: %v", err)
|
||||||
}
|
}
|
||||||
csr := &certv1beta1.CertificateSigningRequest{
|
csr := &certv1.CertificateSigningRequest{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "csr",
|
Name: "csr",
|
||||||
},
|
},
|
||||||
Spec: certv1beta1.CertificateSigningRequestSpec{
|
Spec: certv1.CertificateSigningRequestSpec{
|
||||||
Request: test.request,
|
Request: test.request,
|
||||||
Usages: test.usages,
|
Usages: test.usages,
|
||||||
SignerName: &test.signerName,
|
SignerName: test.signerName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = impersonationClient.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
_, err = impersonationClient.CertificatesV1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create testing CSR: %v", err)
|
t.Fatalf("failed to create testing CSR: %v", err)
|
||||||
}
|
}
|
||||||
@ -212,7 +207,7 @@ func buildNodeClientRoleForUser(name string, resourceType string) *rbacv1.Cluste
|
|||||||
Rules: []rbacv1.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{
|
{
|
||||||
Verbs: []string{"create"},
|
Verbs: []string{"create"},
|
||||||
APIGroups: []string{certv1beta1.SchemeGroupVersion.Group},
|
APIGroups: []string{certv1.SchemeGroupVersion.Group},
|
||||||
Resources: []string{resourceType},
|
Resources: []string{resourceType},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2020 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package certificates
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
capi "k8s.io/api/certificates/v1beta1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Verifies that the signerName field defaulting is wired up correctly.
|
|
||||||
// An exhaustive set of test cases for all permutations of the possible
|
|
||||||
// defaulting cases is written as a unit tests in the
|
|
||||||
// `pkg/apis/certificates/...` directory.
|
|
||||||
// This test cases exists to show that the defaulting function is wired up into
|
|
||||||
// the apiserver correctly.
|
|
||||||
func TestCSRSignerNameDefaulting(t *testing.T) {
|
|
||||||
strPtr := func(s string) *string { return &s }
|
|
||||||
tests := map[string]struct {
|
|
||||||
csr capi.CertificateSigningRequestSpec
|
|
||||||
expectedSignerName string
|
|
||||||
}{
|
|
||||||
"defaults to legacy-unknown if not recognised": {
|
|
||||||
csr: capi.CertificateSigningRequestSpec{
|
|
||||||
Request: pemWithGroup(""),
|
|
||||||
Usages: []capi.KeyUsage{capi.UsageKeyEncipherment, capi.UsageDigitalSignature},
|
|
||||||
},
|
|
||||||
expectedSignerName: capi.LegacyUnknownSignerName,
|
|
||||||
},
|
|
||||||
"does not default signerName if an explicit value is provided": {
|
|
||||||
csr: capi.CertificateSigningRequestSpec{
|
|
||||||
Request: pemWithGroup(""),
|
|
||||||
Usages: []capi.KeyUsage{capi.UsageKeyEncipherment, capi.UsageDigitalSignature},
|
|
||||||
SignerName: strPtr("example.com/my-custom-signer"),
|
|
||||||
},
|
|
||||||
expectedSignerName: "example.com/my-custom-signer",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, test := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
_, s, closeFn := framework.RunAMaster(nil)
|
|
||||||
defer closeFn()
|
|
||||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
|
||||||
csrClient := client.CertificatesV1beta1().CertificateSigningRequests()
|
|
||||||
csr := &capi.CertificateSigningRequest{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testcsr"},
|
|
||||||
Spec: test.csr,
|
|
||||||
}
|
|
||||||
csr, err := csrClient.Create(context.TODO(), csr, metav1.CreateOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create CSR resource: %v", err)
|
|
||||||
}
|
|
||||||
if *csr.Spec.SignerName != test.expectedSignerName {
|
|
||||||
t.Errorf("expected CSR signerName to be %q but it was %q", test.expectedSignerName, *csr.Spec.SignerName)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
208
test/integration/certificates/deprecated_api_test.go
Normal file
208
test/integration/certificates/deprecated_api_test.go
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package certificates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
|
certv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/informers"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
restclient "k8s.io/client-go/rest"
|
||||||
|
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
|
capi "k8s.io/kubernetes/pkg/apis/certificates"
|
||||||
|
"k8s.io/kubernetes/pkg/controller/certificates/approver"
|
||||||
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO this test can be removed once we get to 1.22 and v1beta1 is no longer allowed
|
||||||
|
// Verifies that the signerName field defaulting is wired up correctly.
|
||||||
|
// An exhaustive set of test cases for all permutations of the possible
|
||||||
|
// defaulting cases is written as a unit tests in the
|
||||||
|
// `pkg/apis/certificates/...` directory.
|
||||||
|
// This test cases exists to show that the defaulting function is wired up into
|
||||||
|
// the apiserver correctly.
|
||||||
|
func TestCSRSignerNameDefaulting(t *testing.T) {
|
||||||
|
strPtr := func(s string) *string { return &s }
|
||||||
|
tests := map[string]struct {
|
||||||
|
csr certv1beta1.CertificateSigningRequestSpec
|
||||||
|
expectedSignerName string
|
||||||
|
}{
|
||||||
|
"defaults to legacy-unknown if not recognised": {
|
||||||
|
csr: certv1beta1.CertificateSigningRequestSpec{
|
||||||
|
Request: pemWithGroup(""),
|
||||||
|
Usages: []certv1beta1.KeyUsage{certv1beta1.UsageKeyEncipherment, certv1beta1.UsageDigitalSignature},
|
||||||
|
},
|
||||||
|
expectedSignerName: capi.LegacyUnknownSignerName,
|
||||||
|
},
|
||||||
|
"does not default signerName if an explicit value is provided": {
|
||||||
|
csr: certv1beta1.CertificateSigningRequestSpec{
|
||||||
|
Request: pemWithGroup(""),
|
||||||
|
Usages: []certv1beta1.KeyUsage{certv1beta1.UsageKeyEncipherment, certv1beta1.UsageDigitalSignature},
|
||||||
|
SignerName: strPtr("example.com/my-custom-signer"),
|
||||||
|
},
|
||||||
|
expectedSignerName: "example.com/my-custom-signer",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, test := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
_, s, closeFn := framework.RunAMaster(nil)
|
||||||
|
defer closeFn()
|
||||||
|
client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
||||||
|
csrClient := client.CertificatesV1beta1().CertificateSigningRequests()
|
||||||
|
csr := &certv1beta1.CertificateSigningRequest{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "testcsr"},
|
||||||
|
Spec: test.csr,
|
||||||
|
}
|
||||||
|
csr, err := csrClient.Create(context.TODO(), csr, metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create CSR resource: %v", err)
|
||||||
|
}
|
||||||
|
if *csr.Spec.SignerName != test.expectedSignerName {
|
||||||
|
t.Errorf("expected CSR signerName to be %q but it was %q", test.expectedSignerName, *csr.Spec.SignerName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this test can be removed once we get to 1.22 and v1beta1 is no longer allowed
|
||||||
|
// Verifies that the CertificateSubjectRestriction admission controller works as expected.
|
||||||
|
func TestDeprecatedCertificateSubjectRestrictionPlugin(t *testing.T) {
|
||||||
|
tests := map[string]struct {
|
||||||
|
signerName string
|
||||||
|
group string
|
||||||
|
error string
|
||||||
|
}{
|
||||||
|
"should admit a request if signerName is NOT kube-apiserver-client and org is system:masters": {
|
||||||
|
signerName: certv1beta1.LegacyUnknownSignerName,
|
||||||
|
group: "system:masters",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, test := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
// Run an apiserver with the default configuration options.
|
||||||
|
s := kubeapiservertesting.StartTestServerOrDie(t, kubeapiservertesting.NewDefaultTestServerOptions(), []string{""}, framework.SharedEtcd())
|
||||||
|
defer s.TearDownFn()
|
||||||
|
client := clientset.NewForConfigOrDie(s.ClientConfig)
|
||||||
|
|
||||||
|
// Attempt to create the CSR resource.
|
||||||
|
csr := buildDeprecatedTestingCSR("csr", test.signerName, test.group)
|
||||||
|
_, err := client.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
||||||
|
if err != nil && test.error != err.Error() {
|
||||||
|
t.Errorf("expected error %q but got: %v", test.error, err)
|
||||||
|
}
|
||||||
|
if err == nil && test.error != "" {
|
||||||
|
t.Errorf("expected to get an error %q but got none", test.error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildDeprecatedTestingCSR(name, signerName, groupName string) *certv1beta1.CertificateSigningRequest {
|
||||||
|
return &certv1beta1.CertificateSigningRequest{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Spec: certv1beta1.CertificateSigningRequestSpec{
|
||||||
|
SignerName: &signerName,
|
||||||
|
Request: pemWithGroup(groupName),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this test can be removed once we get to 1.22 and v1beta1 is no longer allowed
|
||||||
|
// Integration tests that verify the behaviour of the CSR auto-approving controller.
|
||||||
|
func TestDeprecatedController_AutoApproval(t *testing.T) {
|
||||||
|
tests := map[string]struct {
|
||||||
|
signerName string
|
||||||
|
request []byte
|
||||||
|
usages []certv1beta1.KeyUsage
|
||||||
|
username string
|
||||||
|
autoApproved bool
|
||||||
|
grantNodeClient bool
|
||||||
|
grantSelfNodeClient bool
|
||||||
|
}{
|
||||||
|
"should not auto-approve CSR that has kube-apiserver-client-kubelet signerName that does not match requirements": {
|
||||||
|
signerName: certv1.KubeAPIServerClientKubeletSignerName,
|
||||||
|
request: pemWithGroup("system:notnodes"),
|
||||||
|
autoApproved: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, test := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
// Run an apiserver with the default configuration options.
|
||||||
|
s := kubeapiservertesting.StartTestServerOrDie(t, kubeapiservertesting.NewDefaultTestServerOptions(), []string{""}, framework.SharedEtcd())
|
||||||
|
defer s.TearDownFn()
|
||||||
|
client := clientset.NewForConfigOrDie(s.ClientConfig)
|
||||||
|
informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(s.ClientConfig, "certificatesigningrequest-informers")), time.Second)
|
||||||
|
|
||||||
|
// Register the controller
|
||||||
|
c := approver.NewCSRApprovingController(client, informers.Certificates().V1().CertificateSigningRequests())
|
||||||
|
// Start the controller & informers
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
defer close(stopCh)
|
||||||
|
informers.Start(stopCh)
|
||||||
|
go c.Run(1, stopCh)
|
||||||
|
|
||||||
|
// Configure appropriate permissions
|
||||||
|
if test.grantNodeClient {
|
||||||
|
grantUserNodeClientPermissions(t, client, test.username, false)
|
||||||
|
}
|
||||||
|
if test.grantSelfNodeClient {
|
||||||
|
grantUserNodeClientPermissions(t, client, test.username, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a client that impersonates the test case 'username' to ensure the `spec.username`
|
||||||
|
// field on the CSR is set correctly.
|
||||||
|
impersonationConfig := restclient.CopyConfig(s.ClientConfig)
|
||||||
|
impersonationConfig.Impersonate.UserName = test.username
|
||||||
|
impersonationClient, err := clientset.NewForConfig(impersonationConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error in create clientset: %v", err)
|
||||||
|
}
|
||||||
|
csr := &certv1beta1.CertificateSigningRequest{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "csr",
|
||||||
|
},
|
||||||
|
Spec: certv1beta1.CertificateSigningRequestSpec{
|
||||||
|
Request: test.request,
|
||||||
|
Usages: test.usages,
|
||||||
|
SignerName: &test.signerName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = impersonationClient.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create testing CSR: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.autoApproved {
|
||||||
|
if err := waitForCertificateRequestApproved(client, csr.Name); err != nil {
|
||||||
|
t.Errorf("failed to wait for CSR to be auto-approved: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := ensureCertificateRequestNotApproved(client, csr.Name); err != nil {
|
||||||
|
t.Errorf("failed to ensure that CSR was not auto-approved: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -25,11 +25,11 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
capi "k8s.io/api/certificates/v1beta1"
|
certv1 "k8s.io/api/certificates/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
certclientset "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
certclientset "k8s.io/client-go/kubernetes/typed/certificates/v1"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
|
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
@ -41,14 +41,14 @@ func TestCSRSignerNameFieldSelector(t *testing.T) {
|
|||||||
defer closeFn()
|
defer closeFn()
|
||||||
|
|
||||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
||||||
csrClient := client.CertificatesV1beta1().CertificateSigningRequests()
|
csrClient := client.CertificatesV1().CertificateSigningRequests()
|
||||||
csr1 := createTestingCSR(t, csrClient, "csr-1", "example.com/signer-name-1", "")
|
csr1 := createTestingCSR(t, csrClient, "csr-1", "example.com/signer-name-1", "")
|
||||||
csr2 := createTestingCSR(t, csrClient, "csr-2", "example.com/signer-name-2", "")
|
csr2 := createTestingCSR(t, csrClient, "csr-2", "example.com/signer-name-2", "")
|
||||||
// csr3 has the same signerName as csr2 so we can ensure multiple items are returned when running a filtered
|
// csr3 has the same signerName as csr2 so we can ensure multiple items are returned when running a filtered
|
||||||
// LIST call.
|
// LIST call.
|
||||||
csr3 := createTestingCSR(t, csrClient, "csr-3", "example.com/signer-name-2", "")
|
csr3 := createTestingCSR(t, csrClient, "csr-3", "example.com/signer-name-2", "")
|
||||||
|
|
||||||
signerOneList, err := client.CertificatesV1beta1().CertificateSigningRequests().List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=example.com/signer-name-1"})
|
signerOneList, err := client.CertificatesV1().CertificateSigningRequests().List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=example.com/signer-name-1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to list CSRs with spec.signerName=example.com/signer-name-1")
|
t.Errorf("unable to list CSRs with spec.signerName=example.com/signer-name-1")
|
||||||
return
|
return
|
||||||
@ -59,7 +59,7 @@ func TestCSRSignerNameFieldSelector(t *testing.T) {
|
|||||||
t.Errorf("expected CSR named 'csr-1' to be returned but got %q", signerOneList.Items[0].Name)
|
t.Errorf("expected CSR named 'csr-1' to be returned but got %q", signerOneList.Items[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
signerTwoList, err := client.CertificatesV1beta1().CertificateSigningRequests().List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=example.com/signer-name-2"})
|
signerTwoList, err := client.CertificatesV1().CertificateSigningRequests().List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=example.com/signer-name-2"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to list CSRs with spec.signerName=example.com/signer-name-2")
|
t.Errorf("unable to list CSRs with spec.signerName=example.com/signer-name-2")
|
||||||
return
|
return
|
||||||
@ -73,7 +73,7 @@ func TestCSRSignerNameFieldSelector(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestingCSR(t *testing.T, certClient certclientset.CertificateSigningRequestInterface, name, signerName, groupName string) *capi.CertificateSigningRequest {
|
func createTestingCSR(t *testing.T, certClient certclientset.CertificateSigningRequestInterface, name, signerName, groupName string) *certv1.CertificateSigningRequest {
|
||||||
csr, err := certClient.Create(context.TODO(), buildTestingCSR(name, signerName, groupName), metav1.CreateOptions{})
|
csr, err := certClient.Create(context.TODO(), buildTestingCSR(name, signerName, groupName), metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create testing CSR: %v", err)
|
t.Fatalf("failed to create testing CSR: %v", err)
|
||||||
@ -81,14 +81,16 @@ func createTestingCSR(t *testing.T, certClient certclientset.CertificateSigningR
|
|||||||
return csr
|
return csr
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTestingCSR(name, signerName, groupName string) *capi.CertificateSigningRequest {
|
func buildTestingCSR(name, signerName, groupName string) *certv1.CertificateSigningRequest {
|
||||||
return &capi.CertificateSigningRequest{
|
return &certv1.CertificateSigningRequest{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Spec: capi.CertificateSigningRequestSpec{
|
Spec: certv1.CertificateSigningRequestSpec{
|
||||||
SignerName: &signerName,
|
SignerName: signerName,
|
||||||
Request: pemWithGroup(groupName),
|
Request: pemWithGroup(groupName),
|
||||||
|
// this is the old defaulting for usages
|
||||||
|
Usages: []certv1.KeyUsage{certv1.UsageDigitalSignature, certv1.UsageKeyEncipherment},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user