Skip to content

Commit

Permalink
Merge pull request #945 from GoogleCloudPlatform/jccb/org-policy-factory
Browse files Browse the repository at this point in the history
Org policy factory
  • Loading branch information
juliocc authored Nov 3, 2022
2 parents eae0f96 + ecda25d commit 8b786a7
Show file tree
Hide file tree
Showing 19 changed files with 598 additions and 240 deletions.
9 changes: 7 additions & 2 deletions modules/folder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ module "folder" {
# tftest modules=1 resources=8
```

### Organization policy factory

See the [organization policy factory in the project module](../project#organization-policy-factory).

### Firewall policy factory

In the same way as for the [organization](../organization) module, the in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run `terraform`).
Expand Down Expand Up @@ -311,8 +315,9 @@ module "folder" {
| [logging_sinks](variables.tf#L105) | Logging sinks to create for this folder. | <code title="map&#40;object&#40;&#123;&#10; destination &#61; string&#10; type &#61; string&#10; filter &#61; string&#10; include_children &#61; bool&#10; exclusions &#61; map&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [name](variables.tf#L126) | Folder name. | <code>string</code> | | <code>null</code> |
| [org_policies](variables.tf#L132) | Organization policies applied to this folder keyed by policy name. | <code title="map&#40;object&#40;&#123;&#10; inherit_from_parent &#61; optional&#40;bool&#41; &#35; for list policies only.&#10; reset &#61; optional&#40;bool&#41;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; condition &#61; object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; expression &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; title &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [parent](variables.tf#L172) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L182) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [org_policies_data_path](variables.tf#L172) | | <code>string</code> | | <code>null</code> |
| [parent](variables.tf#L178) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L188) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |

## Outputs

Expand Down
51 changes: 50 additions & 1 deletion modules/folder/organization-policies.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,57 @@
# tfdoc:file:description Folder-level organization policies.

locals {
_factory_data_raw = (
var.org_policies_data_path == null
? tomap({})
: merge([
for f in fileset(var.org_policies_data_path, "*.yaml") :
yamldecode(file("${var.org_policies_data_path}/${f}"))
]...)
)

# simulate applying defaults to data coming from yaml files
_factory_data = {
for k, v in local._factory_data_raw :
k => {
inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, null)
allow = can(v.allow) ? {
all = try(v.allow.all, null)
values = try(v.allow.values, null)
} : null
deny = can(v.deny) ? {
all = try(v.deny.all, null)
values = try(v.deny.values, null)
} : null
enforce = try(v.enforce, true)

rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
all = try(r.allow.all, null)
values = try(r.allow.values, null)
} : null
deny = can(r.deny) ? {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
} : null
enforce = try(r.enforce, true)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
location = try(r.condition.location, null)
title = try(r.condition.title, null)
}
}
]
}
}

_org_policies = merge(local._factory_data, var.org_policies)

org_policies = {
for k, v in var.org_policies :
for k, v in local._org_policies :
k => merge(v, {
name = "${local.folder.name}/policies/${k}"
parent = local.folder.name
Expand Down
6 changes: 6 additions & 0 deletions modules/folder/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ variable "org_policies" {
nullable = false
}

variable "org_policies_data_path" {
description = ""
type = string
default = null
}

variable "parent" {
description = "Parent in folders/folder_id or organizations/org_id format."
type = string
Expand Down
9 changes: 7 additions & 2 deletions modules/organization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ If you set audit policies via the `iam_audit_config_authoritative` variable, be

Some care must also be takend with the `groups_iam` variable (and in some situations with the additive variables) to ensure that variable keys are static values, so that Terraform is able to compute the dependency graph.

### Organization policy factory

See the [organization policy factory in the project module](../project#organization-policy-factory).

## Hierarchical firewall policies

Hirerarchical firewall policies can be managed in two ways:
Expand Down Expand Up @@ -336,8 +340,9 @@ module "org" {
| [logging_exclusions](variables.tf#L122) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_sinks](variables.tf#L129) | Logging sinks to create for this organization. | <code title="map&#40;object&#40;&#123;&#10; destination &#61; string&#10; type &#61; string&#10; filter &#61; string&#10; include_children &#61; bool&#10; bq_partitioned_table &#61; bool&#10; exclusions &#61; map&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies](variables.tf#L151) | Organization policies applied to this organization keyed by policy name. | <code title="map&#40;object&#40;&#123;&#10; inherit_from_parent &#61; optional&#40;bool&#41; &#35; for list policies only.&#10; reset &#61; optional&#40;bool&#41;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; condition &#61; object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; expression &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; title &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L200) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables.tf#L206) | Tags by key name. The `iam` attribute behaves like the similarly named one at module level. | <code title="map&#40;object&#40;&#123;&#10; description &#61; string&#10; iam &#61; map&#40;list&#40;string&#41;&#41;&#10; values &#61; map&#40;object&#40;&#123;&#10; description &#61; string&#10; iam &#61; map&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [org_policies_data_path](variables.tf#L200) | | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L206) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables.tf#L212) | Tags by key name. The `iam` attribute behaves like the similarly named one at module level. | <code title="map&#40;object&#40;&#123;&#10; description &#61; string&#10; iam &#61; map&#40;list&#40;string&#41;&#41;&#10; values &#61; map&#40;object&#40;&#123;&#10; description &#61; string&#10; iam &#61; map&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |

## Outputs

Expand Down
51 changes: 50 additions & 1 deletion modules/organization/organization-policies.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,57 @@
# tfdoc:file:description Organization-level organization policies.

locals {
_factory_data_raw = (
var.org_policies_data_path == null
? tomap({})
: merge([
for f in fileset(var.org_policies_data_path, "*.yaml") :
yamldecode(file("${var.org_policies_data_path}/${f}"))
]...)
)

# simulate applying defaults to data coming from yaml files
_factory_data = {
for k, v in local._factory_data_raw :
k => {
inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, null)
allow = can(v.allow) ? {
all = try(v.allow.all, null)
values = try(v.allow.values, null)
} : null
deny = can(v.deny) ? {
all = try(v.deny.all, null)
values = try(v.deny.values, null)
} : null
enforce = try(v.enforce, true)

rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
all = try(r.allow.all, null)
values = try(r.allow.values, null)
} : null
deny = can(r.deny) ? {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
} : null
enforce = try(r.enforce, true)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
location = try(r.condition.location, null)
title = try(r.condition.title, null)
}
}
]
}
}

_org_policies = merge(local._factory_data, var.org_policies)

org_policies = {
for k, v in var.org_policies :
for k, v in local._org_policies :
k => merge(v, {
name = "${var.organization_id}/policies/${k}"
parent = var.organization_id
Expand Down
6 changes: 6 additions & 0 deletions modules/organization/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ variable "organization_id" {
}
}

variable "org_policies_data_path" {
description = ""
type = string
default = null
}

variable "tag_bindings" {
description = "Tag bindings for this organization, in key => tag value id format."
type = map(string)
Expand Down
Loading

0 comments on commit 8b786a7

Please sign in to comment.