From 78230d9420620e766c6ac351d954c7f44d570423 Mon Sep 17 00:00:00 2001
From: Artem Lifshits <55093318+artem-lifshits@users.noreply.github.com>
Date: Thu, 31 Oct 2024 11:36:16 +0100
Subject: [PATCH] RMS: policy assignment&definition (#2701)
RMS: policy assignment&definition
Summary of the Pull Request
Policy assignment resource
Policy definition data source
PR Checklist
Refers to: #2659
Tests added/passed.
Documentation updated.
Schema updated.
Release notes added.
Acceptance Steps Performed
2024/10/30 20:32:08 [INFO] Building Swift S3 auth structure
2024/10/30 20:32:08 [INFO] Setting AWS metadata API timeout to 100ms
2024/10/30 20:32:10 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2024/10/30 20:32:10 [INFO] Swift S3 Auth provider used: "StaticProvider"
=== RUN TestAccPolicyAssignment_custom
=== PAUSE TestAccPolicyAssignment_custom
=== CONT TestAccPolicyAssignment_custom
--- PASS: TestAccPolicyAssignment_custom (439.98s)
PASS
Process finished with the exit code 0
2024/10/30 20:40:31 [INFO] Building Swift S3 auth structure
2024/10/30 20:40:31 [INFO] Setting AWS metadata API timeout to 100ms
2024/10/30 20:40:33 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2024/10/30 20:40:33 [INFO] Swift S3 Auth provider used: "StaticProvider"
=== RUN TestAccPolicyAssignment_basic
=== PAUSE TestAccPolicyAssignment_basic
=== CONT TestAccPolicyAssignment_basic
--- PASS: TestAccPolicyAssignment_basic (491.21s)
PASS
Process finished with the exit code 0
Reviewed-by: Anton Sidelnikov
---
.../data-sources/rms_policy_definitions_v1.md | 72 +++
docs/resources/rms_policy_assignment_v1.md | 173 ++++++
...ekomcloud_rms_policy_assignment_v1_test.go | 342 +++++++++++
opentelekomcloud/common/utils.go | 14 +
opentelekomcloud/provider.go | 2 +
opentelekomcloud/services/dms/common.go | 16 -
.../data_source_opentelekomcloud_flavor_v2.go | 2 +-
...ntelekomcloud_rms_policy_definitions_v1.go | 200 +++++++
...entelekomcloud_rms_policy_assignment_v1.go | 536 ++++++++++++++++++
.../notes/rms_policies-0f92edd815065b57.yaml | 6 +
10 files changed, 1346 insertions(+), 17 deletions(-)
create mode 100644 docs/data-sources/rms_policy_definitions_v1.md
create mode 100644 docs/resources/rms_policy_assignment_v1.md
create mode 100644 opentelekomcloud/acceptance/rms/resource_opentelekomcloud_rms_policy_assignment_v1_test.go
create mode 100644 opentelekomcloud/services/rms/data_opentelekomcloud_rms_policy_definitions_v1.go
create mode 100644 opentelekomcloud/services/rms/resource_opentelekomcloud_rms_policy_assignment_v1.go
create mode 100644 releasenotes/notes/rms_policies-0f92edd815065b57.yaml
diff --git a/docs/data-sources/rms_policy_definitions_v1.md b/docs/data-sources/rms_policy_definitions_v1.md
new file mode 100644
index 000000000..dcb58c19a
--- /dev/null
+++ b/docs/data-sources/rms_policy_definitions_v1.md
@@ -0,0 +1,72 @@
+---
+subcategory: "Config"
+layout: "opentelekomcloud"
+page_title: "OpenTelekomCloud: opentelekomcloud_rms_policy_definitions_v1"
+sidebar_current: "docs-opentelekomcloud-datasource-rms-policy-definitions-v1"
+description: |-
+ Manages an RMS Policy Definitions data source within OpenTelekomCloud.
+---
+
+Up-to-date reference of API arguments for RMS Policy Definitions you can get at
+[documentation portal](https://docs.otc.t-systems.com/config/api-ref/apis/compliance/querying_all_built-in_policies.html#rms-04-0501)
+
+
+# opentelekomcloud_rms_policy_definitions_v1
+
+Use this data source to query policy definition list.
+
+## Example Usage
+
+```hcl
+variable "trigger_type" {}
+
+data "opentelekomcloud_rms_policy_definitions_v1" "test" {
+ trigger_type = var.trigger_type
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `name` - (Optional, String) Specifies the name of the policy definitions used to query definition list.
+
+* `policy_type` - (Optional, String) Specifies the policy type used to query definition list.
+ The valid value is **builtin**.
+
+* `policy_rule_type` - (Optional, String) Specifies the policy rule type used to query definition list.
+
+* `trigger_type` - (Optional, String) Specifies the trigger type used to query definition list.
+ The valid values are **resource** and **period**.
+
+* `keywords` - (Optional, List) Specifies the keyword list used to query definition list.
+
+## Attribute Reference
+
+In addition to all arguments above, the following attributes are exported:
+
+* `id` - The data source ID.
+
+* `definitions` - The policy definition list.
+ The [object](#policy_definitions) structure is documented below.
+
+
+The `definitions` block supports:
+
+* `id` - The ID of the policy definition.
+
+* `name` - The name of the policy definition.
+
+* `policy_type` - The policy type of the policy definition.
+
+* `description` - The description of the policy definition.
+
+* `policy_rule_type` - The policy rule type of the policy definition.
+
+* `policy_rule` - The policy rule of the policy definition.
+
+* `trigger_type` - The trigger type of the policy definition.
+
+* `keywords` - The keyword list of the policy definition.
+
+* `parameters` - The parameter reference map of the policy definition.
diff --git a/docs/resources/rms_policy_assignment_v1.md b/docs/resources/rms_policy_assignment_v1.md
new file mode 100644
index 000000000..128dd7e13
--- /dev/null
+++ b/docs/resources/rms_policy_assignment_v1.md
@@ -0,0 +1,173 @@
+---
+subcategory: "Config"
+layout: "opentelekomcloud"
+page_title: "OpenTelekomCloud: opentelekomcloud_rms_policy_assignment_v1"
+sidebar_current: "docs-opentelekomcloud-rms-policy-assignment-v1"
+description: |-
+ Manages an RMS Policy Assignment resource within OpenTelekomCloud.
+---
+
+Up-to-date reference of API arguments for RMS Policy Assignment you can get at
+[documentation portal](https://docs.otc.t-systems.com/config/api-ref/apis/compliance/index.html)
+
+# opentelekomcloud_rms_policy_assignment_v1
+
+Using this resource to assign the policy and evaluate OpenTelekomCloud resources.
+
+## Example Usage
+
+### Assign a built-in policy to check a specified instance by a flavor
+
+```hcl
+variable "policy_assignment_name" {}
+variable "region_name" {}
+variable "ecs_instance_id" {}
+variable "compliant_flavor" {}
+
+data "opentelekomcloud_rms_policy_definitions_v1" "test" {
+ name = "allowed-ecs-flavors"
+}
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = var.policy_assignment_name
+ description = "An ECS is noncompliant if its flavor is not in the specified flavor list (filter by resource ID)."
+ policy_definition_id = try(data.opentelekomcloud_rms_policy_definitions_v1.test.definitions[0].id, "")
+ status = "Enabled"
+
+ policy_filter {
+ region = var.region_name
+ resource_provider = "ecs"
+ resource_type = "cloudservers"
+ resource_id = var.ecs_instance_id
+ }
+
+ parameters = {
+ listOfAllowedFlavors = "[\"${var.compliant_flavor}\"]"
+ }
+}
+```
+
+### Assign a custom policy
+
+```hcl
+variable "policy_assignment_name" {}
+variable "function_urn" {}
+variable "function_version" {}
+variable "rms_admin_trust_agency" {}
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = var.policy_assignment_name
+ description = "The ECS instances that do not conform to the custom function logic are considered non-compliant."
+ status = "Enabled"
+
+ custom_policy {
+ function_urn = "${var.function_urn}:${var.function_version}"
+ auth_type = "agency"
+ auth_value = {
+ agency_name = "\"${var.rms_admin_trust_agency}\""
+ }
+ }
+
+ parameters = {
+ string_example = "\"string_value\""
+ array_example = "[\"array_element\"]"
+ object_example = "{\"terraform_version\":\"1.xx.x\"}"
+ }
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `name` - (Required, String, ForceNew) Specifies the name of the policy assignment.
+ The valid length is limited from `1` to `64`.
+ Change this parameter will create a new resource.
+
+* `description` - (Optional, String) Specifies the description of the policy assignment, which contain maximum of
+ `512` characters.
+
+* `policy_definition_id` - (Optional, String) Specifies the ID of the built-in policy definition.
+ This parameter and `custom_policy` are alternative.
+
+* `period` - (Optional, String) Specifies the period of the policy assignment.
+ The valid values are as follows:
+ + **One_Hour**
+ + **Three_Hours**
+ + **Six_Hours**
+ + **Twelve_Hours**
+ + **TwentyFour_Hours**
+
+ Most one of `period` and `policy_filter` can be configured.
+
+* `policy_filter` - (Optional, List) Specifies the configuration used to filter resources.
+ The [object](#rms_policy_filter) structure is documented below.
+
+-> If the `period` is configured, it means that the evaluation is performed periodically.
+ If the `policy_filter` is configured, it means that the evaluation is performed on the specified resources through
+ the filter. If neither parameter is configured, it means that the evaluation is performed on all resources under the
+ account.
+
+* `custom_policy` - (Optional, List) Specifies the configuration of the custom policy.
+ The [object](#rms_custom_policy) structure is documented below.
+
+* `parameters` - (Optional, Map) Specifies the rule definition of the policy assignment.
+
+* `status` - (Optional, String) Specifies the expect status of the policy.
+ The valid values are **Enabled** and **Disabled**.
+
+
+The `policy_filter` block supports:
+
+* `region` - (Optional, String) Specifies the name of the region to which the filtered resources belong.
+
+* `resource_provider` - (Optional, String) Specifies the service name to which the filtered resources belong.
+
+* `resource_type` - (Optional, String) Specifies the resource type of the filtered resources.
+
+* `resource_id` - (Optional, String) Specifies the resource ID used to filter a specified resource.
+
+* `tag_key` - (Optional, String) Specifies the tag name used to filter resources.
+ This parameter and `resource_id` are alternative.
+
+* `tag_value` - (Optional, String) Specifies the tag value used to filter resources.
+ Required if `tag_key` is set.
+
+
+The `custom_policy` block supports:
+
+* `function_urn` - (Required, String) Specifies the function URN used to create the custom policy.
+
+* `auth_type` - (Required, String) Specifies the authorization type of the custom policy.
+
+* `auth_value` - (Optional, Map) Specifies the authorization value of the custom policy.
+
+## Attribute Reference
+
+In addition to all arguments above, the following attributes are exported:
+
+* `id` - The ID of the policy assignment.
+
+* `type` - The type of the policy assignment.
+ The valid values are as follows:
+ + **builtin**
+ + **custom**
+
+* `created_at` - The creation time of the policy assignment.
+
+* `updated_at` - The latest update time of the policy assignment.
+
+## Timeouts
+
+This resource provides the following timeouts configuration options:
+
+* `create` - Default is 5 minutes.
+* `update` - Default is 5 minutes.
+
+## Import
+
+Policy assignments can be imported using their `id`, e.g.
+
+```bash
+$ terraform import opentelekomcloud_rms_policy_assignment_v1.test 63f48e3762ce955981ab7e25
+```
diff --git a/opentelekomcloud/acceptance/rms/resource_opentelekomcloud_rms_policy_assignment_v1_test.go b/opentelekomcloud/acceptance/rms/resource_opentelekomcloud_rms_policy_assignment_v1_test.go
new file mode 100644
index 000000000..432acd557
--- /dev/null
+++ b/opentelekomcloud/acceptance/rms/resource_opentelekomcloud_rms_policy_assignment_v1_test.go
@@ -0,0 +1,342 @@
+package rms
+
+import (
+ "fmt"
+ "regexp"
+ "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"
+ "github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/compliance"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/common"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/env"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/services/rms"
+)
+
+var (
+ statusReg = regexp.MustCompile(`^(Enabled|Evaluating)$`)
+)
+
+func getPolicyAssignmentResourceFunc(conf *cfg.Config, state *terraform.ResourceState) (interface{}, error) {
+ client, err := conf.RmsV1Client(env.OS_REGION_NAME)
+ if err != nil {
+ return nil, fmt.Errorf("error creating RMS V1 client: %s", err)
+ }
+
+ domainId := rms.GetRmsDomainId(client, conf)
+
+ return compliance.GetRule(client, domainId, state.Primary.ID)
+}
+
+func TestAccPolicyAssignment_basic(t *testing.T) {
+ var (
+ obj compliance.PolicyRule
+
+ rName = "opentelekomcloud_rms_policy_assignment_v1.test"
+ name = "rms-test" + acctest.RandString(5)
+ basicConfig = testAccPolicyAssignment_ecsConfig(name)
+ )
+
+ rc := common.InitResourceCheck(
+ rName,
+ &obj,
+ getPolicyAssignmentResourceFunc,
+ )
+
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() {
+ common.TestAccPreCheck(t)
+ },
+ ProviderFactories: common.TestAccProviderFactories,
+ CheckDestroy: rc.CheckResourceDestroy(),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccPolicyAssignment_basic(basicConfig, name, "Disabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(rName, "type", rms.AssignmentTypeBuiltin),
+ resource.TestCheckResourceAttr(rName, "name", name),
+ resource.TestCheckResourceAttrPair(rName, "policy_definition_id",
+ "data.opentelekomcloud_rms_policy_definitions_v1.test", "definitions.0.id"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.region", env.OS_REGION_NAME),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.resource_provider", "ecs"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.resource_type", "cloudservers"),
+ resource.TestCheckResourceAttrPair(rName, "policy_filter.0.resource_id",
+ "opentelekomcloud_compute_instance_v2.test", "id"),
+ resource.TestCheckResourceAttr(rName, "status", "Disabled"),
+ resource.TestCheckResourceAttrSet(rName, "parameters.listOfAllowedFlavors"),
+ resource.TestCheckResourceAttrSet(rName, "created_at"),
+ resource.TestCheckResourceAttrSet(rName, "updated_at"),
+ ),
+ },
+ {
+ Config: testAccPolicyAssignment_basic(basicConfig, name, "Enabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestMatchResourceAttr(rName, "status", statusReg),
+ ),
+ },
+ {
+ Config: testAccPolicyAssignment_basicUpdate(basicConfig, name, "Enabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(rName, "type", rms.AssignmentTypeBuiltin),
+ resource.TestCheckResourceAttr(rName, "name", name),
+ resource.TestCheckResourceAttrPair(rName, "policy_definition_id",
+ "data.opentelekomcloud_rms_policy_definitions_v1.test", "definitions.0.id"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.region", env.OS_REGION_NAME),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.resource_provider", "ecs"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.resource_type", "cloudservers"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.tag_key", "foo"),
+ resource.TestCheckResourceAttr(rName, "policy_filter.0.tag_value", "bar"),
+ resource.TestMatchResourceAttr(rName, "status", statusReg),
+ resource.TestCheckResourceAttrSet(rName, "parameters.listOfAllowedFlavors"),
+ resource.TestCheckResourceAttrSet(rName, "created_at"),
+ resource.TestCheckResourceAttrSet(rName, "updated_at"),
+ ),
+ },
+ {
+ ResourceName: rName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func testAccPolicyAssignment_ecsConfig(name string) string {
+ return fmt.Sprintf(`
+
+
+resource "opentelekomcloud_vpc_v1" "test" {
+ name = "%[1]s"
+ cidr = "192.168.0.0/16"
+}
+
+resource "opentelekomcloud_vpc_subnet_v1" "test" {
+ name = "%[1]s"
+ vpc_id = opentelekomcloud_vpc_v1.test.id
+ cidr = cidrsubnet(opentelekomcloud_vpc_v1.test.cidr, 4, 1)
+ gateway_ip = cidrhost(cidrsubnet(opentelekomcloud_vpc_v1.test.cidr, 4, 1), 1)
+}
+
+resource "opentelekomcloud_networking_secgroup_v2" "test" {
+ name = "%[1]s"
+ delete_default_rules = true
+}
+
+resource "opentelekomcloud_compute_instance_v2" "test" {
+ name = "%[1]s"
+ image_name = "Standard_Debian_11_latest"
+ flavor_name = "s3.large.2"
+ security_groups = [opentelekomcloud_networking_secgroup_v2.test.name]
+ availability_zone = "eu-de-01"
+
+ network {
+ uuid = opentelekomcloud_vpc_subnet_v1.test.id
+ }
+}
+`, name)
+}
+
+func testAccPolicyAssignment_basic(basicConfig, name, status string) string {
+ return fmt.Sprintf(`
+%[1]s
+
+data "opentelekomcloud_compute_flavor_v2" "test" {
+ name = "s3.large.2"
+}
+
+data "opentelekomcloud_rms_policy_definitions_v1" "test" {
+ name = "allowed-ecs-flavors"
+}
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = "%[2]s"
+ description = "Test description"
+ policy_definition_id = try(data.opentelekomcloud_rms_policy_definitions_v1.test.definitions[0].id, "")
+ status = "%[3]s"
+
+ policy_filter {
+ region = "%[4]s"
+ resource_provider = "ecs"
+ resource_type = "cloudservers"
+ resource_id = opentelekomcloud_compute_instance_v2.test.id
+ }
+
+ parameters = {
+ listOfAllowedFlavors = "[\"${data.opentelekomcloud_compute_flavor_v2.test.id}\"]"
+ }
+}
+`, basicConfig, name, status, env.OS_REGION_NAME)
+}
+
+func testAccPolicyAssignment_basicUpdate(basicConfig, name, status string) string {
+ return fmt.Sprintf(`
+%[1]s
+
+data "opentelekomcloud_compute_flavor_v2" "test" {
+ name = "s3.large.2"
+}
+
+data "opentelekomcloud_rms_policy_definitions_v1" "test" {
+ name = "allowed-ecs-flavors"
+}
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = "%[2]s"
+ description = "Test description"
+ policy_definition_id = try(data.opentelekomcloud_rms_policy_definitions_v1.test.definitions[0].id, "")
+ status = "%[3]s"
+
+ policy_filter {
+ region = "%[4]s"
+ resource_provider = "ecs"
+ resource_type = "cloudservers"
+ tag_key = "foo"
+ tag_value = "bar"
+ }
+
+ parameters = {
+ listOfAllowedFlavors = "[\"${data.opentelekomcloud_compute_flavor_v2.test.id}\"]"
+ }
+}
+`, basicConfig, name, status, env.OS_REGION_NAME)
+}
+
+func TestAccPolicyAssignment_custom(t *testing.T) {
+ var (
+ obj compliance.PolicyRule
+
+ rName = "opentelekomcloud_rms_policy_assignment_v1.test"
+ name = "rms-test-" + acctest.RandString(5)
+ customConfig = testAccPolicyAssignment_customConfig(name)
+ )
+
+ rc := common.InitResourceCheck(
+ rName,
+ &obj,
+ getPolicyAssignmentResourceFunc,
+ )
+
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() {
+ common.TestAccPreCheck(t)
+ },
+ ProviderFactories: common.TestAccProviderFactories,
+ CheckDestroy: rc.CheckResourceDestroy(),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccPolicyAssignment_custom(customConfig, name, "Disabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(rName, "type", rms.AssignmentTypeCustom),
+ resource.TestCheckResourceAttr(rName, "description", "Test description"),
+ resource.TestCheckResourceAttr(rName, "name", name),
+ resource.TestCheckResourceAttr(rName, "status", "Disabled"),
+ resource.TestCheckResourceAttr(rName, "parameters.string_test", "\"string_value\""),
+ resource.TestCheckResourceAttr(rName, "parameters.array_test", "[\"array_element\"]"),
+ resource.TestCheckResourceAttr(rName, "parameters.object_test", "{\"terraform_version\":\"1.xx.x\"}"),
+ resource.TestCheckResourceAttrSet(rName, "created_at"),
+ resource.TestCheckResourceAttrSet(rName, "updated_at"),
+ ),
+ },
+ {
+ Config: testAccPolicyAssignment_custom(customConfig, name, "Enabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestMatchResourceAttr(rName, "status", statusReg),
+ ),
+ },
+ {
+ Config: testAccPolicyAssignment_customUpdate(customConfig, name, "Enabled"),
+ Check: resource.ComposeTestCheckFunc(
+ rc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(rName, "name", name),
+ resource.TestCheckResourceAttr(rName, "parameters.string_test", "\"update_string_value\""),
+ resource.TestCheckResourceAttr(rName, "parameters.update_array_test", "[\"array_element\"]"),
+ resource.TestCheckResourceAttr(rName, "parameters.object_test", "{\"update_terraform_version\":\"1.xx.xx\"}"),
+ resource.TestMatchResourceAttr(rName, "status", statusReg),
+ ),
+ },
+ {
+ ResourceName: rName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func testAccPolicyAssignment_customConfig(name string) string {
+ customConfig := testAccPolicyAssignment_ecsConfig(name)
+
+ return fmt.Sprintf(`
+%[1]s
+
+resource "opentelekomcloud_fgs_function_v2" "test" {
+ name = "%[2]s"
+ code_type = "inline"
+ handler = "index.handler"
+ runtime = "Node.js10.16"
+ functiongraph_version = "v2"
+ app = "default"
+ memory_size = 128
+ timeout = 3
+}
+`, customConfig, name)
+}
+
+func testAccPolicyAssignment_custom(customConfig, name, status string) string {
+ return fmt.Sprintf(`
+%[1]s
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = "%[2]s"
+ description = "Test description"
+ status = "%[3]s"
+
+ custom_policy {
+ function_urn = "${opentelekomcloud_fgs_function_v2.test.urn}:${opentelekomcloud_fgs_function_v2.test.version}"
+ auth_type = "agency"
+ auth_value = {
+ agency_name = "\"rms_tracker_agency\""
+ }
+ }
+
+ parameters = {
+ string_test = "\"string_value\""
+ array_test = "[\"array_element\"]"
+ object_test = "{\"terraform_version\":\"1.xx.x\"}"
+ }
+}
+`, customConfig, name, status)
+}
+
+func testAccPolicyAssignment_customUpdate(customConfig, name, status string) string {
+ return fmt.Sprintf(`
+%[1]s
+
+resource "opentelekomcloud_rms_policy_assignment_v1" "test" {
+ name = "%[2]s"
+ description = "Test description"
+ status = "%[3]s"
+
+ custom_policy {
+ function_urn = "${opentelekomcloud_fgs_function_v2.test.urn}:${opentelekomcloud_fgs_function_v2.test.version}"
+ auth_type = "agency"
+ auth_value = {
+ agency_name = "\"rms_tracker_agency\""
+ }
+ }
+
+ parameters = {
+ string_test = "\"update_string_value\""
+ update_array_test = "[\"array_element\"]"
+ object_test = "{\"update_terraform_version\":\"1.xx.xx\"}"
+ }
+}
+`, customConfig, name, status)
+}
diff --git a/opentelekomcloud/common/utils.go b/opentelekomcloud/common/utils.go
index 603bc1595..c9b22ac91 100644
--- a/opentelekomcloud/common/utils.go
+++ b/opentelekomcloud/common/utils.go
@@ -547,3 +547,17 @@ func hasMapContain(rawMap map[string]string, filterKey, filterValue string) bool
return false
}
}
+
+// StrSliceContainsAnother checks whether a string slice (b) contains another string slice (s).
+func StrSliceContainsAnother(b []string, s []string) bool {
+ // The empty set is the subset of any set.
+ if len(s) < 1 {
+ return true
+ }
+ for _, v := range s {
+ if !StrSliceContains(b, v) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/opentelekomcloud/provider.go b/opentelekomcloud/provider.go
index 4a94d6b26..6851991d0 100644
--- a/opentelekomcloud/provider.go
+++ b/opentelekomcloud/provider.go
@@ -330,6 +330,7 @@ func Provider() *schema.Provider {
"opentelekomcloud_rds_flavors_v1": rds.DataSourceRdsFlavorV1(),
"opentelekomcloud_rds_flavors_v3": rds.DataSourceRdsFlavorV3(),
"opentelekomcloud_rds_versions_v3": rds.DataSourceRdsVersionsV3(),
+ "opentelekomcloud_rms_policy_definitions_v1": rms.DataSourcePolicyDefinitions(),
"opentelekomcloud_rts_software_deployment_v1": rts.DataSourceRtsSoftwareDeploymentV1(),
"opentelekomcloud_rts_software_config_v1": rts.DataSourceRtsSoftwareConfigV1(),
"opentelekomcloud_rts_stack_resource_v1": rts.DataSourceRTSStackResourcesV1(),
@@ -528,6 +529,7 @@ func Provider() *schema.Provider {
"opentelekomcloud_rds_read_replica_v3": rds.ResourceRdsReadReplicaV3(),
"opentelekomcloud_rms_advanced_query_v1": rms.ResourceRmsAdvancedQueryV1(),
"opentelekomcloud_rms_resource_recorder_v1": rms.ResourceRmsResourceRecorderV1(),
+ "opentelekomcloud_rms_policy_assignment_v1": rms.ResourceRmsPolicyAssignmentV1(),
"opentelekomcloud_rts_software_deployment_v1": rts.ResourceRtsSoftwareDeploymentV1(),
"opentelekomcloud_rts_software_config_v1": rts.ResourceSoftwareConfigV1(),
"opentelekomcloud_rts_stack_v1": rts.ResourceRTSStackV1(),
diff --git a/opentelekomcloud/services/dms/common.go b/opentelekomcloud/services/dms/common.go
index 73e799083..0d39a25cb 100644
--- a/opentelekomcloud/services/dms/common.go
+++ b/opentelekomcloud/services/dms/common.go
@@ -4,8 +4,6 @@ import (
"encoding/json"
"log"
"strings"
-
- "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common"
)
const (
@@ -27,17 +25,3 @@ func MarshalValue(i interface{}) string {
return strings.Trim(string(jsonRaw), `"`)
}
-
-// StrSliceContainsAnother checks whether a string slice (b) contains another string slice (s).
-func StrSliceContainsAnother(b []string, s []string) bool {
- // The empty set is the subset of any set.
- if len(s) < 1 {
- return true
- }
- for _, v := range s {
- if !common.StrSliceContains(b, v) {
- return false
- }
- }
- return true
-}
diff --git a/opentelekomcloud/services/dms/data_source_opentelekomcloud_flavor_v2.go b/opentelekomcloud/services/dms/data_source_opentelekomcloud_flavor_v2.go
index 91b931e09..784f1e245 100644
--- a/opentelekomcloud/services/dms/data_source_opentelekomcloud_flavor_v2.go
+++ b/opentelekomcloud/services/dms/data_source_opentelekomcloud_flavor_v2.go
@@ -263,7 +263,7 @@ func filterFlavors(d *schema.ResourceData, flavorList []products.EngineProduct)
if scOk && io.IOSpec != sc.(string) {
continue
}
- if StrSliceContainsAnother(io.AvailableZones, common.ExpandToStringList(azs)) {
+ if common.StrSliceContainsAnother(io.AvailableZones, common.ExpandToStringList(azs)) {
validIOs = append(validIOs, io)
}
}
diff --git a/opentelekomcloud/services/rms/data_opentelekomcloud_rms_policy_definitions_v1.go b/opentelekomcloud/services/rms/data_opentelekomcloud_rms_policy_definitions_v1.go
new file mode 100644
index 000000000..bcdba5b21
--- /dev/null
+++ b/opentelekomcloud/services/rms/data_opentelekomcloud_rms_policy_definitions_v1.go
@@ -0,0 +1,200 @@
+package rms
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "log"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
+ "github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/compliance"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/fmterr"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/helper/hashcode"
+)
+
+func DataSourcePolicyDefinitions() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourcePolicyDefinitionsRead,
+
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "policy_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "policy_rule_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "trigger_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "keywords": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "definitions": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "policy_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "description": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "policy_rule_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "policy_rule": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "trigger_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "keywords": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "parameters": {
+ Type: schema.TypeMap,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func filterPolicyDefinitionsByKeywords(definitions []compliance.PolicyDefinition,
+ keywords []interface{}) []compliance.PolicyDefinition {
+ if len(keywords) < 1 {
+ return definitions
+ }
+
+ filter := common.ExpandToStringList(keywords)
+ result := make([]compliance.PolicyDefinition, 0, len(definitions))
+ for _, v := range definitions {
+ if common.StrSliceContainsAnother(v.Keywords, filter) {
+ result = append(result, v)
+ }
+ }
+ return result
+}
+
+func flattenDefinitionParameters(parameters map[string]compliance.PolicyParameterDefinition) (
+ map[string]interface{}, error) {
+ if len(parameters) < 1 {
+ return nil, nil
+ }
+
+ result := make(map[string]interface{})
+ for k, v := range parameters {
+ jsonBytes, err := json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("generate json string failed: %s", err)
+ }
+ result[k] = string(jsonBytes)
+ }
+ return result, nil
+}
+
+func filterPolicyDefinitions(definitions []compliance.PolicyDefinition,
+ d *schema.ResourceData) ([]map[string]interface{}, []string, error) {
+ filter := map[string]interface{}{
+ "Name": d.Get("name"),
+ "PolicyType": d.Get("policy_type"),
+ "PolicyRuleType": d.Get("policy_rule_type"),
+ "TriggerType": d.Get("trigger_type"),
+ }
+ filtResult, err := common.FilterSliceWithField(definitions, filter)
+ if err != nil {
+ return nil, nil, fmt.Errorf("filter component runtimes failed: %s", err)
+ }
+ log.Printf("[DEBUG] Filter %d policy definitions from server through options: %v", len(filtResult), filter)
+
+ result := make([]map[string]interface{}, len(filtResult))
+ ids := make([]string, len(filtResult))
+ for i, val := range filtResult {
+ definition := val.(compliance.PolicyDefinition)
+ ids[i] = definition.ID
+ dm := map[string]interface{}{
+ "id": definition.ID,
+ "name": definition.Name,
+ "policy_type": definition.PolicyType,
+ "description": definition.Description,
+ "policy_rule_type": definition.PolicyRuleType,
+ "policy_rule": definition.PolicyRule,
+ "trigger_type": definition.TriggerType,
+ "keywords": definition.Keywords,
+ }
+
+ params, err := flattenDefinitionParameters(definition.Parameters)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to flatten definition parameters: %s", err)
+ }
+ dm["parameters"] = params
+
+ jsonBytes, err := json.Marshal(definition.PolicyRule)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to generate json string: %s", err)
+ }
+ dm["policy_rule"] = string(jsonBytes)
+
+ result[i] = dm
+ }
+ return result, ids, nil
+}
+
+func dataSourcePolicyDefinitionsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*cfg.Config)
+ client, err := common.ClientFromCtx(ctx, rmsClientV1, func() (*golangsdk.ServiceClient, error) {
+ return config.RmsV1Client(config.GetRegion(d))
+ })
+ if err != nil {
+ return fmterr.Errorf(errCreationRMSV1Client, err)
+ }
+
+ definitions, err := compliance.ListAllPolicies(client)
+ if err != nil {
+ return diag.Errorf("error getting the policy definition list form server: %s", err)
+ }
+
+ filterResult := filterPolicyDefinitionsByKeywords(definitions, d.Get("keywords").([]interface{}))
+ dm, ids, err := filterPolicyDefinitions(filterResult, d)
+ if err != nil {
+ return diag.Errorf("error query policy definitions: %s", err)
+ }
+ d.SetId(hashcode.Strings(ids))
+
+ if err = d.Set("definitions", dm); err != nil {
+ return diag.Errorf("error saving the information of the policy definitions to state: %s", err)
+ }
+ return nil
+}
diff --git a/opentelekomcloud/services/rms/resource_opentelekomcloud_rms_policy_assignment_v1.go b/opentelekomcloud/services/rms/resource_opentelekomcloud_rms_policy_assignment_v1.go
new file mode 100644
index 000000000..871b38ec3
--- /dev/null
+++ b/opentelekomcloud/services/rms/resource_opentelekomcloud_rms_policy_assignment_v1.go
@@ -0,0 +1,536 @@
+package rms
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "log"
+ "reflect"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/go-multierror"
+ "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/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+ golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
+ "github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/compliance"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg"
+ "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/fmterr"
+)
+
+const (
+ AssignmentTypeBuiltin = "builtin"
+ AssignmentTypeCustom = "custom"
+
+ AssignmentStatusDisabled = "Disabled"
+ AssignmentStatusEnabled = "Enabled"
+ AssignmentStatusEvaluating = "Evaluating"
+)
+
+func ResourceRmsPolicyAssignmentV1() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourcePolicyAssignmentCreate,
+ ReadContext: resourcePolicyAssignmentRead,
+ UpdateContext: resourcePolicyAssignmentUpdate,
+ DeleteContext: resourcePolicyAssignmentDelete,
+
+ Timeouts: &schema.ResourceTimeout{
+ Create: schema.DefaultTimeout(5 * time.Minute),
+ Update: schema.DefaultTimeout(5 * time.Minute),
+ },
+
+ Importer: &schema.ResourceImporter{
+ StateContext: schema.ImportStatePassthroughContext,
+ },
+
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "policy_definition_id": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "period": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "policy_filter": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "resource_provider": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "resource_type": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "resource_id": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "tag_key": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "tag_value": {
+ Type: schema.TypeString,
+ Optional: true,
+ RequiredWith: []string{"policy_filter.0.tag_key"},
+ },
+ },
+ },
+ },
+ "custom_policy": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "function_urn": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "auth_type": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "auth_value": {
+ Type: schema.TypeMap,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ ValidateFunc: validation.StringIsJSON,
+ },
+ },
+ },
+ },
+ },
+ "parameters": {
+ Type: schema.TypeMap,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ ValidateFunc: validation.StringIsJSON,
+ },
+ },
+ "status": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+ "type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "created_at": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "updated_at": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ }
+}
+
+func buildPolicyFilter(filters []interface{}) compliance.PolicyFilterDefinition {
+ if len(filters) < 1 {
+ return compliance.PolicyFilterDefinition{}
+ }
+ filter := filters[0].(map[string]interface{})
+ return compliance.PolicyFilterDefinition{
+ RegionID: filter["region"].(string),
+ ResourceProvider: filter["resource_provider"].(string),
+ ResourceType: filter["resource_type"].(string),
+ ResourceID: filter["resource_id"].(string),
+ TagKey: filter["tag_key"].(string),
+ TagValue: filter["tag_value"].(string),
+ }
+}
+
+func buildCustomPolicy(policies []interface{}) (*compliance.CustomPolicy, error) {
+ if len(policies) < 1 {
+ return nil, nil
+ }
+ policy := policies[0].(map[string]interface{})
+ result := compliance.CustomPolicy{
+ FunctionUrn: policy["function_urn"].(string),
+ AuthType: policy["auth_type"].(string),
+ }
+ authValues := make(map[string]interface{})
+ for k, jsonVal := range policy["auth_value"].(map[string]interface{}) {
+ var value interface{}
+ err := json.Unmarshal([]byte(jsonVal.(string)), &value)
+ if err != nil {
+ return &result, fmt.Errorf("error analyzing authorization value: %s", err)
+ }
+ authValues[k] = value
+ }
+ result.AuthValue = authValues
+
+ return &result, nil
+}
+
+func buildRuleParameters(parameters map[string]interface{}) (map[string]compliance.PolicyParameter, error) {
+ if len(parameters) < 1 {
+ return nil, nil
+ }
+ result := make(map[string]compliance.PolicyParameter)
+ for k, jsonVal := range parameters {
+ var value interface{}
+ err := json.Unmarshal([]byte(jsonVal.(string)), &value)
+ if err != nil {
+ return result, fmt.Errorf("error analyzing parameter value: %s", err)
+ }
+ result[k] = compliance.PolicyParameter{
+ Value: value,
+ }
+ }
+ return result, nil
+}
+
+func buildPolicyAssignmentCreateOpts(d *schema.ResourceData) (compliance.AddRuleOpts, error) {
+ result := compliance.AddRuleOpts{
+ Name: d.Get("name").(string),
+ Description: d.Get("description").(string),
+ PolicyAssignmentType: AssignmentTypeBuiltin,
+ PolicyFilter: buildPolicyFilter(d.Get("policy_filter").([]interface{})),
+ PolicyDefinitionID: d.Get("policy_definition_id").(string),
+ Period: d.Get("period").(string),
+ }
+ customPolicy, err := buildCustomPolicy(d.Get("custom_policy").([]interface{}))
+ if err != nil {
+ return result, err
+ }
+ result.CustomPolicy = customPolicy
+ if customPolicy != nil {
+ result.PolicyAssignmentType = AssignmentTypeCustom
+ }
+
+ parameters, err := buildRuleParameters(d.Get("parameters").(map[string]interface{}))
+ if err != nil {
+ return result, err
+ }
+ result.Parameters = parameters
+
+ return result, nil
+}
+
+func updatePolicyAssignmentStatus(client *golangsdk.ServiceClient, domainId, assignmentId,
+ statusConfig string) (err error) {
+ switch statusConfig {
+ case AssignmentStatusDisabled:
+ err = compliance.DisableRule(client, domainId, assignmentId)
+ case AssignmentStatusEnabled:
+ err = compliance.EnableRule(client, domainId, assignmentId)
+ }
+ return
+}
+
+func policyAssignmentRefreshFunc(client *golangsdk.ServiceClient, domainId,
+ assignmentId string) resource.StateRefreshFunc {
+ return func() (interface{}, string, error) {
+ resp, err := compliance.GetRule(client, domainId, assignmentId)
+ if err != nil {
+ return resp, "ERROR", err
+ }
+ return resp, resp.State, nil
+ }
+}
+
+func resourcePolicyAssignmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*cfg.Config)
+ client, err := common.ClientFromCtx(ctx, rmsClientV1, func() (*golangsdk.ServiceClient, error) {
+ return config.RmsV1Client(config.GetRegion(d))
+ })
+ if err != nil {
+ return fmterr.Errorf(errCreationRMSV1Client, err)
+ }
+
+ opts, err := buildPolicyAssignmentCreateOpts(d)
+ if err != nil {
+ return diag.Errorf("error creating the create option structure of the RMS policy assignment: %s", err)
+ }
+ domainId := GetRmsDomainId(client, config)
+ opts.DomainId = domainId
+
+ resp, err := compliance.AddRule(client, opts)
+ if err != nil {
+ return diag.Errorf("error creating policy assignment resource: %s", err)
+ }
+
+ assignmentId := resp.ID
+ d.SetId(assignmentId)
+
+ // it will take too long time to become enabled when the resources are very huge.
+ // so we wait for the enabled status only when user want to disable it during creating.
+ if statusConfig := d.Get("status").(string); statusConfig == AssignmentStatusDisabled {
+ log.Printf("[DEBUG] Waiting for the policy assignment (%s) status to become enabled, then disable it", assignmentId)
+ stateConf := &resource.StateChangeConf{
+ Pending: []string{AssignmentStatusDisabled, AssignmentStatusEvaluating},
+ Target: []string{AssignmentStatusEnabled},
+ Refresh: policyAssignmentRefreshFunc(client, domainId, assignmentId),
+ Timeout: d.Timeout(schema.TimeoutCreate),
+ Delay: 10 * time.Second,
+ PollInterval: 10 * time.Second,
+ ContinuousTargetOccurence: 2,
+ }
+ _, err = stateConf.WaitForStateContext(ctx)
+ if err != nil {
+ return diag.Errorf("error waiting for the policy assignment (%s) status to become enabled: %s",
+ assignmentId, err)
+ }
+
+ err = updatePolicyAssignmentStatus(client, domainId, assignmentId, statusConfig)
+ if err != nil {
+ return diag.Errorf("error disabling the status of the policy assignment: %s", err)
+ }
+ }
+
+ clientCtx := common.CtxWithClient(ctx, client, errCreationRMSV1Client)
+ return resourcePolicyAssignmentRead(clientCtx, d, meta)
+}
+
+func flattenPolicyFilter(filter compliance.PolicyFilterDefinition) []map[string]interface{} {
+ if reflect.DeepEqual(filter, compliance.PolicyFilterDefinition{}) {
+ return nil
+ }
+
+ return []map[string]interface{}{
+ {
+ "region": filter.RegionID,
+ "resource_provider": filter.ResourceProvider,
+ "resource_type": filter.ResourceType,
+ "resource_id": filter.ResourceID,
+ "tag_key": filter.TagKey,
+ "tag_value": filter.TagValue,
+ },
+ }
+}
+
+func flattenCustomPolicy(customPolicy *compliance.CustomPolicy) ([]map[string]interface{}, error) {
+ if customPolicy == nil {
+ return nil, nil
+ }
+
+ authValues := make(map[string]interface{})
+ for k, v := range customPolicy.AuthValue {
+ jsonBytes, err := json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("generate json string failed: %s", err)
+ }
+ authValues[k] = string(jsonBytes)
+ }
+ return []map[string]interface{}{
+ {
+ "function_urn": customPolicy.FunctionUrn,
+ "auth_type": customPolicy.AuthType,
+ "auth_value": authValues,
+ },
+ }, nil
+}
+
+func flattenPolicyParameters(parameters map[string]compliance.PolicyParameter) (map[string]interface{},
+ error) {
+ if len(parameters) < 1 {
+ return nil, nil
+ }
+
+ result := make(map[string]interface{})
+ for k, v := range parameters {
+ jsonBytes, err := json.Marshal(v.Value)
+ if err != nil {
+ return nil, fmt.Errorf("generate json string failed: %s", err)
+ }
+ result[k] = string(jsonBytes)
+ }
+ return result, nil
+}
+
+func resourcePolicyAssignmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*cfg.Config)
+ client, err := common.ClientFromCtx(ctx, rmsClientV1, func() (*golangsdk.ServiceClient, error) {
+ return config.RmsV1Client(config.GetRegion(d))
+ })
+ if err != nil {
+ return fmterr.Errorf(errCreationRMSV1Client, err)
+ }
+
+ domainId := GetRmsDomainId(client, config)
+ assignmentId := d.Id()
+ resp, err := compliance.GetRule(client, domainId, assignmentId)
+ if err != nil {
+ return common.CheckDeletedDiag(d, err, "RMS policy assignment")
+ }
+
+ customPolicy, err := flattenCustomPolicy(resp.CustomPolicy)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ parameters, err := flattenPolicyParameters(resp.Parameters)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ mErr := multierror.Append(nil,
+ d.Set("type", resp.PolicyAssignmentType),
+ d.Set("name", resp.Name),
+ d.Set("description", resp.Description),
+ d.Set("policy_definition_id", resp.PolicyDefinitionID),
+ d.Set("period", resp.Period),
+ d.Set("policy_filter", flattenPolicyFilter(*resp.PolicyFilter)),
+ d.Set("custom_policy", customPolicy),
+ d.Set("parameters", parameters),
+ d.Set("status", resp.State),
+ d.Set("created_at", resp.Created),
+ d.Set("updated_at", resp.Updated),
+ )
+
+ if mErr.ErrorOrNil() != nil {
+ return diag.Errorf("error saving policy assignment resource (%s) fields: %s", assignmentId, mErr)
+ }
+ return nil
+}
+
+func buildPolicyAssignmentUpdateOpts(d *schema.ResourceData) (compliance.UpdateRuleOpts, error) {
+ result := compliance.UpdateRuleOpts{
+ Name: d.Get("name").(string),
+ Description: d.Get("description").(string),
+ PolicyAssignmentType: AssignmentTypeBuiltin,
+ PolicyFilter: buildPolicyFilter(d.Get("policy_filter").([]interface{})),
+ PolicyDefinitionID: d.Get("policy_definition_id").(string),
+ Period: d.Get("period").(string),
+ }
+ customPolicy, err := buildCustomPolicy(d.Get("custom_policy").([]interface{}))
+ if err != nil {
+ return result, err
+ }
+ result.CustomPolicy = customPolicy
+ if customPolicy != nil {
+ result.PolicyAssignmentType = AssignmentTypeCustom
+ }
+
+ parameters, err := buildRuleParameters(d.Get("parameters").(map[string]interface{}))
+ if err != nil {
+ return result, err
+ }
+ result.Parameters = parameters
+
+ return result, nil
+}
+
+func resourcePolicyAssignmentUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*cfg.Config)
+ client, err := common.ClientFromCtx(ctx, rmsClientV1, func() (*golangsdk.ServiceClient, error) {
+ return config.RmsV1Client(config.GetRegion(d))
+ })
+ if err != nil {
+ return fmterr.Errorf(errCreationRMSV1Client, err)
+ }
+
+ assignmentId := d.Id()
+ domainId := GetRmsDomainId(client, config)
+
+ if d.HasChange("status") {
+ oldVal, newVal := d.GetChange("status")
+ err = updatePolicyAssignmentStatus(client, domainId, d.Id(), d.Get("status").(string))
+ if err != nil {
+ return diag.Errorf("error updating the status of the policy assignment (%s): %s", assignmentId, err)
+ }
+
+ if newVal.(string) == AssignmentStatusEnabled {
+ log.Printf("[DEBUG] Waiting for the policy assignment (%s) status to become %s.", assignmentId,
+ strings.ToLower(newVal.(string)))
+ stateConf := &resource.StateChangeConf{
+ Pending: []string{oldVal.(string)},
+ Target: []string{AssignmentStatusEvaluating, AssignmentStatusEnabled},
+ Refresh: policyAssignmentRefreshFunc(client, domainId, assignmentId),
+ Timeout: d.Timeout(schema.TimeoutUpdate),
+ Delay: 10 * time.Second,
+ PollInterval: 10 * time.Second,
+ ContinuousTargetOccurence: 2,
+ }
+ _, err = stateConf.WaitForStateContext(ctx)
+ if err != nil {
+ return diag.Errorf("error waiting for the policy assignment (%s) status to become %s: %s",
+ assignmentId, strings.ToLower(newVal.(string)), err)
+ }
+ }
+ }
+ if d.HasChangeExcept("status") {
+ opts, err := buildPolicyAssignmentUpdateOpts(d)
+ if err != nil {
+ return diag.Errorf("error creating the update option structure of the RMS policy assignment: %s", err)
+ }
+
+ opts.DomainId = domainId
+ opts.PolicyAssignmentId = assignmentId
+
+ _, err = compliance.UpdateRule(client, opts)
+ if err != nil {
+ return diag.Errorf("error updating policy assignment resource (%s): %s", assignmentId, err)
+ }
+ currentStatus := d.Get("status").(string)
+ log.Printf("[DEBUG] Waiting for the policy assignment (%s) status to become %s.", assignmentId,
+ strings.ToLower(currentStatus))
+ stateConf := &resource.StateChangeConf{
+ Target: []string{currentStatus},
+ Refresh: policyAssignmentRefreshFunc(client, domainId, assignmentId),
+ Timeout: d.Timeout(schema.TimeoutUpdate),
+ Delay: 10 * time.Second,
+ PollInterval: 10 * time.Second,
+ ContinuousTargetOccurence: 2,
+ }
+ _, err = stateConf.WaitForStateContext(ctx)
+ if err != nil {
+ return diag.Errorf("error waiting for the policy assignment (%s) status to become %s: %s",
+ assignmentId, strings.ToLower(currentStatus), err)
+ }
+ }
+
+ return resourcePolicyAssignmentRead(ctx, d, meta)
+}
+
+func resourcePolicyAssignmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*cfg.Config)
+ client, err := common.ClientFromCtx(ctx, rmsClientV1, func() (*golangsdk.ServiceClient, error) {
+ return config.RmsV1Client(config.GetRegion(d))
+ })
+ if err != nil {
+ return fmterr.Errorf(errCreationRMSV1Client, err)
+ }
+ var (
+ assignmentId = d.Id()
+ domainId = GetRmsDomainId(client, config)
+ )
+ if d.Get("status").(string) == AssignmentStatusEnabled {
+ err = compliance.DisableRule(client, domainId, assignmentId)
+ if err != nil {
+ return diag.Errorf("failed to disable the policy assignment (%s): %s", assignmentId, err)
+ }
+ }
+
+ err = compliance.Delete(client, domainId, assignmentId)
+ if err != nil {
+ return diag.Errorf("error deleting the policy assignment (%s): %s", assignmentId, err)
+ }
+ return nil
+}
diff --git a/releasenotes/notes/rms_policies-0f92edd815065b57.yaml b/releasenotes/notes/rms_policies-0f92edd815065b57.yaml
new file mode 100644
index 000000000..e1cfe2299
--- /dev/null
+++ b/releasenotes/notes/rms_policies-0f92edd815065b57.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ **[RMS]** Add new resource ``resource/opentelekomcloud_rms_policy_assignment_v1`` (`#2701 `_)
+ - |
+ **[RMS]** Add new data source ``data_source/opentelekomcloud_rms_policy_definitions_v1`` (`#2701 `_)