diff --git a/README.md b/README.md index 995f72f..9f20665 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ The following modules are available: - [Policies](./policies/) - [Groups](./groups/) - [Dynamic Groups](./dynamic-groups/) +- [Identity Domains](./identity-domains/) Within each module you find an *examples* folder. Each example is a fully runnable Terraform configuration that you can quickly test and put to use by modifying the input data according to your own needs. @@ -22,6 +23,7 @@ This repository is part of a broader collection of repositories containing modul - [Governance](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-governance) - [Security](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security) - [Observability & Monitoring](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-observability) +- [Secure Workloads](https://github.com/oracle-quickstart/terraform-oci-secure-workloads) The modules in this collection are designed for flexibility, are straightforward to use, and enforce CIS OCI Foundations Benchmark recommendations when possible. diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 88de51d..993bcd0 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,12 @@ +# November 01, 2023 Release Notes - 0.1.7 +## New +1. Identity Domains module, supporting identity domains, groups, and dynamic groups. +2. Groups and dynamic groups can be created in existing identity domains. + +## Updates +### Policy Module +1. Multiple intents can be declared for a specific compartment through *cislz-cmp-type* attribute. This configures the compartment (through the creation of necessary policy grants) to host resources that can be managed by different groups. + # October 06, 2023 Release Notes - 0.1.6 ## Updates diff --git a/identity-domains/README.md b/identity-domains/README.md new file mode 100644 index 0000000..0089bf8 --- /dev/null +++ b/identity-domains/README.md @@ -0,0 +1,151 @@ +# CIS OCI Landing Zone Identity Domains Module + +![Landing Zone logo](../landing_zone_300.png) + +This module manages Identity and Access Management (IAM) Identity Domains, Identity Domain Groups and Identity Domain Dynamic Groups in Oracle Cloud Infrastructure (OCI) based on maps of objects. Identity Domains are a fundamental construct in OCI IAM, they represent a user a group population and its associated configurations and security settings (such as Federation, MFA). + +Check [module specification](./SPEC.md) for a full description of module requirements, supported variables, managed resources and outputs. + +Check the [examples](./examples/) folder for actual module usage. + +- [Requirements](#requirements) +- [How to Invoke the Module](#invoke) +- [Module Functioning](#functioning) +- [Related Documentation](#related) +- [Known Issues](#issues) + +## Requirements + +### IAM Permissions + +This module requires the following OCI IAM permission: +``` +Allow group to manage domains in tenancy +``` +### Terraform Version < 1.3.x and Optional Object Type Attributes +This module relies on [Terraform Optional Object Type Attributes feature](https://developer.hashicorp.com/terraform/language/expressions/type-constraints#optional-object-type-attributes), which is experimental from Terraform 0.14.x to 1.2.x. It shortens the amount of input values in complex object types, by having Terraform automatically inserting a default value for any missing optional attributes. The feature has been promoted and it is no longer experimental in Terraform 1.3.x. + +**As is, this module can only be used with Terraform versions up to 1.2.x**, because it can be consumed by other modules via [OCI Resource Manager service](https://docs.oracle.com/en-us/iaas/Content/ResourceManager/home.htm), that still does not support Terraform 1.3.x. + +Upon running *terraform plan* with Terraform versions prior to 1.3.x, Terraform displays the following warning: +``` +Warning: Experimental feature "module_variable_optional_attrs" is active +``` + +Note the warning is harmless. The code has been tested with Terraform 1.3.x and the implementation is fully compatible. + +If you really want to use Terraform 1.3.x, in [providers.tf](./providers.tf): +1. Change the terraform version requirement to: +``` +required_version = ">= 1.3.0" +``` +2. Remove the line: +``` +experiments = [module_variable_optional_attrs] +``` + +## How to Invoke the Module + +Terraform modules can be invoked locally or remotely. + +For invoking the module locally, just set the module *source* attribute to the module file path (relative path works). The following example assumes the module is two folders up in the file system. +``` + +module "identity_domains" { + source = "../../" + tenancy_ocid = var.tenancy_ocid + identity_domains_configuration = var.identity_domains_configuration + identity_domain_groups_configuration = var.identity_domain_groups_configuration + identity_domain_dynamic_groups_configuration = var.identity_domain_dynamic_groups_configuration +} +``` + +For invoking the module remotely, set the module *source* attribute to the groups module folder in this repository, as shown: +``` +module "identity_domains" { + source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-iam/identity-domains" + tenancy_id = var.tenancy_id + identity_domains_configuration = var.identity_domains_configuration + identity_domain_groups_configuration = var.identity_domain_groups_configuration + identity_domain_dynamic_groups_configuration = var.identity_domain_dynamic_groups_configuration +} +``` +For referring to a specific module version, append *ref=\* to the *source* attribute value, as in: +``` + source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-iam//identity-domains?ref=v0.1.0" +``` + +## Module Functioning + +The module defines three top-level input variables named *identity_domains_configuration*, *identity_domain_groups_configuration*, and *identity_domain_dynamic_groups_configuration*, for identity domains related attributes. A fourth top-level input variable, *compartments_dependency*, is used for bringing in externally managed compartments into identity domains configuration. See [External Dependencies](#extdep) section. + +## Defining Identity Domains +Use *identity_domains_configuration* attribute. It supports the following attributes: + + - **default_compartment_id**: (Optional) defines the compartment for all identity domains, unless overriden by *compartment_id* attribute within each identity domain. This attribute is overloaded: it can be either a compartment OCID or a reference (a key) to the compartment OCID. *tenancy_ocid* is used if undefined. See [External Dependencies](#extdep) section. + - **default_defined_tags**: (Optional) defined tags to apply to all resources, unless overriden by *defined_tags* attribute within each resource. + - **default_freeform_tags**: (Optional) freeform tags to apply to all resources, unless overriden by *freeform_tags* attribute within each resource. + - **identity_domains**: (Optional) the map of objects that defines the identity domains, where each object corresponds to an identity domain resource. + - **compartment_id**: (Optional) The compartment for the identity domain. This attribute is overloaded: it can be either a compartment OCID or a reference (a key) to the compartment OCID. *default_compartment_id* is used if undefined. See [External Dependencies](#extdep). + - **display_name**: (Required) The mutable display name for the identity domain. + - **description**: (Required) The description of the identity domain. + - **home_region**: (Required) The region name of the identity domain. The tenancy home region name is used if undefined. Example: us-ashburn-1 + - **license_type**: (Required) The license type of the identity domain. Examples: free, oracle-apps-premium, premium, external-user. + - **admin_email**: (Optional) The email address of the identity domain administrator. + - **admin_first_name**: (Optional) The first name of the identity domain administrator. + - **admin_last_name**: (Optional) The last name of the identity domain administrator. + - **admin_user_name**: (Optional) The username for the identity domain administrator. + - **is_hidden_on_login**: (Optional) Indicates whether the identity domain is hidden on login screen or not. Example: true + - **is_notification_bypassed**: Indicates if admin user created in the Identity Domain would like to receive notification like welcome email or not. Required field only if admin information is provided, otherwise optional. + - **is_primary_email_required**: (Optional) Indicates whether users in the domain are required to have a primary email address or not. Example: true + - **defined_tags**: (Optional) defined tags to apply to the identity domain. *default_defined_tags* is used if undefined. + - **freeform_tags**: (Optional) free tags to apply to the identity domain. *default_freeform_tags* is used if undefined. + +## Defining Identity Domain Groups +Use *identity_domain_groups_configuration* attribute. It supports the following attributes: + + - **default_identity_domain_id**: (Optional) defines the identity domain for all groups, unless overriden by *identity_domain_id* attribute within each group. This attribute is overloaded: it can be either an existing identity domain OCID (if provisioning the group in an existing identity domain) or the identity domain reference (key) in identity_domains map. + - **default_defined_tags**: (Optional) defined tags to apply to all resources, unless overriden by *defined_tags* attribute within each resource. + - **default_freeform_tags**: (Optional) freeform tags to apply to all resources, unless overriden by *freeform_tags* attribute within each resource. + - **groups**: (Optional) the map of objects that defines groups of users, where each object corresponds to a group resource. + - **identity_domain_id**: (Optional) The identity domain for the group. This attribute is overloaded: it can be either an existing identity domain OCID (if provisioning the group in an existing identity domain) or the identity domain reference (key) in identity_domains map. + - **name**: (Required) The display name of the group. + - **description**: (Optional) The description of the group. + - **requestable**: (Optional) Flag controlling whether group membership can be requested by users through self service console. Example: true + - **members**: (Optional) List of existing user names to assign to the group. + - **defined_tags**: (Optional) defined tags to apply to the group. *default_defined_tags* is used if undefined. + - **freeform_tags**: (Optional) free tags to apply to the group. *default_freeform_tags* is used if undefined. + +## Defining Identity Domain Dynamic Groups +Use *identity_domain_dynamic_groups_configuration* attribute. It supports the following attributes: + + - **default_identity_domain_id**: (Optional) defines the identity domain for all dynamic groups, unless overriden by *identity_domain_id* attribute within each dynamic group. This attribute is overloaded: it can be either an identity domain OCID or a reference (a key) to the identity domain OCID. + - **default_defined_tags**: (Optional) defined tags to apply to all resources, unless overriden by *defined_tags* attribute within each resource. + - **default_freeform_tags**: (Optional) freeform tags to apply to all resources, unless overriden by *freeform_tags* attribute within each resource. + - **dynamic_groups**: (Optional) the map of objects that defines dynamic groups, where each object corresponds to a dynamic group resource. + - **identity_domain_id**: (Optional) The identity domain for the dynamic group. This attribute is overloaded: it can be either an existing identity domain OCID (if provisioning the dynamic group in an existing identity domain) or the identity domain reference (key) in identity_domains map. + - **name**: (Required) The display name of the dynamic group. + - **description**: (Optional) The description of the dynamic group. + - **matching_rule**: (Required) An expression that defines the principals assigned to the dynamic group resource. + - **defined_tags**: (Optional) defined tags to apply to the group. *default_defined_tags* is used if undefined. + - **freeform_tags**: (Optional) free tags to apply to the group. *default_freeform_tags* is used if undefined. + +Check the [examples](./examples/) folder for module usage. Specifically, see [vision](./examples/vision/README.md) example to deploy two identity domains including groups and dynamic_groups. + +### External Dependencies + +An optional feature, external dependencies are resources managed elsewhere that resources managed by this module may depend on. The following dependencies are supported: + +- **compartments_dependency**: A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an *id* attribute with the compartment OCID. This mechanism allows for the usage of referring keys (instead of OCIDs) in identity domains *default_compartment_id* and *compartment_id* attributes. The module replaces the keys by the OCIDs provided within *compartments_dependency* map. Contents of *compartments_dependency is typically the output of a [Compartments module](../compartments/) client. + +## Related Documentation +- [Managing Identity Domains](https://docs.oracle.com/en-us/iaas/Content/Identity/domains/overview.htm) +- [Identity Domains in Terraform OCI Provider](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domain) + +## Known Issues +1. Terraform will not destroy identity domains. In order do destroy an identity domain, first run ```terraform destroy``` to destroy contained resources (groups, dynamic groups...). The error ```"Error: 412-PreConditionFailed, Cannot perform DELETE_DOMAIN operation on Domain with Status CREATED"``` is returned. Then deactivate and delete the identity domain(s) using the OCI console or OCI CLI, as in: +``` + oci iam domain deactivate --domain-id + oci iam domain delete --domain-id +``` + diff --git a/identity-domains/SPEC.md b/identity-domains/SPEC.md new file mode 100644 index 0000000..a037217 --- /dev/null +++ b/identity-domains/SPEC.md @@ -0,0 +1,47 @@ +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | < 1.3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_domain.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domain) | resource | +| [oci_identity_domains_dynamic_resource_group.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domains_dynamic_resource_group) | resource | +| [oci_identity_domains_group.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domains_group) | resource | +| [oci_identity_domain.dyngrp_domain](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_domain) | data source | +| [oci_identity_domain.grp_domain](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_domain) | data source | +| [oci_identity_domains_users.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_domains_users) | data source | +| [oci_identity_regions.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_regions) | data source | +| [oci_identity_tenancy.this](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_tenancy) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartments\_dependency](#input\_compartments\_dependency) | A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the compartment OCID) of string type. | `map(any)` | `null` | no | +| [identity\_domain\_dynamic\_groups\_configuration](#input\_identity\_domain\_dynamic\_groups\_configuration) | The identity domain dynamic groups configuration. |
object({
default_identity_domain_id = optional(string)
default_defined_tags = optional(map(string))
default_freeform_tags = optional(map(string))
dynamic_groups = map(object({
identity_domain_id = optional(string),
name = string,
description = optional(string),
matching_rule = string,
defined_tags = optional(map(string)),
freeform_tags = optional(map(string))
}))
})
| `null` | no | +| [identity\_domain\_groups\_configuration](#input\_identity\_domain\_groups\_configuration) | The identity domain groups configuration. |
object({
default_identity_domain_id = optional(string)
default_defined_tags = optional(map(string))
default_freeform_tags = optional(map(string))
groups = map(object({
identity_domain_id = optional(string),
name = string,
description = optional(string),
requestable = optional(bool),
members = optional(list(string)),
defined_tags = optional(map(string)),
freeform_tags = optional(map(string))
}))
})
| `null` | no | +| [identity\_domains\_configuration](#input\_identity\_domains\_configuration) | The identity domains configuration. |
object({
default_compartment_id = optional(string)
default_defined_tags = optional(map(string))
default_freeform_tags = optional(map(string))
identity_domains = map(object({
compartment_id = optional(string),
display_name = string,
description = string,
home_region = optional(string),
license_type = string,
admin_email = optional(string),
admin_first_name = optional(string),
admin_last_name = optional(string),
admin_user_name = optional(string),
is_hidden_on_login = optional(bool),
is_notification_bypassed = optional(bool),
is_primary_email_required = optional(bool),
defined_tags = optional(map(string)),
freeform_tags = optional(map(string))
}))
})
| `null` | no | +| [module\_name](#input\_module\_name) | The module name. | `string` | `"iam-identity-domains"` | no | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of the tenancy. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [identity\_domain\_dynamic\_groups](#output\_identity\_domain\_dynamic\_groups) | The identity domain groups | +| [identity\_domain\_groups](#output\_identity\_domain\_groups) | The identity domain groups | +| [identity\_domains](#output\_identity\_domains) | The identity domains. | diff --git a/identity-domains/dynamic-groups.tf b/identity-domains/dynamic-groups.tf new file mode 100644 index 0000000..c9d3f2e --- /dev/null +++ b/identity-domains/dynamic-groups.tf @@ -0,0 +1,39 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +data "oci_identity_domain" "dyngrp_domain" { + for_each = (var.identity_domain_dynamic_groups_configuration != null ) ? (var.identity_domain_dynamic_groups_configuration["dynamic_groups"] != null ? var.identity_domain_dynamic_groups_configuration["dynamic_groups"] : {}) : {} + domain_id = each.value.identity_domain_id != null ? each.value.identity_domain_id : var.identity_domain_dynamic_groups_configuration.default_identity_domain_id +} + +resource "oci_identity_domains_dynamic_resource_group" "these" { + for_each = var.identity_domain_dynamic_groups_configuration != null ? var.identity_domain_dynamic_groups_configuration.dynamic_groups : {} + + idcs_endpoint = contains(keys(oci_identity_domain.these),coalesce(each.value.identity_domain_id,"None")) ? oci_identity_domain.these[each.value.identity_domain_id].url : (contains(keys(oci_identity_domain.these),coalesce(var.identity_domain_dynamic_groups_configuration.default_identity_domain_id,"None") ) ? oci_identity_domain.these[var.identity_domain_dynamic_groups_configuration.default_identity_domain_id].url : data.oci_identity_domain.dyngrp_domain[each.key].url) + + display_name = each.value.name + schemas = ["urn:ietf:params:scim:schemas:oracle:idcs:DynamicResourceGroup"] + description = each.value.description + matching_rule = each.value.matching_rule + + + urnietfparamsscimschemasoracleidcsextension_oci_tags { + + dynamic "defined_tags" { + for_each = each.value.defined_tags != null ? each.value.defined_tags : (var.identity_domain_groups_configuration.default_defined_tags !=null ? var.identity_domain_groups_configuration.default_defined_tags : {}) + content { + key = split(".",defined_tags["key"])[1] + namespace = split(".",defined_tags["key"])[0] + value = defined_tags["value"] + } + } + + dynamic "freeform_tags" { + for_each = each.value.freeform_tags != null ? each.value.freeform_tags : (var.identity_domain_groups_configuration.default_freeform_tags !=null ? var.identity_domain_groups_configuration.default_freeform_tags : {}) + content { + key = freeform_tags["key"] + value = freeform_tags["value"] + } + } + + } +} \ No newline at end of file diff --git a/identity-domains/examples/existing-domains/README.md b/identity-domains/examples/existing-domains/README.md new file mode 100644 index 0000000..b3e6378 --- /dev/null +++ b/identity-domains/examples/existing-domains/README.md @@ -0,0 +1,26 @@ +# OCI Identity Domains Module Usage Example - Vision identity domains +## Introduction + +This example shows how to deploy Identity and Access Management (IAM) identity domain Groups and Dynamic Groups with existing Identity Domains in Oracle Cloud Infrastructure (OCI) for a hypothetical Vision entity. + +It creates the following resources in one or more preexisting identity domains: + + *Groups*: "Dev Group 1" and "Prod Group 1" + + *Dynamic Groups*: vision-sec-fun-dynamic-group, vision-appdev-fun-dynamic-group, vision-appdev-computeagent-dynamic-group, and vision-database-kms-dynamic-group + + + +## Using this example +1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice. + +**NOTE**: Each object in the *Groups* and *Dynamic Groups* map is indexed by an uppercase string, like *GRP1*, *GRP2*, *SEC-FUN-DYN-GROUP*, etc. These strings are used by Terraform as keys to the actual managed resources. They can actually be any random strings, but once defined they **must not be changed**, or Terraform will try to destroy and recreate the groups. + +2. Within *\*.auto.tfvars, provide tenancy connectivity information + +3. In this folder, run the typical Terraform workflow: +``` +terraform init +terraform plan -out plan.out +terraform apply plan.out +``` \ No newline at end of file diff --git a/identity-domains/examples/existing-domains/input.auto.tfvars.template b/identity-domains/examples/existing-domains/input.auto.tfvars.template new file mode 100644 index 0000000..e6d82b9 --- /dev/null +++ b/identity-domains/examples/existing-domains/input.auto.tfvars.template @@ -0,0 +1,79 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +#--------------------------------------------------------------------------------------------------------------------- +# 1. Rename this file to .auto.tfvars, where is any name of your choice. +# 2. Provide values for "Tenancy Connectivity Variables". + +# Each object in the *identity_domains* map is indexed by an uppercase string, like DEV-DOMAIN, QA-DOMAIN, etc. +# These strings are used by Terraform as keys to the actual managed resources. +# They can actually be any random strings, but once defined they MUST NOT BE CHANGED, +# or Terraform will try to destroy and recreate the identity domains. +#--------------------------------------------------------------------------------------------------------------------- + +#--------------------------------------- +# Tenancy Connectivity Variables +#--------------------------------------- + +tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: "). +user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile"). +fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side). +private_key_path = "" # This is the full path on your local system to the API signing private key. +private_key_password = "" # This is the password that protects the private key, if any. +region = "" # This is your tenancy home region. + + +#--------------------------------------- +# Input variable +#--------------------------------------- + +identity_domain_groups_configuration = { + default_identity_domain_id : "" + default_defined_tags : null + default_freeform_tags : null + + dynamic_groups = { + SEC-FUN-DYN-GROUP : { + identity_domain_id = ".auto.tfvars*, where *\* is any name of your choice. + +**NOTE**: Each object in the *Identity Domains*, *Groups* and *Dynamic Groups* map is indexed by an uppercase string, like *DEV-DOMAIN*, *DEV-COMPARTMENT*, *GRP1*, *SEC-FUN-DYN-GROUP*, etc. These strings are used by Terraform as keys to the actual managed resources. They can actually be any random strings, but once defined they **must not be changed**, or Terraform will try to destroy and recreate the groups. + +2. Within *\*.auto.tfvars, provide tenancy connectivity information + +3. In this folder, run the typical Terraform workflow: +``` +terraform init +terraform plan -out plan.out +terraform apply plan.out +``` \ No newline at end of file diff --git a/identity-domains/examples/external-dependency-Compartments/input.auto.tfvars.template b/identity-domains/examples/external-dependency-Compartments/input.auto.tfvars.template new file mode 100644 index 0000000..f50e0eb --- /dev/null +++ b/identity-domains/examples/external-dependency-Compartments/input.auto.tfvars.template @@ -0,0 +1,174 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +#--------------------------------------------------------------------------------------------------------------------- +# 1. Rename this file to .auto.tfvars, where is any name of your choice. +# 2. Provide values for "Tenancy Connectivity Variables". + +# Each object in the *identity_domains* map is indexed by an uppercase string, like DEV-DOMAIN, QA-DOMAIN, etc. +# These strings are used by Terraform as keys to the actual managed resources. +# They can actually be any random strings, but once defined they MUST NOT BE CHANGED, +# or Terraform will try to destroy and recreate the identity domains. +#--------------------------------------------------------------------------------------------------------------------- + +#--------------------------------------- +# Tenancy Connectivity Variables +#--------------------------------------- + +tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: "). +user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile"). +fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side). +private_key_path = "" # This is the full path on your local system to the API signing private key. +private_key_password = "" # This is the password that protects the private key, if any. +region = "" # This is your tenancy home region. + + +#--------------------------------------- +# Input variable +#--------------------------------------- + +identity_domains_configuration = { + #default_compartment_id : null + default_compartment_id : "DEV-COMPARTMENT" + default_defined_tags : null + default_freeform_tags : null + identity_domains : { + DEV-DOMAIN : { + compartment_id = null + display_name = "VISION_DEV_Identity_Domain" + description = "VISION DEV Identity Domain" + home_region = "us-ashburn-1" + license_type = "free" + + admin_email = "" + admin_first_name = "" + admin_last_name = "" + admin_user_name = "" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = false + + } + PROD-DOMAIN : { + compartment_id = "PROD-COMPARTMENT" + display_name = "VISION_PROD_Identity_Domain" + description = "VISION PROD Identity Domain" + home_region = "us-ashburn-1" + license_type = "free" + + admin_email = "" + admin_first_name = "" + admin_last_name = "" + admin_user_name = "" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = true + + } + + } +} + +identity_domains_configuration = { + #default_compartment_id : null + default_compartment_id : "DEV-COMPARTMENT" + default_defined_tags : null + default_freeform_tags : null + identity_domains : { + DEV-DOMAIN : { + compartment_id = null + display_name = "VISION_DEV_Identity_Domain" + description = "VISION DEV Identity Domain" + home_region = "" + license_type = "free" + + admin_email = "gsaurez@me.com" + admin_first_name = "Gustavo" + admin_last_name = "Saurez" + admin_user_name = "gsrz" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = false + + } + PROD-DOMAIN : { + compartment_id = "PROD-COMPARTMENT" + display_name = "VISION_PROD_Identity_Domain" + description = "VISION PROD Identity Domain" + home_region = "" + license_type = "free" + + admin_email = "gsaurez@me.com" + admin_first_name = "Gustavo" + admin_last_name = "Saurez" + admin_user_name = "gsaurez@me.com" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = true + + } + + } +} + +identity_domain_groups_configuration = { + default_identity_domain_id : "DEV-DOMAIN" + default_defined_tags : null + default_freeform_tags : null + groups : { + GRP1 : { + identity_domain_id = null + name = "devgroup1" + description = "Dev Group 1" + + } + GRP2 : { + identity_domain_id = "PROD-DOMAIN" + name = "prodgroup1" + description = "Prod Group 1" + } + } +} + +identity_domain_dynamic_groups_configuration = { + default_identity_domain_id : "PROD-DOMAIN" + default_defined_tags : null + default_freeform_tags : null + + dynamic_groups = { + SEC-FUN-DYN-GROUP : { + identity_domain_id = "DEV-DOMAIN" + name : "vision-sec-fun-dynamic-group", + description : "Dynamic group for security functions execution.", + matching_rule : "ALL {resource.type = 'fnfunc',resource.compartment.id = ''}" + }, + APPDEV-FUN-DYN-GROUP : { + name : "vision-appdev-fun-dynamic-group", + description : "Dynamic group for application functions execution.", + matching_rule : "ALL {resource.type = 'fnfunc',resource.compartment.id = ''}" + }, + APPDEV-COMPUTE-AGENT-DYN-GROUP : { + name : "vision-appdev-computeagent-dynamic-group", + description : "Dynamic group for Compute Agent plugin execution.", + matching_rule : "ALL {resource.type = 'managementagent',resource.compartment.id = ''}" + }, + DATABASE-KMS-DYN-GROUP : { + name : "vision-database-kms-dynamic-group", + description : "Dynamic group for databases accessing Key Management service (aka Vault service).", + matching_rule : "ALL {resource.compartment.id = ''}" + } + } +} + +oci_compartments_dependency = { + DEV-COMPARTMENT = { + id = ".auto.tfvars*, where *\* is any name of your choice. + +**NOTE**: Each object in the *Identity Domains*, *Groups* and *Dynamic Groups* map is indexed by an uppercase string, like *DEV-DOMAIN*, *PROD-DOMAIN*, *GRP1*, *SEC-FUN-DYN-GROUP*, etc. These strings are used by Terraform as keys to the actual managed resources. They can actually be any random strings, but once defined they **must not be changed**, or Terraform will try to destroy and recreate the groups. + +2. Within *\*.auto.tfvars, provide tenancy connectivity information + +3. In this folder, run the typical Terraform workflow: +``` +terraform init +terraform plan -out plan.out +terraform apply plan.out +``` \ No newline at end of file diff --git a/identity-domains/examples/vision/input.auto.tfvars.template b/identity-domains/examples/vision/input.auto.tfvars.template new file mode 100644 index 0000000..e007ce3 --- /dev/null +++ b/identity-domains/examples/vision/input.auto.tfvars.template @@ -0,0 +1,124 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +#--------------------------------------------------------------------------------------------------------------------- +# 1. Rename this file to .auto.tfvars, where is any name of your choice. +# 2. Provide values for "Tenancy Connectivity Variables". + +# Each object in the *identity_domains* map is indexed by an uppercase string, like DEV-DOMAIN, QA-DOMAIN, etc. +# These strings are used by Terraform as keys to the actual managed resources. +# They can actually be any random strings, but once defined they MUST NOT BE CHANGED, +# or Terraform will try to destroy and recreate the identity domains. +#--------------------------------------------------------------------------------------------------------------------- + +#--------------------------------------- +# Tenancy Connectivity Variables +#--------------------------------------- + +tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: "). +user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile"). +fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side). +private_key_path = "" # This is the full path on your local system to the API signing private key. +private_key_password = "" # This is the password that protects the private key, if any. +region = "" # This is your tenancy home region. + + +#--------------------------------------- +# Input variable +#--------------------------------------- + +identity_domains_configuration = { + #default_compartment_id : null + default_compartment_id : "" + default_defined_tags : null + default_freeform_tags : null + identity_domains : { + DEV-DOMAIN : { + compartment_id = null + display_name = "VISION_DEV_Identity_Domain" + description = "VISION DEV Identity Domain" + home_region = "" + license_type = "free" + + admin_email = "" + admin_first_name = "" + admin_last_name = "" + admin_user_name = "" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = false + + } + PROD-DOMAIN : { + compartment_id = "" + display_name = "VISION_PROD_Identity_Domain" + description = "VISION PROD Identity Domain" + home_region = "" + license_type = "free" + + admin_email = "" + admin_first_name = "" + admin_last_name = "" + admin_user_name = "" + + is_hidden_on_login = false + is_notification_bypassed = false + is_primary_email_required = true + + } + + } + + +} + + +identity_domain_groups_configuration = { + default_identity_domain_id : "DEV-DOMAIN" + default_defined_tags : null + default_freeform_tags : null + groups : { + GRP1 : { + identity_domain_id = null + name = "devgroup1" + description = "Dev Group 1" + + } + GRP2 : { + identity_domain_id = "PROD-DOMAIN" + name = "prodgroup1" + description = "Prod Group 1" + } + } +} + +identity_domain_dynamic_groups_configuration = { + default_identity_domain_id : "PROD-DOMAIN" + default_defined_tags : null + default_freeform_tags : null + + dynamic_groups = { + SEC-FUN-DYN-GROUP : { + identity_domain_id = "DEV-DOMAIN" + name : "vision-sec-fun-dynamic-group", + description : "Dynamic group for security functions execution.", + matching_rule : "ALL {resource.type = 'fnfunc',resource.compartment.id = ''}" + }, + APPDEV-FUN-DYN-GROUP : { + name : "vision-appdev-fun-dynamic-group", + description : "Dynamic group for application functions execution.", + matching_rule : "ALL {resource.type = 'fnfunc',resource.compartment.id = ''}" + }, + APPDEV-COMPUTE-AGENT-DYN-GROUP : { + name : "vision-appdev-computeagent-dynamic-group", + description : "Dynamic group for Compute Agent plugin execution.", + matching_rule : "ALL {resource.type = 'managementagent',resource.compartment.id = ''}" + }, + DATABASE-KMS-DYN-GROUP : { + name : "vision-database-kms-dynamic-group", + description : "Dynamic group for databases accessing Key Management service (aka Vault service).", + matching_rule : "ALL {resource.compartment.id = ''}" + } + } +} \ No newline at end of file diff --git a/identity-domains/examples/vision/main.tf b/identity-domains/examples/vision/main.tf new file mode 100644 index 0000000..bcc531c --- /dev/null +++ b/identity-domains/examples/vision/main.tf @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +module "vision_identity_domains" { + source = "../../" + tenancy_ocid = var.tenancy_ocid + identity_domains_configuration = var.identity_domains_configuration + identity_domain_groups_configuration = var.identity_domain_groups_configuration + identity_domain_dynamic_groups_configuration = var.identity_domain_dynamic_groups_configuration + +} \ No newline at end of file diff --git a/identity-domains/examples/vision/outputs.tf b/identity-domains/examples/vision/outputs.tf new file mode 100644 index 0000000..5c6b009 --- /dev/null +++ b/identity-domains/examples/vision/outputs.tf @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +output "identity-domains" { + description = "The identity domains." + value = module.vision_identity_domains.identity_domains +} + +output "identity-domain-groups" { + description = "The identity domain groups." + value = module.vision_identity_domains.identity_domain_groups +} + diff --git a/identity-domains/examples/vision/providers.tf b/identity-domains/examples/vision/providers.tf new file mode 100644 index 0000000..5061cb6 --- /dev/null +++ b/identity-domains/examples/vision/providers.tf @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +provider "oci" { + region = var.region + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + private_key_password = var.private_key_password +} + +terraform { + required_version = "< 1.3.0" + required_providers { + oci = { + source = "oracle/oci" + } + } + experiments = [module_variable_optional_attrs] +} \ No newline at end of file diff --git a/identity-domains/examples/vision/variables.tf b/identity-domains/examples/vision/variables.tf new file mode 100644 index 0000000..f5267e5 --- /dev/null +++ b/identity-domains/examples/vision/variables.tf @@ -0,0 +1,69 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +variable "tenancy_ocid" {} +variable "region" {description = "Your tenancy home region"} +variable "user_ocid" {default = ""} +variable "fingerprint" {default = ""} +variable "private_key_path" {default = ""} +variable "private_key_password" {default = ""} + +variable "identity_domains_configuration" { + description = "The identity domains configuration." + type = object({ + default_compartment_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + identity_domains = map(object({ + compartment_id = optional(string), + display_name = string, + description = string, + home_region = optional(string), + license_type = string, + admin_email = optional(string), + admin_first_name = optional(string), + admin_last_name = optional(string), + admin_user_name = optional(string), + is_hidden_on_login = optional(bool), + is_notification_bypassed = optional(bool), + is_primary_email_required = optional(bool), + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) + default = null +} + +variable "identity_domain_groups_configuration" { + description = "The identity domain groups configuration." + type = object({ + default_identity_domain_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + groups = map(object({ + identity_domain_id = optional(string), + name = string, + description = optional(string), + requestable = optional(bool) + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) +} + +variable "identity_domain_dynamic_groups_configuration" { + description = "The identity domain dynamic groups configuration." + type = object({ + default_identity_domain_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + dynamic_groups = map(object({ + identity_domain_id = optional(string), + name = string, + description = optional(string), + matching_rule = string, + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) +} diff --git a/identity-domains/groups.tf b/identity-domains/groups.tf new file mode 100644 index 0000000..c981637 --- /dev/null +++ b/identity-domains/groups.tf @@ -0,0 +1,70 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +data "oci_identity_domain" "grp_domain" { + for_each = (var.identity_domain_groups_configuration != null ) ? (var.identity_domain_groups_configuration["groups"] != null ? var.identity_domain_groups_configuration["groups"] : {}) : {} + domain_id = each.value.identity_domain_id != null ? each.value.identity_domain_id : var.identity_domain_groups_configuration.default_identity_domain_id +} + +data "oci_identity_domains_users" "these" { + + for_each = var.identity_domain_groups_configuration != null ? (var.identity_domain_groups_configuration.groups != null ? var.identity_domain_groups_configuration.groups : {} ): {} + idcs_endpoint = contains(keys(oci_identity_domain.these),coalesce(each.value.identity_domain_id,"None")) ? oci_identity_domain.these[each.value.identity_domain_id].url : (contains(keys(oci_identity_domain.these),coalesce(var.identity_domain_groups_configuration.default_identity_domain_id,"None") ) ? oci_identity_domain.these[var.identity_domain_groups_configuration.default_identity_domain_id].url : data.oci_identity_domain.grp_domain[each.key].url) + + +} + +locals { + users = { for k,g in (var.identity_domain_groups_configuration != null ? var.identity_domain_groups_configuration["groups"]: {}) : k => + { for u in data.oci_identity_domains_users.these[k].users : u.user_name => u.id}} +} + + + +resource "oci_identity_domains_group" "these" { + for_each = var.identity_domain_groups_configuration != null ? var.identity_domain_groups_configuration.groups : {} + + idcs_endpoint = contains(keys(oci_identity_domain.these),coalesce(each.value.identity_domain_id,"None")) ? oci_identity_domain.these[each.value.identity_domain_id].url : (contains(keys(oci_identity_domain.these),coalesce(var.identity_domain_groups_configuration.default_identity_domain_id,"None") ) ? oci_identity_domain.these[var.identity_domain_groups_configuration.default_identity_domain_id].url : data.oci_identity_domain.grp_domain[each.key].url) + + display_name = each.value.name + schemas = ["urn:ietf:params:scim:schemas:core:2.0:Group","urn:ietf:params:scim:schemas:oracle:idcs:extension:group:Group","urn:ietf:params:scim:schemas:extension:custom:2.0:Group"] + + urnietfparamsscimschemasoracleidcsextensiongroup_group { + creation_mechanism = "api" + description = each.value.description + } + + urnietfparamsscimschemasoracleidcsextensionrequestable_group { + requestable = each.value.requestable + } + + dynamic "members" { + for_each = each.value.members != null ? each.value.members : [] + content { + type = "User" + value = local.users[each.key][members["value"]] + + } + } + urnietfparamsscimschemasoracleidcsextension_oci_tags { + + dynamic "defined_tags" { + for_each = each.value.defined_tags != null ? each.value.defined_tags : (var.identity_domain_groups_configuration.default_defined_tags !=null ? var.identity_domain_groups_configuration.default_defined_tags : {}) + content { + key = split(".",defined_tags["key"])[1] + namespace = split(".",defined_tags["key"])[0] + value = defined_tags["value"] + } + } + + + dynamic "freeform_tags" { + for_each = each.value.freeform_tags != null ? each.value.freeform_tags : (var.identity_domain_groups_configuration.default_freeform_tags !=null ? var.identity_domain_groups_configuration.default_freeform_tags : {}) + content { + key = freeform_tags["key"] + value = freeform_tags["value"] + } + } + + } +} \ No newline at end of file diff --git a/identity-domains/main.tf b/identity-domains/main.tf new file mode 100644 index 0000000..27b094d --- /dev/null +++ b/identity-domains/main.tf @@ -0,0 +1,40 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +data "oci_identity_regions" "these" {} + +data "oci_identity_tenancy" "this" { + tenancy_id = var.tenancy_ocid +} + +locals { + regions_map = { for r in data.oci_identity_regions.these.regions : r.key => r.name } + home_region_key = data.oci_identity_tenancy.this.home_region_key +} + + + +resource "oci_identity_domain" "these" { + for_each = var.identity_domains_configuration != null ? var.identity_domains_configuration.identity_domains : {} + #compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.identity_domains_configuration.default_compartment_id)) > 0 ? var.identity_domains_configuration.default_compartment_id : var.compartments_dependency[var.identity_domains_configuration.default_compartment_id].id) + compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (var.identity_domains_configuration.default_compartment_id != null ? (length(regexall("^ocid1.*$", var.identity_domains_configuration.default_compartment_id)) > 0 ? var.identity_domains_configuration.default_compartment_id : var.compartments_dependency[var.identity_domains_configuration.default_compartment_id].id) : var.tenancy_ocid) + + + display_name = each.value.display_name + description = each.value.description + #home_region = each.value.home_region + home_region = each.value.home_region != null ? each.value.home_region : local.regions_map[local.home_region_key] + license_type = each.value.license_type + + admin_email = each.value.admin_email + admin_first_name = each.value.admin_first_name + admin_last_name = each.value.admin_last_name + admin_user_name = each.value.admin_user_name + + is_hidden_on_login = each.value.is_hidden_on_login + is_notification_bypassed = each.value.is_notification_bypassed + is_primary_email_required = each.value.is_primary_email_required + + defined_tags = each.value.defined_tags != null ? each.value.defined_tags : var.identity_domains_configuration.default_defined_tags != null ? var.identity_domains_configuration.default_defined_tags : null + freeform_tags = merge(local.cislz_module_tag, each.value.freeform_tags != null ? each.value.freeform_tags : var.identity_domains_configuration.default_freeform_tags != null ? var.identity_domains_configuration.default_freeform_tags : null) +} \ No newline at end of file diff --git a/identity-domains/metadata.tf b/identity-domains/metadata.tf new file mode 100644 index 0000000..bf48fbe --- /dev/null +++ b/identity-domains/metadata.tf @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +#-- Used to inform module and release number. +locals { + cislz_module_tag = {"cislz-terraform-module" : fileexists("${path.module}/../release.txt") ? "${var.module_name}/${file("${path.module}/../release.txt")}" : "${var.module_name}"} +} \ No newline at end of file diff --git a/identity-domains/outputs.tf b/identity-domains/outputs.tf new file mode 100644 index 0000000..879d78a --- /dev/null +++ b/identity-domains/outputs.tf @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +output "identity_domains" { + description = "The identity domains." + value = oci_identity_domain.these +} + +output "identity_domain_groups" { + description = "The identity domain groups" + value = oci_identity_domains_group.these +} + +output "identity_domain_dynamic_groups" { + description = "The identity domain groups" + value = oci_identity_domains_dynamic_resource_group.these +} + diff --git a/identity-domains/providers.tf b/identity-domains/providers.tf new file mode 100644 index 0000000..410f000 --- /dev/null +++ b/identity-domains/providers.tf @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +terraform { + required_version = "< 1.3.0" + required_providers { + oci = { + source = "oracle/oci" + } + } + experiments = [module_variable_optional_attrs] +} \ No newline at end of file diff --git a/identity-domains/variables.tf b/identity-domains/variables.tf new file mode 100644 index 0000000..86055ad --- /dev/null +++ b/identity-domains/variables.tf @@ -0,0 +1,82 @@ +# Copyright (c) 2023 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +variable "tenancy_ocid" { + type = string + description = "The OCID of the tenancy." +} + +variable "identity_domains_configuration" { + description = "The identity domains configuration." + type = object({ + default_compartment_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + identity_domains = map(object({ + compartment_id = optional(string), + display_name = string, + description = string, + home_region = optional(string), + license_type = string, + admin_email = optional(string), + admin_first_name = optional(string), + admin_last_name = optional(string), + admin_user_name = optional(string), + is_hidden_on_login = optional(bool), + is_notification_bypassed = optional(bool), + is_primary_email_required = optional(bool), + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) + default = null +} + +variable "identity_domain_groups_configuration" { + description = "The identity domain groups configuration." + type = object({ + default_identity_domain_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + groups = map(object({ + identity_domain_id = optional(string), + name = string, + description = optional(string), + requestable = optional(bool), + members = optional(list(string)), + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) + default = null +} + +variable "identity_domain_dynamic_groups_configuration" { + description = "The identity domain dynamic groups configuration." + type = object({ + default_identity_domain_id = optional(string) + default_defined_tags = optional(map(string)) + default_freeform_tags = optional(map(string)) + dynamic_groups = map(object({ + identity_domain_id = optional(string), + name = string, + description = optional(string), + matching_rule = string, + defined_tags = optional(map(string)), + freeform_tags = optional(map(string)) + })) + }) + default = null +} + +variable module_name { + description = "The module name." + type = string + default = "iam-identity-domains" +} + +variable compartments_dependency { + description = "A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the compartment OCID) of string type." + type = map(any) + default = null +} diff --git a/policies/README.md b/policies/README.md index d315fac..93905d3 100644 --- a/policies/README.md +++ b/policies/README.md @@ -250,7 +250,7 @@ Currently supported values: - **exainfra**: compartment´s intent to hold *Exatada Cloud Service Infrastructure* related resources, hence this value drives the creation of *Exatada Cloud Service infrastructure* policies. - **enclosing**: drives the creation of policies that are scoped to more than one compartment, as a compartment tagged as *enclosing* is intended to be the parent of above compartment types. -**Note**: Multiple values can be assigned to *cislz-cmp-type*, as a comma separated list. +**Note**: Multiple values can be assigned to *cislz-cmp-type*, as a comma separated string of values. ##### cislz-consumer-groups-\ Attribute @@ -260,7 +260,7 @@ The *cislz-consumer-groups-\* metadata attributes define the groups tha Picture the use case where a single compartment provide network and security services. It might be the case it requires distinct administrators for network and security resources. Moreover, distinct database administrators (Dev admin and Prod admin) may need access to those resources. In this scenario, the compartment metadata would be like: ``` -cislz-cmp-type: "network", "security" +cislz-cmp-type: "network,security" cislz-consumer-groups-network: "network-admin" cislz-consumer-groups-security: "security-admin" cislz-consumer-groups-database: "dev-database-admin", "prod-database-admin" diff --git a/policies/application_cmp_policy.tf b/policies/application_cmp_policy.tf index 004ddc8..766ff80 100644 --- a/policies/application_cmp_policy.tf +++ b/policies/application_cmp_policy.tf @@ -82,8 +82,7 @@ locals { application_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-application-policy")) => { - #name = "${local.cmp_policy_name_prefix}${values["name"]}-application${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-application${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-application${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") compartment_ocid = values.ocid description = "CIS Landing Zone policy for Application compartment." defined_tags = var.policies_configuration.defined_tags @@ -92,6 +91,6 @@ locals { local.storage_admin_grants_on_application_cmp_map[k],local.security_admin_grants_on_application_cmp_map[k], local.compute_agent_grants_on_application_cmp_map[k]) } - if values["cmp-type"] == "application" + if contains(split(",",values["cmp-type"]),"application") } } \ No newline at end of file diff --git a/policies/database_cmp_policy.tf b/policies/database_cmp_policy.tf index 2cb1f45..d01e706 100644 --- a/policies/database_cmp_policy.tf +++ b/policies/database_cmp_policy.tf @@ -87,8 +87,7 @@ locals { database_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-database-policy")) => { - #name = "${local.cmp_policy_name_prefix}${values["name"]}-database${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-database${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-database${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") compartment_ocid = values.ocid description = "CIS Landing Zone policy for Database compartment." defined_tags = var.policies_configuration.defined_tags @@ -97,6 +96,6 @@ locals { local.appdev_admin_grants_on_database_cmp_map[k],local.storage_admin_grants_on_database_cmp_map[k], local.security_admin_grants_on_database_cmp_map[k], local.database_kms_grants_on_database_cmp_map[k]) } - if values["cmp-type"] == "database" + if contains(split(",",values["cmp-type"]),"database") } } \ No newline at end of file diff --git a/policies/enclosing_cmp_policy.tf b/policies/enclosing_cmp_policy.tf index e35420e..0f1cb1a 100644 --- a/policies/enclosing_cmp_policy.tf +++ b/policies/enclosing_cmp_policy.tf @@ -68,8 +68,7 @@ locals { enclosing_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-enclosing-policy")) => { - #name = values["ocid"] != var.tenancy_ocid ? "${local.cmp_policy_name_prefix}${values["name"]}-enclosing-${random_string.this.result}${local.policy_name_suffix}" : "${local.cmp_policy_name_prefix}${k}-enclosing-${random_string.this.result}${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-enclosing${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-enclosing${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") compartment_ocid = values.ocid description = "CIS Landing Zone policy for enclosing compartment." defined_tags = var.policies_configuration.defined_tags @@ -77,7 +76,7 @@ locals { statements = concat(local.read_grants_on_enclosing_cmp_map[k],local.iam_admin_grants_on_enclosing_cmp_map[k], local.security_admin_grants_on_enclosing_cmp_map[k],local.application_admin_grants_on_enclosing_cmp_map[k]) } - if values["cmp-type"] == "enclosing" + if contains(split(",",values["cmp-type"]),"enclosing") } } diff --git a/policies/exainfra_cmp_policy.tf b/policies/exainfra_cmp_policy.tf index 46b069e..ffc8c06 100644 --- a/policies/exainfra_cmp_policy.tf +++ b/policies/exainfra_cmp_policy.tf @@ -60,8 +60,7 @@ locals { exainfra_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-exainfra-policy")) => { - #name = "${local.cmp_policy_name_prefix}${values["name"]}-exainfra${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-exainfra${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-exainfra${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") compartment_ocid = values.ocid description = "CIS Landing Zone policy for Exadata Cloud Service infrastructure compartment." defined_tags = var.policies_configuration.defined_tags @@ -71,6 +70,6 @@ locals { local.database_admin_grants_on_exainfra_cmp_map[k], local.security_admin_grants_on_exainfra_cmp_map[k]) } - if values["cmp-type"] == "exainfra" + if contains(split(",",values["cmp-type"]),"exainfra") } } \ No newline at end of file diff --git a/policies/network_cmp_policy.tf b/policies/network_cmp_policy.tf index 5fad903..e80b786 100644 --- a/policies/network_cmp_policy.tf +++ b/policies/network_cmp_policy.tf @@ -92,8 +92,7 @@ locals { network_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-network-policy")) => { - #name = "${local.cmp_policy_name_prefix}${values["name"]}-network${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-network${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-network${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") compartment_ocid = values.ocid description = "CIS Landing Zone policy for Network compartment." defined_tags = var.policies_configuration.defined_tags @@ -103,6 +102,6 @@ locals { #local.database_admin_grants_on_network_cmp_map[k],local.exainfra_admin_grants_on_network_cmp_map[k], local.common_admin_grants_on_network_cmp_map[k], local.storage_admin_grants_on_network_cmp_map[k]) } - if values["cmp-type"] == "network" + if contains(split(",",values["cmp-type"]),"network") } } \ No newline at end of file diff --git a/policies/security_cmp_policy.tf b/policies/security_cmp_policy.tf index 09366a8..887691c 100644 --- a/policies/security_cmp_policy.tf +++ b/policies/security_cmp_policy.tf @@ -89,16 +89,15 @@ locals { security_cmps_policies = { for k, values in local.cmp_name_to_cislz_tag_map : (upper("${k}-security-policy")) => { - #name = "${local.cmp_policy_name_prefix}${values["name"]}-security${local.policy_name_suffix}" - name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? "${values["name"]}${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}" - compartment_ocid : values.ocid - description : "CIS Landing Zone policy for Security compartment." - defined_tags : var.policies_configuration.defined_tags - freeform_tags : var.policies_configuration.freeform_tags - statements : concat(local.security_read_grants_on_security_cmp_map[k],local.security_admin_grants_on_security_cmp_map[k], + name = length(regexall("^${local.policy_name_prefix}", values["name"])) > 0 ? (length(split(",",values["cmp-type"])) > 1 ? "${values["name"]}-security${local.policy_name_suffix}" : "${values["name"]}${local.policy_name_suffix}") : (length(split(",",values["cmp-type"])) > 1 ? "${local.policy_name_prefix}${values["name"]}-security${local.policy_name_suffix}" : "${local.policy_name_prefix}${values["name"]}${local.policy_name_suffix}") + compartment_ocid = values.ocid + description = "CIS Landing Zone policy for Security compartment." + defined_tags = var.policies_configuration.defined_tags + freeform_tags = var.policies_configuration.freeform_tags + statements = concat(local.security_read_grants_on_security_cmp_map[k],local.security_admin_grants_on_security_cmp_map[k], local.common_grants_on_security_cmp_map[k], local.storage_admin_grants_on_security_cmp_map[k],local.database_kms_grants_on_security_cmp_map[k]) } - if values["cmp-type"] == "security" + if contains(split(",",values["cmp-type"]),"security") } } diff --git a/release.txt b/release.txt index c946ee6..1180819 100644 --- a/release.txt +++ b/release.txt @@ -1 +1 @@ -0.1.6 +0.1.7