OCI,Terraform & IaC : Creating Compartments for CIS Foundation Architecture

OCI,Terraform & IaC : Creating Compartments for CIS Foundation Architecture

In this third blog post series , we will be creating 4 main compartments

  • Security Compartment
  • Network Compartment
  • App/Dev Compartment
  • Database Compartment

The compartments above are based on the CIS Foundation Architecture, which is an architecture that starts with the compartment design for the tenancy along with groups and policies for segregation of duties.

We will be using what we created in the past blog post, and we will just build on that. 

The first thing I did was now instead of using a set value for the compartment resource, I use the for_each Meta-Argument. Terraform will create one instance of the resource for each member of that map or set. With the exception of the var.compartment_ocid, I will be grabbing the values from var.compartments object map.

resource "oci_identity_compartment" "cmpts" {
  for_each = var.compartments
    name           = each.value.name
    description    = each.value.description
    enable_delete  = each.value.enable_delete
    compartment_id = var.compartment_ocid

    provisioner "local-exec" {
    command = "sleep 60"
  }
}

The other change that I did, was in the variables.tf, which was add a complex datatype variable object map called compartments.

A map is a data structure that allows you to store and manage a collection of key-value pairs. Maps are often used to define input variables, output values, and resource configurations. An object is a structural type that can hold several types of values. It is a set of named attributes, each with its own type.

I did it this way, as later on I will be setting the default values out of the object, but for now, this is just to show that we can create. I used the names and description from the actual CIS Foundation Landing Zone, no need to reinvent the wheel.

variable "compartments" {
  type = map(object({
    name          = string
    description   = string
    enable_delete = string
  }))
  default = {
    key1 = {
      name = "network-cmp"
      description ="CIS Landing Zone compartment for all network related resources: VCNs, subnets, network gateways, security lists, NSGs, load balancers, VNICs, and others." 
      enable_delete = "false"
    }
    key2 = {
      name = "security-cmp"
      description = "CIS Landing Zone compartment for all security related resources: vaults, topics, notifications, logging, scanning, and others."
      enable_delete = "false"
    }
    key3 = {
      name = "appdev-cmp"
      description= "CIS Landing Zone compartment for all security related resources: vaults, topics, notifications, logging, scanning, and others."
      enable_delete = "true"
    }
    key4 = {
      name = "database-cmp"
      description= "CIS Landing Zone compartment for all database related resources."
      enable_delete = "true"
    }
  }
}

Last, we will modify the outputs.tf so that we can show the result of each compartment resource we created. We use a for Expression, which its  input can be a list, a set, a tuple, a map, or an object. It is important to note that

The type of brackets around the for expression decide what type of result it produces. The [ and ], produces a tuple. If you use { and } instead, the result is an object and you must provide two result expressions that are separated by the =>symbol, this expression produces an object whose attributes are the original elements.

output "compartments" {
  description = "The compartments, indexed by keys in var.compartments."
  value = {for k, v in var.compartments : k => oci_identity_compartment.cmpts[k]}
} 

The result of the changes we have mentioned so creates 4 compartments and below is the output. 

[opc@oracle-rene-cloud-ace vol02_compartment_cis]$ terraform apply
data.oci_identity_availability_domains.ADs: Reading...
data.oci_identity_region_subscriptions.home_region_subscriptions: Reading...
data.oci_identity_availability_domains.ADs: Read complete after 0s [id=IdentityAvailabilityDomainsDataSource-2545584872]
data.oci_identity_region_subscriptions.home_region_subscriptions: Read complete after 0s [id=IdentityRegionSubscriptionsDataSource-2545584872]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_identity_compartment.these["key1"] will be created
  + resource "oci_identity_compartment" "these" {
      + compartment_id = "ocid1.compartment.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      + defined_tags   = (known after apply)
      + description    = "CIS Landing Zone compartment for all network related resources: VCNs, subnets, network gateways, security lists, NSGs, load balancers, VNICs, and others."
      + enable_delete  = false
      + freeform_tags  = (known after apply)
      + id             = (known after apply)
      + inactive_state = (known after apply)
      + is_accessible  = (known after apply)
      + name           = "network-cmp"
      + state          = (known after apply)
      + time_created   = (known after apply)
    }
...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

oci_identity_compartment.these["key1"]: Creating...
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

compartments = {
  "key1" = {
    "compartment_id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "defined_tags" = tomap({
      "Oracle-Tags.CreatedBy" = "default/[email protected]"
      "Oracle-Tags.CreatedOn" = "2024-02-15T19:33:47.798Z"
    })
    "description" = "CIS Landing Zone compartment for all network related resources: VCNs, subnets, network gateways, security lists, NSGs, load balancers, VNICs, and others."
    "enable_delete" = false
    "freeform_tags" = tomap({})
    "id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "inactive_state" = tostring(null)
    "is_accessible" = true
    "name" = "network-cmp"
    "state" = "ACTIVE"
    "time_created" = "2024-02-15 19:33:47.863 +0000 UTC"
    "timeouts" = null /* object */
  }
  "key2" = {
    "compartment_id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "defined_tags" = tomap({
      "Oracle-Tags.CreatedBy" = "default/[email protected]"
      "Oracle-Tags.CreatedOn" = "2024-02-15T19:33:47.796Z"
    })
    "description" = "CIS Landing Zone compartment for all security related resources: vaults, topics, notifications, logging, scanning, and others."
    "enable_delete" = false
    "freeform_tags" = tomap({})
    "id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "inactive_state" = tostring(null)
    "is_accessible" = true
    "name" = "security-cmp"
    "state" = "ACTIVE"
    "time_created" = "2024-02-15 19:33:48.258 +0000 UTC"
    "timeouts" = null /* object */
  }
  "key3" = {
    "compartment_id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "defined_tags" = tomap({
      "Oracle-Tags.CreatedBy" = "default/[email protected]"
      "Oracle-Tags.CreatedOn" = "2024-02-15T19:33:47.822Z"
    })
    "description" = "CIS Landing Zone compartment for all security related resources: vaults, topics, notifications, logging, scanning, and others."
    "enable_delete" = true
    "freeform_tags" = tomap({})
    "id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "inactive_state" = tostring(null)
    "is_accessible" = true
    "name" = "appdev-cmp"
    "state" = "ACTIVE"
    "time_created" = "2024-02-15 19:33:49.203 +0000 UTC"
    "timeouts" = null /* object */
  }
  "key4" = {
    "compartment_id" = "ocid1.compartment.oc1.. aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "defined_tags" = tomap({
      "Oracle-Tags.CreatedBy" = "default/[email protected]"
      "Oracle-Tags.CreatedOn" = "2024-02-15T19:33:47.802Z"
    })
    "description" = "CIS Landing Zone compartment for all database related resources."
    "enable_delete" = true
    "freeform_tags" = tomap({})
    "id" = "ocid1.compartment.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "inactive_state" = tostring(null)
    "is_accessible" = true
    "name" = "database-cmp"
    "state" = "ACTIVE"
    "time_created" = "2024-02-15 19:33:48.659 +0000 UTC"
    "timeouts" = null /* object */
  }
}

Conclusion

In this blog post, we discussed the CIS Foundations Landing Zone, how to use complex data types and for Expressions. In the next series we will delve into creating a VCN and start having more fun with Terraform

Tags:
, ,
Rene Antunez
[email protected]
No Comments

Sorry, the comment form is closed at this time.