Add tests for org policy custom constraints

This commit is contained in:
Aleksandr Averbukh 2022-11-08 18:10:13 +01:00
parent 3bd2e1c0ea
commit aae6ab132c
8 changed files with 150 additions and 67 deletions

View File

@ -0,0 +1,62 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
locals {
_custom_constraints_factory_data_raw = (
var.org_policy_custom_constraints_data_path == null
? tomap({})
: tomap(merge([
for f in fileset(var.org_policy_custom_constraints_data_path, "*.yaml") :
yamldecode(file("${var.org_policy_custom_constraints_data_path}/${f}"))
]...))
)
_custom_constraints_factory_data = {
for k, v in local._custom_constraints_factory_data_raw :
k => {
display_name = try(v.display_name, null)
description = try(v.description, null)
action_type = v.action_type
condition = v.condition
method_types = v.method_types
resource_types = v.resource_types
}
}
_custom_constraints = merge(local._custom_constraints_factory_data, var.org_policy_custom_constraints)
custom_constraints = {
for k, v in local._custom_constraints :
k => merge(v, {
name = k
parent = var.organization_id
})
}
}
resource "google_org_policy_custom_constraint" "constraint" {
provider = google-beta
for_each = local.custom_constraints
name = each.value.name
parent = each.value.parent
display_name = each.value.display_name
description = each.value.description
action_type = each.value.action_type
condition = each.value.condition
method_types = each.value.method_types
resource_types = each.value.resource_types
}

View File

@ -88,37 +88,6 @@ locals {
]
})
}
_custom_constraints_factory_data_raw = (
var.org_policy_custom_constraints_data_path == null
? tomap({})
: merge([
for f in fileset(var.org_policy_custom_constraints_data_path, "*.yaml") :
yamldecode(file("${var.org_policy_custom_constraints_data_path}/${f}"))
]...)
)
_custom_constraints_factory_data = {
for k, v in local._custom_constraints_factory_data_raw :
k => {
display_name = try(v.display_name, null)
description = try(v.description, null)
action_type = v.action_type
condition = v.condition
method_types = v.method_types
resource_types = v.resource_types
}
}
_custom_constraints = merge(local._custom_constraints_factory_data, var.org_policy_custom_constraints)
custom_constraints = {
for k, v in local._custom_constraints :
k => merge(v, {
name = k
parent = var.organization_id
})
}
}
resource "google_org_policy_policy" "default" {
@ -184,17 +153,3 @@ resource "google_org_policy_policy" "default" {
google_org_policy_custom_constraint.constraint,
]
}
resource "google_org_policy_custom_constraint" "constraint" {
provider = google-beta
for_each = local.custom_constraints
name = each.value.name
parent = each.value.parent
display_name = each.value.display_name
description = each.value.description
action_type = each.value.action_type
condition = each.value.condition
method_types = each.value.method_types
resource_types = each.value.resource_types
}

View File

@ -15,21 +15,23 @@
*/
module "test" {
source = "../../../../modules/organization"
organization_id = "organizations/1234567890"
custom_roles = var.custom_roles
firewall_policies = var.firewall_policies
firewall_policy_association = var.firewall_policy_association
firewall_policy_factory = var.firewall_policy_factory
group_iam = var.group_iam
iam = var.iam
iam_additive = var.iam_additive
iam_additive_members = var.iam_additive_members
iam_audit_config = var.iam_audit_config
logging_sinks = var.logging_sinks
logging_exclusions = var.logging_exclusions
org_policies = var.org_policies
org_policies_data_path = var.org_policies_data_path
tag_bindings = var.tag_bindings
tags = var.tags
source = "../../../../modules/organization"
organization_id = "organizations/1234567890"
custom_roles = var.custom_roles
firewall_policies = var.firewall_policies
firewall_policy_association = var.firewall_policy_association
firewall_policy_factory = var.firewall_policy_factory
group_iam = var.group_iam
iam = var.iam
iam_additive = var.iam_additive
iam_additive_members = var.iam_additive_members
iam_audit_config = var.iam_audit_config
logging_sinks = var.logging_sinks
logging_exclusions = var.logging_exclusions
org_policies = var.org_policies
org_policies_data_path = var.org_policies_data_path
org_policy_custom_constraints = var.org_policy_custom_constraints
org_policy_custom_constraints_data_path = var.org_policy_custom_constraints_data_path
tag_bindings = var.tag_bindings
tags = var.tags
}

View File

