Add tests for org policy custom constraints
This commit is contained in:
parent
3bd2e1c0ea
commit
aae6ab132c
|
@ -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
|
||||||
|
}
|
|
@ -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" {
|
resource "google_org_policy_policy" "default" {
|
||||||
|
@ -184,17 +153,3 @@ resource "google_org_policy_policy" "default" {
|
||||||
google_org_policy_custom_constraint.constraint,
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ module "test" {
|
||||||
logging_exclusions = var.logging_exclusions
|
logging_exclusions = var.logging_exclusions
|
||||||
org_policies = var.org_policies
|
org_policies = var.org_policies
|
||||||
org_policies_data_path = var.org_policies_data_path
|
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
|
tag_bindings = var.tag_bindings
|
||||||
tags = var.tags
|
tags = var.tags
|
||||||
}
|
}
|
||||||
|
|
|
@ -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."
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,6 +79,16 @@ variable "org_policies_data_path" {
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "org_policy_custom_constraints" {
|
||||||
|
type = any
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "org_policy_custom_constraints_data_path" {
|
||||||
|
type = any
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
variable "tag_bindings" {
|
variable "tag_bindings" {
|
||||||
type = any
|
type = any
|
||||||
default = null
|
default = null
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import pathlib
|
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):
|
def test_policy_boolean(plan_runner):
|
||||||
|
@ -31,6 +31,13 @@ def test_policy_list(plan_runner):
|
||||||
validate_policy_list(resources)
|
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):
|
def test_factory_policy_boolean(plan_runner, tfvars_to_yaml, tmp_path):
|
||||||
dest = tmp_path / 'policies.yaml'
|
dest = tmp_path / 'policies.yaml'
|
||||||
tfvars_to_yaml('test.orgpolicies-boolean.tfvars', dest, 'org_policies')
|
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')
|
tfvars_to_yaml('test.orgpolicies-list.tfvars', dest, 'org_policies')
|
||||||
_, resources = plan_runner(org_policies_data_path=f'"{tmp_path}"')
|
_, resources = plan_runner(org_policies_data_path=f'"{tmp_path}"')
|
||||||
validate_policy_list(resources)
|
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)
|
||||||
|
|
|
@ -72,11 +72,10 @@ def test_policy_implementation():
|
||||||
'- name = "${local.folder.name}/policies/${k}"\n',
|
'- name = "${local.folder.name}/policies/${k}"\n',
|
||||||
'- parent = local.folder.name\n',
|
'- parent = local.folder.name\n',
|
||||||
'+ name = "${var.organization_id}/policies/${k}"\n',
|
'+ name = "${var.organization_id}/policies/${k}"\n',
|
||||||
'+ parent = var.organization_id\n',
|
'+ parent = var.organization_id\n', ' \n',
|
||||||
' \n',
|
|
||||||
' is_boolean_policy = v.allow == null && v.deny == null\n',
|
' is_boolean_policy = v.allow == null && v.deny == null\n',
|
||||||
' has_values = (\n',
|
' has_values = (\n',
|
||||||
'@@ -143,4 +143,12 @@\n',
|
'@@ -143,4 +143,13 @@\n',
|
||||||
' }\n',
|
' }\n',
|
||||||
' }\n',
|
' }\n',
|
||||||
' }\n',
|
' }\n',
|
||||||
|
@ -87,6 +86,7 @@ def test_policy_implementation():
|
||||||
'+ google_organization_iam_custom_role.roles,\n',
|
'+ google_organization_iam_custom_role.roles,\n',
|
||||||
'+ google_organization_iam_member.additive,\n',
|
'+ google_organization_iam_member.additive,\n',
|
||||||
'+ google_organization_iam_policy.authoritative,\n',
|
'+ google_organization_iam_policy.authoritative,\n',
|
||||||
|
'+ google_org_policy_custom_constraint.constraint,\n',
|
||||||
'+ ]\n',
|
'+ ]\n',
|
||||||
' }\n',
|
' }\n'
|
||||||
]
|
]
|
||||||
|
|
|
@ -138,3 +138,25 @@ def validate_policy_list(resources):
|
||||||
'enforce': None,
|
'enforce': None,
|
||||||
'values': []
|
'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'
|
||||||
|
|
Loading…
Reference in New Issue