github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/secrets/store.go (about) 1 package secrets 2 3 import ( 4 "fmt" 5 6 api_v1 "k8s.io/api/core/v1" 7 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 ) 9 10 // SecretReference holds a reference to a secret stored on the file system. 11 type SecretReference struct { 12 Secret *api_v1.Secret 13 Path string 14 Error error 15 } 16 17 // SecretFileManager manages secrets on the file system. 18 type SecretFileManager interface { 19 AddOrUpdateSecret(secret *api_v1.Secret) string 20 DeleteSecret(key string) 21 } 22 23 // SecretStore stores secrets that the Ingress Controller uses. 24 type SecretStore interface { 25 AddOrUpdateSecret(secret *api_v1.Secret) 26 DeleteSecret(key string) 27 GetSecret(key string) *SecretReference 28 } 29 30 // LocalSecretStore implements SecretStore interface. 31 // It validates the secrets and manages them on the file system (via SecretFileManager). 32 type LocalSecretStore struct { 33 secrets map[string]*SecretReference 34 manager SecretFileManager 35 } 36 37 // NewLocalSecretStore creates a new LocalSecretStore. 38 func NewLocalSecretStore(manager SecretFileManager) *LocalSecretStore { 39 return &LocalSecretStore{ 40 secrets: make(map[string]*SecretReference), 41 manager: manager, 42 } 43 } 44 45 // AddOrUpdateSecret adds or updates a secret. 46 // The secret will only be updated on the file system if it is valid and if it is already on the file system. 47 // If the secret becomes invalid, it will be removed from the filesystem. 48 func (s *LocalSecretStore) AddOrUpdateSecret(secret *api_v1.Secret) { 49 secretRef, exists := s.secrets[getResourceKey(&secret.ObjectMeta)] 50 if !exists { 51 secretRef = &SecretReference{Secret: secret} 52 } else { 53 secretRef.Secret = secret 54 } 55 56 secretRef.Error = ValidateSecret(secret) 57 58 if secretRef.Path != "" { 59 if secretRef.Error != nil { 60 s.manager.DeleteSecret(getResourceKey(&secret.ObjectMeta)) 61 secretRef.Path = "" 62 } else { 63 secretRef.Path = s.manager.AddOrUpdateSecret(secret) 64 } 65 } 66 67 s.secrets[getResourceKey(&secret.ObjectMeta)] = secretRef 68 } 69 70 // DeleteSecret deletes a secret. 71 func (s *LocalSecretStore) DeleteSecret(key string) { 72 storedSecret, exists := s.secrets[key] 73 if !exists { 74 return 75 } 76 77 delete(s.secrets, key) 78 79 if storedSecret.Path == "" { 80 return 81 } 82 83 s.manager.DeleteSecret(key) 84 } 85 86 // GetSecret returns a SecretReference. 87 // If the secret doesn't exist, is of an unsupported type, or invalid, the Error field will include an error. 88 // If the secret is valid but isn't present on the file system, the secret will be written to the file system. 89 func (s *LocalSecretStore) GetSecret(key string) *SecretReference { 90 secretRef, exists := s.secrets[key] 91 if !exists { 92 return &SecretReference{ 93 Error: fmt.Errorf("secret doesn't exist or of an unsupported type"), 94 } 95 } 96 97 if secretRef.Error == nil && secretRef.Path == "" { 98 secretRef.Path = s.manager.AddOrUpdateSecret(secretRef.Secret) 99 } 100 101 return secretRef 102 } 103 104 func getResourceKey(meta *metav1.ObjectMeta) string { 105 return fmt.Sprintf("%s/%s", meta.Namespace, meta.Name) 106 } 107 108 // FakeSecretStore is a fake implementation of SecretStore. 109 type FakeSecretStore struct { 110 secrets map[string]*SecretReference 111 } 112 113 // NewFakeSecretsStore creates a new FakeSecretStore. 114 func NewFakeSecretsStore(secrets map[string]*SecretReference) *FakeSecretStore { 115 return &FakeSecretStore{ 116 secrets: secrets, 117 } 118 } 119 120 // NewEmptyFakeSecretsStore creates a new empty FakeSecretStore. 121 func NewEmptyFakeSecretsStore() *FakeSecretStore { 122 return &FakeSecretStore{ 123 secrets: make(map[string]*SecretReference), 124 } 125 } 126 127 // AddOrUpdateSecret is a fake implementation of AddOrUpdateSecret. 128 func (s *FakeSecretStore) AddOrUpdateSecret(secret *api_v1.Secret) { 129 secretRef, exists := s.secrets[getResourceKey(&secret.ObjectMeta)] 130 if !exists { 131 secretRef = &SecretReference{Secret: secret} 132 } else { 133 secretRef.Secret = secret 134 } 135 s.secrets[getResourceKey(&secret.ObjectMeta)] = secretRef 136 } 137 138 // DeleteSecret is a fake implementation of DeleteSecret. 139 func (s *FakeSecretStore) DeleteSecret(key string) { 140 } 141 142 // GetSecret is a fake implementation of GetSecret. 143 func (s *FakeSecretStore) GetSecret(key string) *SecretReference { 144 secretRef, exists := s.secrets[key] 145 if !exists { 146 return &SecretReference{ 147 Error: fmt.Errorf("secret doesn't exist"), 148 } 149 } 150 151 return secretRef 152 }