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  }