github.com/IBM-Cloud/bluemix-go@v0.0.0-20240314082800-4e02a69b84b2/api/iampap/iampapv1/authorization_policy_test.go (about) 1 package iampapv1 2 3 import ( 4 "log" 5 "net/http" 6 7 bluemix "github.com/IBM-Cloud/bluemix-go" 8 "github.com/IBM-Cloud/bluemix-go/client" 9 "github.com/IBM-Cloud/bluemix-go/crn" 10 "github.com/IBM-Cloud/bluemix-go/models" 11 "github.com/IBM-Cloud/bluemix-go/session" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 "github.com/onsi/gomega/ghttp" 15 ) 16 17 var _ = Describe("AuthorizationPolicies", func() { 18 var server *ghttp.Server 19 var repo AuthorizationPolicyRepository 20 21 BeforeEach(func() { 22 server = ghttp.NewServer() 23 repo = newTestAuthorizationPolicyRepo(server.URL()) 24 }) 25 26 AfterEach(func() { 27 server.Close() 28 }) 29 30 Describe("List()", func() { 31 Context("when there is no policy", func() { 32 BeforeEach(func() { 33 server.AppendHandlers(ghttp.CombineHandlers( 34 ghttp.VerifyRequest(http.MethodGet, "/acms/v2/accounts/account1-id/policies"), 35 ghttp.RespondWith(http.StatusOK, `{}`), 36 )) 37 }) 38 39 It("should return empty result", func() { 40 policies, err := repo.List("account1-id", nil) 41 Expect(err).Should(Succeed()) 42 Expect(policies).Should(BeEmpty()) 43 }) 44 }) 45 Context("when there is one authorization policy", func() { 46 BeforeEach(func() { 47 server.AppendHandlers(ghttp.CombineHandlers( 48 ghttp.VerifyRequest(http.MethodGet, "/acms/v2/accounts/account1-id/policies", "type=authorization"), 49 ghttp.RespondWith(http.StatusOK, `{ 50 "policies": [ 51 { 52 "id": "c723d05f-8f8c-4ef5-a44d-bc400cbde25e", 53 "createdById": "IBMid-270006V8HD", 54 "updatedById": "IBMid-270006V8HD", 55 "roles": [ 56 { 57 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 58 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 59 "displayName": "Reader", 60 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 61 } 62 ], 63 "resources": [ 64 { 65 "serviceName": "kms-test", 66 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 67 } 68 ], 69 "subjects": [ 70 { 71 "serviceName": "cloud-object-storage", 72 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 73 } 74 ] 75 } 76 ] 77 }`), 78 )) 79 }) 80 81 It("should return the policy", func() { 82 policies, err := repo.List("account1-id", &AuthorizationPolicySearchQuery{ 83 Type: AuthorizationPolicyType, 84 }) 85 Expect(err).Should(Succeed()) 86 Expect(policies).Should(HaveLen(1)) 87 Expect(policies[0].ID).To(Equal("c723d05f-8f8c-4ef5-a44d-bc400cbde25e")) 88 Expect(policies[0].Roles[0].ID.String()).To(Equal("crn:v1:bluemix:public:iam::::serviceRole:Reader")) 89 Expect(policies[0].Resources[0].AccountID).To(Equal("2bff70b5d2cc4b400814eca0bb730daa")) 90 Expect(policies[0].Subjects[0].ServiceName).To(Equal("cloud-object-storage")) 91 }) 92 }) 93 94 Context("when there are multiple policies", func() { 95 BeforeEach(func() { 96 server.AppendHandlers(ghttp.CombineHandlers( 97 ghttp.RespondWith(http.StatusOK, `{ 98 "policies": [ 99 { 100 "id": "c723d05f-8f8c-4ef5-a44d-bc400cbde25e", 101 "createdById": "IBMid-270006V8HD", 102 "updatedById": "IBMid-270006V8HD", 103 "roles": [ 104 { 105 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 106 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 107 "displayName": "Reader", 108 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 109 } 110 ], 111 "resources": [ 112 { 113 "serviceName": "kms-test", 114 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 115 } 116 ], 117 "subjects": [ 118 { 119 "serviceName": "cloud-object-storage", 120 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 121 } 122 ] 123 }, 124 { 125 "id": "25afbf1b-d849-4d13-b3d9-a0768b5c29aa", 126 "createdById": "IBMid-270006V8HD", 127 "updatedById": "IBMid-270006V8HD", 128 "roles": [ 129 { 130 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Administrator", 131 "id": "crn:v1:bluemix:public:iam::::serviceRole:Administrator", 132 "displayName": "Administrator", 133 "description": "As an administrator, you can perform all platform actions based on the resource this role is being assigned, including assigning access policies to other users." 134 } 135 ], 136 "resources": [ 137 { 138 "serviceName": "kms-test", 139 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 140 } 141 ], 142 "subjects": [ 143 { 144 "serviceName": "cloud-object-storage", 145 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 146 } 147 ] 148 } 149 ] 150 }`), 151 )) 152 }) 153 154 It("should return all results", func() { 155 policies, err := repo.List("account1-id", &AuthorizationPolicySearchQuery{ 156 Type: AccessPolicyType, 157 }) 158 Expect(err).Should(Succeed()) 159 Expect(policies).Should(HaveLen(2)) 160 161 Expect(policies[0].ID).To(Equal("c723d05f-8f8c-4ef5-a44d-bc400cbde25e")) 162 Expect(policies[0].Roles[0].ID.String()).To(Equal("crn:v1:bluemix:public:iam::::serviceRole:Reader")) 163 Expect(policies[0].Resources[0].AccountID).To(Equal("2bff70b5d2cc4b400814eca0bb730daa")) 164 Expect(policies[0].Subjects[0].ServiceName).To(Equal("cloud-object-storage")) 165 166 Expect(policies[1].ID).To(Equal("25afbf1b-d849-4d13-b3d9-a0768b5c29aa")) 167 Expect(policies[1].Roles[0].ID.String()).To(Equal("crn:v1:bluemix:public:iam::::serviceRole:Administrator")) 168 Expect(policies[1].Resources[0].ServiceName).To(Equal("kms-test")) 169 Expect(policies[1].Subjects[0].AccountID).To(Equal("2bff70b5d2cc4b400814eca0bb730daa")) 170 }) 171 }) 172 173 Context("when there is error", func() { 174 BeforeEach(func() { 175 server.AppendHandlers(ghttp.CombineHandlers( 176 ghttp.RespondWith(http.StatusBadRequest, `[{ 177 "StatusCode": 400, 178 "code": "missing_token_in_request", 179 "message": "Token not included in request. Please add token with authorization header." 180 }]`), 181 )) 182 }) 183 184 It("should return error", func() { 185 _, err := repo.List("account1-id", &AuthorizationPolicySearchQuery{ 186 SubjectID: "123", 187 AccessGroupID: "567", 188 }) 189 Expect(err).Should(HaveOccurred()) 190 }) 191 }) 192 }) 193 194 Describe("Get()", func() { 195 Context("when policy is found", func() { 196 BeforeEach(func() { 197 server.AppendHandlers(ghttp.CombineHandlers( 198 ghttp.VerifyRequest(http.MethodGet, "/acms/v2/accounts/account1-id/policies/foo"), 199 ghttp.RespondWith(http.StatusOK, `{ 200 "id": "c723d05f-8f8c-4ef5-a44d-bc400cbde25e", 201 "createdById": "IBMid-270006V8HD", 202 "updatedById": "IBMid-270006V8HD", 203 "roles": [ 204 { 205 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 206 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 207 "displayName": "Reader", 208 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 209 } 210 ], 211 "resources": [ 212 { 213 "serviceName": "kms-test", 214 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 215 } 216 ], 217 "subjects": [ 218 { 219 "serviceName": "cloud-object-storage", 220 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 221 } 222 ] 223 }`), 224 )) 225 }) 226 227 It("should return success", func() { 228 p, err := repo.Get("account1-id", "foo") 229 Expect(err).Should(Succeed()) 230 Expect(p.ID).To(Equal("c723d05f-8f8c-4ef5-a44d-bc400cbde25e")) 231 Expect(p.Roles[0].ID.String()).To(Equal("crn:v1:bluemix:public:iam::::serviceRole:Reader")) 232 Expect(p.Resources[0].AccountID).To(Equal("2bff70b5d2cc4b400814eca0bb730daa")) 233 Expect(p.Subjects[0].ServiceName).To(Equal("cloud-object-storage")) 234 }) 235 }) 236 237 Context("when there is error fails", func() { 238 BeforeEach(func() { 239 server.AppendHandlers(ghttp.CombineHandlers( 240 ghttp.VerifyRequest(http.MethodGet, "/acms/v2/accounts/account1-id/policies/foo"), 241 ghttp.RespondWith(http.StatusNotFound, `{ 242 "errors": [{ 243 "StatusCode": 404, 244 "code": "not_found", 245 "message": "policy not found" 246 }], 247 }`), 248 )) 249 }) 250 251 It("should return error", func() { 252 _, err := repo.Get("account1-id", "foo") 253 Expect(err).Should(HaveOccurred()) 254 }) 255 }) 256 257 }) 258 259 Describe("Create", func() { 260 Context("when creation succeeds", func() { 261 BeforeEach(func() { 262 header := http.Header{} 263 header.Add("Etag", "abc") 264 server.AppendHandlers(ghttp.CombineHandlers( 265 ghttp.VerifyRequest(http.MethodPost, "/acms/v2/accounts/account1-id/policies"), 266 ghttp.VerifyJSON(`{ 267 "roles": [ 268 { 269 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 270 "displayName": "Reader", 271 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 272 } 273 ], 274 "resources": [ 275 { 276 "serviceName": "kms-test", 277 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 278 } 279 ], 280 "subjects": [ 281 { 282 "serviceName": "cloud-object-storage", 283 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 284 } 285 ] 286 }`), 287 ghttp.RespondWith(http.StatusCreated, `{ 288 "id": "c723d05f-8f8c-4ef5-a44d-bc400cbde25e", 289 "createdById": "IBMid-270006V8HD", 290 "updatedById": "IBMid-270006V8HD", 291 "roles": [ 292 { 293 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 294 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 295 "displayName": "Reader", 296 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 297 } 298 ], 299 "resources": [ 300 { 301 "serviceName": "kms-test", 302 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 303 } 304 ], 305 "subjects": [ 306 { 307 "serviceName": "cloud-object-storage", 308 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 309 } 310 ] 311 }`, header), 312 )) 313 }) 314 It("should return created authorization policy", func() { 315 p, err := repo.Create("account1-id", AuthorizationPolicy{ 316 Roles: []models.PolicyRole{ 317 models.PolicyRole{ 318 ID: crn.CRN{ 319 Scheme: "crn", 320 Version: "v1", 321 CName: "bluemix", 322 CType: "public", 323 ServiceName: "iam", 324 Region: "", 325 ScopeType: "", 326 Scope: "", 327 ServiceInstance: "", 328 ResourceType: "serviceRole", 329 Resource: "Reader", 330 }, 331 DisplayName: "Reader", 332 Description: "As a reader, you can perform read-only actions within a service such as viewing service-specific resources.", 333 }, 334 }, 335 Resources: []models.PolicyResource{ 336 models.PolicyResource{ 337 ServiceName: "kms-test", 338 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 339 }, 340 }, 341 Subjects: []models.PolicyResource{ 342 models.PolicyResource{ 343 ServiceName: "cloud-object-storage", 344 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 345 }, 346 }, 347 }) 348 Expect(err).To(Succeed()) 349 Expect(p.ID).To(Equal("c723d05f-8f8c-4ef5-a44d-bc400cbde25e")) 350 }) 351 }) 352 Context("when creation fails", func() { 353 BeforeEach(func() { 354 server.AppendHandlers(ghttp.CombineHandlers( 355 ghttp.VerifyRequest(http.MethodPost, "/acms/v2/accounts/account1-id/policies"), 356 ghttp.VerifyJSON(`{ 357 "roles": [ 358 { 359 "id": "crn:v1:bluemix:public:iam::::serviceRole:Administrator", 360 "displayName": "Administrator", 361 "description": "As an administrator, you can perform all platform actions based on the resource this role is being assigned, including assigning access policies to other users." 362 } 363 ], 364 "resources": [ 365 { 366 "serviceName": "kms-test", 367 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 368 } 369 ], 370 "subjects": [ 371 { 372 "serviceName": "cloud-object-storage", 373 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 374 } 375 ] 376 }`), 377 ghttp.RespondWith(http.StatusUnauthorized, `{ 378 "errors": [{ 379 "StatusCode": 401, 380 "code": "Invalid token", 381 "message": "No groups found for the member test." 382 }], 383 }`), 384 )) 385 }) 386 It("should return error", func() { 387 _, err := repo.Create("account1-id", AuthorizationPolicy{ 388 Roles: []models.PolicyRole{ 389 models.PolicyRole{ 390 ID: crn.CRN{ 391 Scheme: "crn", 392 Version: "v1", 393 CName: "bluemix", 394 CType: "public", 395 ServiceName: "iam", 396 Region: "", 397 ScopeType: "", 398 Scope: "", 399 ServiceInstance: "", 400 ResourceType: "serviceRole", 401 Resource: "Administrator", 402 }, 403 DisplayName: "Administrator", 404 Description: "As an administrator, you can perform all platform actions based on the resource this role is being assigned, including assigning access policies to other users.", 405 }, 406 }, 407 Resources: []models.PolicyResource{ 408 models.PolicyResource{ 409 ServiceName: "kms-test", 410 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 411 }, 412 }, 413 Subjects: []models.PolicyResource{ 414 models.PolicyResource{ 415 ServiceName: "cloud-object-storage", 416 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 417 }, 418 }, 419 }) 420 Expect(err).To(HaveOccurred()) 421 }) 422 }) 423 }) 424 425 Describe("Update", func() { 426 Context("when update succeeds", func() { 427 BeforeEach(func() { 428 header := http.Header{} 429 header.Add("Etag", "abc") 430 server.AppendHandlers(ghttp.CombineHandlers( 431 ghttp.VerifyRequest(http.MethodPut, "/acms/v2/accounts/account1-id/policies/foo"), 432 ghttp.VerifyHeaderKV("If-Match", "abc"), 433 ghttp.VerifyJSON(`{ 434 "roles": [ 435 { 436 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 437 "displayName": "Reader", 438 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 439 } 440 ], 441 "resources": [ 442 { 443 "serviceName": "kms-test", 444 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 445 } 446 ], 447 "subjects": [ 448 { 449 "serviceName": "cloud-object-storage", 450 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 451 } 452 ] 453 }`), 454 ghttp.RespondWith(http.StatusOK, `{ 455 "id": "c723d05f-8f8c-4ef5-a44d-bc400cbde25e", 456 "createdById": "IBMid-270006V8HD", 457 "updatedById": "IBMid-270006V8HD", 458 "roles": [ 459 { 460 "crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 461 "id": "crn:v1:bluemix:public:iam::::serviceRole:Reader", 462 "displayName": "Reader", 463 "description": "As a reader, you can perform read-only actions within a service such as viewing service-specific resources." 464 } 465 ], 466 "resources": [ 467 { 468 "serviceName": "kms-test", 469 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 470 } 471 ], 472 "subjects": [ 473 { 474 "serviceName": "cloud-object-storage", 475 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 476 } 477 ] 478 }`, header), 479 )) 480 }) 481 It("should return updated authorization policy", func() { 482 p, err := repo.Update("account1-id", "foo", AuthorizationPolicy{ 483 Roles: []models.PolicyRole{ 484 models.PolicyRole{ 485 ID: crn.CRN{ 486 Scheme: "crn", 487 Version: "v1", 488 CName: "bluemix", 489 CType: "public", 490 ServiceName: "iam", 491 Region: "", 492 ScopeType: "", 493 Scope: "", 494 ServiceInstance: "", 495 ResourceType: "serviceRole", 496 Resource: "Reader", 497 }, 498 DisplayName: "Reader", 499 Description: "As a reader, you can perform read-only actions within a service such as viewing service-specific resources.", 500 }, 501 }, 502 Resources: []models.PolicyResource{ 503 models.PolicyResource{ 504 ServiceName: "kms-test", 505 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 506 }, 507 }, 508 Subjects: []models.PolicyResource{ 509 models.PolicyResource{ 510 ServiceName: "cloud-object-storage", 511 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 512 }, 513 }, 514 }, "abc") 515 Expect(err).To(Succeed()) 516 Expect(p.ID).To(Equal("c723d05f-8f8c-4ef5-a44d-bc400cbde25e")) 517 Expect(p.Version).To(Equal("abc")) 518 }) 519 }) 520 Context("when update fails", func() { 521 BeforeEach(func() { 522 server.AppendHandlers(ghttp.CombineHandlers( 523 ghttp.VerifyRequest(http.MethodPut, "/acms/v2/accounts/account1-id/policies/foo"), 524 ghttp.VerifyHeaderKV("If-Match", "abc"), 525 ghttp.VerifyJSON(`{ 526 "roles": [ 527 { 528 "id": "crn:v1:bluemix:public:iam::::serviceRole:Administrator", 529 "displayName": "Administrator", 530 "description": "As an administrator, you can perform all platform actions based on the resource this role is being assigned, including assigning access policies to other users." 531 } 532 ], 533 "resources": [ 534 { 535 "serviceName": "kms-test", 536 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 537 } 538 ], 539 "subjects": [ 540 { 541 "serviceName": "cloud-object-storage", 542 "accountId": "2bff70b5d2cc4b400814eca0bb730daa" 543 } 544 ] 545 }`), 546 ghttp.RespondWith(http.StatusUnauthorized, `{ 547 "errors": [{ 548 "StatusCode": 401, 549 "code": "Invalid token", 550 "message": "No groups found for the member test." 551 }], 552 }`), 553 )) 554 }) 555 It("should return error", func() { 556 _, err := repo.Update("account1-id", "foo", AuthorizationPolicy{ 557 Roles: []models.PolicyRole{ 558 models.PolicyRole{ 559 ID: crn.CRN{ 560 Scheme: "crn", 561 Version: "v1", 562 CName: "bluemix", 563 CType: "public", 564 ServiceName: "iam", 565 Region: "", 566 ScopeType: "", 567 Scope: "", 568 ServiceInstance: "", 569 ResourceType: "serviceRole", 570 Resource: "Administrator", 571 }, 572 DisplayName: "Administrator", 573 Description: "As an administrator, you can perform all platform actions based on the resource this role is being assigned, including assigning access policies to other users.", 574 }, 575 }, 576 Resources: []models.PolicyResource{ 577 models.PolicyResource{ 578 ServiceName: "kms-test", 579 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 580 }, 581 }, 582 Subjects: []models.PolicyResource{ 583 models.PolicyResource{ 584 ServiceName: "cloud-object-storage", 585 AccountID: "2bff70b5d2cc4b400814eca0bb730daa", 586 }, 587 }, 588 }, "abc") 589 Expect(err).To(HaveOccurred()) 590 }) 591 }) 592 }) 593 594 Describe("Delete()", func() { 595 Context("when deletion succeeds", func() { 596 BeforeEach(func() { 597 server.AppendHandlers(ghttp.CombineHandlers( 598 ghttp.VerifyRequest(http.MethodDelete, "/acms/v1/policies/foo"), 599 ghttp.RespondWith(http.StatusNoContent, ""), 600 )) 601 }) 602 603 It("should return success", func() { 604 err := repo.Delete("account1-id", "foo") 605 Expect(err).Should(Succeed()) 606 }) 607 }) 608 609 Context("when deletion fails", func() { 610 BeforeEach(func() { 611 server.AppendHandlers(ghttp.CombineHandlers( 612 ghttp.VerifyRequest(http.MethodDelete, "/acms/v1/policies/foo"), 613 ghttp.RespondWith(http.StatusNotFound, `{ 614 "errors": [{ 615 "StatusCode": 404, 616 "code": "not_found", 617 "message": "policy not found" 618 }], 619 }`), 620 )) 621 }) 622 623 It("should return error", func() { 624 err := repo.Delete("account1-id", "foo") 625 Expect(err).Should(HaveOccurred()) 626 Expect(err.Error()).Should(ContainSubstring("not_found")) 627 }) 628 }) 629 630 }) 631 }) 632 633 func newTestAuthorizationPolicyRepo(url string) AuthorizationPolicyRepository { 634 sess, err := session.New() 635 if err != nil { 636 log.Fatal(err) 637 } 638 conf := sess.Config.Copy() 639 conf.Endpoint = &url 640 client := client.Client{ 641 Config: conf, 642 ServiceName: bluemix.IAMPAPService, 643 } 644 return NewAuthorizationPolicyRepository(&client) 645 }