github.com/Azure/aad-pod-identity@v1.8.17/pkg/nmi/standard_test.go (about) 1 package nmi 2 3 import ( 4 "context" 5 "encoding/base64" 6 "reflect" 7 "testing" 8 9 aadpodid "github.com/Azure/aad-pod-identity/pkg/apis/aadpodidentity" 10 auth "github.com/Azure/aad-pod-identity/pkg/auth" 11 "github.com/Azure/aad-pod-identity/pkg/k8s" 12 "github.com/Azure/aad-pod-identity/pkg/metrics" 13 14 v1 "k8s.io/api/core/v1" 15 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/client-go/kubernetes/fake" 17 ) 18 19 type TestKubeClient struct { 20 k8s.Client 21 azureIdentities interface{} 22 err error 23 } 24 25 func NewTestKubeClient(azids interface{}) *TestKubeClient { 26 return &TestKubeClient{ 27 azureIdentities: azids, 28 } 29 } 30 31 func (c *TestKubeClient) ListPodIds(podns, podname string) (map[string][]aadpodid.AzureIdentity, error) { 32 identities, _ := c.azureIdentities.(map[string][]aadpodid.AzureIdentity) 33 return identities, c.err 34 } 35 36 func TestGetTokenForMatchingIDBySP(t *testing.T) { 37 fakeClient := fake.NewSimpleClientset() 38 reporter, err := metrics.NewReporter() 39 if err != nil { 40 t.Fatalf("expected nil error, got: %+v", err) 41 } 42 auth.InitReporter(reporter) 43 44 secret := &v1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "clientSecret"}, Data: make(map[string][]byte)} 45 val, _ := base64.StdEncoding.DecodeString("YWJjZA==") 46 secret.Data["key1"] = val 47 _, err = fakeClient.CoreV1().Secrets("default").Create(context.TODO(), secret, metav1.CreateOptions{}) 48 if err != nil { 49 t.Fatalf("Error creating secret: %v", err) 50 } 51 52 kubeClient := &k8s.KubeClient{ClientSet: fakeClient} 53 tokenClient, err := NewStandardTokenClient(kubeClient, Config{}) 54 if err != nil { 55 t.Fatalf("expected err to be nil, got: %v", err) 56 } 57 58 secretRef := v1.SecretReference{ 59 Name: "clientSecret", 60 Namespace: "default", 61 } 62 63 podID := aadpodid.AzureIdentity{ 64 Spec: aadpodid.AzureIdentitySpec{ 65 Type: aadpodid.ServicePrincipal, 66 TenantID: "11111111-1111-1111-1111-111111111111", 67 ClientID: "aabc0000-a83v-9h4m-000j-2c0a66b0c1f9", 68 ClientPassword: secretRef, 69 }, 70 } 71 _, _ = tokenClient.GetTokens(context.Background(), podID.Spec.ClientID, "https://management.azure.com/", podID) 72 } 73 74 func TestGetTokenForMatchingIDBySPCertificate(t *testing.T) { 75 fakeClient := fake.NewSimpleClientset() 76 reporter, err := metrics.NewReporter() 77 if err != nil { 78 t.Fatalf("expected nil error, got: %+v", err) 79 } 80 auth.InitReporter(reporter) 81 82 secret := &v1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "certificate"}, Data: make(map[string][]byte)} 83 val, _ := base64.StdEncoding.DecodeString("YWJjZA==") 84 secret.Data["certificate"] = val 85 secret.Data["password"] = val 86 _, err = fakeClient.CoreV1().Secrets("default").Create(context.TODO(), secret, metav1.CreateOptions{}) 87 if err != nil { 88 t.Fatalf("Error creating secret: %v", err) 89 } 90 91 kubeClient := &k8s.KubeClient{ClientSet: fakeClient} 92 tokenClient, err := NewStandardTokenClient(kubeClient, Config{}) 93 if err != nil { 94 t.Fatalf("expected err to be nil, got: %v", err) 95 } 96 97 secretRef := v1.SecretReference{ 98 Name: "certificate", 99 Namespace: "default", 100 } 101 102 podID := aadpodid.AzureIdentity{ 103 Spec: aadpodid.AzureIdentitySpec{ 104 Type: aadpodid.ServicePrincipalCertificate, 105 TenantID: "tid", 106 ClientID: "aabc0000-a83v-9h4m-000j-2c0a66b0c1f9", 107 ClientPassword: secretRef, 108 }, 109 } 110 _, _ = tokenClient.GetTokens(context.Background(), podID.Spec.ClientID, "https://management.azure.com/", podID) 111 } 112 113 func TestGetIdentitiesStandardClient(t *testing.T) { 114 cases := []struct { 115 name string 116 azureIdentities map[string][]aadpodid.AzureIdentity 117 clientID string 118 resourceID string 119 expectedErr bool 120 expectedAzureIdentity *aadpodid.AzureIdentity 121 isNamespaced bool 122 podName string 123 podNamespace string 124 }{ 125 { 126 name: "no azure identities", 127 azureIdentities: make(map[string][]aadpodid.AzureIdentity), 128 expectedErr: true, 129 expectedAzureIdentity: nil, 130 podName: "pod1", 131 podNamespace: "default", 132 }, 133 { 134 name: "azure identities with old 1.3/1.4, no request client id", 135 azureIdentities: map[string][]aadpodid.AzureIdentity{ 136 "": { 137 { 138 ObjectMeta: metav1.ObjectMeta{ 139 Name: "azid1", 140 Namespace: "default", 141 }, 142 Spec: aadpodid.AzureIdentitySpec{ 143 ClientID: "clientid1", 144 }, 145 }, 146 { 147 ObjectMeta: metav1.ObjectMeta{ 148 Name: "azid2", 149 Namespace: "default", 150 }, 151 Spec: aadpodid.AzureIdentitySpec{ 152 ClientID: "clientid2", 153 }, 154 }, 155 }, 156 }, 157 expectedErr: false, 158 expectedAzureIdentity: &aadpodid.AzureIdentity{ 159 ObjectMeta: metav1.ObjectMeta{ 160 Name: "azid1", 161 Namespace: "default", 162 }, 163 Spec: aadpodid.AzureIdentitySpec{ 164 ClientID: "clientid1", 165 }, 166 }, 167 podName: "pod2", 168 podNamespace: "default", 169 }, 170 { 171 name: "no identity requested, found in created state only", 172 azureIdentities: map[string][]aadpodid.AzureIdentity{ 173 aadpodid.AssignedIDCreated: { 174 { 175 ObjectMeta: metav1.ObjectMeta{ 176 Name: "azid3", 177 Namespace: "default", 178 }, 179 Spec: aadpodid.AzureIdentitySpec{ 180 ClientID: "clientid3", 181 }, 182 }, 183 { 184 ObjectMeta: metav1.ObjectMeta{ 185 Name: "azid4", 186 Namespace: "default", 187 }, 188 Spec: aadpodid.AzureIdentitySpec{ 189 ClientID: "clientid4", 190 }, 191 }, 192 }, 193 }, 194 expectedAzureIdentity: &aadpodid.AzureIdentity{}, 195 expectedErr: true, 196 podName: "pod3", 197 podNamespace: "default", 198 }, 199 { 200 name: "no identity requested, found in assigned state", 201 azureIdentities: map[string][]aadpodid.AzureIdentity{ 202 aadpodid.AssignedIDAssigned: { 203 { 204 ObjectMeta: metav1.ObjectMeta{ 205 Name: "azid5", 206 Namespace: "default", 207 }, 208 Spec: aadpodid.AzureIdentitySpec{ 209 ClientID: "clientid5", 210 }, 211 }, 212 { 213 ObjectMeta: metav1.ObjectMeta{ 214 Name: "azid6", 215 Namespace: "default", 216 }, 217 Spec: aadpodid.AzureIdentitySpec{ 218 ClientID: "clientid6", 219 }, 220 }, 221 }, 222 }, 223 expectedErr: false, 224 expectedAzureIdentity: &aadpodid.AzureIdentity{ 225 ObjectMeta: metav1.ObjectMeta{ 226 Name: "azid5", 227 Namespace: "default", 228 }, 229 Spec: aadpodid.AzureIdentitySpec{ 230 ClientID: "clientid5", 231 }, 232 }, 233 podName: "pod4", 234 podNamespace: "default", 235 }, 236 { 237 name: "client id in request, no identity with same client id in assigned state", 238 azureIdentities: map[string][]aadpodid.AzureIdentity{ 239 aadpodid.AssignedIDCreated: { 240 { 241 ObjectMeta: metav1.ObjectMeta{ 242 Name: "azid1", 243 Namespace: "default", 244 }, 245 Spec: aadpodid.AzureIdentitySpec{ 246 ClientID: "clientid1", 247 }, 248 }, 249 }, 250 aadpodid.AssignedIDAssigned: { 251 { 252 ObjectMeta: metav1.ObjectMeta{ 253 Name: "azid2", 254 Namespace: "default", 255 }, 256 Spec: aadpodid.AzureIdentitySpec{ 257 ClientID: "clientid2", 258 ResourceID: "clientid1", // ensure that we are matching against ClientID 259 }, 260 }, 261 }, 262 }, 263 expectedErr: true, 264 expectedAzureIdentity: &aadpodid.AzureIdentity{}, 265 podName: "pod5", 266 podNamespace: "default", 267 clientID: "clientid1", 268 }, 269 { 270 name: "resource id in request, no identity with same resource id in assigned state", 271 azureIdentities: map[string][]aadpodid.AzureIdentity{ 272 aadpodid.AssignedIDCreated: { 273 { 274 ObjectMeta: metav1.ObjectMeta{ 275 Name: "azid1", 276 Namespace: "default", 277 }, 278 Spec: aadpodid.AzureIdentitySpec{ 279 ResourceID: "resourceid1", 280 }, 281 }, 282 }, 283 aadpodid.AssignedIDAssigned: { 284 { 285 ObjectMeta: metav1.ObjectMeta{ 286 Name: "azid2", 287 Namespace: "default", 288 }, 289 Spec: aadpodid.AzureIdentitySpec{ 290 ClientID: "resourceid1", // ensure we are matching against ResourceID 291 ResourceID: "resourceid2", 292 }, 293 }, 294 }, 295 }, 296 expectedErr: true, 297 expectedAzureIdentity: &aadpodid.AzureIdentity{}, 298 podName: "pod5", 299 podNamespace: "default", 300 resourceID: "resourceid1", 301 }, 302 { 303 name: "client id in request, found matching identity", 304 azureIdentities: map[string][]aadpodid.AzureIdentity{ 305 aadpodid.AssignedIDCreated: { 306 { 307 ObjectMeta: metav1.ObjectMeta{ 308 Name: "azid1", 309 Namespace: "default", 310 }, 311 Spec: aadpodid.AzureIdentitySpec{ 312 ClientID: "clientid1", 313 }, 314 }, 315 }, 316 aadpodid.AssignedIDAssigned: { 317 { 318 ObjectMeta: metav1.ObjectMeta{ 319 Name: "azid2", 320 Namespace: "default", 321 }, 322 Spec: aadpodid.AzureIdentitySpec{ 323 ClientID: "clientid2", 324 ResourceID: "resourceid2", 325 }, 326 }, 327 }, 328 }, 329 expectedAzureIdentity: &aadpodid.AzureIdentity{ 330 ObjectMeta: metav1.ObjectMeta{ 331 Name: "azid2", 332 Namespace: "default", 333 }, 334 Spec: aadpodid.AzureIdentitySpec{ 335 ClientID: "clientid2", 336 ResourceID: "resourceid2", 337 }, 338 }, 339 podName: "pod5", 340 podNamespace: "default", 341 clientID: "clientid2", 342 }, 343 { 344 name: "resource id in request, found matching identity", 345 azureIdentities: map[string][]aadpodid.AzureIdentity{ 346 aadpodid.AssignedIDCreated: { 347 { 348 ObjectMeta: metav1.ObjectMeta{ 349 Name: "azid1", 350 Namespace: "default", 351 }, 352 Spec: aadpodid.AzureIdentitySpec{ 353 ResourceID: "resourceid1", 354 }, 355 }, 356 }, 357 aadpodid.AssignedIDAssigned: { 358 { 359 ObjectMeta: metav1.ObjectMeta{ 360 Name: "azid2", 361 Namespace: "default", 362 }, 363 Spec: aadpodid.AzureIdentitySpec{ 364 ClientID: "resourceid2", 365 ResourceID: "resourceid2", 366 }, 367 }, 368 }, 369 }, 370 expectedAzureIdentity: &aadpodid.AzureIdentity{ 371 ObjectMeta: metav1.ObjectMeta{ 372 Name: "azid2", 373 Namespace: "default", 374 }, 375 Spec: aadpodid.AzureIdentitySpec{ 376 ClientID: "resourceid2", 377 ResourceID: "resourceid2", 378 }, 379 }, 380 podName: "pod5", 381 podNamespace: "default", 382 resourceID: "resourceid2", 383 }, 384 { 385 name: "no identity requested, identity in same namespace returned with force namespace mode", 386 azureIdentities: map[string][]aadpodid.AzureIdentity{ 387 aadpodid.AssignedIDAssigned: { 388 { 389 ObjectMeta: metav1.ObjectMeta{ 390 Name: "azid2", 391 Namespace: "default", 392 }, 393 Spec: aadpodid.AzureIdentitySpec{ 394 ClientID: "clientid2", 395 }, 396 }, 397 { 398 ObjectMeta: metav1.ObjectMeta{ 399 Name: "azid1", 400 Namespace: "default", 401 }, 402 Spec: aadpodid.AzureIdentitySpec{ 403 ClientID: "clientid1", 404 }, 405 }, 406 { 407 ObjectMeta: metav1.ObjectMeta{ 408 Name: "azid3", 409 Namespace: "testns", 410 }, 411 Spec: aadpodid.AzureIdentitySpec{ 412 ClientID: "clientid3", 413 }, 414 }, 415 }, 416 }, 417 expectedErr: false, 418 expectedAzureIdentity: &aadpodid.AzureIdentity{ 419 ObjectMeta: metav1.ObjectMeta{ 420 Name: "azid3", 421 Namespace: "testns", 422 }, 423 Spec: aadpodid.AzureIdentitySpec{ 424 ClientID: "clientid3", 425 }, 426 }, 427 podName: "pod8", 428 podNamespace: "testns", 429 isNamespaced: true, 430 }, 431 } 432 433 for _, tc := range cases { 434 t.Run(tc.name, func(t *testing.T) { 435 tokenClient, err := NewStandardTokenClient(NewTestKubeClient(tc.azureIdentities), Config{ 436 Mode: "standard", 437 RetryAttemptsForCreated: 2, 438 RetryAttemptsForAssigned: 1, 439 FindIdentityRetryIntervalInSeconds: 1, 440 Namespaced: tc.isNamespaced, 441 }) 442 if err != nil { 443 t.Fatalf("expected err to be nil, got: %v", err) 444 } 445 446 azIdentity, err := tokenClient.GetIdentities(context.Background(), tc.podNamespace, tc.podName, tc.clientID, tc.resourceID) 447 if tc.expectedErr != (err != nil) { 448 t.Fatalf("expected error: %v, got: %v", tc.expectedErr, err) 449 } 450 if !reflect.DeepEqual(tc.expectedAzureIdentity, azIdentity) { 451 t.Fatalf("expected the azure identity to be equal") 452 } 453 }) 454 } 455 }