github.com/IBM-Cloud/bluemix-go@v0.0.0-20240314082800-4e02a69b84b2/api/iampap/iampapv1/v1_policies_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/session"
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/onsi/gomega/ghttp"
    13  )
    14  
    15  var _ = Describe("V1Policies", func() {
    16  	var server *ghttp.Server
    17  	var repo V1PolicyRepository
    18  
    19  	BeforeEach(func() {
    20  		server = ghttp.NewServer()
    21  		repo = newv1Policy(server.URL())
    22  	})
    23  
    24  	AfterEach(func() {
    25  		server.Close()
    26  	})
    27  
    28  	Describe("List()", func() {
    29  		Context("When there are policies", func() {
    30  			BeforeEach(func() {
    31  				server.AppendHandlers(ghttp.CombineHandlers(
    32  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies", "account_id=account1-id&type=access"),
    33  					ghttp.RespondWith(http.StatusOK, `{
    34  						"policies": [
    35  						  {
    36  							"id": "285a9542-c08c-43c6-8f0a-632dc5801b64",
    37  							"type": "access",
    38  							"subjects": [{
    39  								"attributes": [{
    40  									"name": "iam_id",
    41  									"value": "IBMid-060001MNR3"
    42  								}]
    43  							}],
    44  							"roles": [
    45  							  {
    46  								"role_id": "crn:v1:bluemix:public:iam::::role:Editor",
    47  								"display_name": "Editor",
    48  								"description": "As an editor, you can perform all platform actions except for managing the account and assigning access policies."
    49  							  }
    50  							],
    51  							"resources": [{
    52  								"attributes": [{
    53  									"name": "accountId",
    54  									"value": "b8b618cc651496dd7a0634264d071843"
    55  								},{
    56  									"name": "resourceType",
    57  									"value": "resource-group"
    58  								},{
    59  									"name": "resource",
    60  									"value": "247bd6f43b5f7af30b43a13724020b52"
    61  								}]
    62  							}],
    63  							"href": "https://iam.cloud.ibm.com/v1/policies/285a9542-c08c-43c6-8f0a-632dc5801b64",
    64  							"created_at": "2018-04-17T06:53:46.342Z",
    65  							"created_by_id": "IBMid-270004WA4U",
    66  							"last_modified_at": "2018-04-17T06:53:46.342Z",
    67  							"last_modified_by_id": "2018-04-17T06:53:46.342Z"
    68  						  },
    69  						  {
    70  							"id": "1a369e5f-3339-4fbb-b52f-97ff364c9e7a",
    71  							"type": "access",
    72  							"subjects": [{
    73  								"attributes": [{
    74  									"name": "iam_id",
    75  									"value": "IBMid-2700076QDK"
    76  								}]
    77  							}],
    78  							"roles": [
    79  							  {
    80  								"role_id": "crn:v1:bluemix:public:iam::::role:Editor",
    81  								"display_name": "Editor",
    82  								"description": "As an editor, you can perform all platform actions except for managing the account and assigning access policies."
    83  							  }
    84  							],
    85  							"resources": [{
    86  								"attributes": [{
    87  									"name": "accountId",
    88  									"value": "b8b618cc651496dd7a0634264d071843"
    89  								}]
    90  							}],
    91  							"href": "https://iam.cloud.ibm.com/v1/policies/1a369e5f-3339-4fbb-b52f-97ff364c9e7a",
    92  							"created_at": null,
    93  							"created_by_id": null,
    94  							"last_modified_at": null,
    95  							"last_modified_by_id": null
    96  						  },
    97  						  {
    98  							"id": "cecc91ff-b680-4705-ba1c-c7f1fefcf02d",
    99  							"type": "access",
   100  							"subjects": [{
   101  								"attributes": [{
   102  									"name": "access_group_id",
   103  									"value": "AccessGroupId-888620a2-be96-47f9-a214-4ae995ef17ad"
   104  								}]
   105  							}],
   106  							"roles": [
   107  							  {
   108  								"role_id": "crn:v1:bluemix:public:iam::::role:Viewer",
   109  								"display_name": "Viewer",
   110  								"description": "As a viewer, you can view service instances, but you can't modify them."
   111  							  }
   112  							],
   113  							"resources": [{
   114  								"attributes": [{
   115  									"name": "accountId",
   116  									"value": "b8b618cc651496dd7a0634264d071843"
   117  								},{
   118  									"name": "resourceType",
   119  									"value": "resource-group"
   120  								},{
   121  									"name": "resource",
   122  									"value": "7f3f9f3ee8e64bf880ecec527c6f7c39"
   123  								}]
   124  							}],
   125  							"href": "https://iam.cloud.ibm.com/v1/policies/cecc91ff-b680-4705-ba1c-c7f1fefcf02d",
   126  							"created_at": "2018-03-26T09:07:03.853Z",
   127  							"created_by_id": "IBMid-270004WA4U",
   128  							"last_modified_at": "2018-03-26T09:07:03.853Z",
   129  							"last_modified_by_id": "IBMid-270004WA4U"
   130  						  }
   131  						]
   132  					}`),
   133  				))
   134  			})
   135  			It("should return all policies", func() {
   136  				policies, err := repo.List(SearchParams{
   137  					AccountID: "account1-id",
   138  					Type:      AccessPolicyType,
   139  				})
   140  				Expect(err).ShouldNot(HaveOccurred())
   141  				Expect(policies).To(HaveLen(3))
   142  				Expect(policies[0].ID).To(Equal("285a9542-c08c-43c6-8f0a-632dc5801b64"))
   143  				Expect(policies[0].Subjects[0].IAMID()).To(Equal("IBMid-060001MNR3"))
   144  				Expect(policies[0].Resources[0].AccountID()).To(Equal("b8b618cc651496dd7a0634264d071843"))
   145  				Expect(policies[0].Resources[0].ResourceType()).To(Equal("resource-group"))
   146  				Expect(policies[0].Resources[0].Resource()).To(Equal("247bd6f43b5f7af30b43a13724020b52"))
   147  				Expect(policies[0].Roles[0].RoleID).To(Equal("crn:v1:bluemix:public:iam::::role:Editor"))
   148  
   149  				Expect(policies[1].ID).To(Equal("1a369e5f-3339-4fbb-b52f-97ff364c9e7a"))
   150  				Expect(policies[1].Subjects[0].IAMID()).To(Equal("IBMid-2700076QDK"))
   151  				Expect(policies[1].Resources[0].AccountID()).To(Equal("b8b618cc651496dd7a0634264d071843"))
   152  				Expect(policies[1].Resources[0].ResourceType()).To(Equal(""))
   153  				Expect(policies[1].Resources[0].Resource()).To(Equal(""))
   154  				Expect(policies[0].Roles[0].RoleID).To(Equal("crn:v1:bluemix:public:iam::::role:Editor"))
   155  
   156  				Expect(policies[2].ID).To(Equal("cecc91ff-b680-4705-ba1c-c7f1fefcf02d"))
   157  				Expect(policies[2].Subjects[0].AccessGroupID()).To(Equal("AccessGroupId-888620a2-be96-47f9-a214-4ae995ef17ad"))
   158  				Expect(policies[2].Resources[0].AccountID()).To(Equal("b8b618cc651496dd7a0634264d071843"))
   159  				Expect(policies[2].Resources[0].ResourceType()).To(Equal("resource-group"))
   160  				Expect(policies[2].Resources[0].Resource()).To(Equal("7f3f9f3ee8e64bf880ecec527c6f7c39"))
   161  				Expect(policies[2].Roles[0].RoleID).To(Equal("crn:v1:bluemix:public:iam::::role:Viewer"))
   162  			})
   163  		})
   164  
   165  		Context("When there is no policy", func() {
   166  			BeforeEach(func() {
   167  				server.AppendHandlers(ghttp.CombineHandlers(
   168  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies", "account_id=account1-id&type=access&iam_id=foo"),
   169  					ghttp.RespondWith(http.StatusOK, `{
   170  						"policies": []
   171  					}`),
   172  				))
   173  			})
   174  			It("should return empty", func() {
   175  				policies, err := repo.List(SearchParams{
   176  					AccountID: "account1-id",
   177  					IAMID:     "foo",
   178  					Type:      AccessPolicyType,
   179  				})
   180  				Expect(err).ShouldNot(HaveOccurred())
   181  				Expect(policies).To(HaveLen(0))
   182  			})
   183  		})
   184  
   185  		Context("When there is error", func() {
   186  			BeforeEach(func() {
   187  				server.AppendHandlers(ghttp.CombineHandlers(
   188  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies", "account_id=account1-id&type=access&access_group_id=foo"),
   189  					ghttp.RespondWith(http.StatusUnauthorized, `{
   190  						"trace": "aac0333a26c64caaa5528bfeed3de4b8",
   191  						"errors": [
   192  							{
   193  								"code": "invalid_token",
   194  								"message": "The provided IAM token is invalid."
   195  							}
   196  						],
   197  						"status_code": 401
   198  					}`),
   199  				))
   200  			})
   201  			It("should return empty", func() {
   202  				policies, err := repo.List(SearchParams{
   203  					AccountID:     "account1-id",
   204  					AccessGroupID: "foo",
   205  					Type:          AccessPolicyType,
   206  				})
   207  				Expect(err).Should(HaveOccurred())
   208  				Expect(policies).To(HaveLen(0))
   209  			})
   210  		})
   211  	})
   212  
   213  	Describe("Get()", func() {
   214  		Context("When the policy is found", func() {
   215  			BeforeEach(func() {
   216  				server.AppendHandlers(ghttp.CombineHandlers(
   217  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies/policy-id"),
   218  					ghttp.RespondWith(http.StatusOK, `{
   219  						"id": "policy-id",
   220  						"type": "access",
   221  						"subjects": [{
   222  							"attributes": [{
   223  								"name": "iam_id",
   224  								"value": "IBMid-270006V8HD"
   225  							}]
   226  						}],
   227  						"roles": [
   228  							{
   229  								"role_id": "crn:v1:bluemix:public:iam::::role:Viewer",
   230  								"display_name": "Viewer",
   231  								"description": "As a viewer, you can view service instances, but you can't modify them."
   232  							}
   233  						],
   234  						"resources": [{
   235  							"attributes": [{
   236  								"name": "resourceType",
   237  								"value": "resource-group"
   238  							},{
   239  								"name": "resource",
   240  								"value": "5e0f4f2166a04667aea9440ad4850232"
   241  							}]
   242  						}],
   243  						"href": "https://iam.cloud.ibm.com/v1/policies/0b3cea25-fc07-49b1-986b-90846085cfeb",
   244  						"created_at": "2017-11-10T04:37:44.943Z",
   245  						"created_by_id": "IBMid-310000JVN5",
   246  						"last_modified_at": "2017-11-10T04:37:44.943Z",
   247  						"last_modified_by_id": "IBMid-310000JVN5"
   248  				}`, http.Header{"ETag": []string{"3-a283be20686c2c71c512e73e9ee2ce9c"}}),
   249  				))
   250  			})
   251  			It("should return the policy", func() {
   252  				p, err := repo.Get("policy-id")
   253  				Expect(err).ShouldNot(HaveOccurred())
   254  				Expect(p.ID).To(Equal("policy-id"))
   255  				Expect(p.Type).To(Equal(AccessPolicyType))
   256  				Expect(p.Subjects[0].IAMID()).To(Equal("IBMid-270006V8HD"))
   257  				Expect(p.Roles[0].RoleID).To(Equal("crn:v1:bluemix:public:iam::::role:Viewer"))
   258  				Expect(p.Resources[0].Resource()).To(Equal("5e0f4f2166a04667aea9440ad4850232"))
   259  				Expect(p.Href).To(Equal("https://iam.cloud.ibm.com/v1/policies/0b3cea25-fc07-49b1-986b-90846085cfeb"))
   260  				Expect(p.CreatedAt).To(Equal("2017-11-10T04:37:44.943Z"))
   261  				Expect(p.CreatedByID).To(Equal("IBMid-310000JVN5"))
   262  				Expect(p.LastModifiedAt).To(Equal("2017-11-10T04:37:44.943Z"))
   263  				Expect(p.LastModifiedByID).To(Equal("IBMid-310000JVN5"))
   264  				Expect(p.Version).To(Equal("3-a283be20686c2c71c512e73e9ee2ce9c"))
   265  			})
   266  		})
   267  
   268  		Context("When the policy is not found", func() {
   269  			BeforeEach(func() {
   270  				server.AppendHandlers(ghttp.CombineHandlers(
   271  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies/policy-id"),
   272  					ghttp.RespondWith(http.StatusNotFound, `{
   273  						"trace": "10cdeb89a930420a83f8d295e5dad851",
   274  						"errors": [
   275  							{
   276  								"code": "policy_not_found",
   277  								"message": "Policy with Id 285a9542-c08c-43c6-8f0a-632dc5801b64 not found."
   278  							}
   279  						],
   280  						"status_code": 404
   281  					}`),
   282  				))
   283  			})
   284  			It("should return not found error", func() {
   285  				p, err := repo.Get("policy-id")
   286  				Expect(err).To(HaveOccurred())
   287  				Expect(err.Error()).To(ContainSubstring("policy_not_found"))
   288  				Expect(p).To(BeZero())
   289  			})
   290  		})
   291  
   292  		Context("When there is error", func() {
   293  			BeforeEach(func() {
   294  				server.AppendHandlers(ghttp.CombineHandlers(
   295  					ghttp.VerifyRequest(http.MethodGet, "/v1/policies/policy-id"),
   296  					ghttp.RespondWith(http.StatusUnauthorized, `{
   297  						"trace": "aac0333a26c64caaa5528bfeed3de4b8",
   298  						"errors": [
   299  							{
   300  								"code": "invalid_token",
   301  								"message": "The provided IAM token is invalid."
   302  							}
   303  						],
   304  						"status_code": 401
   305  					}`),
   306  				))
   307  			})
   308  			It("should return the error", func() {
   309  				p, err := repo.Get("policy-id")
   310  				Expect(err).To(HaveOccurred())
   311  				Expect(p).To(BeZero())
   312  			})
   313  		})
   314  	})
   315  
   316  	Describe("Delete()", func() {
   317  		Context("Delete successfully", func() {
   318  			BeforeEach(func() {
   319  				server.AppendHandlers(ghttp.CombineHandlers(
   320  					ghttp.VerifyRequest(http.MethodDelete, "/v1/policies/policy-id"),
   321  					ghttp.RespondWith(http.StatusNoContent, nil),
   322  				))
   323  			})
   324  			It("should return the error", func() {
   325  				err := repo.Delete("policy-id")
   326  				Expect(err).ShouldNot(HaveOccurred())
   327  			})
   328  		})
   329  
   330  		Context("Deletion fails", func() {
   331  			BeforeEach(func() {
   332  				server.AppendHandlers(ghttp.CombineHandlers(
   333  					ghttp.VerifyRequest(http.MethodDelete, "/v1/policies/policy-id"),
   334  					ghttp.RespondWith(http.StatusUnauthorized, `{
   335  						"trace": "aac0333a26c64caaa5528bfeed3de4b8",
   336  						"errors": [
   337  							{
   338  								"code": "invalid_token",
   339  								"message": "The provided IAM token is invalid."
   340  							}
   341  						],
   342  						"status_code": 401
   343  					}`),
   344  				))
   345  			})
   346  			It("should return the error", func() {
   347  				err := repo.Delete("policy-id")
   348  				Expect(err).To(HaveOccurred())
   349  			})
   350  		})
   351  	})
   352  
   353  	Describe("Create()", func() {
   354  		Context("Create successfully", func() {
   355  			BeforeEach(func() {
   356  				server.AppendHandlers(ghttp.CombineHandlers(
   357  					ghttp.VerifyRequest(http.MethodPost, "/v1/policies"),
   358  					ghttp.VerifyJSON(`{
   359  						"type": "access",
   360  						"subjects": [{
   361  							"attributes": [{
   362  								"name": "iam_id",
   363  								"value": "IBMid-270006V8HD"
   364  							}]
   365  						}],
   366  						"roles": [{
   367  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
   368  						}],
   369  						"resources": [{
   370  							"attributes": [{
   371  								"name": "resourceType",
   372  								"value": "resource-group"
   373  							},{
   374  								"name": "resource",
   375  								"value": "5e0f4f2166a04667aea9440ad4850232"
   376  
   377  							}]
   378  						}]
   379  					}`),
   380  					ghttp.RespondWith(http.StatusOK, `{
   381  						"id": "policy-id",
   382  						"type": "access",
   383  						"subjects": [{
   384  							"attributes": [{
   385  								"name": "iam_id",
   386  								"value": "IBMid-270006V8HD"
   387  							}]
   388  						}],
   389  						"roles": [{
   390  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer",
   391  							"display_name": "Viewer",
   392  							"description": "As a viewer, you can view service instances, but you can't modify them."
   393  						}],
   394  						"resources": [{
   395  							"attributes": [{
   396  								"name": "resourceType",
   397  								"value": "resource-group"
   398  							},{
   399  								"name": "resource",
   400  								"value": "5e0f4f2166a04667aea9440ad4850232"
   401  							}]
   402  						}],
   403  						"href": "https://iam.cloud.ibm.com/v1/policies/0b3cea25-fc07-49b1-986b-90846085cfeb",
   404  						"created_at": "2017-11-10T04:37:44.943Z",
   405  						"created_by_id": "IBMid-310000JVN5",
   406  						"last_modified_at": "2017-11-10T04:37:44.943Z",
   407  						"last_modified_by_id": "IBMid-310000JVN5"
   408  				}`, http.Header{"ETag": []string{"3-a283be20686c2c71c512e73e9ee2ce9c"}}),
   409  				))
   410  			})
   411  			It("should return the created policy", func() {
   412  				policy, err := repo.Create(Policy{
   413  					Type: AccessPolicyType,
   414  					Subjects: []Subject{
   415  						{
   416  							Attributes: []Attribute{
   417  								{
   418  									Name:  "iam_id",
   419  									Value: "IBMid-270006V8HD",
   420  								},
   421  							},
   422  						},
   423  					},
   424  					Roles: []Role{
   425  						{
   426  							RoleID: "crn:v1:bluemix:public:iam::::role:Viewer",
   427  						},
   428  					},
   429  					Resources: []Resource{
   430  						{
   431  							Attributes: []Attribute{
   432  								{
   433  									Name:  "resourceType",
   434  									Value: "resource-group",
   435  								},
   436  								{
   437  									Name:  "resource",
   438  									Value: "5e0f4f2166a04667aea9440ad4850232",
   439  								},
   440  							},
   441  						},
   442  					},
   443  				})
   444  
   445  				Expect(err).ShouldNot(HaveOccurred())
   446  				Expect(policy).ShouldNot(BeZero())
   447  				Expect(policy.Type).To(Equal(AccessPolicyType))
   448  				Expect(policy.Subjects).To(HaveLen(1))
   449  				Expect(policy.Subjects[0].IAMID()).To(Equal("IBMid-270006V8HD"))
   450  				Expect(policy.Roles).To(HaveLen(1))
   451  				Expect(policy.Roles[0].Name).To(Equal("Viewer"))
   452  				Expect(policy.Resources).To(HaveLen(1))
   453  				Expect(policy.Resources[0].Resource()).To(Equal("5e0f4f2166a04667aea9440ad4850232"))
   454  				Expect(policy.Version).To(Equal("3-a283be20686c2c71c512e73e9ee2ce9c"))
   455  			})
   456  		})
   457  
   458  		Context("Creation fails", func() {
   459  			BeforeEach(func() {
   460  				server.AppendHandlers(ghttp.CombineHandlers(
   461  					ghttp.VerifyRequest(http.MethodPost, "/v1/policies"),
   462  					ghttp.VerifyJSON(`{
   463  						"type": "authorization",
   464  						"subjects": [{
   465  							"attributes": [{
   466  								"name": "iam_id",
   467  								"value": "IBMid-270006V8HD"
   468  							}]
   469  						}],
   470  						"roles": [{
   471  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
   472  						}],
   473  						"resources": [{
   474  							"attributes": [{
   475  								"name": "resourceType",
   476  								"value": "resource-group"
   477  							},{
   478  								"name": "resource",
   479  								"value": "5e0f4f2166a04667aea9440ad4850232"
   480  							}]
   481  						}]
   482  					}`),
   483  					ghttp.RespondWith(http.StatusBadRequest, `{
   484  						"trace": "c2567d5d81674a93af790a512e770b8d",
   485  						"errors": [{
   486  							"code": "invalid_body",
   487  							"message": "Invalid body format. Check missing parameters."
   488  						}],
   489  						"status_code": 400
   490  				}`),
   491  				))
   492  			})
   493  			It("should return error", func() {
   494  				policy, err := repo.Create(Policy{
   495  					Type: AuthorizationPolicyType,
   496  					Subjects: []Subject{
   497  						{
   498  							Attributes: []Attribute{
   499  								{
   500  									Name:  "iam_id",
   501  									Value: "IBMid-270006V8HD",
   502  								},
   503  							},
   504  						},
   505  					},
   506  					Roles: []Role{
   507  						{
   508  							RoleID: "crn:v1:bluemix:public:iam::::role:Viewer",
   509  						},
   510  					},
   511  					Resources: []Resource{
   512  						{
   513  							Attributes: []Attribute{
   514  								{
   515  									Name:  "resourceType",
   516  									Value: "resource-group",
   517  								},
   518  								{
   519  									Name:  "resource",
   520  									Value: "5e0f4f2166a04667aea9440ad4850232",
   521  								},
   522  							},
   523  						},
   524  					},
   525  				})
   526  
   527  				Expect(err).Should(HaveOccurred())
   528  				Expect(policy).Should(BeZero())
   529  			})
   530  		})
   531  	})
   532  
   533  	Describe("Update()", func() {
   534  		Context("Update successfully", func() {
   535  			BeforeEach(func() {
   536  				server.AppendHandlers(ghttp.CombineHandlers(
   537  					ghttp.VerifyRequest(http.MethodPut, "/v1/policies/policy-id"),
   538  					ghttp.VerifyHeaderKV("If-Match", "abc"),
   539  					ghttp.VerifyJSON(`{
   540  						"type": "access",
   541  						"subjects": [{
   542  							"attributes": [{
   543  								"name": "iam_id",
   544  								"value": "IBMid-270006V8HD"
   545  							}]
   546  						}],
   547  						"roles": [{
   548  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
   549  						}],
   550  						"resources": [{
   551  							"attributes": [{
   552  								"name": "resourceType",
   553  								"value": "resource-group"
   554  							},{
   555  								"name": "resource",
   556  								"value": "5e0f4f2166a04667aea9440ad4850232"
   557  							}]
   558  						}]
   559  					}`),
   560  					ghttp.RespondWith(http.StatusOK, `{
   561  						"id": "policy-id",
   562  						"type": "access",
   563  						"subjects": [{
   564  							"attributes": [{
   565  								"name": "iam_id",
   566  								"value": "IBMid-270006V8HD"
   567  							}]
   568  						}],
   569  						"roles": [{
   570  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer",
   571  							"display_name": "Viewer",
   572  							"description": "As a viewer, you can view service instances, but you can't modify them."
   573  						}],
   574  						"resources": [{
   575  							"attributes": [{
   576  								"name": "resourceType",
   577  								"value": "resource-group"
   578  							},{
   579  								"name": "resource",
   580  								"value": "5e0f4f2166a04667aea9440ad4850232"
   581  							}]
   582  						}],
   583  						"href": "https://iam.cloud.ibm.com/v1/policies/0b3cea25-fc07-49b1-986b-90846085cfeb",
   584  						"created_at": "2017-11-10T04:37:44.943Z",
   585  						"created_by_id": "IBMid-310000JVN5",
   586  						"last_modified_at": "2017-11-10T04:37:44.943Z",
   587  						"last_modified_by_id": "IBMid-310000JVN5"
   588  				}`, http.Header{"ETag": []string{"3-a283be20686c2c71c512e73e9ee2ce9c"}}),
   589  				))
   590  			})
   591  			It("should return the updated policy", func() {
   592  				policy, err := repo.Update("policy-id", Policy{
   593  					Type: AccessPolicyType,
   594  					Subjects: []Subject{
   595  						{
   596  							Attributes: []Attribute{
   597  								{
   598  									Name:  "iam_id",
   599  									Value: "IBMid-270006V8HD",
   600  								},
   601  							},
   602  						},
   603  					},
   604  					Roles: []Role{
   605  						{
   606  							RoleID: "crn:v1:bluemix:public:iam::::role:Viewer",
   607  						},
   608  					},
   609  					Resources: []Resource{
   610  						{
   611  							Attributes: []Attribute{
   612  								{
   613  									Name:  "resourceType",
   614  									Value: "resource-group",
   615  								},
   616  								{
   617  									Name:  "resource",
   618  									Value: "5e0f4f2166a04667aea9440ad4850232",
   619  								},
   620  							},
   621  						},
   622  					},
   623  				}, "abc")
   624  
   625  				Expect(err).ShouldNot(HaveOccurred())
   626  				Expect(policy).ShouldNot(BeZero())
   627  				Expect(policy.Type).To(Equal(AccessPolicyType))
   628  				Expect(policy.Subjects).To(HaveLen(1))
   629  				Expect(policy.Subjects[0].IAMID()).To(Equal("IBMid-270006V8HD"))
   630  				Expect(policy.Roles).To(HaveLen(1))
   631  				Expect(policy.Roles[0].Name).To(Equal("Viewer"))
   632  				Expect(policy.Resources).To(HaveLen(1))
   633  				Expect(policy.Resources[0].Resource()).To(Equal("5e0f4f2166a04667aea9440ad4850232"))
   634  				Expect(policy.Version).To(Equal("3-a283be20686c2c71c512e73e9ee2ce9c"))
   635  			})
   636  		})
   637  
   638  		Context("Update fails", func() {
   639  			BeforeEach(func() {
   640  				server.AppendHandlers(ghttp.CombineHandlers(
   641  					ghttp.VerifyRequest(http.MethodPut, "/v1/policies/policy-id"),
   642  					ghttp.VerifyHeaderKV("If-Match", "abc"),
   643  					ghttp.VerifyJSON(`{
   644  						"type": "authorization",
   645  						"subjects": [{
   646  							"attributes": [{
   647  								"name": "iam_id",
   648  								"value": "IBMid-270006V8HD"
   649  							}]
   650  						}],
   651  						"roles": [{
   652  							"role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
   653  						}],
   654  						"resources": [{
   655  							"attributes": [{
   656  								"name": "resourceType",
   657  								"value": "resource-group"
   658  							},{
   659  								"name": "resource",
   660  								"value": "5e0f4f2166a04667aea9440ad4850232"
   661  							}]
   662  						}]
   663  					}`),
   664  					ghttp.RespondWith(http.StatusBadRequest, `{
   665  						"trace": "c2567d5d81674a93af790a512e770b8d",
   666  						"errors": [{
   667  							"code": "invalid_body",
   668  							"message": "Invalid body format. Check missing parameters."
   669  						}],
   670  						"status_code": 400
   671  				}`),
   672  				))
   673  			})
   674  			It("should return error", func() {
   675  				policy, err := repo.Update("policy-id", Policy{
   676  					Type: AuthorizationPolicyType,
   677  					Subjects: []Subject{
   678  						{
   679  							Attributes: []Attribute{
   680  								{
   681  									Name:  "iam_id",
   682  									Value: "IBMid-270006V8HD",
   683  								},
   684  							},
   685  						},
   686  					},
   687  					Roles: []Role{
   688  						{
   689  							RoleID: "crn:v1:bluemix:public:iam::::role:Viewer",
   690  						},
   691  					},
   692  					Resources: []Resource{
   693  						{
   694  							Attributes: []Attribute{
   695  								{
   696  									Name:  "resourceType",
   697  									Value: "resource-group",
   698  								},
   699  								{
   700  									Name:  "resource",
   701  									Value: "5e0f4f2166a04667aea9440ad4850232",
   702  								},
   703  							},
   704  						},
   705  					},
   706  				}, "abc")
   707  
   708  				Expect(err).Should(HaveOccurred())
   709  				Expect(policy).Should(BeZero())
   710  			})
   711  		})
   712  	})
   713  })
   714  
   715  func newv1Policy(url string) V1PolicyRepository {
   716  
   717  	sess, err := session.New()
   718  	if err != nil {
   719  		log.Fatal(err)
   720  	}
   721  	conf := sess.Config.Copy()
   722  	conf.Endpoint = &url
   723  	client := client.Client{
   724  		Config:      conf,
   725  		ServiceName: bluemix.IAMPAPService,
   726  	}
   727  	return NewV1PolicyRepository(&client)
   728  }