github.com/argoproj/argo-cd@v1.8.7/util/db/gpgkeys_test.go (about) 1 package db 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 v1 "k8s.io/api/core/v1" 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/apimachinery/pkg/runtime" 12 "k8s.io/client-go/kubernetes/fake" 13 14 "github.com/argoproj/argo-cd/common" 15 "github.com/argoproj/argo-cd/test" 16 "github.com/argoproj/argo-cd/util/settings" 17 ) 18 19 // GPG config map with a single key and good mapping 20 var gpgCMEmpty = v1.ConfigMap{ 21 ObjectMeta: metav1.ObjectMeta{ 22 Name: common.ArgoCDGPGKeysConfigMapName, 23 Namespace: testNamespace, 24 Labels: map[string]string{ 25 "app.kubernetes.io/part-of": "argocd", 26 }, 27 }, 28 } 29 30 // GPG config map with a single key and good mapping 31 var gpgCMSingleGoodPubkey = v1.ConfigMap{ 32 ObjectMeta: metav1.ObjectMeta{ 33 Name: common.ArgoCDGPGKeysConfigMapName, 34 Namespace: testNamespace, 35 Labels: map[string]string{ 36 "app.kubernetes.io/part-of": "argocd", 37 }, 38 }, 39 Data: map[string]string{ 40 "4AEE18F83AFDEB23": test.MustLoadFileToString("../gpg/testdata/github.asc"), 41 }, 42 } 43 44 // GPG config map with two keys and good mapping 45 var gpgCMMultiGoodPubkey = v1.ConfigMap{ 46 ObjectMeta: metav1.ObjectMeta{ 47 Name: common.ArgoCDGPGKeysConfigMapName, 48 Namespace: testNamespace, 49 Labels: map[string]string{ 50 "app.kubernetes.io/part-of": "argocd", 51 }, 52 }, 53 Data: map[string]string{ 54 "FDC79815400D88A9": test.MustLoadFileToString("../gpg/testdata/johndoe.asc"), 55 "F7842A5CEAA9C0B1": test.MustLoadFileToString("../gpg/testdata/janedoe.asc"), 56 }, 57 } 58 59 // GPG config map with a single key and bad mapping 60 var gpgCMSingleKeyWrongId = v1.ConfigMap{ 61 ObjectMeta: metav1.ObjectMeta{ 62 Name: common.ArgoCDGPGKeysConfigMapName, 63 Namespace: testNamespace, 64 Labels: map[string]string{ 65 "app.kubernetes.io/part-of": "argocd", 66 }, 67 }, 68 Data: map[string]string{ 69 "5AEE18F83AFDEB23": test.MustLoadFileToString("../gpg/testdata/github.asc"), 70 }, 71 } 72 73 // GPG config map with a garbage pub key 74 var gpgCMGarbagePubkey = v1.ConfigMap{ 75 ObjectMeta: metav1.ObjectMeta{ 76 Name: common.ArgoCDGPGKeysConfigMapName, 77 Namespace: testNamespace, 78 Labels: map[string]string{ 79 "app.kubernetes.io/part-of": "argocd", 80 }, 81 }, 82 Data: map[string]string{ 83 "4AEE18F83AFDEB23": test.MustLoadFileToString("../gpg/testdata/garbage.asc"), 84 }, 85 } 86 87 // GPG config map with a wrong key 88 var gpgCMGarbageCMKey = v1.ConfigMap{ 89 ObjectMeta: metav1.ObjectMeta{ 90 Name: common.ArgoCDGPGKeysConfigMapName, 91 Namespace: testNamespace, 92 Labels: map[string]string{ 93 "app.kubernetes.io/part-of": "argocd", 94 }, 95 }, 96 Data: map[string]string{ 97 "wullerosekaufe": test.MustLoadFileToString("../gpg/testdata/github.asc"), 98 }, 99 } 100 101 // Returns a fake client set for use in tests 102 func getGPGKeysClientset(gpgCM v1.ConfigMap) *fake.Clientset { 103 cm := v1.ConfigMap{ 104 ObjectMeta: metav1.ObjectMeta{ 105 Name: "argocd-cm", 106 Namespace: testNamespace, 107 Labels: map[string]string{ 108 "app.kubernetes.io/part-of": "argocd", 109 }, 110 }, 111 Data: nil, 112 } 113 114 return fake.NewSimpleClientset([]runtime.Object{&cm, &gpgCM}...) 115 } 116 117 func Test_ValidatePGPKey(t *testing.T) { 118 // Good case - single PGP key 119 { 120 key, err := validatePGPKey(test.MustLoadFileToString("../gpg/testdata/github.asc")) 121 assert.NoError(t, err) 122 assert.NotNil(t, key) 123 assert.Equal(t, "4AEE18F83AFDEB23", key.KeyID) 124 assert.NotEmpty(t, key.Owner) 125 assert.NotEmpty(t, key.KeyData) 126 assert.NotEmpty(t, key.SubType) 127 } 128 // Bad case - Garbage 129 { 130 key, err := validatePGPKey(test.MustLoadFileToString("../gpg/testdata/garbage.asc")) 131 assert.Error(t, err) 132 assert.Nil(t, key) 133 } 134 // Bad case - more than one key 135 { 136 key, err := validatePGPKey(test.MustLoadFileToString("../gpg/testdata/multi.asc")) 137 assert.Error(t, err) 138 assert.Nil(t, key) 139 } 140 } 141 142 func Test_ListConfiguredGPGPublicKeys(t *testing.T) { 143 // Good case. Single key in input, right mapping to Key ID in CM 144 { 145 clientset := getGPGKeysClientset(gpgCMSingleGoodPubkey) 146 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 147 db := NewDB(testNamespace, settings, clientset) 148 if db == nil { 149 panic("could not get database") 150 } 151 keys, err := db.ListConfiguredGPGPublicKeys(context.Background()) 152 assert.NoError(t, err) 153 assert.Len(t, keys, 1) 154 } 155 // Good case. No certificates in ConfigMap 156 { 157 clientset := getGPGKeysClientset(gpgCMEmpty) 158 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 159 db := NewDB(testNamespace, settings, clientset) 160 if db == nil { 161 panic("could not get database") 162 } 163 keys, err := db.ListConfiguredGPGPublicKeys(context.Background()) 164 assert.NoError(t, err) 165 assert.Len(t, keys, 0) 166 } 167 // Bad case. Single key in input, wrong mapping to Key ID in CM 168 { 169 clientset := getGPGKeysClientset(gpgCMSingleKeyWrongId) 170 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 171 db := NewDB(testNamespace, settings, clientset) 172 if db == nil { 173 panic("could not get database") 174 } 175 keys, err := db.ListConfiguredGPGPublicKeys(context.Background()) 176 assert.Error(t, err) 177 assert.Len(t, keys, 0) 178 } 179 // Bad case. Garbage public key 180 { 181 clientset := getGPGKeysClientset(gpgCMGarbagePubkey) 182 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 183 db := NewDB(testNamespace, settings, clientset) 184 if db == nil { 185 panic("could not get database") 186 } 187 keys, err := db.ListConfiguredGPGPublicKeys(context.Background()) 188 assert.Error(t, err) 189 assert.Len(t, keys, 0) 190 } 191 // Bad case. Garbage ConfigMap key in data 192 { 193 clientset := getGPGKeysClientset(gpgCMGarbageCMKey) 194 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 195 db := NewDB(testNamespace, settings, clientset) 196 if db == nil { 197 panic("could not get database") 198 } 199 keys, err := db.ListConfiguredGPGPublicKeys(context.Background()) 200 assert.Error(t, err) 201 assert.Len(t, keys, 0) 202 } 203 } 204 205 func Test_AddGPGPublicKey(t *testing.T) { 206 // Good case 207 { 208 clientset := getGPGKeysClientset(gpgCMEmpty) 209 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 210 db := NewDB(testNamespace, settings, clientset) 211 212 // Key should be added 213 new, skipped, err := db.AddGPGPublicKey(context.Background(), test.MustLoadFileToString("../gpg/testdata/github.asc")) 214 assert.NoError(t, err) 215 assert.Len(t, new, 1) 216 assert.Len(t, skipped, 0) 217 cm, err := settings.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName) 218 assert.NoError(t, err) 219 assert.Len(t, cm.Data, 1) 220 221 // Same key should not be added, but skipped 222 new, skipped, err = db.AddGPGPublicKey(context.Background(), test.MustLoadFileToString("../gpg/testdata/github.asc")) 223 assert.NoError(t, err) 224 assert.Len(t, new, 0) 225 assert.Len(t, skipped, 1) 226 cm, err = settings.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName) 227 assert.NoError(t, err) 228 assert.Len(t, cm.Data, 1) 229 230 // New keys should be added 231 new, skipped, err = db.AddGPGPublicKey(context.Background(), test.MustLoadFileToString("../gpg/testdata/multi.asc")) 232 assert.NoError(t, err) 233 assert.Len(t, new, 2) 234 assert.Len(t, skipped, 0) 235 cm, err = settings.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName) 236 assert.NoError(t, err) 237 assert.Len(t, cm.Data, 3) 238 239 // Same new keys should be skipped 240 new, skipped, err = db.AddGPGPublicKey(context.Background(), test.MustLoadFileToString("../gpg/testdata/multi.asc")) 241 assert.NoError(t, err) 242 assert.Len(t, new, 0) 243 assert.Len(t, skipped, 2) 244 cm, err = settings.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName) 245 assert.NoError(t, err) 246 assert.Len(t, cm.Data, 3) 247 248 // Garbage input should result in error 249 new, skipped, err = db.AddGPGPublicKey(context.Background(), test.MustLoadFileToString("../gpg/testdata/garbage.asc")) 250 assert.Error(t, err) 251 assert.Nil(t, new) 252 assert.Nil(t, skipped) 253 cm, err = settings.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName) 254 assert.NoError(t, err) 255 assert.Len(t, cm.Data, 3) 256 } 257 } 258 259 func Test_DeleteGPGPublicKey(t *testing.T) { 260 defer os.Setenv("GNUPGHOME", "") 261 // Good case 262 { 263 clientset := getGPGKeysClientset(gpgCMMultiGoodPubkey) 264 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 265 db := NewDB(testNamespace, settings, clientset) 266 267 // Key should be removed 268 err := db.DeleteGPGPublicKey(context.Background(), "FDC79815400D88A9") 269 assert.NoError(t, err) 270 271 // Key should not exist anymore, therefore can't be deleted again 272 err = db.DeleteGPGPublicKey(context.Background(), "FDC79815400D88A9") 273 assert.Error(t, err) 274 275 // One key left in configuration 276 n, err := db.ListConfiguredGPGPublicKeys(context.Background()) 277 assert.NoError(t, err) 278 assert.Len(t, n, 1) 279 280 // Key should be removed 281 err = db.DeleteGPGPublicKey(context.Background(), "F7842A5CEAA9C0B1") 282 assert.NoError(t, err) 283 284 // Key should not exist anymore, therefore can't be deleted again 285 err = db.DeleteGPGPublicKey(context.Background(), "F7842A5CEAA9C0B1") 286 assert.Error(t, err) 287 288 // No key left in configuration 289 n, err = db.ListConfiguredGPGPublicKeys(context.Background()) 290 assert.NoError(t, err) 291 assert.Len(t, n, 0) 292 293 } 294 // Bad case - empty ConfigMap 295 { 296 clientset := getGPGKeysClientset(gpgCMEmpty) 297 settings := settings.NewSettingsManager(context.Background(), clientset, testNamespace) 298 db := NewDB(testNamespace, settings, clientset) 299 300 // Key should be removed 301 err := db.DeleteGPGPublicKey(context.Background(), "F7842A5CEAA9C0B1") 302 assert.Error(t, err) 303 } 304 }