@ -0,0 +1,18 @@
org_policy_custom_constraints = {
"custom.gkeEnableAutoUpgrade" = {
resource_types = ["container.googleapis.com/NodePool"]
method_types = ["CREATE"]
condition = "resource.management.autoUpgrade == true"
action_type = "ALLOW"
display_name = "Enable node auto-upgrade"
description = "All node pools must have node auto-upgrade enabled."
},
"custom.dataprocNoMoreThan10Workers" = {
resource_types = ["dataproc.googleapis.com/Cluster"]
method_types = ["CREATE", "UPDATE"]
condition = "resource.config.workerConfig.numInstances + resource.config.secondaryWorkerConfig.numInstances > 10"
action_type = "DENY"
display_name = "Total number of worker instances cannot be larger than 10"
description = "Cluster cannot have more than 10 workers, including primary and secondary workers."
}
}

View File

@ -79,6 +79,16 @@ variable "org_policies_data_path" {
default = null
}
variable "org_policy_custom_constraints" {
type = any
default = {}
}
variable "org_policy_custom_constraints_data_path" {
type = any
default = null
}
variable "tag_bindings" {
type = any
default = null

View File

@ -14,7 +14,7 @@
import pathlib
from .validate_policies import validate_policy_boolean, validate_policy_list
from .validate_policies import validate_policy_boolean, validate_policy_list, validate_policy_custom_constraints
def test_policy_boolean(plan_runner):
@ -31,6 +31,13 @@ def test_policy_list(plan_runner):
validate_policy_list(resources)
def test_policy_custom_constraints(plan_runner):
"Test org policy custom constraints."
tfvars = 'test.orgpolicy-custom-constraints.tfvars'
_, resources = plan_runner(tf_var_file=tfvars)
validate_policy_custom_constraints(resources)
def test_factory_policy_boolean(plan_runner, tfvars_to_yaml, tmp_path):
dest = tmp_path / 'policies.yaml'
tfvars_to_yaml('test.orgpolicies-boolean.tfvars', dest, 'org_policies')
@ -43,3 +50,10 @@ def test_factory_policy_list(plan_runner, tfvars_to_yaml, tmp_path):
tfvars_to_yaml('test.orgpolicies-list.tfvars', dest, 'org_policies')
_, resources = plan_runner(org_policies_data_path=f'"{tmp_path}"')
validate_policy_list(resources)
def test_factory_policy_custom_constraints(plan_runner, tfvars_to_yaml, tmp_path):
dest = tmp_path / 'constraints.yaml'
tfvars_to_yaml('test.orgpolicy-custom-constraints.tfvars', dest, 'org_policy_custom_constraints')
_, resources = plan_runner(org_policy_custom_constraints_data_path=f'"{tmp_path}"')
validate_policy_custom_constraints(resources)

View File

@ -72,11 +72,10 @@ def test_policy_implementation():
'- name = "${local.folder.name}/policies/${k}"\n',
'- parent = local.folder.name\n',
'+ name = "${var.organization_id}/policies/${k}"\n',
'+ parent = var.organization_id\n',
' \n',
'+ parent = var.organization_id\n', ' \n',
' is_boolean_policy = v.allow == null && v.deny == null\n',
' has_values = (\n',
'@@ -143,4 +143,12 @@\n',
'@@ -143,4 +143,13 @@\n',
' }\n',
' }\n',
' }\n',
@ -87,6 +86,7 @@ def test_policy_implementation():
'+ google_organization_iam_custom_role.roles,\n',
'+ google_organization_iam_member.additive,\n',
'+ google_organization_iam_policy.authoritative,\n',
'+ google_org_policy_custom_constraint.constraint,\n',
'+ ]\n',
' }\n',
' }\n'
]

View File

@ -138,3 +138,25 @@ def validate_policy_list(resources):
'enforce': None,
'values': []
}
def validate_policy_custom_constraints(resources):
assert len(resources) == 2
assert all(
r['values']['parent'] == 'organizations/1234567890' for r in resources)
constraints = {
r['index']: r['values']
for r in resources
if r['type'] == 'google_org_policy_custom_constraint'
}
assert len(constraints) == 2
c1 = constraints['custom.gkeEnableAutoUpgrade']
assert c1['resource_types'][0] == 'container.googleapis.com/NodePool'
assert c1['method_types'] == ['CREATE']
assert c1['condition'] == 'resource.management.autoUpgrade == true'
assert c1['action_type'] == 'ALLOW'
c2 = constraints['custom.dataprocNoMoreThan10Workers']
assert c2['resource_types'][0] == 'dataproc.googleapis.com/Cluster'
assert c2['method_types'] == ['CREATE', 'UPDATE']
assert c2['condition'] == 'resource.config.workerConfig.numInstances + resource.config.secondaryWorkerConfig.numInstances > 10'
assert c2['action_type'] == 'DENY'