From 6e4bad95740e22fc196fb06f4860fd095de168bf Mon Sep 17 00:00:00 2001 From: hariarla <68221277+hariarla@users.noreply.github.com> Date: Tue, 29 Aug 2023 22:38:24 +0530 Subject: [PATCH] Add access group template support (#4750) * Add access group template support * implement review comments * minor changes to assignment * remove account_id changes --- .../ibm-iam-accessgroups-templates/README.md | 150 +++ .../ibm-iam-accessgroups-templates/main.tf | 143 +++ .../ibm-iam-accessgroups-templates/outputs.tf | 18 + .../variables.tf | 116 ++ .../versions.tf | 9 + ibm/provider/provider.go | 21 +- ...bm_iam_access_group_template_assignment.go | 296 ++++++ ...m_access_group_template_assignment_test.go | 37 + ..._ibm_iam_access_group_template_versions.go | 604 +++++++++++ ...iam_access_group_template_versions_test.go | 46 + .../resource_ibm_iam_access_group_template.go | 780 ++++++++++++++ ...bm_iam_access_group_template_assignment.go | 416 ++++++++ ...m_access_group_template_assignment_test.go | 231 ++++ ...urce_ibm_iam_access_group_template_test.go | 176 ++++ ...e_ibm_iam_access_group_template_version.go | 993 ++++++++++++++++++ ..._iam_access_group_template_version_test.go | 201 ++++ .../d/iam_access_group_template.html.markdown | 82 ++ ...ss_group_template_assignment.html.markdown | 52 + ...cess_group_template_versions.html.markdown | 81 ++ .../r/iam_access_group_template.html.markdown | 196 ++++ ...ss_group_template_assignment.html.markdown | 62 ++ ...ccess_group_template_version.html.markdown | 204 ++++ 22 files changed, 4907 insertions(+), 7 deletions(-) create mode 100644 examples/ibm-iam-accessgroups-templates/README.md create mode 100644 examples/ibm-iam-accessgroups-templates/main.tf create mode 100644 examples/ibm-iam-accessgroups-templates/outputs.tf create mode 100644 examples/ibm-iam-accessgroups-templates/variables.tf create mode 100644 examples/ibm-iam-accessgroups-templates/versions.tf create mode 100644 ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment.go create mode 100644 ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment_test.go create mode 100644 ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_versions.go create mode 100644 ibm/service/iamaccessgroup/data_source_ibm_ibm_iam_access_group_template_versions_test.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment_test.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_test.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version.go create mode 100644 ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version_test.go create mode 100644 website/docs/d/iam_access_group_template.html.markdown create mode 100644 website/docs/d/iam_access_group_template_assignment.html.markdown create mode 100644 website/docs/d/iam_access_group_template_versions.html.markdown create mode 100644 website/docs/r/iam_access_group_template.html.markdown create mode 100644 website/docs/r/iam_access_group_template_assignment.html.markdown create mode 100644 website/docs/r/iam_access_group_template_version.html.markdown diff --git a/examples/ibm-iam-accessgroups-templates/README.md b/examples/ibm-iam-accessgroups-templates/README.md new file mode 100644 index 0000000000..d10b61c9f9 --- /dev/null +++ b/examples/ibm-iam-accessgroups-templates/README.md @@ -0,0 +1,150 @@ +# Example for IAMAccessGroupsV2 + +This example illustrates how to use the IAMAccessGroupsV2 + +The following types of resources are supported: + +* ibm_iam_access_group_template +* ibm_iam_access_group_template_version +* ibm_iam_access_group_template_assignment + +## Usage + +To run this example, execute the following commands: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Run `terraform destroy` when you don't need these resources. + + +## IAMAccessGroupsV2 resources + +ibm_iam_access_group_template resource: + +```hcl +resource "iam_access_group_template" "iam_access_group_template_instance" { + transaction_id = var.iam_access_group_template_transaction_id + name = var.iam_access_group_template_name + description = var.iam_access_group_template_description + group = var.iam_access_group_template_group + policy_template_references = var.iam_access_group_template_policy_template_references +} +``` +ibm_iam_access_group_template_version resource: + +```hcl +resource "iam_access_group_template_version" "iam_access_group_template_version_instance" { + template_id = var.iam_access_group_template_version_template_id + transaction_id = var.iam_access_group_template_version_transaction_id + name = var.iam_access_group_template_version_name + description = var.iam_access_group_template_version_description + group = var.iam_access_group_template_version_group + policy_template_references = var.iam_access_group_template_version_policy_template_references +} +``` +ibm_iam_access_group_template_assignment resource: + +```hcl +resource "iam_access_group_template_assignment" "iam_access_group_template_assignment_instance" { + transaction_id = var.iam_access_group_template_assignment_transaction_id + template_id = var.iam_access_group_template_assignment_template_id + template_version = var.iam_access_group_template_assignment_template_version + target_type = var.iam_access_group_template_assignment_target_type + target = var.iam_access_group_template_assignment_target +} +``` + +## IamAccessGroupsV2 data sources + +ibm_iam_access_group_template data source: + +```hcl +data "iam_access_group_template" "iam_access_group_template_instance" { + transaction_id = var.iam_access_group_template_transaction_id + verbose = var.iam_access_group_template_verbose +} +``` +ibm_iam_access_group_template_versions data source: + +```hcl +data "ibm_iam_access_group_template_version" "ibm_iam_access_group_template_version_instance" { + template_id = var.ibm_iam_access_group_template_version_template_id +} +``` +ibm_iam_access_group_template_assignment data source: + +```hcl +data "iam_access_group_template_assignment" "iam_access_group_template_assignment_instance" { + template_id = var.iam_access_group_template_assignment_template_id + template_version = var.iam_access_group_template_assignment_template_version + target = var.iam_access_group_template_assignment_target + status = var.iam_access_group_template_assignment_status + transaction_id = var.iam_access_group_template_assignment_transaction_id +} +``` + +## Assumptions + +1. TODO + +## Notes + +1. TODO + +## Requirements + +| Name | Version | +|------|---------| +| terraform | ~> 0.12 | + +## Providers + +| Name | Version | +|------|---------| +| ibm | 1.13.1 | + +## Inputs + +ibm_iam_access_group_template input: + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| transaction_id | An optional transaction id for the request. | `string` | false | +| name | The name of the access group template. | `string` | true | +| description | The description of the access group template. | `string` | false | +| group | Access Group Component. | `` | false | +| policy_template_references | References to policy templates assigned to the access group template. | `list()` | false | + +ibm_iam_access_group_template_version input: + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| template_id | ID of the template that you want to create a new version of. | `string` | true | +| transaction_id | An optional transaction id for the request. | `string` | false | +| name | The name of the access group template. | `string` | false | +| description | The description of the access group template version. | `string` | false | +| group | Access Group Component. | `` | false | +| policy_template_references | References to policy templates assigned to the access group template version. | `list()` | false | + +ibm_iam_access_group_template_assignment input: + +| Name | Description | Type | Required | +|------|-------------|------|---------| +| transaction_id | An optional transaction id for the request. | `string` | false | +| template_id | The ID of the template that the assignment is based on. | `string` | true | +| template_version | The version of the template that the assignment is based on. | `string` | true | +| target_type | The type of the entity that the assignment applies to. | `string` | true | +| target | The ID of the entity that the assignment applies to. | `string` | true | + +## Outputs + +| Name | Description | +|------|-------------| +| ibm_iam_access_group_template | ibm_iam_access_group_template object | +| ibm_iam_access_group_template_version | ibm_iam_access_group_template_version object | +| ibm_iam_access_group_template_assignment | ibm_iam_access_group_template_assignment object | diff --git a/examples/ibm-iam-accessgroups-templates/main.tf b/examples/ibm-iam-accessgroups-templates/main.tf new file mode 100644 index 0000000000..30dd7a2b6d --- /dev/null +++ b/examples/ibm-iam-accessgroups-templates/main.tf @@ -0,0 +1,143 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key +} + +// Provision iam_access_group_template resource instance +resource "ibm_iam_access_group_template" "iam_access_group_template_instance" { + transaction_id = var.iam_access_group_template_transaction_id + name = var.iam_access_group_template_name + description = var.iam_access_group_template_description + group { + name = "name" + description = "description" + members { + users = [ "users" ] + services = [ "services" ] + action_controls { + add = true + remove = true + } + } + assertions { + rules { + name = "name" + expiration = 1 + realm_name = "realm_name" + conditions { + claim = "claim" + operator = "operator" + value = "value" + } + action_controls { + remove = true + update = true + } + } + action_controls { + add = true + remove = true + update = true + } + } + action_controls { + access { + add = true + } + } + } + policy_template_references { + id = "id" + version = "version" + } +} + +// Provision iam_access_group_template_version resource instance +resource "ibm_iam_access_group_template_version" "iam_access_group_template_version_instance" { + template_id = var.iam_access_group_template_version_template_id + transaction_id = var.iam_access_group_template_version_transaction_id + name = var.iam_access_group_template_version_name + description = var.iam_access_group_template_version_description + group { + name = "name" + description = "description" + members { + users = [ "users" ] + services = [ "services" ] + action_controls { + add = true + remove = true + } + } + assertions { + rules { + name = "name" + expiration = 1 + realm_name = "realm_name" + conditions { + claim = "claim" + operator = "operator" + value = "value" + } + action_controls { + remove = true + update = true + } + } + action_controls { + add = true + remove = true + update = true + } + } + action_controls { + access { + add = true + } + } + } + policy_template_references { + id = "id" + version = "version" + } +} + +// Provision iam_access_group_template_assignment resource instance +resource "ibm_iam_access_group_template_assignment" "iam_access_group_template_assignment_instance" { + transaction_id = var.iam_access_group_template_assignment_transaction_id + template_id = var.iam_access_group_template_assignment_template_id + template_version = var.iam_access_group_template_assignment_template_version + target_type = var.iam_access_group_template_assignment_target_type + target = var.iam_access_group_template_assignment_target +} + +// Data source is not linked to a resource instance +// Uncomment if an existing data source instance exists +/* +// Create iam_access_group_template data source +data "ibm_iam_access_group_template" "iam_access_group_template_instance" { + transaction_id = var.iam_access_group_template_transaction_id + verbose = var.iam_access_group_template_verbose +} +*/ + +// Data source is not linked to a resource instance +// Uncomment if an existing data source instance exists +/* +// Create ibm_iam_access_group_template_version data source +data "ibm_ibm_iam_access_group_template_version" "ibm_iam_access_group_template_version_instance" { + template_id = var.ibm_iam_access_group_template_version_template_id +} +*/ + +// Data source is not linked to a resource instance +// Uncomment if an existing data source instance exists +/* +// Create iam_access_group_template_assignment data source +data "ibm_iam_access_group_template_assignment" "iam_access_group_template_assignment_instance" { + template_id = var.iam_access_group_template_assignment_template_id + template_version = var.iam_access_group_template_assignment_template_version + target = var.iam_access_group_template_assignment_target + status = var.iam_access_group_template_assignment_status + transaction_id = var.iam_access_group_template_assignment_transaction_id +} +*/ diff --git a/examples/ibm-iam-accessgroups-templates/outputs.tf b/examples/ibm-iam-accessgroups-templates/outputs.tf new file mode 100644 index 0000000000..8f3bada755 --- /dev/null +++ b/examples/ibm-iam-accessgroups-templates/outputs.tf @@ -0,0 +1,18 @@ +// This output allows iam_access_group_template data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_iam_access_group_template" { + value = ibm_iam_access_group_template.iam_access_group_template_instance + description = "iam_access_group_template resource instance" +} +// This output allows iam_access_group_template_version data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_iam_access_group_template_version" { + value = ibm_iam_access_group_template_version.iam_access_group_template_version_instance + description = "iam_access_group_template_version resource instance" +} +// This output allows iam_access_group_template_assignment data to be referenced by other resources and the terraform CLI +// Modify this output if only certain data should be exposed +output "ibm_iam_access_group_template_assignment" { + value = ibm_iam_access_group_template_assignment.iam_access_group_template_assignment_instance + description = "iam_access_group_template_assignment resource instance" +} diff --git a/examples/ibm-iam-accessgroups-templates/variables.tf b/examples/ibm-iam-accessgroups-templates/variables.tf new file mode 100644 index 0000000000..ee851b13a1 --- /dev/null +++ b/examples/ibm-iam-accessgroups-templates/variables.tf @@ -0,0 +1,116 @@ +variable "ibmcloud_api_key" { + description = "IBM Cloud API key" + type = string +} + +// Resource arguments for iam_access_group_template +variable "iam_access_group_template_transaction_id" { + description = "An optional transaction id for the request." + type = string + default = "transaction_id" +} +variable "iam_access_group_template_name" { + description = "The name of the access group template." + type = string + default = "IAM Admin Group template" +} +variable "iam_access_group_template_description" { + description = "The description of the access group template." + type = string + default = "This access group template allows admin access to all IAM platform services in the account." +} + +// Resource arguments for iam_access_group_template_version +variable "iam_access_group_template_version_template_id" { + description = "ID of the template that you want to create a new version of." + type = string + default = "template_id" +} +variable "iam_access_group_template_version_transaction_id" { + description = "An optional transaction id for the request." + type = string + default = "transaction_id" +} +variable "iam_access_group_template_version_name" { + description = "The name of the access group template." + type = string + default = "IAM Admin Group template 2" +} +variable "iam_access_group_template_version_description" { + description = "The description of the access group template." + type = string + default = "This access group template allows admin access to all IAM platform services in the account." +} + +// Resource arguments for iam_access_group_template_assignment +variable "iam_access_group_template_assignment_transaction_id" { + description = "An optional transaction id for the request." + type = string + default = "transaction_id" +} +variable "iam_access_group_template_assignment_template_id" { + description = "The ID of the template that the assignment is based on." + type = string + default = "AccessGroupTemplateId-4be4" +} +variable "iam_access_group_template_assignment_template_version" { + description = "The version of the template that the assignment is based on." + type = string + default = "1" +} +variable "iam_access_group_template_assignment_target_type" { + description = "The type of the entity that the assignment applies to." + type = string + default = "AccountGroup" +} +variable "iam_access_group_template_assignment_target" { + description = "The ID of the entity that the assignment applies to." + type = string + default = "0a45594d0f-123" +} + +// Data source arguments for iam_access_group_template +variable "iam_access_group_template_transaction_id" { + description = "An optional transaction id for the request." + type = string + default = "placeholder" +} +variable "iam_access_group_template_verbose" { + description = "If `verbose=true`, IAM resource details are returned. If performance is a concern, leave the `verbose` parameter off so that details are not retrieved." + type = bool + default = true +} + +// Data source arguments for ibm_iam_access_group_template_version +variable "ibm_iam_access_group_template_version_template_id" { + description = "ID of the template that you want to list all versions of." + type = string + default = "template_id" +} + +// Data source arguments for iam_access_group_template_assignment +variable "iam_access_group_template_assignment_template_id" { + description = "Filter results by Template Id." + type = string + default = "placeholder" +} +variable "iam_access_group_template_assignment_template_version" { + description = "Filter results by Template Version." + type = string + default = "placeholder" +} +variable "iam_access_group_template_assignment_target" { + description = "Filter results by the assignment target." + type = string + default = "placeholder" +} +variable "iam_access_group_template_assignment_status" { + description = "Filter results by the assignment status." + type = string + default = "placeholder" +} +variable "iam_access_group_template_assignment_transaction_id" { + description = "An optional transaction id for the request." + type = string + default = "placeholder" +} diff --git a/examples/ibm-iam-accessgroups-templates/versions.tf b/examples/ibm-iam-accessgroups-templates/versions.tf new file mode 100644 index 0000000000..54c9d03e8d --- /dev/null +++ b/examples/ibm-iam-accessgroups-templates/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.52.0-beta0" + } + } +} diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index 6e95b6fd16..da7adfebbf 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -342,6 +342,8 @@ func Provider() *schema.Provider { "ibm_hpcs_vault": hpcs.DataSourceIbmVault(), "ibm_iam_access_group": iamaccessgroup.DataSourceIBMIAMAccessGroup(), "ibm_iam_access_group_policy": iampolicy.DataSourceIBMIAMAccessGroupPolicy(), + "ibm_iam_access_group_template_versions": iamaccessgroup.DataSourceIBMIAMAccessGroupTemplateVersions(), + "ibm_iam_access_group_template_assignment": iamaccessgroup.DataSourceIBMIAMAccessGroupTemplateAssignment(), "ibm_iam_account_settings": iamidentity.DataSourceIBMIAMAccountSettings(), "ibm_iam_auth_token": iamidentity.DataSourceIBMIAMAuthToken(), "ibm_iam_role_actions": iampolicy.DataSourceIBMIAMRoleAction(), @@ -946,6 +948,9 @@ func Provider() *schema.Provider { "ibm_iam_access_group": iamaccessgroup.ResourceIBMIAMAccessGroup(), "ibm_iam_access_group_account_settings": iamaccessgroup.ResourceIBMIAMAccessGroupAccountSettings(), "ibm_iam_account_settings": iamidentity.ResourceIBMIAMAccountSettings(), + "ibm_iam_access_group_template": iamaccessgroup.ResourceIBMIAMAccessGroupTemplate(), + "ibm_iam_access_group_template_version": iamaccessgroup.ResourceIBMIAMAccessGroupTemplateVersion(), + "ibm_iam_access_group_template_assignment": iamaccessgroup.ResourceIBMIAMAccessGroupTemplateAssignment(), "ibm_iam_custom_role": iampolicy.ResourceIBMIAMCustomRole(), "ibm_iam_access_group_dynamic_rule": iamaccessgroup.ResourceIBMIAMDynamicRule(), "ibm_iam_access_group_members": iamaccessgroup.ResourceIBMIAMAccessGroupMembers(), @@ -1514,13 +1519,15 @@ func Validator() validate.ValidatorDict { "ibm_container_ingress_secret_opaque": kubernetes.ResourceIBMContainerIngressSecretOpaqueValidator(), "ibm_container_cluster_feature": kubernetes.ResourceIBMContainerClusterFeatureValidator(), - "ibm_iam_access_group_dynamic_rule": iamaccessgroup.ResourceIBMIAMDynamicRuleValidator(), - "ibm_iam_access_group_members": iamaccessgroup.ResourceIBMIAMAccessGroupMembersValidator(), - - "ibm_iam_trusted_profile_claim_rule": iamidentity.ResourceIBMIAMTrustedProfileClaimRuleValidator(), - "ibm_iam_trusted_profile_link": iamidentity.ResourceIBMIAMTrustedProfileLinkValidator(), - "ibm_iam_service_api_key": iamidentity.ResourceIBMIAMServiceAPIKeyValidator(), - "ibm_iam_trusted_profile_identity": iamidentity.ResourceIBMIamTrustedProfileIdentityValidator(), + "ibm_iam_access_group_dynamic_rule": iamaccessgroup.ResourceIBMIAMDynamicRuleValidator(), + "ibm_iam_access_group_members": iamaccessgroup.ResourceIBMIAMAccessGroupMembersValidator(), + "ibm_iam_access_group_template": iamaccessgroup.ResourceIBMIAMAccessGroupTemplateValidator(), + "ibm_iam_access_group_template_version": iamaccessgroup.ResourceIBMIAMAccessGroupTemplateVersionValidator(), + "ibm_iam_access_group_template_assignment": iamaccessgroup.ResourceIBMIAMAccessGroupTemplateAssignmentValidator(), + "ibm_iam_trusted_profile_claim_rule": iamidentity.ResourceIBMIAMTrustedProfileClaimRuleValidator(), + "ibm_iam_trusted_profile_link": iamidentity.ResourceIBMIAMTrustedProfileLinkValidator(), + "ibm_iam_service_api_key": iamidentity.ResourceIBMIAMServiceAPIKeyValidator(), + "ibm_iam_trusted_profile_identity": iamidentity.ResourceIBMIamTrustedProfileIdentityValidator(), "ibm_iam_trusted_profile_policy": iampolicy.ResourceIBMIAMTrustedProfilePolicyValidator(), "ibm_iam_access_group_policy": iampolicy.ResourceIBMIAMAccessGroupPolicyValidator(), diff --git a/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment.go b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment.go new file mode 100644 index 0000000000..bf6569f3da --- /dev/null +++ b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment.go @@ -0,0 +1,296 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +func DataSourceIBMIAMAccessGroupTemplateAssignment() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIAMAccessGroupTemplateAssignmentRead, + + Schema: map[string]*schema.Schema{ + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "Enterprise account ID.", + }, + "template_id": { + Type: schema.TypeString, + Optional: true, + Description: "Filter results by Template Id.", + }, + "template_version": { + Type: schema.TypeString, + Optional: true, + Description: "Filter results by Template Version.", + }, + "target": { + Type: schema.TypeString, + Optional: true, + Description: "Filter results by the assignment target.", + }, + "status": { + Type: schema.TypeString, + Optional: true, + Description: "Filter results by the assignment status.", + }, + "transaction_id": { + Type: schema.TypeString, + Optional: true, + Description: "An optional transaction id for the request.", + }, + "limit": { + Type: schema.TypeInt, + Computed: true, + Description: "Maximum number of items returned in the response.", + }, + "offset": { + Type: schema.TypeInt, + Computed: true, + Description: "Index of the first item returned in the response.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Total number of items matching the query.", + }, + "first": { + Type: schema.TypeList, + Computed: true, + Description: "A link object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "A string containing the link’s URL.", + }, + }, + }, + }, + "last": { + Type: schema.TypeList, + Computed: true, + Description: "A link object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "A string containing the link’s URL.", + }, + }, + }, + }, + "assignments": { + Type: schema.TypeList, + Computed: true, + Description: "List of template assignments.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the assignment.", + }, + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the account that the assignment belongs to.", + }, + "template_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the template that the assignment is based on.", + }, + "template_version": { + Type: schema.TypeString, + Computed: true, + Description: "The version of the template that the assignment is based on.", + }, + "target_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the entity that the assignment applies to.", + }, + "target": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the entity that the assignment applies to.", + }, + "operation": { + Type: schema.TypeString, + Computed: true, + Description: "The operation that the assignment applies to (e.g. 'assign', 'update', 'remove').", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the assignment (e.g. 'accepted', 'in_progress', 'succeeded', 'failed', 'superseded').", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL of the assignment resource.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the assignment was created.", + }, + "created_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The user or system that created the assignment.", + }, + "last_modified_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the assignment was last updated.", + }, + "last_modified_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The user or system that last updated the assignment.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIAMAccessGroupTemplateAssignmentRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + listAssignmentsOptions := &iamaccessgroupsv2.ListAssignmentsOptions{} + + userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() + if err != nil { + return diag.FromErr(err) + } + + listAssignmentsOptions.SetAccountID(userDetails.UserAccount) + if _, ok := d.GetOk("template_id"); ok { + listAssignmentsOptions.SetTemplateID(d.Get("template_id").(string)) + } + if _, ok := d.GetOk("template_version"); ok { + listAssignmentsOptions.SetTemplateVersion(d.Get("template_version").(string)) + } + if _, ok := d.GetOk("target"); ok { + listAssignmentsOptions.SetTarget(d.Get("target").(string)) + } + if _, ok := d.GetOk("status"); ok { + listAssignmentsOptions.SetStatus(d.Get("status").(string)) + } + if _, ok := d.GetOk("transaction_id"); ok { + listAssignmentsOptions.SetTransactionID(d.Get("transaction_id").(string)) + } + + listTemplateAssignmentResponse, response, err := iamAccessGroupsClient.ListAssignmentsWithContext(context, listAssignmentsOptions) + if err != nil { + log.Printf("[DEBUG] ListAssignmentsWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("ListAssignmentsWithContext failed %s\n%s", err, response)) + } + + d.SetId(dataSourceIBMIAMAccessGroupTemplateAssignmentID(d)) + + if err = d.Set("limit", flex.IntValue(listTemplateAssignmentResponse.Limit)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting limit: %s", err)) + } + + if err = d.Set("offset", flex.IntValue(listTemplateAssignmentResponse.Offset)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting offset: %s", err)) + } + + if err = d.Set("total_count", flex.IntValue(listTemplateAssignmentResponse.TotalCount)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting total_count: %s", err)) + } + + first := []map[string]interface{}{} + if listTemplateAssignmentResponse.First != nil { + modelMap, err := dataSourceIBMIAMAccessGroupTemplateAssignmentHrefStructToMap(listTemplateAssignmentResponse.First) + if err != nil { + return diag.FromErr(err) + } + first = append(first, modelMap) + } + if err = d.Set("first", first); err != nil { + return diag.FromErr(fmt.Errorf("Error setting first %s", err)) + } + + last := []map[string]interface{}{} + if listTemplateAssignmentResponse.Last != nil { + modelMap, err := dataSourceIBMIAMAccessGroupTemplateAssignmentHrefStructToMap(listTemplateAssignmentResponse.Last) + if err != nil { + return diag.FromErr(err) + } + last = append(last, modelMap) + } + if err = d.Set("last", last); err != nil { + return diag.FromErr(fmt.Errorf("Error setting last %s", err)) + } + + assignments := []map[string]interface{}{} + if listTemplateAssignmentResponse.Assignments != nil { + for _, modelItem := range listTemplateAssignmentResponse.Assignments { + modelMap, err := dataSourceIBMIAMAccessGroupTemplateAssignmentTemplateAssignmentResponseToMap(&modelItem) + if err != nil { + return diag.FromErr(err) + } + assignments = append(assignments, modelMap) + } + } + if err = d.Set("assignments", assignments); err != nil { + return diag.FromErr(fmt.Errorf("Error setting assignments %s", err)) + } + + return nil +} + +// dataSourceIBMIAMAccessGroupTemplateAssignmentID returns a reasonable ID for the list. +func dataSourceIBMIAMAccessGroupTemplateAssignmentID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func dataSourceIBMIAMAccessGroupTemplateAssignmentHrefStructToMap(model *iamaccessgroupsv2.HrefStruct) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Href != nil { + modelMap["href"] = model.Href + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateAssignmentTemplateAssignmentResponseToMap(model *iamaccessgroupsv2.TemplateAssignmentResponse) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = model.ID + modelMap["account_id"] = model.AccountID + modelMap["template_id"] = model.TemplateID + modelMap["template_version"] = model.TemplateVersion + modelMap["target_type"] = model.TargetType + modelMap["target"] = model.Target + modelMap["operation"] = model.Operation + modelMap["status"] = model.Status + modelMap["href"] = model.Href + modelMap["created_at"] = model.CreatedAt.String() + modelMap["created_by_id"] = model.CreatedByID + modelMap["last_modified_at"] = model.LastModifiedAt.String() + modelMap["last_modified_by_id"] = model.LastModifiedByID + return modelMap, nil +} diff --git a/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment_test.go b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment_test.go new file mode 100644 index 0000000000..ca28c8f822 --- /dev/null +++ b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_assignment_test.go @@ -0,0 +1,37 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMIAMAccessGroupTemplateAssignmentDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateAssignmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateAssignmentDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_iam_access_group_template_assignment.template", "assignments.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentDataSourceConfig() string { + return fmt.Sprintf(` + data "ibm_iam_access_group_template_assignment" "template" { + } + `) + +} diff --git a/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_versions.go b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_versions.go new file mode 100644 index 0000000000..5fb78aa827 --- /dev/null +++ b/ibm/service/iamaccessgroup/data_source_ibm_iam_access_group_template_versions.go @@ -0,0 +1,604 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +func DataSourceIBMIAMAccessGroupTemplateVersions() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIAMAccessGroupTemplateVersionRead, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + Description: "ID of the template that you want to list all versions of.", + }, + "first": { + Type: schema.TypeList, + Computed: true, + Description: "A link object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "A string containing the link’s URL.", + }, + }, + }, + }, + "previous": { + Type: schema.TypeList, + Computed: true, + Description: "A link object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "A string containing the link’s URL.", + }, + }, + }, + }, + "last": { + Type: schema.TypeList, + Computed: true, + Description: "A link object.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "A string containing the link’s URL.", + }, + }, + }, + }, + "group_template_versions": { + Type: schema.TypeList, + Computed: true, + Description: "A list of access group template versions.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the template.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the template.", + }, + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the account associated with the template.", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "The version number of the template.", + }, + "committed": { + Type: schema.TypeBool, + Computed: true, + Description: "A boolean indicating whether the template is committed or not.", + }, + "group": { + Type: schema.TypeList, + Computed: true, + Description: "Access Group Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: "Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "Access group description. This is shown in child accounts.", + }, + "members": { + Type: schema.TypeList, + Computed: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "users": { + Type: schema.TypeList, + Computed: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "services": { + Type: schema.TypeList, + Computed: true, + Description: "Array of service IDs to add to the template.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "action_controls": { + Type: schema.TypeList, + Computed: true, + Description: "Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them.", + }, + "remove": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for removing enterprise-managed members from an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "assertions": { + Type: schema.TypeList, + Computed: true, + Description: "Assertions Input Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rules": { + Type: schema.TypeList, + Computed: true, + Description: "Dynamic rules to automatically add federated users to access groups based on specific identity attributes.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: "Dynamic rule name.", + }, + "expiration": { + Type: schema.TypeInt, + Computed: true, + Description: "Session duration in hours. Access group membership is revoked after this time period expires. Users must log back in to refresh their access group membership.", + }, + "realm_name": { + Type: schema.TypeString, + Computed: true, + Description: "The identity provider (IdP) URL.", + }, + "conditions": { + Type: schema.TypeList, + Computed: true, + Description: "Conditions of membership. You can think of this as a key:value pair.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "claim": { + Type: schema.TypeString, + Computed: true, + Description: "The key in the key:value pair.", + }, + "operator": { + Type: schema.TypeString, + Computed: true, + Description: "Compares the claim and the value.", + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: "The value in the key:value pair.", + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + Computed: true, + Description: "Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "remove": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for removing this enterprise-managed dynamic rule.", + }, + "update": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for updating this enterprise-managed dynamic rule.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + Computed: true, + Description: "Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it.", + }, + "remove": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + "update": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + Computed: true, + Description: "Access group action controls component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access": { + Type: schema.TypeList, + Computed: true, + Description: "Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Computed: true, + Description: "Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "policy_template_references": { + Type: schema.TypeList, + Computed: true, + Description: "A list of policy templates associated with the template.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "Policy template ID.", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "Policy template version.", + }, + }, + }, + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL to the template resource.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time the template was created.", + }, + "created_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who created the template.", + }, + "last_modified_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time the template was last modified.", + }, + "last_modified_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who last modified the template.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIAMAccessGroupTemplateVersionRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + listTemplateVersionsOptions := &iamaccessgroupsv2.ListTemplateVersionsOptions{} + + listTemplateVersionsOptions.SetTemplateID(d.Get("template_id").(string)) + + var pager *iamaccessgroupsv2.TemplateVersionsPager + pager, err = iamAccessGroupsClient.NewTemplateVersionsPager(listTemplateVersionsOptions) + if err != nil { + return diag.FromErr(err) + } + + allItems, err := pager.GetAll() + if err != nil { + log.Printf("[DEBUG] TemplateVersionsPager.GetAll() failed %s", err) + return diag.FromErr(fmt.Errorf("TemplateVersionsPager.GetAll() failed %s", err)) + } + + d.SetId(dataSourceIBMIAMAccessGroupTemplateVersionID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := dataSourceIBMIAMAccessGroupTemplateVersionListTemplateVersionResponseToMap(&modelItem) + if err != nil { + return diag.FromErr(err) + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("group_template_versions", mapSlice); err != nil { + return diag.FromErr(fmt.Errorf("Error setting group_template_versions %s", err)) + } + + return nil +} + +// dataSourceIBMIAMAccessGroupTemplateVersionID returns a reasonable ID for the list. +func dataSourceIBMIAMAccessGroupTemplateVersionID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func dataSourceIBMIAMAccessGroupTemplateVersionHrefStructToMap(model *iamaccessgroupsv2.HrefStruct) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Href != nil { + modelMap["href"] = model.Href + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionListTemplateVersionResponseToMap(model *iamaccessgroupsv2.ListTemplateVersionResponse) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = model.Name + modelMap["description"] = model.Description + modelMap["account_id"] = model.AccountID + modelMap["version"] = model.Version + modelMap["committed"] = model.Committed + groupMap, err := dataSourceIBMIAMAccessGroupTemplateVersionAccessGroupResponseToMap(model.Group) + if err != nil { + return modelMap, err + } + modelMap["group"] = []map[string]interface{}{groupMap} + policyTemplateReferences := []map[string]interface{}{} + for _, policyTemplateReferencesItem := range model.PolicyTemplateReferences { + policyTemplateReferencesItemMap, err := dataSourceIBMIAMAccessGroupTemplateVersionPolicyTemplatesToMap(&policyTemplateReferencesItem) + if err != nil { + return modelMap, err + } + policyTemplateReferences = append(policyTemplateReferences, policyTemplateReferencesItemMap) + } + modelMap["policy_template_references"] = policyTemplateReferences + modelMap["href"] = model.Href + modelMap["created_at"] = model.CreatedAt + modelMap["created_by_id"] = model.CreatedByID + modelMap["last_modified_at"] = model.LastModifiedAt + modelMap["last_modified_by_id"] = model.LastModifiedByID + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionAccessGroupResponseToMap(model *iamaccessgroupsv2.AccessGroupResponse) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = model.Name + if model.Description != nil { + modelMap["description"] = model.Description + } + if model.Members != nil { + membersMap, err := dataSourceIBMIAMAccessGroupTemplateVersionMembersToMap(model.Members) + if err != nil { + return modelMap, err + } + modelMap["members"] = []map[string]interface{}{membersMap} + } + if model.Assertions != nil { + assertionsMap, err := dataSourceIBMIAMAccessGroupTemplateVersionAssertionsToMap(model.Assertions) + if err != nil { + return modelMap, err + } + modelMap["assertions"] = []map[string]interface{}{assertionsMap} + } + if model.ActionControls != nil { + actionControlsMap, err := dataSourceIBMIAMAccessGroupTemplateVersionGroupActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionMembersToMap(model *iamaccessgroupsv2.Members) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Users != nil { + modelMap["users"] = model.Users + } + if model.Services != nil { + modelMap["services"] = model.Services + } + if model.ActionControls != nil { + actionControlsMap, err := dataSourceIBMIAMAccessGroupTemplateVersionMembersActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionMembersActionControlsToMap(model *iamaccessgroupsv2.MembersActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionAssertionsToMap(model *iamaccessgroupsv2.Assertions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Rules != nil { + rules := []map[string]interface{}{} + for _, rulesItem := range model.Rules { + rulesItemMap, err := dataSourceIBMIAMAccessGroupTemplateVersionAssertionsRuleToMap(&rulesItem) + if err != nil { + return modelMap, err + } + rules = append(rules, rulesItemMap) + } + modelMap["rules"] = rules + } + if model.ActionControls != nil { + actionControlsMap, err := dataSourceIBMIAMAccessGroupTemplateVersionAssertionsActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionAssertionsRuleToMap(model *iamaccessgroupsv2.AssertionsRule) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = model.Name + } + if model.Expiration != nil { + modelMap["expiration"] = flex.IntValue(model.Expiration) + } + if model.RealmName != nil { + modelMap["realm_name"] = model.RealmName + } + if model.Conditions != nil { + conditions := []map[string]interface{}{} + for _, conditionsItem := range model.Conditions { + conditionsItemMap, err := dataSourceIBMIAMAccessGroupTemplateVersionConditionsToMap(&conditionsItem) + if err != nil { + return modelMap, err + } + conditions = append(conditions, conditionsItemMap) + } + modelMap["conditions"] = conditions + } + if model.ActionControls != nil { + actionControlsMap, err := dataSourceIBMIAMAccessGroupTemplateVersionRuleActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionConditionsToMap(model *iamaccessgroupsv2.Conditions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Claim != nil { + modelMap["claim"] = model.Claim + } + if model.Operator != nil { + modelMap["operator"] = model.Operator + } + if model.Value != nil { + modelMap["value"] = model.Value + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionRuleActionControlsToMap(model *iamaccessgroupsv2.RuleActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionAssertionsActionControlsToMap(model *iamaccessgroupsv2.AssertionsActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionGroupActionControlsToMap(model *iamaccessgroupsv2.GroupActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Access != nil { + accessMap, err := dataSourceIBMIAMAccessGroupTemplateVersionAccessActionControlsToMap(model.Access) + if err != nil { + return modelMap, err + } + modelMap["access"] = []map[string]interface{}{accessMap} + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionAccessActionControlsToMap(model *iamaccessgroupsv2.AccessActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + return modelMap, nil +} + +func dataSourceIBMIAMAccessGroupTemplateVersionPolicyTemplatesToMap(model *iamaccessgroupsv2.PolicyTemplates) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = model.ID + } + if model.Version != nil { + modelMap["version"] = model.Version + } + return modelMap, nil +} diff --git a/ibm/service/iamaccessgroup/data_source_ibm_ibm_iam_access_group_template_versions_test.go b/ibm/service/iamaccessgroup/data_source_ibm_ibm_iam_access_group_template_versions_test.go new file mode 100644 index 0000000000..95d0252aac --- /dev/null +++ b/ibm/service/iamaccessgroup/data_source_ibm_ibm_iam_access_group_template_versions_test.go @@ -0,0 +1,46 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMIAMAccessGroupTemplateVersionsDataSourceBasic(t *testing.T) { + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateVersionDataSourceConfigBasic(name, agName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_iam_access_group_template_versions.template", "group_template_versions.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIAMAccessGroupTemplateVersionDataSourceConfigBasic(name string, agName string) string { + return fmt.Sprintf(` + + resource "ibm_iam_access_group_template" "template" { + name = "%s" + description = "Testing4" + group { + name = "%s" + } + } + data "ibm_iam_access_group_template_versions" "template" { + template_id = ibm_iam_access_group_template.template.template_id + } + `, name, agName) +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template.go new file mode 100644 index 0000000000..405d383aa9 --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template.go @@ -0,0 +1,780 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup + +import ( + "context" + "fmt" + "log" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +func ResourceIBMIAMAccessGroupTemplate() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIAMAccessGroupTemplateCreate, + ReadContext: resourceIBMIAMAccessGroupTemplateVersionRead, + UpdateContext: resourceIBMIAMAccessGroupTemplateVersionUpdate, + DeleteContext: resourceIBMIAMAccessGroupTemplateVersionDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "transaction_id": { + Type: schema.TypeString, + Optional: true, + + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template", "transaction_id"), + Description: "An optional transaction id for the request.", + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template", "name"), + Description: "The name of the access group template.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template", "description"), + Description: "The description of the access group template.", + }, + "account_id": { + Type: schema.TypeString, + Computed: true, + + Description: "The ID of the account to which the access group template is assigned.", + }, + "group": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Access Group Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Access group description. This is shown in child accounts.", + }, + "members": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "users": { + Type: schema.TypeList, + Optional: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "services": { + Type: schema.TypeList, + Optional: true, + Description: "Array of service IDs to add to the template.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them.", + }, + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing enterprise-managed members from an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "assertions": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Assertions Input Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rules": { + Type: schema.TypeList, + Optional: true, + Description: "Dynamic rules to automatically add federated users to access groups based on specific identity attributes.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Description: "Dynamic rule name.", + }, + "expiration": { + Type: schema.TypeInt, + Optional: true, + Description: "Session duration in hours. Access group membership is revoked after this time period expires. Users must log back in to refresh their access group membership.", + }, + "realm_name": { + Type: schema.TypeString, + Optional: true, + Description: "The identity provider (IdP) URL.", + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Description: "Conditions of membership. You can think of this as a key:value pair.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "claim": { + Type: schema.TypeString, + Optional: true, + Description: "The key in the key:value pair.", + }, + "operator": { + Type: schema.TypeString, + Optional: true, + Description: "Compares the claim and the value.", + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: "The value in the key:value pair.", + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing this enterprise-managed dynamic rule.", + }, + "update": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for updating this enterprise-managed dynamic rule.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it.", + }, + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + "update": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Access group action controls component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "policy_template_references": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "References to policy templates assigned to the access group template.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + Description: "Policy template ID.", + }, + "version": { + Type: schema.TypeString, + Optional: true, + Description: "Policy template version.", + }, + }, + }, + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "The version of the access group template.", + }, + "committed": { + Type: schema.TypeBool, + Computed: true, + Optional: true, + Description: "A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts.", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL of the access group template resource.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the access group template was created.", + }, + "created_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who created the access group template.", + }, + "last_modified_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the access group template was last modified.", + }, + "last_modified_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who last modified the access group template.", + }, + "template_id": { + Type: schema.TypeString, + Computed: true, + Description: "Template ID.", + }, + }, + } +} + +func ResourceIBMIAMAccessGroupTemplateValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "transaction_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 50, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\-\s]+$`, + MinValueLength: 1, + MaxValueLength: 100, + }, + validate.ValidateSchema{ + Identifier: "description", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\-\s]+$`, + MinValueLength: 0, + MaxValueLength: 250, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_iam_access_group_template", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIAMAccessGroupTemplateCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + createTemplateOptions := &iamaccessgroupsv2.CreateTemplateOptions{} + + createTemplateOptions.SetName(d.Get("name").(string)) + + userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() + if err != nil { + return diag.FromErr(err) + } + + createTemplateOptions.SetAccountID(userDetails.UserAccount) + + if _, ok := d.GetOk("description"); ok { + createTemplateOptions.SetDescription(d.Get("description").(string)) + } + if _, ok := d.GetOk("group"); ok { + groupModel, err := resourceIBMIAMAccessGroupTemplateMapToAccessGroupRequest(d.Get("group.0").(map[string]interface{})) + if err != nil { + return diag.FromErr(err) + } + createTemplateOptions.SetGroup(groupModel) + } + if _, ok := d.GetOk("policy_template_references"); ok { + var policyTemplateReferences []iamaccessgroupsv2.PolicyTemplates + for _, v := range d.Get("policy_template_references").([]interface{}) { + value := v.(map[string]interface{}) + policyTemplateReferencesItem, err := resourceIBMIAMAccessGroupTemplateMapToPolicyTemplates(value) + if err != nil { + return diag.FromErr(err) + } + policyTemplateReferences = append(policyTemplateReferences, *policyTemplateReferencesItem) + } + createTemplateOptions.SetPolicyTemplateReferences(policyTemplateReferences) + } + if _, ok := d.GetOk("transaction_id"); ok { + createTemplateOptions.SetTransactionID(d.Get("transaction_id").(string)) + } + + templateResponse, response, err := iamAccessGroupsClient.CreateTemplateWithContext(context, createTemplateOptions) + if err != nil { + log.Printf("[DEBUG] CreateTemplateWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("CreateTemplateWithContext failed %s\n%s", err, response)) + } + version, _ := strconv.Atoi(*templateResponse.Version) + + d.SetId(fmt.Sprintf("%s/%d", *templateResponse.ID, version)) + + return resourceIBMIAMAccessGroupTemplateVersionRead(context, d, meta) +} + +func resourceIBMIAMAccessGroupTemplateMapToAccessGroupRequest(modelMap map[string]interface{}) (*iamaccessgroupsv2.AccessGroupRequest, error) { + model := &iamaccessgroupsv2.AccessGroupRequest{} + model.Name = core.StringPtr(modelMap["name"].(string)) + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["members"] != nil && len(modelMap["members"].([]interface{})) > 0 { + MembersModel, err := resourceIBMIAMAccessGroupTemplateMapToMembers(modelMap["members"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Members = MembersModel + } + if modelMap["assertions"] != nil && len(modelMap["assertions"].([]interface{})) > 0 { + AssertionsModel, err := resourceIBMIAMAccessGroupTemplateMapToAssertions(modelMap["assertions"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Assertions = AssertionsModel + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateMapToGroupActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToMembers(modelMap map[string]interface{}) (*iamaccessgroupsv2.Members, error) { + model := &iamaccessgroupsv2.Members{} + if modelMap["users"] != nil { + users := []string{} + for _, usersItem := range modelMap["users"].([]interface{}) { + users = append(users, usersItem.(string)) + } + model.Users = users + } + if modelMap["services"] != nil { + services := []string{} + for _, servicesItem := range modelMap["services"].([]interface{}) { + services = append(services, servicesItem.(string)) + } + model.Services = services + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateMapToMembersActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToMembersActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.MembersActionControls, error) { + model := &iamaccessgroupsv2.MembersActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToAssertions(modelMap map[string]interface{}) (*iamaccessgroupsv2.Assertions, error) { + model := &iamaccessgroupsv2.Assertions{} + if modelMap["rules"] != nil { + rules := []iamaccessgroupsv2.AssertionsRule{} + for _, rulesItem := range modelMap["rules"].([]interface{}) { + rulesItemModel, err := resourceIBMIAMAccessGroupTemplateMapToAssertionsRule(rulesItem.(map[string]interface{})) + if err != nil { + return model, err + } + rules = append(rules, *rulesItemModel) + } + model.Rules = rules + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateMapToAssertionsActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToAssertionsRule(modelMap map[string]interface{}) (*iamaccessgroupsv2.AssertionsRule, error) { + model := &iamaccessgroupsv2.AssertionsRule{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["expiration"] != nil { + model.Expiration = core.Int64Ptr(int64(modelMap["expiration"].(int))) + } + if modelMap["realm_name"] != nil && modelMap["realm_name"].(string) != "" { + model.RealmName = core.StringPtr(modelMap["realm_name"].(string)) + } + if modelMap["conditions"] != nil { + conditions := []iamaccessgroupsv2.Conditions{} + for _, conditionsItem := range modelMap["conditions"].([]interface{}) { + conditionsItemModel, err := resourceIBMIAMAccessGroupTemplateMapToConditions(conditionsItem.(map[string]interface{})) + if err != nil { + return model, err + } + conditions = append(conditions, *conditionsItemModel) + } + model.Conditions = conditions + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateMapToRuleActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToConditions(modelMap map[string]interface{}) (*iamaccessgroupsv2.Conditions, error) { + model := &iamaccessgroupsv2.Conditions{} + if modelMap["claim"] != nil && modelMap["claim"].(string) != "" { + model.Claim = core.StringPtr(modelMap["claim"].(string)) + } + if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { + model.Operator = core.StringPtr(modelMap["operator"].(string)) + } + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToRuleActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.RuleActionControls, error) { + model := &iamaccessgroupsv2.RuleActionControls{} + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + if modelMap["update"] != nil { + model.Update = core.BoolPtr(modelMap["update"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToAssertionsActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.AssertionsActionControls, error) { + model := &iamaccessgroupsv2.AssertionsActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + if modelMap["update"] != nil { + model.Update = core.BoolPtr(modelMap["update"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToGroupActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.GroupActionControls, error) { + model := &iamaccessgroupsv2.GroupActionControls{} + if modelMap["access"] != nil && len(modelMap["access"].([]interface{})) > 0 { + AccessModel, err := resourceIBMIAMAccessGroupTemplateMapToAccessActionControls(modelMap["access"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Access = AccessModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToAccessActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.AccessActionControls, error) { + model := &iamaccessgroupsv2.AccessActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateMapToPolicyTemplates(modelMap map[string]interface{}) (*iamaccessgroupsv2.PolicyTemplates, error) { + model := &iamaccessgroupsv2.PolicyTemplates{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["version"] != nil && modelMap["version"].(string) != "" { + model.Version = core.StringPtr(modelMap["version"].(string)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateAccessGroupResponseToMap(model *iamaccessgroupsv2.AccessGroupResponse) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = model.Name + if model.Description != nil { + modelMap["description"] = model.Description + } + if model.Members != nil { + membersMap, err := resourceIBMIAMAccessGroupTemplateMembersToMap(model.Members) + if err != nil { + return modelMap, err + } + modelMap["members"] = []map[string]interface{}{membersMap} + } + if model.Assertions != nil { + assertionsMap, err := resourceIBMIAMAccessGroupTemplateAssertionsToMap(model.Assertions) + if err != nil { + return modelMap, err + } + modelMap["assertions"] = []map[string]interface{}{assertionsMap} + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateGroupActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateMembersToMap(model *iamaccessgroupsv2.Members) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Users != nil { + modelMap["users"] = model.Users + } + if model.Services != nil { + modelMap["services"] = model.Services + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateMembersActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateMembersActionControlsToMap(model *iamaccessgroupsv2.MembersActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateAssertionsToMap(model *iamaccessgroupsv2.Assertions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Rules != nil { + rules := []map[string]interface{}{} + for _, rulesItem := range model.Rules { + rulesItemMap, err := resourceIBMIAMAccessGroupTemplateAssertionsRuleToMap(&rulesItem) + if err != nil { + return modelMap, err + } + rules = append(rules, rulesItemMap) + } + modelMap["rules"] = rules + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateAssertionsActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateAssertionsRuleToMap(model *iamaccessgroupsv2.AssertionsRule) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = model.Name + } + if model.Expiration != nil { + modelMap["expiration"] = flex.IntValue(model.Expiration) + } + if model.RealmName != nil { + modelMap["realm_name"] = model.RealmName + } + if model.Conditions != nil { + conditions := []map[string]interface{}{} + for _, conditionsItem := range model.Conditions { + conditionsItemMap, err := resourceIBMIAMAccessGroupTemplateConditionsToMap(&conditionsItem) + if err != nil { + return modelMap, err + } + conditions = append(conditions, conditionsItemMap) + } + modelMap["conditions"] = conditions + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateRuleActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateConditionsToMap(model *iamaccessgroupsv2.Conditions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Claim != nil { + modelMap["claim"] = model.Claim + } + if model.Operator != nil { + modelMap["operator"] = model.Operator + } + if model.Value != nil { + modelMap["value"] = model.Value + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateRuleActionControlsToMap(model *iamaccessgroupsv2.RuleActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateAssertionsActionControlsToMap(model *iamaccessgroupsv2.AssertionsActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateGroupActionControlsToMap(model *iamaccessgroupsv2.GroupActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Access != nil { + accessMap, err := resourceIBMIAMAccessGroupTemplateAccessActionControlsToMap(model.Access) + if err != nil { + return modelMap, err + } + modelMap["access"] = []map[string]interface{}{accessMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateAccessActionControlsToMap(model *iamaccessgroupsv2.AccessActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplatePolicyTemplatesToMap(model *iamaccessgroupsv2.PolicyTemplates) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = model.ID + } + if model.Version != nil { + modelMap["version"] = model.Version + } + return modelMap, nil +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment.go new file mode 100644 index 0000000000..fb786da9a6 --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment.go @@ -0,0 +1,416 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +const ( + envAGAssignmentTimeoutDurationKey = "IAM_ACCESS_GROUP_ASSIGNMENT_STATE_REFRESH_TIMEOUT_IN_SECONDS" + InProgress = "in_progress" + complete = "complete" + failed = "failed" +) + +func ResourceIBMIAMAccessGroupTemplateAssignment() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIAMAccessGroupTemplateAssignmentCreate, + ReadContext: resourceIBMIAMAccessGroupTemplateAssignmentRead, + UpdateContext: resourceIBMIAMAccessGroupTemplateAssignmentUpdate, + DeleteContext: resourceIBMIAMAccessGroupTemplateAssignmentDelete, + Importer: &schema.ResourceImporter{}, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "transaction_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_assignment", "transaction_id"), + Description: "An optional transaction id for the request.", + }, + "template_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_assignment", "template_id"), + Description: "The ID of the template that the assignment is based on.", + }, + "template_version": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_assignment", "template_version"), + Description: "The version of the template that the assignment is based on.", + }, + "target_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_assignment", "target_type"), + Description: "The type of the entity that the assignment applies to.", + }, + "target": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_assignment", "target"), + Description: "The ID of the entity that the assignment applies to.", + }, + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the account that the assignment belongs to.", + }, + "operation": { + Type: schema.TypeString, + Computed: true, + Description: "The operation that the assignment applies to (e.g. 'assign', 'update', 'remove').", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the assignment (e.g. 'accepted', 'in_progress', 'succeeded', 'failed', 'superseded').", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL of the assignment resource.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the assignment was created.", + }, + "created_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The user or system that created the assignment.", + }, + "last_modified_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the assignment was last updated.", + }, + "last_modified_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The user or system that last updated the assignment.", + }, + "etag": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceIBMIAMAccessGroupTemplateAssignmentValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "transaction_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 50, + }, + validate.ValidateSchema{ + Identifier: "template_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 100, + }, + validate.ValidateSchema{ + Identifier: "template_version", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[0-9]+$`, + MinValueLength: 1, + MaxValueLength: 2, + }, + validate.ValidateSchema{ + Identifier: "target_type", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Required: true, + AllowedValues: "Account, AccountGroup", + Regexp: `^[a-zA-Z-]+$`, + MinValueLength: 7, + MaxValueLength: 12, + }, + validate.ValidateSchema{ + Identifier: "target", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 50, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_iam_access_group_template_assignment", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIAMAccessGroupTemplateAssignmentCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + createAssignmentOptions := &iamaccessgroupsv2.CreateAssignmentOptions{} + + createAssignmentOptions.SetTemplateID(d.Get("template_id").(string)) + createAssignmentOptions.SetTemplateVersion(d.Get("template_version").(string)) + createAssignmentOptions.SetTargetType(d.Get("target_type").(string)) + createAssignmentOptions.SetTarget(d.Get("target").(string)) + if _, ok := d.GetOk("transaction_id"); ok { + createAssignmentOptions.SetTransactionID(d.Get("transaction_id").(string)) + } + + templateAssignmentResponse, response, err := iamAccessGroupsClient.CreateAssignmentWithContext(context, createAssignmentOptions) + if err != nil { + log.Printf("[DEBUG] CreateAssignmentWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("CreateAssignmentWithContext failed %s\n%s", err, response)) + } + + d.SetId(*templateAssignmentResponse.ID) + + _, err = waitForAssignment(d.Timeout(schema.TimeoutCreate), meta, d, isAccessGroupTemplateAssigned) + if err != nil { + return diag.FromErr(fmt.Errorf("error assigning %s", err)) + } + + return resourceIBMIAMAccessGroupTemplateAssignmentRead(context, d, meta) +} + +func resourceIBMIAMAccessGroupTemplateAssignmentRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(d.Id()) + + templateAssignmentVerboseResponse, response, err := iamAccessGroupsClient.GetAssignmentWithContext(context, getAssignmentOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + log.Printf("[DEBUG] GetAssignmentWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("GetAssignmentWithContext failed %s\n%s", err, response)) + } + + if err = d.Set("template_id", templateAssignmentVerboseResponse.TemplateID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting template_id: %s", err)) + } + if err = d.Set("template_version", templateAssignmentVerboseResponse.TemplateVersion); err != nil { + return diag.FromErr(fmt.Errorf("Error setting template_version: %s", err)) + } + if err = d.Set("target_type", templateAssignmentVerboseResponse.TargetType); err != nil { + return diag.FromErr(fmt.Errorf("Error setting target_type: %s", err)) + } + if err = d.Set("target", templateAssignmentVerboseResponse.Target); err != nil { + return diag.FromErr(fmt.Errorf("Error setting target: %s", err)) + } + if err = d.Set("account_id", templateAssignmentVerboseResponse.AccountID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + } + if err = d.Set("operation", templateAssignmentVerboseResponse.Operation); err != nil { + return diag.FromErr(fmt.Errorf("Error setting operation: %s", err)) + } + if err = d.Set("status", templateAssignmentVerboseResponse.Status); err != nil { + return diag.FromErr(fmt.Errorf("Error setting status: %s", err)) + } + if err = d.Set("href", templateAssignmentVerboseResponse.Href); err != nil { + return diag.FromErr(fmt.Errorf("Error setting href: %s", err)) + } + if err = d.Set("created_at", flex.DateTimeToString(templateAssignmentVerboseResponse.CreatedAt)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting created_at: %s", err)) + } + if err = d.Set("created_by_id", templateAssignmentVerboseResponse.CreatedByID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting created_by_id: %s", err)) + } + if err = d.Set("last_modified_at", flex.DateTimeToString(templateAssignmentVerboseResponse.LastModifiedAt)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting last_modified_at: %s", err)) + } + if err = d.Set("last_modified_by_id", templateAssignmentVerboseResponse.LastModifiedByID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting last_modified_by_id: %s", err)) + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return diag.FromErr(fmt.Errorf("Error setting etag: %s", err)) + } + + return nil +} + +func resourceIBMIAMAccessGroupTemplateAssignmentUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + updateAssignmentOptions := &iamaccessgroupsv2.UpdateAssignmentOptions{} + + updateAssignmentOptions.SetAssignmentID(d.Id()) + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(d.Id()) + + templateAssignmentVerboseResponse, response, err := iamAccessGroupsClient.GetAssignmentWithContext(context, getAssignmentOptions) + + if err != nil && templateAssignmentVerboseResponse == nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + log.Printf("[DEBUG] GetAssignmentWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("GetAssignmentWithContext failed %s\n%s", err, response)) + } + + updateAssignmentOptions.SetIfMatch(response.Headers.Get("ETag")) + + hasChange := false + + if d.HasChange("template_version") { + updateAssignmentOptions.SetTemplateVersion(d.Get("template_version").(string)) + hasChange = true + } + + if hasChange { + _, response, err := iamAccessGroupsClient.UpdateAssignmentWithContext(context, updateAssignmentOptions) + if err != nil { + log.Printf("[DEBUG] UpdateAssignmentWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("UpdateAssignmentWithContext failed %s\n%s", err, response)) + } + waitForAssignment(d.Timeout(schema.TimeoutUpdate), meta, d, isAccessGroupTemplateAssigned) + } + + return resourceIBMIAMAccessGroupTemplateAssignmentRead(context, d, meta) +} + +func resourceIBMIAMAccessGroupTemplateAssignmentDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + deleteAssignmentOptions := &iamaccessgroupsv2.DeleteAssignmentOptions{} + + deleteAssignmentOptions.SetAssignmentID(d.Id()) + + response, err := iamAccessGroupsClient.DeleteAssignmentWithContext(context, deleteAssignmentOptions) + if err != nil { + log.Printf("[DEBUG] DeleteAssignmentWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("DeleteAssignmentWithContext failed %s\n%s", err, response)) + } + + waitForAssignment(d.Timeout(schema.TimeoutDelete), meta, d, isAccessGroupTemplateAssignmentDeleted) + + d.SetId("") + + return nil +} + +func waitForAssignment(timeout time.Duration, meta interface{}, d *schema.ResourceData, refreshFn func(string, interface{}) resource.StateRefreshFunc) (interface{}, error) { + + stateConf := &resource.StateChangeConf{ + Pending: []string{InProgress}, + Target: []string{complete}, + Refresh: refreshFn(d.Id(), meta), + Delay: 30 * time.Second, + PollInterval: time.Minute, + Timeout: timeout, + } + + return stateConf.WaitForState() +} + +func isAccessGroupTemplateAssigned(id string, meta interface{}) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return nil, failed, err + } + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(id) + + assignment, response, err := iamAccessGroupsClient.GetAssignment(getAssignmentOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + return nil, failed, err + } + } + + if assignment != nil { + if *assignment.Status == "accepted" || *assignment.Status == "in_progress" { + log.Printf("Assignment still in progress\n") + return assignment, InProgress, nil + } + + if *assignment.Status == "succeeded" { + return assignment, complete, nil + } + + if *assignment.Status == "failed" { + return assignment, failed, fmt.Errorf("[ERROR] The assignment %s did complete but with a 'failed' status. Please check assignment resource for detailed errors: %s\n", id, response) + } + } + + return assignment, failed, fmt.Errorf("[ERROR] Unexpected status reached for assignment %s.: %s\n", id, response) + } +} + +func isAccessGroupTemplateAssignmentDeleted(id string, meta interface{}) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return nil, failed, err + } + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(id) + + assignment, response, err := iamAccessGroupsClient.GetAssignment(getAssignmentOptions) + + if err != nil { + if response != nil && response.StatusCode == 404 { + return assignment, complete, nil + } + + return nil, failed, fmt.Errorf("[ERROR] The assignment %s failed to delete or deletion was not completed within specific timeout period: %s\n%s", id, err, response) + } else { + log.Printf("Assignment removal still in progress\n") + } + return assignment, InProgress, nil + } +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment_test.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment_test.go new file mode 100644 index 0000000000..9fcfc75483 --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_assignment_test.go @@ -0,0 +1,231 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup_test + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +var target string = os.Getenv("IAM_ACCESS_GROUP_ASSIGNMENT_TARGET_ACCOUNT") + +func TestAccIBMIAMAccessGroupTemplateAssignmentBasic(t *testing.T) { + var conf iamaccessgroupsv2.TemplateAssignmentVerboseResponse + var versionConf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateAssignmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateAssignmentConfigBasic(name, agName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template.template", versionConf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + ), + }, + { + Config: testAccCheckIBMIAMAccessGroupTemplateAssignmentConfigUpdateCommit(name, agName, target), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateAssignmentExists("ibm_iam_access_group_template_assignment.assignment", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_assignment.assignment", "target", target), + ), + }, + }, + }) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentConfigBasic(name string, agName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + } + `, name, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentVersionUpdate(name string, agName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + } + + resource "ibm_iam_access_group_template_version" "template" { + template_id = ibm_iam_access_group_template.template.template_id + name = ibm_iam_access_group_template.template.name + description = "Test Terraform Description" + group { + name = "Test Terraform Access Group Name" + assertions { + action_controls { + add = false + remove = true + update = true + } + } + } + } + + `, name, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentConfigVersionUpdateCommit(name string, agName string, target string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + committed = true + } + + resource "ibm_iam_access_group_template_version" "template" { + template_id = ibm_iam_access_group_template.template.template_id + name = ibm_iam_access_group_template.template.name + description = "Test Terraform Description" + group { + name = "Test Terraform Access Group Name" + assertions { + action_controls { + add = true + remove = true + update = true + } + } + } + committed = true + } + + resource ibm_iam_access_group_template_assignment "assignment" { + template_id = ibm_iam_access_group_template_version.template.template_id + template_version = ibm_iam_access_group_template_version.template.version + target_type = "AccountGroup" + target = "%s" + } + `, name, agName, target) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentUpdate(agName string, target string, name string) string { + return fmt.Sprintf(` + resource ibm_iam_access_group_template_assignment "assignment" { + template_id = ibm_iam_access_group_template.template.template_id + template_version = ibm_iam_access_group_template.template.version + target_type = "AccountGroup" + target = "%s" + } + + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + committed = true + } + + resource "ibm_iam_access_group_template_version" "template" { + template_id = ibm_iam_access_group_template.template.template_id + name = ibm_iam_access_group_template.template.name + description = "Test Terraform Description" + group { + name = "Test Terraform Access Group Name" + assertions { + action_controls { + add = true + remove = true + update = true + } + } + } + committed = true + } + `, target, name, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentConfigUpdateCommit(name string, agName string, target string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + committed = true + } + + resource ibm_iam_access_group_template_assignment "assignment" { + template_id = ibm_iam_access_group_template.template.template_id + template_version = ibm_iam_access_group_template.template.version + target_type = "AccountGroup" + target = "%s" + } + `, name, agName, target) +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentExists(n string, obj iamaccessgroupsv2.TemplateAssignmentVerboseResponse) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + iamAccessGroupsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return err + } + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(rs.Primary.ID) + + templateAssignmentResponse, _, err := iamAccessGroupsClient.GetAssignment(getAssignmentOptions) + if err != nil { + return err + } + + obj = *templateAssignmentResponse + return nil + } +} + +func testAccCheckIBMIAMAccessGroupTemplateAssignmentDestroy(s *terraform.State) error { + iamAccessGroupsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_iam_access_group_template_assignment" { + continue + } + + getAssignmentOptions := &iamaccessgroupsv2.GetAssignmentOptions{} + + getAssignmentOptions.SetAssignmentID(rs.Primary.ID) + + // Try to find the key + _, response, err := iamAccessGroupsClient.GetAssignment(getAssignmentOptions) + + if err == nil { + return fmt.Errorf("iam_access_group_template_assignment still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for iam_access_group_template_assignment (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_test.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_test.go new file mode 100644 index 0000000000..cc037fd030 --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_test.go @@ -0,0 +1,176 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +var ( + agName string = fmt.Sprintf("TerraformTemplateTest%d", acctest.RandIntRange(10, 100)) +) + +func TestAccIBMIAMAccessGroupTemplateBasic(t *testing.T) { + var conf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateVersionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateConfigBasic(name, agName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + ), + }, + }, + }) +} + +func TestAccIBMIAMAccessGroupTemplateBasicWithCommit(t *testing.T) { + var conf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateVersionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateConfigBasic(name, agName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + ), + }, + { + Config: testAccCheckIBMIAMAccessGroupTemplateConfigBasicWithCommit(name, agName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "committed", "true"), + ), + }, + }, + }) +} + +func TestAccIBMIAMAccessGroupTemplateBasicWithAssertionAndActionControl(t *testing.T) { + var conf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + description := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateConfig(name, description, agName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "description", description), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + ), + }, + { + ResourceName: "ibm_iam_access_group_template.template", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckIBMIAMAccessGroupTemplateConfigBasic(name string, agName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + } + `, name, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateConfigBasicWithCommit(name string, agName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + group { + name = "%s" + } + committed = true + } + `, name, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateConfig(name string, description string, agName string) string { + return fmt.Sprintf(` + + resource "ibm_iam_access_group_template" "template" { + name = "%s" + description = "%s" + group { + name = "%s" + description = "description" + assertions { + action_controls { + add = true + remove = true + update = true + } + } + action_controls { + access { + add = true + } + } + } + } + `, name, description, agName) +} + +func testAccCheckIBMIAMAccessGroupTemplateDestroy(s *terraform.State) error { + iamAccessGroupsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_iam_access_group_template" { + continue + } + + getLatestTemplateVersionOptions := &iamaccessgroupsv2.GetLatestTemplateVersionOptions{} + + getLatestTemplateVersionOptions.SetTemplateID(rs.Primary.ID) + + // Try to find the key + _, response, err := iamAccessGroupsClient.GetLatestTemplateVersion(getLatestTemplateVersionOptions) + + if err == nil { + return fmt.Errorf("iam_access_group_template still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for iam_access_group_template (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version.go new file mode 100644 index 0000000000..bdcfd9c1c1 --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version.go @@ -0,0 +1,993 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +func ResourceIBMIAMAccessGroupTemplateVersion() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIAMAccessGroupTemplateVersionCreate, + ReadContext: resourceIBMIAMAccessGroupTemplateVersionRead, + UpdateContext: resourceIBMIAMAccessGroupTemplateVersionUpdate, + DeleteContext: resourceIBMIAMAccessGroupTemplateVersionDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_version", "template_id"), + Description: "ID of the template that you want to create a new version of.", + }, + "transaction_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_version", "transaction_id"), + Description: "An optional transaction id for the request.", + }, + "name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_version", "name"), + Description: "The name of the access group template.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_iam_access_group_template_version", "description"), + Description: "The description of the access group template.", + }, + "group": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + ForceNew: true, + Description: "Access Group Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Access group description. This is shown in child accounts.", + }, + "members": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "users": { + Type: schema.TypeList, + Optional: true, + Description: "Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "services": { + Type: schema.TypeList, + Optional: true, + Description: "Array of service IDs to add to the template.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them.", + }, + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing enterprise-managed members from an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "assertions": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Assertions Input Component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rules": { + Type: schema.TypeList, + Optional: true, + Description: "Dynamic rules to automatically add federated users to access groups based on specific identity attributes.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Dynamic rule name.", + }, + "expiration": { + Type: schema.TypeInt, + Optional: true, + Description: "Session duration in hours. Access group membership is revoked after this time period expires. Users must log back in to refresh their access group membership.", + }, + "realm_name": { + Type: schema.TypeString, + Optional: true, + Description: "The identity provider (IdP) URL.", + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Description: "Conditions of membership. You can think of this as a key:value pair.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "claim": { + Type: schema.TypeString, + Optional: true, + Description: "The key in the key:value pair.", + }, + "operator": { + Type: schema.TypeString, + Optional: true, + Description: "Compares the claim and the value.", + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: "The value in the key:value pair.", + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing this enterprise-managed dynamic rule.", + }, + "update": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for updating this enterprise-managed dynamic rule.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it.", + }, + "remove": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + "update": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group.", + }, + }, + }, + }, + }, + }, + }, + "action_controls": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Access group action controls component.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "add": { + Type: schema.TypeBool, + Optional: true, + Description: "Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "policy_template_references": { + Type: schema.TypeList, + Optional: true, + Description: "References to policy templates assigned to the access group template.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + Description: "Policy template ID.", + }, + "version": { + Type: schema.TypeString, + Optional: true, + Description: "Policy template version.", + }, + }, + }, + }, + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the account to which the access group template is assigned.", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "The version of the access group template.", + }, + "committed": { + Type: schema.TypeBool, + Computed: true, + Optional: true, + Description: "A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts.", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL of the access group template resource.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the access group template was created.", + }, + "created_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who created the access group template.", + }, + "last_modified_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time when the access group template was last modified.", + }, + "last_modified_by_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the user who last modified the access group template.", + }, + }, + } +} + +func ResourceIBMIAMAccessGroupTemplateVersionValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "template_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 100, + }, + validate.ValidateSchema{ + Identifier: "transaction_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9_-]+$`, + MinValueLength: 1, + MaxValueLength: 50, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\-\s]+$`, + MinValueLength: 1, + MaxValueLength: 100, + }, + validate.ValidateSchema{ + Identifier: "description", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\-\s]+$`, + MinValueLength: 0, + MaxValueLength: 250, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_iam_access_group_template_version", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIAMAccessGroupTemplateVersionCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + createTemplateVersionOptions := &iamaccessgroupsv2.CreateTemplateVersionOptions{} + + createTemplateVersionOptions.SetTemplateID(d.Get("template_id").(string)) + if _, ok := d.GetOk("name"); ok { + createTemplateVersionOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("description"); ok { + createTemplateVersionOptions.SetDescription(d.Get("description").(string)) + } + if _, ok := d.GetOk("group"); ok { + groupModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToAccessGroupRequest(d.Get("group.0").(map[string]interface{})) + if err != nil { + return diag.FromErr(err) + } + createTemplateVersionOptions.SetGroup(groupModel) + } + if _, ok := d.GetOk("policy_template_references"); ok { + var policyTemplateReferences []iamaccessgroupsv2.PolicyTemplates + for _, v := range d.Get("policy_template_references").([]interface{}) { + value := v.(map[string]interface{}) + policyTemplateReferencesItem, err := resourceIBMIAMAccessGroupTemplateVersionMapToPolicyTemplates(value) + if err != nil { + return diag.FromErr(err) + } + policyTemplateReferences = append(policyTemplateReferences, *policyTemplateReferencesItem) + } + createTemplateVersionOptions.SetPolicyTemplateReferences(policyTemplateReferences) + } + if _, ok := d.GetOk("transaction_id"); ok { + createTemplateVersionOptions.SetTransactionID(d.Get("transaction_id").(string)) + } + + templateVersionResponse, response, err := iamAccessGroupsClient.CreateTemplateVersionWithContext(context, createTemplateVersionOptions) + if err != nil { + log.Printf("[DEBUG] CreateTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("CreateTemplateVersionWithContext failed %s\n%s", err, response)) + } + + d.SetId(fmt.Sprintf("%s/%s", *templateVersionResponse.ID, *templateVersionResponse.Version)) + + return resourceIBMIAMAccessGroupTemplateVersionRead(context, d, meta) +} + +func resourceIBMIAMAccessGroupTemplateVersionRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + getTemplateVersionOptions := &iamaccessgroupsv2.GetTemplateVersionOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + getTemplateVersionOptions.SetTemplateID(parts[0]) + getTemplateVersionOptions.SetVersionNum(parts[1]) + + templateVersionResponse, response, err := iamAccessGroupsClient.GetTemplateVersionWithContext(context, getTemplateVersionOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + log.Printf("[DEBUG] GetTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("GetTemplateVersionWithContext failed %s\n%s", err, response)) + } + + if !core.IsNil(templateVersionResponse.Name) { + if err = d.Set("name", templateVersionResponse.Name); err != nil { + return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + } + } + if !core.IsNil(templateVersionResponse.Description) { + if err = d.Set("description", templateVersionResponse.Description); err != nil { + return diag.FromErr(fmt.Errorf("Error setting description: %s", err)) + } + } + if !core.IsNil(templateVersionResponse.Group) { + groupMap, err := resourceIBMIAMAccessGroupTemplateVersionAccessGroupResponseToMap(templateVersionResponse.Group) + if err != nil { + return diag.FromErr(err) + } + if err = d.Set("group", []map[string]interface{}{groupMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting group: %s", err)) + } + } + if !core.IsNil(templateVersionResponse.PolicyTemplateReferences) { + policyTemplateReferences := []map[string]interface{}{} + for _, policyTemplateReferencesItem := range templateVersionResponse.PolicyTemplateReferences { + policyTemplateReferencesItemMap, err := resourceIBMIAMAccessGroupTemplateVersionPolicyTemplatesToMap(&policyTemplateReferencesItem) + if err != nil { + return diag.FromErr(err) + } + policyTemplateReferences = append(policyTemplateReferences, policyTemplateReferencesItemMap) + } + if err = d.Set("policy_template_references", policyTemplateReferences); err != nil { + return diag.FromErr(fmt.Errorf("Error setting policy_template_references: %s", err)) + } + } + if err = d.Set("account_id", templateVersionResponse.AccountID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting account_id: %s", err)) + } + if err = d.Set("version", templateVersionResponse.Version); err != nil { + return diag.FromErr(fmt.Errorf("Error setting version: %s", err)) + } + if err = d.Set("committed", templateVersionResponse.Committed); err != nil { + return diag.FromErr(fmt.Errorf("Error setting committed: %s", err)) + } + if err = d.Set("href", templateVersionResponse.Href); err != nil { + return diag.FromErr(fmt.Errorf("Error setting href: %s", err)) + } + if err = d.Set("created_at", flex.DateTimeToString(templateVersionResponse.CreatedAt)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting created_at: %s", err)) + } + if err = d.Set("created_by_id", templateVersionResponse.CreatedByID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting created_by_id: %s", err)) + } + if err = d.Set("last_modified_at", flex.DateTimeToString(templateVersionResponse.LastModifiedAt)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting last_modified_at: %s", err)) + } + if err = d.Set("last_modified_by_id", templateVersionResponse.LastModifiedByID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting last_modified_by_id: %s", err)) + } + if err = d.Set("template_id", templateVersionResponse.ID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting template_version__id: %s", err)) + } + + return nil +} + +func resourceIBMIAMAccessGroupTemplateVersionUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + updateTemplateVersionOptions := &iamaccessgroupsv2.UpdateTemplateVersionOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + id := parts[0] + version := parts[1] + updateTemplateVersionOptions.SetTemplateID(id) + updateTemplateVersionOptions.SetVersionNum(version) + + getTemplateVersionOptions := &iamaccessgroupsv2.GetTemplateVersionOptions{} + + getTemplateVersionOptions.SetTemplateID(id) + getTemplateVersionOptions.SetVersionNum(version) + + templateVersionResponse, response, err := iamAccessGroupsClient.GetTemplateVersionWithContext(context, getTemplateVersionOptions) + if err != nil || templateVersionResponse == nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + log.Printf("[DEBUG] GetTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("GetTemplateVersionWithContext failed %s\n%s", err, response)) + } + + updateTemplateVersionOptions.SetIfMatch(response.Headers.Get("ETag")) + + if _, ok := d.GetOk("transaction_id"); ok { + updateTemplateVersionOptions.SetTransactionID(d.Get("transaction_id").(string)) + } + if _, ok := d.GetOk("name"); ok { + updateTemplateVersionOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("description"); ok { + updateTemplateVersionOptions.SetDescription(d.Get("description").(string)) + } + + if _, ok := d.GetOk("group"); ok { + + group, err := resourceIBMIAMAccessGroupTemplateVersionMapToAccessGroupRequest(d.Get("group.0").(map[string]interface{})) + if err != nil { + return diag.FromErr(err) + } + + if err != nil { + return diag.FromErr(err) + } + updateTemplateVersionOptions.SetGroup(group) + } + + if _, ok := d.GetOk("policy_template_references"); ok { + var policyTemplateReferences []iamaccessgroupsv2.PolicyTemplates + for _, v := range d.Get("policy_template_references").([]interface{}) { + value := v.(map[string]interface{}) + policyTemplateReferencesItem, err := resourceIBMIAMAccessGroupTemplateVersionMapToPolicyTemplates(value) + if err != nil { + return diag.FromErr(err) + } + policyTemplateReferences = append(policyTemplateReferences, *policyTemplateReferencesItem) + } + updateTemplateVersionOptions.SetPolicyTemplateReferences(policyTemplateReferences) + } + + _, response, err = iamAccessGroupsClient.UpdateTemplateVersionWithContext(context, updateTemplateVersionOptions) + if err != nil { + log.Printf("[DEBUG] UpdateTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("UpdateTemplateVersionWithContext failed %s\n%s", err, response)) + } + + // Test committed + if d.HasChange("committed") { + commitTemplateOptions := &iamaccessgroupsv2.CommitTemplateOptions{} + commitTemplateOptions.SetTemplateID(id) + commitTemplateOptions.SetVersionNum(version) + commitTemplateOptions.SetIfMatch(response.Headers.Get("ETag")) + if d.Get("committed").(bool) { + response, err = iamAccessGroupsClient.CommitTemplateWithContext(context, commitTemplateOptions) + if err != nil { + log.Printf("[DEBUG] UpdateTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("UpdateTemplateVersionWithContext failed %s\n%s", err, response)) + } + } + } + + return resourceIBMIAMAccessGroupTemplateVersionRead(context, d, meta) +} + +func resourceIBMIAMAccessGroupTemplateVersionDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + iamAccessGroupsClient, err := meta.(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return diag.FromErr(err) + } + + deleteTemplateVersionOptions := &iamaccessgroupsv2.DeleteTemplateVersionOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + deleteTemplateVersionOptions.SetTemplateID(parts[0]) + deleteTemplateVersionOptions.SetVersionNum(parts[1]) + + response, err := iamAccessGroupsClient.DeleteTemplateVersionWithContext(context, deleteTemplateVersionOptions) + if err != nil { + log.Printf("[DEBUG] DeleteTemplateVersionWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("DeleteTemplateVersionWithContext failed %s\n%s", err, response)) + } + + d.SetId("") + + return nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToAccessGroupRequest(modelMap map[string]interface{}) (*iamaccessgroupsv2.AccessGroupRequest, error) { + model := &iamaccessgroupsv2.AccessGroupRequest{} + model.Name = core.StringPtr(modelMap["name"].(string)) + if modelMap["description"] != nil && modelMap["description"].(string) != "" { + model.Description = core.StringPtr(modelMap["description"].(string)) + } + if modelMap["members"] != nil && len(modelMap["members"].([]interface{})) > 0 { + MembersModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToMembers(modelMap["members"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Members = MembersModel + } + if modelMap["assertions"] != nil && len(modelMap["assertions"].([]interface{})) > 0 { + AssertionsModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToAssertions(modelMap["assertions"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Assertions = AssertionsModel + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToGroupActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToMembers(modelMap map[string]interface{}) (*iamaccessgroupsv2.Members, error) { + model := &iamaccessgroupsv2.Members{} + if modelMap["users"] != nil { + users := []string{} + for _, usersItem := range modelMap["users"].([]interface{}) { + users = append(users, usersItem.(string)) + } + model.Users = users + } + if modelMap["services"] != nil { + services := []string{} + for _, servicesItem := range modelMap["services"].([]interface{}) { + services = append(services, servicesItem.(string)) + } + model.Services = services + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToMembersActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToMembersActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.MembersActionControls, error) { + model := &iamaccessgroupsv2.MembersActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToAssertions(modelMap map[string]interface{}) (*iamaccessgroupsv2.Assertions, error) { + model := &iamaccessgroupsv2.Assertions{} + if modelMap["rules"] != nil { + rules := []iamaccessgroupsv2.AssertionsRule{} + for _, rulesItem := range modelMap["rules"].([]interface{}) { + rulesItemModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToAssertionsRule(rulesItem.(map[string]interface{})) + if err != nil { + return model, err + } + rules = append(rules, *rulesItemModel) + } + model.Rules = rules + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToAssertionsActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToAssertionsRule(modelMap map[string]interface{}) (*iamaccessgroupsv2.AssertionsRule, error) { + model := &iamaccessgroupsv2.AssertionsRule{} + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["expiration"] != nil { + model.Expiration = core.Int64Ptr(int64(modelMap["expiration"].(int))) + } + if modelMap["realm_name"] != nil && modelMap["realm_name"].(string) != "" { + model.RealmName = core.StringPtr(modelMap["realm_name"].(string)) + } + if modelMap["conditions"] != nil { + conditions := []iamaccessgroupsv2.Conditions{} + for _, conditionsItem := range modelMap["conditions"].([]interface{}) { + conditionsItemModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToConditions(conditionsItem.(map[string]interface{})) + if err != nil { + return model, err + } + conditions = append(conditions, *conditionsItemModel) + } + model.Conditions = conditions + } + if modelMap["action_controls"] != nil && len(modelMap["action_controls"].([]interface{})) > 0 { + ActionControlsModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToRuleActionControls(modelMap["action_controls"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ActionControls = ActionControlsModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToConditions(modelMap map[string]interface{}) (*iamaccessgroupsv2.Conditions, error) { + model := &iamaccessgroupsv2.Conditions{} + if modelMap["claim"] != nil && modelMap["claim"].(string) != "" { + model.Claim = core.StringPtr(modelMap["claim"].(string)) + } + if modelMap["operator"] != nil && modelMap["operator"].(string) != "" { + model.Operator = core.StringPtr(modelMap["operator"].(string)) + } + if modelMap["value"] != nil && modelMap["value"].(string) != "" { + model.Value = core.StringPtr(modelMap["value"].(string)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToRuleActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.RuleActionControls, error) { + model := &iamaccessgroupsv2.RuleActionControls{} + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + if modelMap["update"] != nil { + model.Update = core.BoolPtr(modelMap["update"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToAssertionsActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.AssertionsActionControls, error) { + model := &iamaccessgroupsv2.AssertionsActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + if modelMap["remove"] != nil { + model.Remove = core.BoolPtr(modelMap["remove"].(bool)) + } + if modelMap["update"] != nil { + model.Update = core.BoolPtr(modelMap["update"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToGroupActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.GroupActionControls, error) { + model := &iamaccessgroupsv2.GroupActionControls{} + if modelMap["access"] != nil && len(modelMap["access"].([]interface{})) > 0 { + AccessModel, err := resourceIBMIAMAccessGroupTemplateVersionMapToAccessActionControls(modelMap["access"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Access = AccessModel + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToAccessActionControls(modelMap map[string]interface{}) (*iamaccessgroupsv2.AccessActionControls, error) { + model := &iamaccessgroupsv2.AccessActionControls{} + if modelMap["add"] != nil { + model.Add = core.BoolPtr(modelMap["add"].(bool)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMapToPolicyTemplates(modelMap map[string]interface{}) (*iamaccessgroupsv2.PolicyTemplates, error) { + model := &iamaccessgroupsv2.PolicyTemplates{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["version"] != nil && modelMap["version"].(string) != "" { + model.Version = core.StringPtr(modelMap["version"].(string)) + } + return model, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionAccessGroupResponseToMap(model *iamaccessgroupsv2.AccessGroupResponse) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["name"] = model.Name + if model.Description != nil { + modelMap["description"] = model.Description + } + if model.Members != nil { + membersMap, err := resourceIBMIAMAccessGroupTemplateVersionMembersToMap(model.Members) + if err != nil { + return modelMap, err + } + modelMap["members"] = []map[string]interface{}{membersMap} + } + if model.Assertions != nil { + assertionsMap, err := resourceIBMIAMAccessGroupTemplateVersionAssertionsToMap(model.Assertions) + if err != nil { + return modelMap, err + } + modelMap["assertions"] = []map[string]interface{}{assertionsMap} + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateVersionGroupActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMembersToMap(model *iamaccessgroupsv2.Members) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Users != nil { + modelMap["users"] = model.Users + } + if model.Services != nil { + modelMap["services"] = model.Services + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateVersionMembersActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionMembersActionControlsToMap(model *iamaccessgroupsv2.MembersActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionAssertionsToMap(model *iamaccessgroupsv2.Assertions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Rules != nil { + rules := []map[string]interface{}{} + for _, rulesItem := range model.Rules { + rulesItemMap, err := resourceIBMIAMAccessGroupTemplateVersionAssertionsRuleToMap(&rulesItem) + if err != nil { + return modelMap, err + } + rules = append(rules, rulesItemMap) + } + modelMap["rules"] = rules + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateVersionAssertionsActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionAssertionsRuleToMap(model *iamaccessgroupsv2.AssertionsRule) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Name != nil { + modelMap["name"] = model.Name + } + if model.Expiration != nil { + modelMap["expiration"] = flex.IntValue(model.Expiration) + } + if model.RealmName != nil { + modelMap["realm_name"] = model.RealmName + } + if model.Conditions != nil { + conditions := []map[string]interface{}{} + for _, conditionsItem := range model.Conditions { + conditionsItemMap, err := resourceIBMIAMAccessGroupTemplateVersionConditionsToMap(&conditionsItem) + if err != nil { + return modelMap, err + } + conditions = append(conditions, conditionsItemMap) + } + modelMap["conditions"] = conditions + } + if model.ActionControls != nil { + actionControlsMap, err := resourceIBMIAMAccessGroupTemplateVersionRuleActionControlsToMap(model.ActionControls) + if err != nil { + return modelMap, err + } + modelMap["action_controls"] = []map[string]interface{}{actionControlsMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionConditionsToMap(model *iamaccessgroupsv2.Conditions) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Claim != nil { + modelMap["claim"] = model.Claim + } + if model.Operator != nil { + modelMap["operator"] = model.Operator + } + if model.Value != nil { + modelMap["value"] = model.Value + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionRuleActionControlsToMap(model *iamaccessgroupsv2.RuleActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionAssertionsActionControlsToMap(model *iamaccessgroupsv2.AssertionsActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + if model.Remove != nil { + modelMap["remove"] = model.Remove + } + if model.Update != nil { + modelMap["update"] = model.Update + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionGroupActionControlsToMap(model *iamaccessgroupsv2.GroupActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Access != nil { + accessMap, err := resourceIBMIAMAccessGroupTemplateVersionAccessActionControlsToMap(model.Access) + if err != nil { + return modelMap, err + } + modelMap["access"] = []map[string]interface{}{accessMap} + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionAccessActionControlsToMap(model *iamaccessgroupsv2.AccessActionControls) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Add != nil { + modelMap["add"] = model.Add + } + return modelMap, nil +} + +func resourceIBMIAMAccessGroupTemplateVersionPolicyTemplatesToMap(model *iamaccessgroupsv2.PolicyTemplates) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.ID != nil { + modelMap["id"] = model.ID + } + if model.Version != nil { + modelMap["version"] = model.Version + } + return modelMap, nil +} diff --git a/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version_test.go b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version_test.go new file mode 100644 index 0000000000..0b1f82b66a --- /dev/null +++ b/ibm/service/iamaccessgroup/resource_ibm_iam_access_group_template_version_test.go @@ -0,0 +1,201 @@ +// Copyright IBM Corp. 2023 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package iamaccessgroup_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2" +) + +var versionAGName string = fmt.Sprintf("TerraformTemplateTest%d", acctest.RandIntRange(10, 100)) + +func TestAccIBMIAMAccessGroupTemplateVersion(t *testing.T) { + var conf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateVersionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateVersionConfigBasic(name, agName, versionAGName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template_version.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "group.0.name", versionAGName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + ), + }, + }, + }) +} + +func TestAccIBMIAMAccessGroupTemplateVersionUpdateWithCommit(t *testing.T) { + var conf iamaccessgroupsv2.TemplateVersionResponse + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIAMAccessGroupTemplateVersionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMIAMAccessGroupTemplateVersionConfigBasic(name, agName, versionAGName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template_version.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "group.0.name", versionAGName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + ), + }, + { + Config: testAccCheckIBMIAMAccessGroupTemplateVersionUpdateWithCommit(name, agName, versionAGName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIAMAccessGroupTemplateVersionExists("ibm_iam_access_group_template_version.template", conf), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "group.0.name", agName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "group.0.name", versionAGName), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template.template", "name", name), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "committed", "true"), + resource.TestCheckResourceAttr("ibm_iam_access_group_template_version.template", "description", "Testing3"), + ), + }, + }, + }) +} + +func testAccCheckIBMIAMAccessGroupTemplateVersionConfigBasic(name string, agName string, versionAGName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + description = "Test Terraform Description" + group { + name = "%s" + } + } + + resource "ibm_iam_access_group_template_version" "template" { + template_id = ibm_iam_access_group_template.template.template_id + name = ibm_iam_access_group_template.template.name + description = "Testing4" + group { + name = "%s" + assertions { + action_controls { + add = false + remove = true + update = true + } + } + } + } + `, name, agName, versionAGName) +} + +func testAccCheckIBMIAMAccessGroupTemplateVersionUpdateWithCommit(name string, agName string, versionAGName string) string { + return fmt.Sprintf(` + resource "ibm_iam_access_group_template" "template" { + name = "%s" + description = "Test Terraform Description" + group { + name = "%s" + } + } + + resource "ibm_iam_access_group_template_version" "template" { + template_id = ibm_iam_access_group_template.template.template_id + name = ibm_iam_access_group_template.template.name + description = "Testing3" + group { + name = "%s" + assertions { + action_controls { + add = true + remove = true + update = true + } + } + } + committed = true + } + `, name, agName, versionAGName) +} + +func testAccCheckIBMIAMAccessGroupTemplateVersionExists(n string, obj iamaccessgroupsv2.TemplateVersionResponse) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + iamAccessGroupsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return err + } + + getTemplateVersionOptions := &iamaccessgroupsv2.GetTemplateVersionOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getTemplateVersionOptions.SetTemplateID(parts[0]) + getTemplateVersionOptions.SetVersionNum(parts[1]) + + templateVersionResponse, _, err := iamAccessGroupsClient.GetTemplateVersion(getTemplateVersionOptions) + if err != nil { + return err + } + + obj = *templateVersionResponse + return nil + } +} + +func testAccCheckIBMIAMAccessGroupTemplateVersionDestroy(s *terraform.State) error { + iamAccessGroupsClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMAccessGroupsV2() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_iam_access_group_template_version" { + continue + } + + getTemplateVersionOptions := &iamaccessgroupsv2.GetTemplateVersionOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getTemplateVersionOptions.SetTemplateID(parts[0]) + getTemplateVersionOptions.SetVersionNum(parts[1]) + + // Try to find the key + _, response, err := iamAccessGroupsClient.GetTemplateVersion(getTemplateVersionOptions) + + if err == nil { + return fmt.Errorf("iam_access_group_template_version still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for iam_access_group_template_version (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/website/docs/d/iam_access_group_template.html.markdown b/website/docs/d/iam_access_group_template.html.markdown new file mode 100644 index 0000000000..b1b6b8c7b6 --- /dev/null +++ b/website/docs/d/iam_access_group_template.html.markdown @@ -0,0 +1,82 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template" +description: |- + Get information about iam_access_group_template +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template + +Provides a read-only data source to retrieve information about an iam_access_group_template. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_iam_access_group_template" "iam_access_group_template" { + verbose = true +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `transaction_id` - (Optional, String) An optional transaction id for the request. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. +* `verbose` - (Optional, Boolean) If `verbose=true`, IAM resource details are returned. If performance is a concern, leave the `verbose` parameter off so that details are not retrieved. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the iam_access_group_template. +* `name` - (String) The name of the access group template. +* `description` - (String) The description of the access group template. +* `account_id` - (String) Enterprise account id. +* `version` - (String) The version of the access group template. +* `committed` - (Boolean) A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts. +* `group` - (List) Access Group Component. +Nested schema for **group**: + * `name` - (String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * `description` - (String) Access group description. This is shown in child accounts. + * `members` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `users` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * `services` - (List) Array of service IDs to add to the template. + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `assertions` - (List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + Nested schema for **rules**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (List) Conditions of membership. You can think of this as a key:value pair. + Nested schema for **conditions**: + * `claim` - (String) The key in the key:value pair. + * `operator` - (String) Compares the claim and the value. + * `value` - (String) The value in the key:value pair. + * `action_controls` - (List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. +* `policy_template_references` - (List) References to policy templates assigned to the access group template. +Nested schema for **policy_template_references**: + * `id` - (String) Policy template ID. + * `version` - (String) Policy template version. +* `href` - (String) The URL of the access group template resource. +* `created_at` - (String) The date and time when the access group template was created. +* `created_by_id` - (String) The ID of the user who created the access group template. +* `last_modified_at` - (String) The date and time when the access group template was last modified. +* `last_modified_by_id` - (String) The ID of the user who last modified the access group template. diff --git a/website/docs/d/iam_access_group_template_assignment.html.markdown b/website/docs/d/iam_access_group_template_assignment.html.markdown new file mode 100644 index 0000000000..a9c7727182 --- /dev/null +++ b/website/docs/d/iam_access_group_template_assignment.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template_assignment" +description: |- + Get information about iam_access_group_template_assignment +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template_assignment + +Provides a read-only data source to retrieve information about an iam_access_group_template_assignment. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_iam_access_group_template_assignment" "iam_access_group_template_assignment" { +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `status` - (Optional, String) Filter results by the assignment status. + * Constraints: Allowable values are: `accepted`, `in_progress`, `succeeded`, `failed`. +* `target` - (Optional, String) Filter results by the assignment target. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. +* `template_id` - (Optional, String) Filter results by Template Id. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. +* `template_version` - (Optional, String) Filter results by Template Version. + * Constraints: The maximum length is `2` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9]+$/`. +* `transaction_id` - (Optional, String) An optional transaction id for the request. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the iam_access_group_template_assignment. +* `account_id` - (String) Enterprise account id. +* `template_id` - (String) The ID of the template that the assignment is based on. +* `template_version` - (String) The version of the template that the assignment is based on. +* `target` - (String) The ID of the entity that the assignment applies to. +* `target_type` - (String) The type of the entity that the assignment applies to. +* `operation` - (String) The operation that the assignment applies to (e.g. 'assign', 'update', 'remove'). +* `status` - (String) The status of the assignment (e.g. 'accepted', 'in_progress', 'succeeded', 'failed', 'superseded'). +* `href` - (String) The URL of the assignment resource. +* `created_at` - (String) The date and time when the assignment was created. +* `created_by_id` - (String) The user or system that created the assignment. +* `last_modified_at` - (String) The date and time when the assignment was last updated. +* `last_modified_by_id` - (String) The user or system that last updated the assignment. + diff --git a/website/docs/d/iam_access_group_template_versions.html.markdown b/website/docs/d/iam_access_group_template_versions.html.markdown new file mode 100644 index 0000000000..25a9254bd2 --- /dev/null +++ b/website/docs/d/iam_access_group_template_versions.html.markdown @@ -0,0 +1,81 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template_version" +description: |- + Get information about ibm_iam_access_group_template_version +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template_version + +Provides a read-only data source to retrieve information about an ibm_iam_access_group_template_version. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_iam_access_group_template_versions" "iam_access_group_template_version_instance" { + template_id = ibm_iam_access_group_template_versions.iam_access_group_template_version_instance.template_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +* `template_id` - (Required, Forces new resource, String) ID of the template that you want to list all versions of. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +* `id` - The unique identifier of the iam_access_group_template. +* `name` - (String) The name of the access group template. +* `description` - (String) The description of the access group template. +* `account_id` - (String) Enterprise account id. +* `version` - (String) The version of the access group template. +* `committed` - (Boolean) A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts. +* `group` - (List) Access Group Component. +Nested schema for **group**: + * `name` - (String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * `description` - (String) Access group description. This is shown in child accounts. + * `members` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `users` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * `services` - (List) Array of service IDs to add to the template. + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `assertions` - (List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + Nested schema for **rules**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (List) Conditions of membership. You can think of this as a key:value pair. + Nested schema for **conditions**: + * `claim` - (String) The key in the key:value pair. + * `operator` - (String) Compares the claim and the value. + * `value` - (String) The value in the key:value pair. + * `action_controls` - (List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. +* `policy_template_references` - (List) References to policy templates assigned to the access group template. +Nested schema for **policy_template_references**: + * `id` - (String) Policy template ID. + * `version` - (String) Policy template version. +* `href` - (String) The URL of the access group template resource. +* `created_at` - (String) The date and time when the access group template was created. +* `created_by_id` - (String) The ID of the user who created the access group template. +* `last_modified_at` - (String) The date and time when the access group template was last modified. +* `last_modified_by_id` - (String) The ID of the user who last modified the access group template. diff --git a/website/docs/r/iam_access_group_template.html.markdown b/website/docs/r/iam_access_group_template.html.markdown new file mode 100644 index 0000000000..ec3bd548c4 --- /dev/null +++ b/website/docs/r/iam_access_group_template.html.markdown @@ -0,0 +1,196 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template" +description: |- + Manages iam_access_group_template. +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template + +Create, update, and delete iam_access_group_templates with this resource. + +## Example Usage + +```hcl +resource "ibm_iam_access_group_template" "iam_access_group_template_instance" { + description = "This access group template allows admin access to all IAM platform services in the account." + group { + name = "name" + description = "description" + members { + users = [ "users" ] + services = [ "services" ] + action_controls { + add = true + remove = true + } + } + assertions { + rules { + name = "name" + expiration = 1 + realm_name = "realm_name" + conditions { + claim = "claim" + operator = "operator" + value = "value" + } + action_controls { + remove = true + update = true + } + } + action_controls { + add = true + remove = true + update = true + } + } + action_controls { + access { + add = true + } + } + } + name = "IAM Admin Group template" + policy_template_references { + id = "id" + version = "version" + } +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `name` - (Required, String) The name of the access group template. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + + **Note:** "Name" will be out of sync when anyone of the version resource updates this parameter. Please update this parameter with the latest version name +* `description` - (Optional, String) The description of the access group template. + * Constraints: The maximum length is `250` characters. The minimum length is `0` characters. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. +* `group` - (Optional, List) Access Group Component. +Nested schema for **group**: + * `action_controls` - (Optional, List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (Optional, List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Optional, Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. + * `assertions` - (Optional, List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Optional, Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Optional, Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Optional, Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (Optional, List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + * Constraints: The maximum length is `50` items. The minimum length is `0` items. + Nested schema for **rules**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Optional, Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Optional, Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (Optional, List) Conditions of membership. You can think of this as a key:value pair. + * Constraints: The maximum length is `50` items. The minimum length is `0` items. + Nested schema for **conditions**: + * `claim` - (Optional, String) The key in the key:value pair. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `operator` - (Optional, String) Compares the claim and the value. + * Constraints: The maximum length is `10` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z-]+$/`. + * `value` - (Optional, String) The value in the key:value pair. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `expiration` - (Optional, Integer) Session duration in hours. Access group membership is revoked after this time period expires. Users must log back in to refresh their access group membership. + * `name` - (Optional, String) Dynamic rule name. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `realm_name` - (Optional, String) The identity provider (IdP) URL. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `description` - (Optional, String) Access group description. This is shown in child accounts. + * Constraints: The maximum length is `250` characters. The minimum length is `0` characters. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `members` - (Optional, List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Optional, Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Optional, Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `services` - (Optional, List) Array of service IDs to add to the template. + * Constraints: The list items must match regular expression `/^[a-zA-Z0-9_-]+$/`. The maximum length is `50` items. The minimum length is `0` items. + * `users` - (Optional, List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * Constraints: The list items must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. The maximum length is `50` items. The minimum length is `0` items. + * `name` - (Required, String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. +* `policy_template_references` - (Optional, List) References to policy templates assigned to the access group template. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **policy_template_references**: + * `id` - (Optional, String) Policy template ID. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `version` - (Optional, String) Policy template version. + * Constraints: The maximum length is `2` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9]+$/`. +* `transaction_id` - (Optional, String) An optional transaction id for the request. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the iam_access_group_template. +* `name` - (String) The name of the access group template. +* `description` - (String) The description of the access group template. +* `account_id` - (String) Enterprise account id. +* `version` - (String) The version of the access group template. +* `committed` - (Boolean) A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts. +* `group` - (List) Access Group Component. +Nested schema for **group**: + * `name` - (String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * `description` - (String) Access group description. This is shown in child accounts. + * `members` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `users` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * `services` - (List) Array of service IDs to add to the template. + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `assertions` - (List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + Nested schema for **rules**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (List) Conditions of membership. You can think of this as a key:value pair. + Nested schema for **conditions**: + * `claim` - (String) The key in the key:value pair. + * `operator` - (String) Compares the claim and the value. + * `value` - (String) The value in the key:value pair. + * `action_controls` - (List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. +* `policy_template_references` - (List) References to policy templates assigned to the access group template. +Nested schema for **policy_template_references**: + * `id` - (String) Policy template ID. + * `version` - (String) Policy template version. +* `href` - (String) The URL of the access group template resource. +* `created_at` - (String) The date and time when the access group template was created. +* `created_by_id` - (String) The ID of the user who created the access group template. +* `last_modified_at` - (String) The date and time when the access group template was last modified. +* `last_modified_by_id` - (String) The ID of the user who last modified the access group template. + + +## Import + +You can import the `ibm_iam_access_group_template` resource by using `id`. The ID of the access group template. + +# Syntax +``` +$ terraform import ibm_iam_access_group_template.iam_access_group_template_instance / +``` diff --git a/website/docs/r/iam_access_group_template_assignment.html.markdown b/website/docs/r/iam_access_group_template_assignment.html.markdown new file mode 100644 index 0000000000..d0ee5650b4 --- /dev/null +++ b/website/docs/r/iam_access_group_template_assignment.html.markdown @@ -0,0 +1,62 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template_assignment" +description: |- + Manages iam_access_group_template_assignment. +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template_assignment + +Create, update, and delete iam_access_group_template_assignments with this resource. + +## Example Usage + +```hcl +resource "ibm_iam_access_group_template_assignment" "iam_access_group_template_assignment_instance" { + target = "0a45594d0f-123" + target_type = "AccountGroup" + template_id = "AccessGroupTemplateId-4be4" + template_version = "1" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `target` - (Required, String) The ID of the entity that the assignment applies to. +* `target_type` - (Required, String) The type of the entity that the assignment applies to. + * Constraints: Allowable values are: `Account`, `AccountGroup`. +* `template_id` - (Required, String) The ID of the template that the assignment is based on. +* `template_version` - (Required, String) The version of the template that the assignment is based on. +* `transaction_id` - (Optional, String) An optional transaction id for the request. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the iam_access_group_template_assignment. +* `account_id` - (String) Enterprise account id. +* `template_id` - (String) The ID of the template that the assignment is based on. +* `template_version` - (String) The version of the template that the assignment is based on. +* `target` - (String) The ID of the entity that the assignment applies to. +* `target_type` - (String) The type of the entity that the assignment applies to. +* `operation` - (String) The operation that the assignment applies to (e.g. 'assign', 'update', 'remove'). +* `status` - (String) The status of the assignment (e.g. 'accepted', 'in_progress', 'succeeded', 'failed', 'superseded'). +* `href` - (String) The URL of the assignment resource. +* `created_at` - (String) The date and time when the assignment was created. +* `created_by_id` - (String) The user or system that created the assignment. +* `last_modified_at` - (String) The date and time when the assignment was last updated. +* `last_modified_by_id` - (String) The user or system that last updated the assignment. +* `etag` - ETag identifier for iam_access_group_template_assignment. + +## Import + +You can import the `ibm_iam_access_group_template_assignment` resource by using `id`. The ID of the assignment. + +# Syntax +``` +$ terraform import ibm_iam_access_group_template_assignment.iam_access_group_template_assignment +``` diff --git a/website/docs/r/iam_access_group_template_version.html.markdown b/website/docs/r/iam_access_group_template_version.html.markdown new file mode 100644 index 0000000000..2111bccb63 --- /dev/null +++ b/website/docs/r/iam_access_group_template_version.html.markdown @@ -0,0 +1,204 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_iam_access_group_template_version" +description: |- + Manages iam_access_group_template_version. +subcategory: "Identity & Access Management (IAM)" +--- + +# ibm_iam_access_group_template_version + +Create, update, and delete iam_access_group_template_versions with this resource. + +## Example Usage + +```hcl +resource "ibm_iam_access_group_template_version" "iam_access_group_template_version_instance" { + description = "This access group template allows admin access to all IAM platform services in the account." + group { + name = "name" + description = "description" + members { + users = [ "users" ] + services = [ "services" ] + action_controls { + add = true + remove = true + } + } + assertions { + rules { + name = "name" + expiration = 1 + realm_name = "realm_name" + conditions { + claim = "claim" + operator = "operator" + value = "value" + } + action_controls { + remove = true + update = true + } + } + action_controls { + add = true + remove = true + update = true + } + } + action_controls { + access { + add = true + } + } + } + name = "IAM Admin Group template 2" + policy_template_references { + id = "id" + version = "version" + } + template_id = "template_id" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +* `description` - (Optional, String) The description of the access group template. + * Constraints: The maximum length is `250` characters. The minimum length is `0` characters. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. +* `group` - (Optional, List) Access Group Component. +Nested schema for **group**: + * `action_controls` - (Optional, List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (Optional, List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Optional, Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. + * `assertions` - (Optional, List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Optional, Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Optional, Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Optional, Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (Optional, List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + * Constraints: The maximum length is `50` items. The minimum length is `0` items. + Nested schema for **rules**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Optional, Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Optional, Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (Optional, List) Conditions of membership. You can think of this as a key:value pair. + * Constraints: The maximum length is `50` items. The minimum length is `0` items. + Nested schema for **conditions**: + * `claim` - (Optional, String) The key in the key:value pair. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `operator` - (Optional, String) Compares the claim and the value. + * Constraints: The maximum length is `10` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z-]+$/`. + * `value` - (Optional, String) The value in the key:value pair. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `expiration` - (Optional, Integer) Session duration in hours. Access group membership is revoked after this time period expires. Users must log back in to refresh their access group membership. + * `name` - (Optional, String) Dynamic rule name. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `realm_name` - (Optional, String) The identity provider (IdP) URL. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `description` - (Optional, String) Access group description. This is shown in child accounts. + * Constraints: The maximum length is `250` characters. The minimum length is `0` characters. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. + * `members` - (Optional, List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `action_controls` - (Optional, List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Optional, Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Optional, Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `services` - (Optional, List) Array of service IDs to add to the template. + * Constraints: The list items must match regular expression `/^[a-zA-Z0-9_-]+$/`. The maximum length is `50` items. The minimum length is `0` items. + * `users` - (Optional, List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * Constraints: The list items must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. The maximum length is `50` items. The minimum length is `0` items. + * `name` - (Required, String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. +* `name` - (Optional, String) The name of the access group template. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9!@#$%^&*()_+{}:;"'<>,.?\/|\\-\\s]+$/`. +* `policy_template_references` - (Optional, List) References to policy templates assigned to the access group template. + * Constraints: The maximum length is `100` items. The minimum length is `0` items. +Nested schema for **policy_template_references**: + * `id` - (Optional, String) Policy template ID. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + * `version` - (Optional, String) Policy template version. + * Constraints: The maximum length is `2` characters. The minimum length is `1` character. The value must match regular expression `/^[0-9]+$/`. +* `template_id` - (Required, Forces new resource, String) ID of the template that you want to create a new version of. + * Constraints: The maximum length is `100` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. +* `transaction_id` - (Optional, String) An optional transaction id for the request. + * Constraints: The maximum length is `50` characters. The minimum length is `1` character. The value must match regular expression `/^[a-zA-Z0-9_-]+$/`. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +* `id` - The unique identifier of the iam_access_group_template. +* `name` - (String) The name of the access group template. +* `description` - (String) The description of the access group template. +* `account_id` - (String) Enterprise account id. +* `version` - (String) The version of the access group template. +* `committed` - (Boolean) A boolean indicating whether the access group template is committed. You must commit a template before you can assign it to child accounts. +* `group` - (List) Access Group Component. +Nested schema for **group**: + * `name` - (String) Give the access group a unique name that doesn't conflict with other templates access group name in the given account. This is shown in child accounts. + * `description` - (String) Access group description. This is shown in child accounts. + * `members` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + Nested schema for **members**: + * `users` - (List) Array of enterprise users to add to the template. All enterprise users that you add to the template must be invited to the child accounts where the template is assigned. + * `services` - (List) Array of service IDs to add to the template. + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add and remove members from the enterprise-managed access group in their account. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding child account members to an enterprise-managed access group. If an access group administrator in a child account adds a member, they can always remove them. + * `remove` - (Boolean) Action control for removing enterprise-managed members from an enterprise-managed access group. + * `assertions` - (List) Assertions Input Component. + Nested schema for **assertions**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can add, remove, and update dynamic rules for the enterprise-managed access group in their account. The inner level RuleActionControls override these `remove` and `update` action controls. + Nested schema for **action_controls**: + * `add` - (Boolean) Action control for adding dynamic rules to an enterprise-managed access group. If an access group administrator in a child account adds a dynamic rule, they can always update or remove it. + * `remove` - (Boolean) Action control for removing enterprise-managed dynamic rules in an enterprise-managed access group. + * `update` - (Boolean) Action control for updating enterprise-managed dynamic rules in an enterprise-managed access group. + * `rules` - (List) Dynamic rules to automatically add federated users to access groups based on specific identity attributes. + Nested schema for **rules**: + * `action_controls` - (List) Control whether or not access group administrators in child accounts can update and remove this dynamic rule in the enterprise-managed access group in their account.This overrides outer level AssertionsActionControls. + Nested schema for **action_controls**: + * `remove` - (Boolean) Action control for removing this enterprise-managed dynamic rule. + * `update` - (Boolean) Action control for updating this enterprise-managed dynamic rule. + * `conditions` - (List) Conditions of membership. You can think of this as a key:value pair. + Nested schema for **conditions**: + * `claim` - (String) The key in the key:value pair. + * `operator` - (String) Compares the claim and the value. + * `value` - (String) The value in the key:value pair. + * `action_controls` - (List) Access group action controls component. + Nested schema for **action_controls**: + * `access` - (List) Control whether or not access group administrators in child accounts can add access policies to the enterprise-managed access group in their account. + Nested schema for **access**: + * `add` - (Boolean) Action control for adding access policies to an enterprise-managed access group in a child account. If an access group administrator in a child account adds a policy, they can always update or remove it. +* `policy_template_references` - (List) References to policy templates assigned to the access group template. +Nested schema for **policy_template_references**: + * `id` - (String) Policy template ID. + * `version` - (String) Policy template version. +* `href` - (String) The URL of the access group template resource. +* `created_at` - (String) The date and time when the access group template was created. +* `created_by_id` - (String) The ID of the user who created the access group template. +* `last_modified_at` - (String) The date and time when the access group template was last modified. +* `last_modified_by_id` - (String) The ID of the user who last modified the access group template. + + +## Import + +You can import the `ibm_iam_access_group_template_version` resource by using `id`. +The `id` property can be formed from `template_id`, and `version_num` in the following format: + +``` +/ +``` +* `template_id`: A string. ID of the template that you want to create a new version of. +* `version_num`: A string. version number in path. + +# Syntax +``` +$ terraform import ibm_iam_access_group_template_version.iam_access_group_template_version / +```