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