k8s.io/kubernetes@v1.29.3/test/integration/secrets/secrets_test.go (about) 1 /* 2 Copyright 2015 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 secrets 18 19 // This file tests use of the secrets API resource. 20 21 import ( 22 "context" 23 "testing" 24 25 "encoding/json" 26 27 v1 "k8s.io/api/core/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/types" 30 clientset "k8s.io/client-go/kubernetes" 31 kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" 32 "k8s.io/kubernetes/test/integration" 33 "k8s.io/kubernetes/test/integration/framework" 34 ) 35 36 func deleteSecretOrErrorf(t *testing.T, c clientset.Interface, ns, name string) { 37 if err := c.CoreV1().Secrets(ns).Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil { 38 t.Errorf("unable to delete secret %v: %v", name, err) 39 } 40 } 41 42 // TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods. 43 func TestSecrets(t *testing.T) { 44 // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. 45 server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) 46 defer server.TearDownFn() 47 48 client := clientset.NewForConfigOrDie(server.ClientConfig) 49 50 ns := framework.CreateNamespaceOrDie(client, "secret", t) 51 defer framework.DeleteNamespaceOrDie(client, ns, t) 52 53 DoTestSecrets(t, client, ns) 54 DoTestSecretsImmutableWithEmptyValue(t, client, ns) 55 } 56 57 // DoTestSecretsImmutableWithEmptyValue Test whether apiserver will judge the secret data inconsistency 58 // if the value of map in secret data is the empty string when patch secret, 59 // and if the Immutable value of secret is true, the patch request is rejected. 60 func DoTestSecretsImmutableWithEmptyValue(t *testing.T, client clientset.Interface, ns *v1.Namespace) { 61 // Make a secret object. Make a secret object. the map in the secret data contains the value of the empty string 62 // make Immutable true, so that if the apiserver judge that the patch secret is inconsistent, it will refuse the patch 63 trueVal := true 64 s := v1.Secret{ 65 ObjectMeta: metav1.ObjectMeta{ 66 Name: "secret", 67 Namespace: ns.Name, 68 }, 69 Immutable: &trueVal, 70 Data: map[string][]byte{ 71 "emptyData": {}, 72 }, 73 } 74 75 if _, err := client.CoreV1().Secrets(s.Namespace).Create(context.TODO(), &s, metav1.CreateOptions{}); err != nil { 76 t.Errorf("unable to create test secret: %v", err) 77 } 78 defer deleteSecretOrErrorf(t, client, s.Namespace, s.Name) 79 80 // Make a patch secret object 81 patchSecret := v1.Secret{ 82 ObjectMeta: metav1.ObjectMeta{ 83 Name: "secret", 84 Namespace: ns.Name, 85 Labels: map[string]string{ 86 "foo": "bar", 87 }, 88 }, 89 Immutable: &trueVal, 90 Data: map[string][]byte{ 91 "emptyData": {}, 92 }, 93 } 94 95 secretPatch, err := json.Marshal(patchSecret) 96 if err != nil { 97 t.Errorf("unable to marshal test secret: %v", err) 98 } 99 100 // Patch secret object, expect patch to succeed, 101 // more detailed discussion is at #119229 102 if _, err := client.CoreV1().Secrets(s.Namespace).Patch(context.TODO(), patchSecret.Name, types.StrategicMergePatchType, secretPatch, metav1.PatchOptions{}); err != nil { 103 t.Errorf("unable to patch test secret: %v", err) 104 } 105 } 106 107 // DoTestSecrets test secrets for one api version. 108 func DoTestSecrets(t *testing.T, client clientset.Interface, ns *v1.Namespace) { 109 // Make a secret object. 110 s := v1.Secret{ 111 ObjectMeta: metav1.ObjectMeta{ 112 Name: "secret", 113 Namespace: ns.Name, 114 }, 115 Data: map[string][]byte{ 116 "data": []byte("value1\n"), 117 }, 118 } 119 120 if _, err := client.CoreV1().Secrets(s.Namespace).Create(context.TODO(), &s, metav1.CreateOptions{}); err != nil { 121 t.Errorf("unable to create test secret: %v", err) 122 } 123 defer deleteSecretOrErrorf(t, client, s.Namespace, s.Name) 124 125 // Template for pods that use a secret. 126 pod := &v1.Pod{ 127 ObjectMeta: metav1.ObjectMeta{ 128 Name: "XXX", 129 Namespace: ns.Name, 130 }, 131 Spec: v1.PodSpec{ 132 Volumes: []v1.Volume{ 133 { 134 Name: "secvol", 135 VolumeSource: v1.VolumeSource{ 136 Secret: &v1.SecretVolumeSource{ 137 SecretName: "secret", 138 }, 139 }, 140 }, 141 }, 142 Containers: []v1.Container{ 143 { 144 Name: "fake-name", 145 Image: "fakeimage", 146 VolumeMounts: []v1.VolumeMount{ 147 { 148 Name: "secvol", 149 MountPath: "/fake/path", 150 ReadOnly: true, 151 }, 152 }, 153 }, 154 }, 155 }, 156 } 157 158 // Create a pod to consume secret. 159 pod.ObjectMeta.Name = "uses-secret" 160 if _, err := client.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{}); err != nil { 161 t.Errorf("Failed to create pod: %v", err) 162 } 163 defer integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name) 164 165 // Create a pod that consumes non-existent secret. 166 pod.ObjectMeta.Name = "uses-non-existent-secret" 167 if _, err := client.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{}); err != nil { 168 t.Errorf("Failed to create pod: %v", err) 169 } 170 defer integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name) 171 // This pod may fail to run, but we don't currently prevent this, and this 172 // test can't check whether the kubelet actually pulls the secret. 173 174 // Verifying contents of the volumes is out of scope for a 175 // apiserver<->kubelet integration test. It is covered by an e2e test. 176 }