module-governance
Last updated on
With Harness Infrastructure as Code and Harness OPA policies you can enforce governance on modules used in a workspace. You can create policies for different types of governance: allowed modules, module versions, or even resources provisioned outside of a module. Below are examples of implementing such governance.
Helper Functions
# Collect all module calls in a TF Plan
module_calls[call] {
walk(input.configuration.root_module, [p, v])
p[count(p)-1] == "module_calls" # node *is* a module_calls map
mc := v[_] # one module_call object
call := mc # its call
}
# Check if an array contains an element
contains(arr, elem) {
arr[_] = elem
}
Allowed Modules
Collect module calls and throw a failure if the module source doesn't match a given pattern:
deny[msg] {
call := module_calls[_]
not startswith(call.source, "../") # allow local modules in parent directories
not startswith(call.source, "./") # allow local modules in the current directory
not startswith(call.source, "app.harness.io/") # allow modules from harness module registry
not startswith(call.source, "terraform-aws-modules/") # allow offical modules from aws
msg := sprintf(
"Module source %q is not allowed",
[call.source],
)
}
Require specific module versioning
For modules where you want to control the versions used, you can make a policy per module to account for custom logic in version matching:
deny[msg] {
allowed_versions := ["2.2.0", "2.3.0"]
call := module_calls[_]
call.source == "terraform-aws-modules/kms/aws"
not contains(allowed_versions, call.version_constraint)
msg := sprintf(
"Module %s version %s is not allowed, must be one of: %s",
[call.source, call.version_constraint, allowed_versions],
)
}
Require specific resource types be provisioned through a module
For sensitive resource types that must only be used inside approved modules, list all resources included in the "root module" and check their type:
deny[msg] {
disallowed_types := ["aws_instance"]
r = input.planned_values.root_module.resources[_]
contains(disallowed_types, r.type)
msg := sprintf(
"Resource of type %s is not allowed outside a module",
[r.type],
)
}