cloud-foundation-fabric/modules/organization-policy
Julio Castillo 1a3bb25917 Update provider version (needed for dns logging support). 2022-10-25 12:15:02 +02:00
..
README.md Test documentation examples in the examples/ folder 2022-09-06 17:46:09 +02:00
main.tf Simplified module interface, proper data structure for policies 2022-07-08 12:24:18 +02:00
outputs.tf Simplified module interface, proper data structure for policies 2022-07-08 12:24:18 +02:00
variables.tf Simplified module interface, proper data structure for policies 2022-07-08 12:24:18 +02:00
versions.tf Update provider version (needed for dns logging support). 2022-10-25 12:15:02 +02:00

README.md

Google Cloud Organization Policy

This module allows creation and management of GCP Organization Policies by defining them in a well formatted yaml files or with HCL.

Yaml based factory can simplify centralized management of Org Policies for a DevSecOps team by providing a simple way to define/structure policies and exclusions.

NOTE: This module uses experimental feature module_variable_optional_attrs which will be included into terraform release 1.3.

Example

Terraform code

# using configuration provided in a set of yaml files
module "org-policy-factory" {
  source = "./fabric/modules/organization-policy"

  config_directory = "./policies"
}

# using configuration provided in the module variable
module "org-policy" {
  source = "./fabric/modules/organization-policy"
  
  policies = {
    "folders/1234567890" = {
      # enforce boolean policy with no conditions
      "iam.disableServiceAccountKeyUpload" = {
        rules = [
          {
            enforce = true
          }
        ]
      },
      # Deny All for compute.vmCanIpForward policy
      "compute.vmCanIpForward" = {
        inherit_from_parent = false
        rules = [
          deny = [] # stands for deny_all
        ]
      }
    },
    "organizations/1234567890" = {
      # allow only internal ingress when match condition env=prod
      "run.allowedIngress" = {
        rules = [
          {
            allow = ["internal"]
            condition = {
              description= "allow ingress"
              expression = "resource.matchTag('123456789/environment', 'prod')"
              title = "allow-for-prod-org"
            }
          }
        ]
      }
    }
  } 
}
# tftest skip

Org Policy definition format and structure

Structure of policies variable

policies = {
  "parent_id" = { # parent id in format projects/project-id, folders/1234567890 or organizations/1234567890.
    "policy_name" = { # policy constraint id, for example compute.vmExternalIpAccess.
      inherit_from_parent = true|false # (Optional) Only for list constraints. Determines the inheritance behavior for this policy.
      reset               = true|false # (Optional) Ignores policies set above this resource and restores the constraint_default enforcement behavior.
      rules               = [ # Up to 10 PolicyRules are allowed.
        {
          allow = ["value1", "value2"] # (Optional) Only for list constraints. Stands for `allow_all` if set to empty list `[]` or to `values.allowed_values` if set to a list of values
          denyl = ["value3", "value4"] # (Optional) Only for list constraints. Stands for `deny_all` if set to empty list `[]` or to `values.denied_values` if set to a list of values
          enforce   = true|false       # (Optional) Only for boolean constraints. If true, then the Policy is enforced.
          condition = {                # (Optional) A condition which determines whether this rule is used in the evaluation of the policy.
            description = "Condition description" # (Optional)
            expression  = "Condition expression"  # (Optional) For example "resource.matchTag('123456789/environment', 'prod')".
            location    = "policy-error.log"      # (Optional) String indicating the location of the expression for error reporting.
            title       = "condition-title"       # (Optional)
          }
        }
      ]
    }
  }
}
# tftest skip

Structure of configuration provided in a yaml file/s

Configuration should be placed in a set of yaml files in the config directory. Policy entry structure as follows:

parent_id: # parent id in format projects/project-id, folders/1234567890 or organizations/1234567890.
  policy_name1: # policy constraint id, for example compute.vmExternalIpAccess.
    inherit_from_parent: true|false # (Optional) Only for list constraints. Determines the inheritance behavior for this policy.
    reset: true|false               # (Optional) Ignores policies set above this resource and restores the constraint_default enforcement behavior.
    rules:
      - allow: ["value1", "value2"] # (Optional) Only for list constraints. Stands for `allow_all` if set to empty list `[]` or to `values.allowed_values` if set to a list of values
        deny: ["value3", "value4"] # (Optional) Only for list constraints. Stands for `deny_all` if set to empty list `[]` or to `values.denied_values` if set to a list of values
        enforce: true|false   # (Optional) Only for boolean constraints. If true, then the Policy is enforced.
        condition:            # (Optional) A condition which determines whether this rule is used in the evaluation of the policy.
          description: Condition description   # (Optional)
          expression: Condition expression     # (Optional) For example resource.matchTag("123456789/environment", "prod")
          location: policy-error.log           # (Optional) String indicating the location of the expression for error reporting.
          title: condition-title               # (Optional)

Module allows policies to be distributed into multiple yaml files for a better management and navigation.

├── org-policies
│   ├── baseline.yaml
│   ├── image-import-projects.yaml
│   └── exclusions.yaml

Organization policies example yaml configuration

cat ./policies/baseline.yaml
organizations/1234567890:
  constraints/compute.vmExternalIpAccess:
    rules:
      - deny: [] # Stands for deny_all = true
folders/1234567890:
  compute.vmCanIpForward:
    inherit_from_parent: false
    reset: false
    rules:
      - allow: [] # Stands for allow_all = true
projects/my-project-id:
  run.allowedIngress:
    inherit_from_parent: true
    rules:
      - allow: ['internal'] # Stands for values.allowed_values
        condition:
          description: allow internal ingress
          expression: resource.matchTag("123456789/environment", "prod")
          location: test.log
          title: allow-for-prod
  iam.allowServiceAccountCredentialLifetimeExtension:
    rules:
      - deny: [] # Stands for deny_all = true
  compute.disableGlobalLoadBalancing:
    reset: true

Variables

name description type required default
config_directory Paths to a folder where organization policy configs are stored in yaml format. Files suffix must be .yaml. string null
policies Organization policies keyed by parent in format projects/project-id, folders/1234567890 or organizations/1234567890. map(map(object({…}))) {}

Outputs

name description sensitive
policies Organization policies.