From c4f49464e6f67e61b56ad8b84b1ec749f61e1796 Mon Sep 17 00:00:00 2001 From: Shaun Colley Date: Fri, 26 Jan 2024 13:47:09 -0500 Subject: [PATCH 1/3] fix(IAM Policy Management): Add operator support to subject_attributes in Authorziation Policy Signed-off-by: Shaun Colley --- ibm/flex/structures.go | 43 +++- ...rce_ibm_iam_authorization_policies_test.go | 4 +- .../resource_ibm_iam_access_group_policy.go | 8 +- .../resource_ibm_iam_authorization_policy.go | 235 ++++++++++++------ ...ource_ibm_iam_authorization_policy_test.go | 105 +++++++- .../r/iam_authorization_policy.html.markdown | 38 ++- 6 files changed, 339 insertions(+), 94 deletions(-) diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index 50dc935f2f..45ea96fb49 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -3334,10 +3334,12 @@ func GetResourceAttribute(name string, r iampolicymanagementv1.PolicyResource) * func GetV2PolicyResourceAttribute(key string, r iampolicymanagementv1.V2PolicyResource) string { for _, a := range r.Attributes { - if *a.Key == key && - (*a.Operator == "stringMatch" || - *a.Operator == "stringEquals") { - return a.Value.(string) + if *a.Key == key { + if *a.Operator == "stringExists" && a.Value == true { + return fmt.Sprint("*") + } else if *a.Operator == "stringMatch" || *a.Operator == "stringEquals" { + return a.Value.(string) + } } } return *core.StringPtr("") @@ -3352,7 +3354,7 @@ func GetSubjectAttribute(name string, s iampolicymanagementv1.PolicySubject) *st return core.StringPtr("") } -func GetV2PolicySubjectAttribute(key string, s iampolicymanagementv1.V2PolicySubject) *string { +func GetV2PolicySubjectAttribute(key string, s iampolicymanagementv1.V2PolicySubject) interface{} { for _, a := range s.Attributes { if *a.Key == key && (*a.Operator == "stringMatch" || @@ -3360,7 +3362,7 @@ func GetV2PolicySubjectAttribute(key string, s iampolicymanagementv1.V2PolicySub return a.Value } } - return core.StringPtr("") + return interface{}(core.StringPtr("")) } func SetResourceAttribute(name *string, value *string, r []iampolicymanagementv1.ResourceAttribute) []iampolicymanagementv1.ResourceAttribute { @@ -3501,6 +3503,7 @@ func GetRoleNamesFromPolicyResponse(policy iampolicymanagementv1.V2PolicyTemplat controlResponse := policy.Control.(*iampolicymanagementv1.ControlResponse) policyRoles := MapRolesToPolicyRoles(controlResponse.Grant.Roles) resourceAttributes := policy.Resource.Attributes + subjectAttributes := policy.Subject.Attributes userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() if err != nil { @@ -3508,11 +3511,20 @@ func GetRoleNamesFromPolicyResponse(policy iampolicymanagementv1.V2PolicyTemplat } var ( - serviceName string - resourceType string - serviceGroupID string + serviceName string + sourceServiceName string + resourceType string + serviceGroupID string ) + for _, a := range subjectAttributes { + if *a.Key == "serviceName" && + (*a.Operator == "stringMatch" || + *a.Operator == "stringEquals") { + sourceServiceName = a.Value.(string) + } + } + for _, a := range resourceAttributes { if *a.Key == "serviceName" && (*a.Operator == "stringMatch" || @@ -3539,6 +3551,11 @@ func GetRoleNamesFromPolicyResponse(policy iampolicymanagementv1.V2PolicyTemplat if accountManagement, ok := d.GetOk("account_management"); ok { isAccountManagementPolicy = accountManagement.(bool) } + + if serviceName == "" && resourceType == "resource-group" { + serviceName = "resource-controller" + } + if serviceName == "" && // no specific service specified !isAccountManagementPolicy && // not all account management services resourceType != "resource-group" && // not to a resource group @@ -3554,6 +3571,14 @@ func GetRoleNamesFromPolicyResponse(policy iampolicymanagementv1.V2PolicyTemplat listRoleOptions.ServiceGroupID = &serviceGroupID } + if sourceServiceName != "" { + listRoleOptions.SourceServiceName = &sourceServiceName + } + + if *policy.Type != "" { + listRoleOptions.PolicyType = policy.Type + } + roleList, _, err := iamPolicyManagementClient.ListRoles(listRoleOptions) if err != nil { diff --git a/ibm/service/iampolicy/data_source_ibm_iam_authorization_policies_test.go b/ibm/service/iampolicy/data_source_ibm_iam_authorization_policies_test.go index 213b185ac1..b33893b921 100644 --- a/ibm/service/iampolicy/data_source_ibm_iam_authorization_policies_test.go +++ b/ibm/service/iampolicy/data_source_ibm_iam_authorization_policies_test.go @@ -73,8 +73,8 @@ func testAccCheckIBMIAMAuthorizationPoliciesDataSourceMultiplePolicies() string resource "ibm_iam_authorization_policy" "policy1" { source_service_name = "is" source_resource_type = "load-balancer" - target_service_name = "cloudcerts" - roles = ["Reader"] + target_service_name = "secrets-manager" + roles = ["SecretsReader"] } ` } diff --git a/ibm/service/iampolicy/resource_ibm_iam_access_group_policy.go b/ibm/service/iampolicy/resource_ibm_iam_access_group_policy.go index 5bfcaf2be9..5dda95b0ab 100644 --- a/ibm/service/iampolicy/resource_ibm_iam_access_group_policy.go +++ b/ibm/service/iampolicy/resource_ibm_iam_access_group_policy.go @@ -481,9 +481,9 @@ func resourceIBMIAMAccessGroupPolicyRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("[ERROR] Error retrieving access group policy: %s\n%s", err, res) } - retrievedAttribute := flex.GetV2PolicySubjectAttribute("access_group_id", *accessGroupPolicy.Subject) - if accessGroupId != *retrievedAttribute { - return fmt.Errorf("[ERROR] Policy %s does not belong to access group %s, retrievedAttr: %s", accessGroupPolicyId, accessGroupId, *retrievedAttribute) + retrievedAttribute := flex.GetV2PolicySubjectAttribute("access_group_id", *accessGroupPolicy.Subject).(string) + if accessGroupId != retrievedAttribute { + return fmt.Errorf("[ERROR] Policy %s does not belong to access group %s, retrievedAttr: %s", accessGroupPolicyId, accessGroupId, retrievedAttribute) } d.Set("access_group_id", accessGroupId) @@ -770,7 +770,7 @@ func resourceIBMIAMAccessGroupPolicyExists(d *schema.ResourceData, meta interfac return false, nil } - tempID := fmt.Sprintf("%s/%s", *flex.GetV2PolicySubjectAttribute("access_group_id", *accessGroupPolicy.Subject), *accessGroupPolicy.ID) + tempID := fmt.Sprintf("%s/%s", flex.GetV2PolicySubjectAttribute("access_group_id", *accessGroupPolicy.Subject), *accessGroupPolicy.ID) return tempID == d.Id(), nil } diff --git a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go index c1facb1f30..8fd91b5e58 100644 --- a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go +++ b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go @@ -139,6 +139,11 @@ func ResourceIBMIAMAuthorizationPolicy() *schema.Resource { Required: true, Description: "Value of attribute.", }, + "operator": { + Type: schema.TypeString, + Optional: true, + Description: "Operator of attribute.", + }, }, }, }, @@ -219,8 +224,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf var sourceServiceName, targetServiceName string policyType := "authorization" - policySubject := &iampolicymanagementv1.PolicySubject{} - policyResource := &iampolicymanagementv1.PolicyResource{} + policySubject := &iampolicymanagementv1.V2PolicySubject{} + policyResource := &iampolicymanagementv1.V2PolicyResource{} userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() if err != nil { @@ -238,23 +243,54 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf a := attribute.(map[string]interface{}) name := a["name"].(string) value := a["value"].(string) + operator := a["operator"].(string) if name == "serviceName" { sourceServiceName = value } - at := iampolicymanagementv1.SubjectAttribute{ - Name: &name, - Value: &value, + + if operator == "" && value == "*" && name == "resourceGroupId" { + at := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: &name, + Value: true, + Operator: core.StringPtr("stringExists"), + } + policySubject.Attributes = append(policySubject.Attributes, at) + } else if operator == "stringExists" { + var resourceValue bool + if value == "true" { + resourceValue = true + } else if value == "false" { + resourceValue = false + } else { + return fmt.Errorf("[ERROR] Only values \"true\" and \"false\" are allowed when operator is \"stringExists\". Received %s.", value) + } + at := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: &name, + Value: &resourceValue, + Operator: &operator, + } + policySubject.Attributes = append(policySubject.Attributes, at) + } else { + if operator == "" { + operator = "stringEquals" + } + at := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: &name, + Value: &value, + Operator: &operator, + } + policySubject.Attributes = append(policySubject.Attributes, at) } - policySubject.Attributes = append(policySubject.Attributes, at) } } else { if name, ok := d.GetOk("source_service_name"); ok { sourceServiceName = name.(string) - serviceNameSubjectAttribute := &iampolicymanagementv1.SubjectAttribute{ - Name: core.StringPtr("serviceName"), + serviceNameSubjectAttribute := &iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("serviceName"), Value: &sourceServiceName, + Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, *serviceNameSubjectAttribute) } @@ -264,35 +300,48 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf sourceServiceAccount = account.(string) } - accountIdSubjectAttribute := &iampolicymanagementv1.SubjectAttribute{ - Name: core.StringPtr("accountId"), + accountIdSubjectAttribute := &iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("accountId"), Value: &sourceServiceAccount, + Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, *accountIdSubjectAttribute) if sID, ok := d.GetOk("source_resource_instance_id"); ok { - serviceInstanceSubjectAttribute := iampolicymanagementv1.SubjectAttribute{ - Name: core.StringPtr("serviceInstance"), + serviceInstanceSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("serviceInstance"), Value: core.StringPtr(sID.(string)), + Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, serviceInstanceSubjectAttribute) } if sType, ok := d.GetOk("source_resource_type"); ok { - resourceTypeSubjectAttribute := iampolicymanagementv1.SubjectAttribute{ - Name: core.StringPtr("resourceType"), + resourceTypeSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("resourceType"), Value: core.StringPtr(sType.(string)), + Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, resourceTypeSubjectAttribute) } if sResGrpID, ok := d.GetOk("source_resource_group_id"); ok { - resourceGroupSubjectAttribute := iampolicymanagementv1.SubjectAttribute{ - Name: core.StringPtr("resourceGroupId"), - Value: core.StringPtr(sResGrpID.(string)), + if sResGrpID == "*" { + resourceGroupSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("resourceGroupId"), + Value: true, + Operator: core.StringPtr("stringExists"), + } + policySubject.Attributes = append(policySubject.Attributes, resourceGroupSubjectAttribute) + } else { + resourceGroupSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ + Key: core.StringPtr("resourceGroupId"), + Value: core.StringPtr(sResGrpID.(string)), + Operator: core.StringPtr("stringEquals"), + } + policySubject.Attributes = append(policySubject.Attributes, resourceGroupSubjectAttribute) } - policySubject.Attributes = append(policySubject.Attributes, resourceGroupSubjectAttribute) } } @@ -309,26 +358,41 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if name == "resourceType" && targetServiceName == "" { targetServiceName = "resource-controller" } - at := iampolicymanagementv1.ResourceAttribute{ - Name: &name, - Value: &value, - Operator: &operator, + if operator == "stringExists" { + var resourceValue bool + if value == "true" { + resourceValue = true + } else { + resourceValue = false + } + at := iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: &name, + Value: &resourceValue, + Operator: &operator, + } + policyResource.Attributes = append(policyResource.Attributes, at) + } else { + at := iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: &name, + Value: &value, + Operator: &operator, + } + policyResource.Attributes = append(policyResource.Attributes, at) } - policyResource.Attributes = append(policyResource.Attributes, at) } } else { if name, ok := d.GetOk("target_service_name"); ok { targetServiceName = name.(string) - serviceNameResourceAttribute := &iampolicymanagementv1.ResourceAttribute{ - Name: core.StringPtr("serviceName"), + serviceNameResourceAttribute := &iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: core.StringPtr("serviceName"), Value: core.StringPtr(targetServiceName), Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, *serviceNameResourceAttribute) } - accountIDResourceAttribute := &iampolicymanagementv1.ResourceAttribute{ - Name: core.StringPtr("accountId"), + accountIDResourceAttribute := &iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: core.StringPtr("accountId"), Value: core.StringPtr(userDetails.UserAccount), Operator: core.StringPtr("stringEquals"), } @@ -336,17 +400,19 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf policyResource.Attributes = append(policyResource.Attributes, *accountIDResourceAttribute) if tID, ok := d.GetOk("target_resource_instance_id"); ok { - serviceInstanceResourceAttribute := iampolicymanagementv1.ResourceAttribute{ - Name: core.StringPtr("serviceInstance"), + serviceInstanceResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: core.StringPtr("serviceInstance"), Value: core.StringPtr(tID.(string)), + Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, serviceInstanceResourceAttribute) } if tType, ok := d.GetOk("target_resource_type"); ok { - resourceTypeResourceAttribute := iampolicymanagementv1.ResourceAttribute{ - Name: core.StringPtr("resourceType"), + resourceTypeResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: core.StringPtr("resourceType"), Value: core.StringPtr(tType.(string)), + Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, resourceTypeResourceAttribute) if targetServiceName == "" { @@ -355,9 +421,10 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf } if tResGrpID, ok := d.GetOk("target_resource_group_id"); ok { - resourceGroupResourceAttribute := iampolicymanagementv1.ResourceAttribute{ - Name: core.StringPtr("resourceGroupId"), + resourceGroupResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ + Key: core.StringPtr("resourceGroupId"), Value: core.StringPtr(tResGrpID.(string)), + Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, resourceGroupResourceAttribute) } @@ -381,13 +448,21 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf return err } - createPolicyOptions := iampapClient.NewCreatePolicyOptions( + policyGrant := &iampolicymanagementv1.Grant{ + Roles: flex.MapPolicyRolesToRoles(roles), + } + policyControl := &iampolicymanagementv1.Control{ + Grant: policyGrant, + } + + createPolicyOptions := iampapClient.NewCreateV2PolicyOptions( + policyControl, "authorization", - []iampolicymanagementv1.PolicySubject{*policySubject}, - roles, - []iampolicymanagementv1.PolicyResource{*policyResource}, ) + createPolicyOptions.SetSubject(policySubject) + createPolicyOptions.SetResource(policyResource) + if description, ok := d.GetOk("description"); ok { des := description.(string) createPolicyOptions.Description = &des @@ -397,7 +472,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf createPolicyOptions.SetHeaders(map[string]string{"Transaction-Id": transactionID.(string)}) } - authPolicy, resp, err := iampapClient.CreatePolicy(createPolicyOptions) + authPolicy, resp, err := iampapClient.CreateV2Policy(createPolicyOptions) if err != nil { return fmt.Errorf("[ERROR] Error creating authorization policy: %s %s", err, resp) } @@ -414,19 +489,19 @@ func resourceIBMIAMAuthorizationPolicyRead(d *schema.ResourceData, meta interfac return err } - getPolicyOptions := &iampolicymanagementv1.GetPolicyOptions{ - PolicyID: core.StringPtr(d.Id()), + getPolicyOptions := &iampolicymanagementv1.GetV2PolicyOptions{ + ID: core.StringPtr(d.Id()), } if transactionID, ok := d.GetOk("transaction_id"); ok { getPolicyOptions.SetHeaders(map[string]string{"Transaction-Id": transactionID.(string)}) } - authorizationPolicy, resp, err := iampapClient.GetPolicy(getPolicyOptions) + authorizationPolicy, resp, err := iampapClient.GetV2Policy(getPolicyOptions) err = resource.Retry(5*time.Minute, func() *resource.RetryError { var err error - authorizationPolicy, resp, err = iampapClient.GetPolicy(getPolicyOptions) + authorizationPolicy, resp, err = iampapClient.GetV2Policy(getPolicyOptions) if err != nil || authorizationPolicy == nil { if resp != nil && resp.StatusCode == 404 { return resource.RetryableError(err) @@ -437,15 +512,12 @@ func resourceIBMIAMAuthorizationPolicyRead(d *schema.ResourceData, meta interfac }) if conns.IsResourceTimeoutError(err) { - authorizationPolicy, resp, err = iampapClient.GetPolicy(getPolicyOptions) + authorizationPolicy, resp, err = iampapClient.GetV2Policy(getPolicyOptions) } if err != nil || resp == nil { return fmt.Errorf("[ERROR] Error retrieving authorizationPolicy: %s %s", err, resp) } - roles := make([]string, len(authorizationPolicy.Roles)) - for i, role := range authorizationPolicy.Roles { - roles[i] = *role.DisplayName - } + roles, err := flex.GetRoleNamesFromPolicyResponse(*authorizationPolicy, d, meta) if authorizationPolicy.Description != nil { d.Set("description", *authorizationPolicy.Description) } @@ -453,21 +525,22 @@ func resourceIBMIAMAuthorizationPolicyRead(d *schema.ResourceData, meta interfac d.Set("transaction_id", resp.Headers["Transaction-Id"][0]) } d.Set("roles", roles) - source := authorizationPolicy.Subjects[0] - target := authorizationPolicy.Resources[0] - - d.Set("resource_attributes", setAuthorizationResourceAttributes(target)) - d.Set("target_resource_instance_id", flex.GetResourceAttribute("serviceInstance", target)) - d.Set("target_resource_type", flex.GetResourceAttribute("resourceType", target)) - d.Set("target_resource_group_id", flex.GetResourceAttribute("resourceGroupId", target)) - d.Set("target_service_name", flex.GetResourceAttribute("serviceName", target)) - - d.Set("subject_attributes", setAuthorizationSubjectAttributes(source)) - d.Set("source_service_name", flex.GetSubjectAttribute("serviceName", source)) - d.Set("source_resource_instance_id", flex.GetSubjectAttribute("serviceInstance", source)) - d.Set("source_resource_type", flex.GetSubjectAttribute("resourceType", source)) - d.Set("source_service_account", flex.GetSubjectAttribute("accountId", source)) - d.Set("source_resource_group_id", flex.GetSubjectAttribute("resourceGroupId", source)) + source := authorizationPolicy.Subject + target := authorizationPolicy.Resource + + d.Set("resource_attributes", setAuthorizationResourceAttributes(*target)) + d.Set("target_resource_instance_id", flex.GetV2PolicyResourceAttribute("serviceInstance", *target)) + d.Set("target_resource_type", flex.GetV2PolicyResourceAttribute("resourceType", *target)) + d.Set("target_resource_group_id", flex.GetV2PolicyResourceAttribute("resourceGroupId", *target)) + d.Set("target_service_name", flex.GetV2PolicyResourceAttribute("serviceName", *target)) + if a, ok := d.GetOk("subject_attributes"); ok { + d.Set("subject_attributes", setAuthorizationSubjectAttributes(*source, a.(*schema.Set))) + } + d.Set("source_service_name", flex.GetV2PolicySubjectAttribute("serviceName", *source)) + d.Set("source_resource_instance_id", flex.GetV2PolicySubjectAttribute("serviceInstance", *source)) + d.Set("source_resource_type", flex.GetV2PolicySubjectAttribute("resourceType", *source)) + d.Set("source_service_account", flex.GetV2PolicySubjectAttribute("accountId", *source)) + d.Set("source_resource_group_id", flex.GetV2PolicySubjectAttribute("resourceGroupId", *source)) return nil } @@ -528,12 +601,12 @@ func resourceIBMIAMAuthorizationPolicyExists(d *schema.ResourceData, meta interf return *authorizationPolicy.ID == d.Id(), nil } -func setAuthorizationResourceAttributes(list iampolicymanagementv1.PolicyResource) []map[string]interface{} { +func setAuthorizationResourceAttributes(list iampolicymanagementv1.V2PolicyResource) []map[string]interface{} { result := make([]map[string]interface{}, 0) for _, attribute := range list.Attributes { l := map[string]interface{}{ - "name": attribute.Name, - "value": attribute.Value, + "name": attribute.Key, + "value": fmt.Sprintf("%v", attribute.Value), "operator": attribute.Operator, } result = append(result, l) @@ -541,12 +614,34 @@ func setAuthorizationResourceAttributes(list iampolicymanagementv1.PolicyResourc return result } -func setAuthorizationSubjectAttributes(list iampolicymanagementv1.PolicySubject) []map[string]interface{} { +func setAuthorizationSubjectAttributes(list iampolicymanagementv1.V2PolicySubject, a *schema.Set) []map[string]interface{} { + previousOperators := make([]string, 0) + + for _, item := range a.List() { + i := item.(map[string]interface{}) + + previousOperators = append(previousOperators, i["operator"].(string)) + } + result := make([]map[string]interface{}, 0) - for _, attribute := range list.Attributes { - l := map[string]interface{}{ - "name": attribute.Name, - "value": attribute.Value, + for i, attribute := range list.Attributes { + var l map[string]interface{} + if previousOperators[i] == "" && attribute.Value == true && *attribute.Operator == "stringExists" { + l = map[string]interface{}{ + "name": attribute.Key, + "value": "*", + } + } else if previousOperators[i] == "" { + l = map[string]interface{}{ + "name": attribute.Key, + "value": fmt.Sprintf("%v", attribute.Value), + } + } else { + l = map[string]interface{}{ + "name": attribute.Key, + "value": fmt.Sprintf("%v", attribute.Value), + "operator": attribute.Operator, + } } result = append(result, l) } diff --git a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy_test.go b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy_test.go index fe5b7436ca..d6a62efaa7 100644 --- a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy_test.go +++ b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy_test.go @@ -107,7 +107,7 @@ func TestAccIBMIAMAuthorizationPolicy_ResourceType(t *testing.T) { testAccCheckIBMIAMAuthorizationPolicyExists("ibm_iam_authorization_policy.policy", conf), resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "source_service_name", "is"), resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "source_resource_type", "load-balancer"), - resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "target_service_name", "hs-crypto"), + resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "target_service_name", "secrets-manager"), ), }, }, @@ -202,6 +202,27 @@ func TestAccIBMIAMAuthorizationPolicy_SourceResourceGroupId_ResourceAttributes(t }) } +func TestAccIBMIAMAuthorizationPolicy_SourceResourceGroupId_ResourceAttributes_WildCard(t *testing.T) { + var conf iampolicymanagementv1.PolicyTemplateMetaData + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAuthorizationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAuthorizationPolicySourceResourceGroupIdResourceAttributesWildCard(acc.Tg_cross_network_account_id, acc.Tg_cross_network_account_id), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAuthorizationPolicyExists("ibm_iam_authorization_policy.policy", conf), + resource.TestCheckResourceAttrSet("ibm_iam_authorization_policy.policy", "id"), + resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "source_service_name", ""), + resource.TestCheckResourceAttr("ibm_iam_authorization_policy.policy", "target_service_name", "cloud-object-storage"), + ), + }, + }, + }) +} + func TestAccIBMIAMAuthorizationPolicy_TargetResourceType(t *testing.T) { var conf iampolicymanagementv1.PolicyTemplateMetaData @@ -265,6 +286,25 @@ func TestAccIBMIAMAuthorizationPolicy_With_Transaction_id(t *testing.T) { }) } +func TestAccIBMIAMAuthorizationPolicy_SourceResourceGroupIdWithStringExistsInSubjectAttributes(t *testing.T) { + var conf iampolicymanagementv1.PolicyTemplateMetaData + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAuthorizationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAuthorizationPolicySourceResourceGroupIdWithStringExistsInSubjectAttributes(acc.Tg_cross_network_account_id, acc.Tg_cross_network_account_id), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAuthorizationPolicyExists("ibm_iam_authorization_policy.policy", conf), + resource.TestCheckResourceAttrSet("ibm_iam_authorization_policy.policy", "id"), + ), + }, + }, + }) +} + func testAccCheckIBMIAMAuthorizationPolicyDestroy(s *terraform.State) error { iamPolicyManagementClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMPolicyManagementV1API() if err != nil { @@ -350,9 +390,9 @@ func testAccCheckIBMIAMAuthorizationPolicyResourceInstance(instanceName string) resource "ibm_iam_authorization_policy" "policy" { source_service_name = "cloud-object-storage" - source_resource_instance_id = ibm_resource_instance.instance1.id + source_resource_instance_id = ibm_resource_instance.instance1.guid target_service_name = "kms" - target_resource_instance_id = ibm_resource_instance.instance2.id + target_resource_instance_id = ibm_resource_instance.instance2.guid roles = ["Reader"] } @@ -364,8 +404,8 @@ func testAccCheckIBMIAMAuthorizationPolicyResourceType() string { resource "ibm_iam_authorization_policy" "policy" { source_service_name = "is" source_resource_type = "load-balancer" - target_service_name = "hs-crypto" - roles = ["Reader"] + target_service_name = "secrets-manager" + roles = ["SecretsReader"] } ` } @@ -426,7 +466,7 @@ func testAccCheckIBMIAMAuthorizationPolicyResourceAttributes(sServiceInstance, t } subject_attributes { name = "serviceInstance" - value = ibm_resource_instance.cos.id + value = ibm_resource_instance.cos.guid } subject_attributes { name = "serviceName" @@ -442,7 +482,7 @@ func testAccCheckIBMIAMAuthorizationPolicyResourceAttributes(sServiceInstance, t } resource_attributes { name = "serviceInstance" - value = ibm_resource_instance.kms.id + value = ibm_resource_instance.kms.guid } } `, sServiceInstance, tServiceInstance, sAccountID, tAccountID) @@ -497,6 +537,31 @@ func testAccCheckIBMIAMAuthorizationPolicySourceResourceGroupIdResourceAttribute `, sAccountID, tAccountID) } +func testAccCheckIBMIAMAuthorizationPolicySourceResourceGroupIdResourceAttributesWildCard(sAccountID, tAccountID string) string { + return fmt.Sprintf(` + resource "ibm_iam_authorization_policy" "policy" { + roles = ["Reader"] + subject_attributes { + name = "accountId" + value = "%s" + } + subject_attributes { + name = "resourceGroupId" + value = "*" + } + + resource_attributes { + name = "serviceName" + value = "cloud-object-storage" + } + resource_attributes { + name = "accountId" + value = "%s" + } + } + `, sAccountID, tAccountID) +} + func testAccCheckIBMIAMAuthorizationPolicyTargetResourceType() string { return ` resource "ibm_iam_authorization_policy" "policy" { @@ -534,3 +599,29 @@ func testAccCheckIBMIAMAuthorizationPolicyResourceTypeAndResourceAttributes(sAcc } `, sAccountID, tAccountID) } + +func testAccCheckIBMIAMAuthorizationPolicySourceResourceGroupIdWithStringExistsInSubjectAttributes(sAccountID, tAccountID string) string { + return fmt.Sprintf(` + resource "ibm_iam_authorization_policy" "policy" { + roles = ["Reader"] + subject_attributes { + name = "accountId" + value = "%s" + } + subject_attributes { + name = "resourceGroupId" + operator = "stringExists" + value = "true" + } + + resource_attributes { + name = "serviceName" + value = "cloud-object-storage" + } + resource_attributes { + name = "accountId" + value = "%s" + } + } + `, sAccountID, tAccountID) +} diff --git a/website/docs/r/iam_authorization_policy.html.markdown b/website/docs/r/iam_authorization_policy.html.markdown index 2758bb8b9d..bac30292cc 100644 --- a/website/docs/r/iam_authorization_policy.html.markdown +++ b/website/docs/r/iam_authorization_policy.html.markdown @@ -66,9 +66,9 @@ resource "ibm_resource_instance" "instance2" { resource "ibm_iam_authorization_policy" "policy" { source_service_name = "cloud-object-storage" - source_resource_instance_id = ibm_resource_instance.instance1.id + source_resource_instance_id = ibm_resource_instance.instance1.guid target_service_name = "kms" - target_resource_instance_id = ibm_resource_instance.instance2.id + target_resource_instance_id = ibm_resource_instance.instance2.guid roles = ["Reader"] } @@ -156,6 +156,40 @@ resource "ibm_iam_authorization_policy" "policy" { } ``` +### Authorization policy between all resource groups in an account and a target service using resource attributes + +```terraform + +resource "ibm_resource_group" "source_resource_group" { + name = "123123" +} + +resource "ibm_iam_authorization_policy" "policy" { + roles = [ + "Reader", + ] + + resource_attributes { + name = "accountId" + operator = "stringEquals" + value = "12345" + } + resource_attributes { + name = "serviceName" + operator = "stringEquals" + value = "cloud-object-storage" + } + + subject_attributes { + name = "accountId" + value = "12345" + } + subject_attributes { + name = "resourceGroupId" + value = "*" + } +} +``` ### Authorization policy between source service and target resource type "resource-group" using resource attributes From 09f3975199db6e4d2f76092245076b9efcb22331 Mon Sep 17 00:00:00 2001 From: Shaun Colley Date: Fri, 26 Jan 2024 13:55:30 -0500 Subject: [PATCH 2/3] fix(IAM Policy Management): re-formatted Signed-off-by: Shaun Colley --- .../resource_ibm_iam_authorization_policy.go | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go index 8fd91b5e58..a242a001d5 100644 --- a/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go +++ b/ibm/service/iampolicy/resource_ibm_iam_authorization_policy.go @@ -250,7 +250,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if operator == "" && value == "*" && name == "resourceGroupId" { at := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: &name, + Key: &name, Value: true, Operator: core.StringPtr("stringExists"), } @@ -265,7 +265,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf return fmt.Errorf("[ERROR] Only values \"true\" and \"false\" are allowed when operator is \"stringExists\". Received %s.", value) } at := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: &name, + Key: &name, Value: &resourceValue, Operator: &operator, } @@ -275,7 +275,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf operator = "stringEquals" } at := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: &name, + Key: &name, Value: &value, Operator: &operator, } @@ -288,8 +288,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf sourceServiceName = name.(string) serviceNameSubjectAttribute := &iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("serviceName"), - Value: &sourceServiceName, + Key: core.StringPtr("serviceName"), + Value: &sourceServiceName, Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, *serviceNameSubjectAttribute) @@ -301,8 +301,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf } accountIdSubjectAttribute := &iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("accountId"), - Value: &sourceServiceAccount, + Key: core.StringPtr("accountId"), + Value: &sourceServiceAccount, Operator: core.StringPtr("stringEquals"), } @@ -310,8 +310,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if sID, ok := d.GetOk("source_resource_instance_id"); ok { serviceInstanceSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("serviceInstance"), - Value: core.StringPtr(sID.(string)), + Key: core.StringPtr("serviceInstance"), + Value: core.StringPtr(sID.(string)), Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, serviceInstanceSubjectAttribute) @@ -319,8 +319,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if sType, ok := d.GetOk("source_resource_type"); ok { resourceTypeSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("resourceType"), - Value: core.StringPtr(sType.(string)), + Key: core.StringPtr("resourceType"), + Value: core.StringPtr(sType.(string)), Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, resourceTypeSubjectAttribute) @@ -329,15 +329,15 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if sResGrpID, ok := d.GetOk("source_resource_group_id"); ok { if sResGrpID == "*" { resourceGroupSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("resourceGroupId"), - Value: true, + Key: core.StringPtr("resourceGroupId"), + Value: true, Operator: core.StringPtr("stringExists"), } policySubject.Attributes = append(policySubject.Attributes, resourceGroupSubjectAttribute) } else { resourceGroupSubjectAttribute := iampolicymanagementv1.V2PolicySubjectAttribute{ - Key: core.StringPtr("resourceGroupId"), - Value: core.StringPtr(sResGrpID.(string)), + Key: core.StringPtr("resourceGroupId"), + Value: core.StringPtr(sResGrpID.(string)), Operator: core.StringPtr("stringEquals"), } policySubject.Attributes = append(policySubject.Attributes, resourceGroupSubjectAttribute) @@ -366,14 +366,14 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf resourceValue = false } at := iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: &name, + Key: &name, Value: &resourceValue, Operator: &operator, } policyResource.Attributes = append(policyResource.Attributes, at) } else { at := iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: &name, + Key: &name, Value: &value, Operator: &operator, } @@ -384,7 +384,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if name, ok := d.GetOk("target_service_name"); ok { targetServiceName = name.(string) serviceNameResourceAttribute := &iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: core.StringPtr("serviceName"), + Key: core.StringPtr("serviceName"), Value: core.StringPtr(targetServiceName), Operator: core.StringPtr("stringEquals"), } @@ -392,7 +392,7 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf } accountIDResourceAttribute := &iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: core.StringPtr("accountId"), + Key: core.StringPtr("accountId"), Value: core.StringPtr(userDetails.UserAccount), Operator: core.StringPtr("stringEquals"), } @@ -401,8 +401,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if tID, ok := d.GetOk("target_resource_instance_id"); ok { serviceInstanceResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: core.StringPtr("serviceInstance"), - Value: core.StringPtr(tID.(string)), + Key: core.StringPtr("serviceInstance"), + Value: core.StringPtr(tID.(string)), Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, serviceInstanceResourceAttribute) @@ -410,8 +410,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if tType, ok := d.GetOk("target_resource_type"); ok { resourceTypeResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: core.StringPtr("resourceType"), - Value: core.StringPtr(tType.(string)), + Key: core.StringPtr("resourceType"), + Value: core.StringPtr(tType.(string)), Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, resourceTypeResourceAttribute) @@ -422,8 +422,8 @@ func resourceIBMIAMAuthorizationPolicyCreate(d *schema.ResourceData, meta interf if tResGrpID, ok := d.GetOk("target_resource_group_id"); ok { resourceGroupResourceAttribute := iampolicymanagementv1.V2PolicyResourceAttribute{ - Key: core.StringPtr("resourceGroupId"), - Value: core.StringPtr(tResGrpID.(string)), + Key: core.StringPtr("resourceGroupId"), + Value: core.StringPtr(tResGrpID.(string)), Operator: core.StringPtr("stringEquals"), } policyResource.Attributes = append(policyResource.Attributes, resourceGroupResourceAttribute) @@ -617,7 +617,7 @@ func setAuthorizationResourceAttributes(list iampolicymanagementv1.V2PolicyResou func setAuthorizationSubjectAttributes(list iampolicymanagementv1.V2PolicySubject, a *schema.Set) []map[string]interface{} { previousOperators := make([]string, 0) - for _, item := range a.List() { + for _, item := range a.List() { i := item.(map[string]interface{}) previousOperators = append(previousOperators, i["operator"].(string)) @@ -631,15 +631,15 @@ func setAuthorizationSubjectAttributes(list iampolicymanagementv1.V2PolicySubjec "name": attribute.Key, "value": "*", } - } else if previousOperators[i] == "" { + } else if previousOperators[i] == "" { l = map[string]interface{}{ "name": attribute.Key, "value": fmt.Sprintf("%v", attribute.Value), } } else { l = map[string]interface{}{ - "name": attribute.Key, - "value": fmt.Sprintf("%v", attribute.Value), + "name": attribute.Key, + "value": fmt.Sprintf("%v", attribute.Value), "operator": attribute.Operator, } } From 03387192cfb03fd96d7cb83ee33f4026df12d739 Mon Sep 17 00:00:00 2001 From: Shaun Colley Date: Mon, 29 Jan 2024 10:04:02 -0500 Subject: [PATCH 3/3] fix(IAM Policy Management): updated package and fixed test case Signed-off-by: Shaun Colley --- go.mod | 2 +- go.sum | 2 ++ ibm/flex/structures.go | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 4742f14c16..d828de7d4e 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta github.com/IBM/keyprotect-go-client v0.12.2 github.com/IBM/networking-go-sdk v0.42.2 - github.com/IBM/platform-services-go-sdk v0.55.0 + github.com/IBM/platform-services-go-sdk v0.56.3 github.com/IBM/project-go-sdk v0.1.6 github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5 github.com/IBM/scc-go-sdk/v5 v5.1.3 diff --git a/go.sum b/go.sum index bbd3619902..086a8bd609 100644 --- a/go.sum +++ b/go.sum @@ -160,6 +160,8 @@ github.com/IBM/networking-go-sdk v0.42.2 h1:caqjx4jyFHi10Vlf3skHvlL6K3YJRVstsmCB github.com/IBM/networking-go-sdk v0.42.2/go.mod h1:lTUZwtUkMANMnrLHFIgRhHrkBfwASY/Iho1fabaPHxo= github.com/IBM/platform-services-go-sdk v0.55.0 h1:W598xZanL61bwd8O2DQexr4qjIr+/tP0Y845zoms5yA= github.com/IBM/platform-services-go-sdk v0.55.0/go.mod h1:CWSprvsCsXWvujmBzbtoJSmbRZS9FVV3O594b0t/GiM= +github.com/IBM/platform-services-go-sdk v0.56.3 h1:DQ1VMQSknhPsdT7d+AybKiZT82esczAkHCIBkwYubzQ= +github.com/IBM/platform-services-go-sdk v0.56.3/go.mod h1:+U6Kg7o5u/Bh4ZkLxjymSgfdpVsaWAtsMtzhwclUry0= github.com/IBM/project-go-sdk v0.1.6 h1:sGrR0ej5wgBDhR2Xvf8Tgi5NmgMAJ77yep/CPGhvOx8= github.com/IBM/project-go-sdk v0.1.6/go.mod h1:lqe0M4cKvABI1iHR1b+KfasVcxQL6nl2VJ8eOyQs8Ig= github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5 h1:NPUhkoOCRuv3OFWt19PmwjXGGTKlvmbuPg9fUrBUNe4= diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index 45ea96fb49..90489c7d74 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -1628,7 +1628,11 @@ func FlattenV2PolicyResource(resource iampolicymanagementv1.V2PolicyResource) [] if len(customAttributes) > 0 { out := make(map[string]string) for _, a := range customAttributes { - out[*a.Key] = fmt.Sprint(a.Value) + if *a.Operator == "stringExists" && a.Value == true { + out[*a.Key] = fmt.Sprint("*") + } else if *a.Operator == "stringMatch" || *a.Operator == "stringEquals" { + out[*a.Key] = fmt.Sprint(a.Value) + } } l["attributes"] = out }