k8s.io/kubernetes@v1.29.3/pkg/kubelet/secret/secret_manager.go (about) 1 /* 2 Copyright 2016 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 secret 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 v1 "k8s.io/api/core/v1" 25 clientset "k8s.io/client-go/kubernetes" 26 podutil "k8s.io/kubernetes/pkg/api/v1/pod" 27 corev1 "k8s.io/kubernetes/pkg/apis/core/v1" 28 "k8s.io/kubernetes/pkg/kubelet/util/manager" 29 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/apimachinery/pkg/runtime" 32 "k8s.io/apimachinery/pkg/util/sets" 33 "k8s.io/apimachinery/pkg/watch" 34 "k8s.io/utils/clock" 35 ) 36 37 // Manager manages Kubernetes secrets. This includes retrieving 38 // secrets or registering/unregistering them via Pods. 39 type Manager interface { 40 // Get secret by secret namespace and name. 41 GetSecret(namespace, name string) (*v1.Secret, error) 42 43 // WARNING: Register/UnregisterPod functions should be efficient, 44 // i.e. should not block on network operations. 45 46 // RegisterPod registers all secrets from a given pod. 47 RegisterPod(pod *v1.Pod) 48 49 // UnregisterPod unregisters secrets from a given pod that are not 50 // used by any other registered pod. 51 UnregisterPod(pod *v1.Pod) 52 } 53 54 // simpleSecretManager implements SecretManager interfaces with 55 // simple operations to apiserver. 56 type simpleSecretManager struct { 57 kubeClient clientset.Interface 58 } 59 60 // NewSimpleSecretManager creates a new SecretManager instance. 61 func NewSimpleSecretManager(kubeClient clientset.Interface) Manager { 62 return &simpleSecretManager{kubeClient: kubeClient} 63 } 64 65 func (s *simpleSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) { 66 return s.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) 67 } 68 69 func (s *simpleSecretManager) RegisterPod(pod *v1.Pod) { 70 } 71 72 func (s *simpleSecretManager) UnregisterPod(pod *v1.Pod) { 73 } 74 75 // secretManager keeps a store with secrets necessary 76 // for registered pods. Different implementations of the store 77 // may result in different semantics for freshness of secrets 78 // (e.g. ttl-based implementation vs watch-based implementation). 79 type secretManager struct { 80 manager manager.Manager 81 } 82 83 func (s *secretManager) GetSecret(namespace, name string) (*v1.Secret, error) { 84 object, err := s.manager.GetObject(namespace, name) 85 if err != nil { 86 return nil, err 87 } 88 if secret, ok := object.(*v1.Secret); ok { 89 return secret, nil 90 } 91 return nil, fmt.Errorf("unexpected object type: %v", object) 92 } 93 94 func (s *secretManager) RegisterPod(pod *v1.Pod) { 95 s.manager.RegisterPod(pod) 96 } 97 98 func (s *secretManager) UnregisterPod(pod *v1.Pod) { 99 s.manager.UnregisterPod(pod) 100 } 101 102 func getSecretNames(pod *v1.Pod) sets.String { 103 result := sets.NewString() 104 podutil.VisitPodSecretNames(pod, func(name string) bool { 105 result.Insert(name) 106 return true 107 }) 108 return result 109 } 110 111 const ( 112 defaultTTL = time.Minute 113 ) 114 115 // NewCachingSecretManager creates a manager that keeps a cache of all secrets 116 // necessary for registered pods. 117 // It implements the following logic: 118 // - whenever a pod is created or updated, the cached versions of all secrets 119 // are invalidated 120 // - every GetObject() call tries to fetch the value from local cache; if it is 121 // not there, invalidated or too old, we fetch it from apiserver and refresh the 122 // value in cache; otherwise it is just fetched from cache 123 func NewCachingSecretManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager { 124 getSecret := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { 125 return kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, opts) 126 } 127 secretStore := manager.NewObjectStore(getSecret, clock.RealClock{}, getTTL, defaultTTL) 128 return &secretManager{ 129 manager: manager.NewCacheBasedManager(secretStore, getSecretNames), 130 } 131 } 132 133 // NewWatchingSecretManager creates a manager that keeps a cache of all secrets 134 // necessary for registered pods. 135 // It implements the following logic: 136 // - whenever a pod is created or updated, we start individual watches for all 137 // referenced objects that aren't referenced from other registered pods 138 // - every GetObject() returns a value from local cache propagated via watches 139 func NewWatchingSecretManager(kubeClient clientset.Interface, resyncInterval time.Duration) Manager { 140 listSecret := func(namespace string, opts metav1.ListOptions) (runtime.Object, error) { 141 return kubeClient.CoreV1().Secrets(namespace).List(context.TODO(), opts) 142 } 143 watchSecret := func(namespace string, opts metav1.ListOptions) (watch.Interface, error) { 144 return kubeClient.CoreV1().Secrets(namespace).Watch(context.TODO(), opts) 145 } 146 newSecret := func() runtime.Object { 147 return &v1.Secret{} 148 } 149 isImmutable := func(object runtime.Object) bool { 150 if secret, ok := object.(*v1.Secret); ok { 151 return secret.Immutable != nil && *secret.Immutable 152 } 153 return false 154 } 155 gr := corev1.Resource("secret") 156 return &secretManager{ 157 manager: manager.NewWatchBasedManager(listSecret, watchSecret, newSecret, isImmutable, gr, resyncInterval, getSecretNames), 158 } 159 }