Add Atmos Validation Policy Execution Context. Update docs @aknysh (#1261)
## what- Add Atmos Validation Policy Execution Context
- Update docs
- Add unit tests
why
Policy Execution Context
Atmos allows enforcing custom governance rules based on metadata about Atmos commands and provides a powerful
policy evaluation mechanism by passing structured metadata to OPA policies at runtime.
This metadata enables fine-grained control over when certain actions (like terraform apply
) are allowed or denied,
based on the context in which they're executed.
Policy Metadata
When Atmos runs a command, it supplies an input object to OPA policies that contains detailed contextual information, such as:
cli_args
: a list of the command line arguments and flags (e.g., executing theatmos terraform apply
command will generate the["terraform", "apply"]
list)vars
: a map of variables passed to the command, either via the stack config files or CLI flags- other contextual attributes such as the stack and component names
Policy Execution Context Example
Below is an OPA policy rule to enforce infrastructure governance during command execution.
Specifically, this rule blocks the execution of atmos terraform apply
if the variable foo
is set to the string "foo"
.
# 'package atmos' is required in all Atmos OPA policies
package atmos
# Atmos looks for the 'errors' (array of strings) output from all OPA policies
# If the 'errors' output contains one or more error messages, Atmos considers the policy failed
# Don't allow `terraform apply` if the `foo` variable is set to `foo`
# The `input` map contains the `cli_args` attribute (a list of the command line arguments and flags)
errors[message] {
count(input.cli_args) >= 2
input.cli_args[0] == "terraform"
input.cli_args[1] == "apply"
input.vars.foo == "foo"
message = "the component can't be applied if the 'foo' variable is set to 'foo'"
}
The rule checks if:
- The
cli_args
list has at least two items - The command (first item in the
cli_args
list) isterraform
- The subcommand (second item in the
cli_args
list) isapply
- The variable
foo
is set to"foo"
If all conditions are true, the rule generates an error message.
The generated error message is added to the errors
array.
Atmos interprets the presence of any messages in errors
as a policy violation and blocks the operation with the
following error:
the component can't be applied if the 'foo' variable is set to 'foo'
exit status 1
Summary by CodeRabbit
- New Features
- Added support for passing CLI arguments context to validation policies, enabling advanced policy enforcement based on command-line input.
- Introduced new test scenarios and configuration files for stack validation using Open Policy Agent (OPA) policies.
- Bug Fixes
- Improved handling and filtering of CLI arguments to ensure accurate context is provided to validation logic.
- Documentation
- Added detailed documentation on policy execution context for OPA integration.
- Updated CLI command documentation metadata and integration guides.
- Tests
- Added new tests for stack validation and describe stacks command execution.
- Chores
- Upgraded Atmos version to 1.177.0 in relevant configurations.
- Removed obsolete debugging statements and improved code comments.
[Stores] Add user-managed replication support to GSM @ohaibbq (#1260)
## whatAdds support for user-managed replication locations to the Google Secret Manager store
why
Cloud projects often have policies that constrain where resources are physically located
Summary by CodeRabbit
-
New Features
- Added support for specifying secret replication locations when creating secrets, allowing choice between automatic and user-managed replication.
-
Tests
- Enhanced tests to cover both automatic and user-managed replication scenarios for secret creation.
Update `stacks.name_template`. Update docs @aknysh (#1264)
## what- Update
stacks.name_template
- Update docs
- Add unit tests
why
For the remote-state terraform module and terraform-provider-utils, allow using the stacks.name_template
setting in atmos.yaml
with a limited context:
.vars.namespace
.vars.tenant
.vars.environment
.vars.stage
name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}"
This will allow using name_template
(instead of name_pattern
) in both Atmos CLI and the remote-state
module (to get the outputs of TF components)
stacks.name_template
serves the same purpose as stacks.name_pattern
(defines the naming convention for the top-level Atmos stacks), but provides much more functionality. Instead of using the predefined context variables as tokens, it uses Go templates.
Atmos Template Functions, Sprig Functions, Gomplate Functions, and Gomplate Datasources are supported as well
name_template
can have complex logic and use template expressions and functions. The following template defines a name_template
that builds a stack_name
string by validating and concatenating several input variables in a hierarchical order.
name_template: |-
{{- $ns := .vars.namespace -}}
{{- $tenant := .vars.tenant -}}
{{- $env := .vars.environment -}}
{{- $stage := .vars.stage -}}
{{- $stack_name := "" -}}
{{- if eq $ns "" -}}
{{- fail "Error: 'namespace' is required." -}}
{{- end -}}
{{- if and (ne $tenant "") (eq $ns "") -}}
{{- fail "Error: 'tenant' requires 'namespace'." -}}
{{- end -}}
{{- if and (ne $env "") (or (eq $tenant "") (eq $ns "")) -}}
{{- fail "Error: 'environment' requires 'tenant' and 'namespace'." -}}
{{- end -}}
{{- if and (ne $stage "") (or (eq $env "") (eq $tenant "") (eq $ns "")) -}}
{{- fail "Error: 'stage' requires 'environment', 'tenant', and 'namespace'." -}}
{{- end -}}
{{- if ne $tenant "" -}}
{{- $stack_name = $tenant -}}
{{- end -}}
{{- if ne $env "" -}}
{{- $stack_name = printf "%s-%s" $stack_name $env -}}
{{- end -}}
{{- if ne $stage "" -}}
{{- $stack_name = printf "%s-%s" $stack_name $stage -}}
{{- end -}}
{{- $stack_name -}}
It pulls values from the Atmos section vars
and assigns them to local template variables:
namespace
tenant
environment
stage
The template enforces hierarchical dependencies between variables:
namespace
is required- If
tenant
is provided,namespace
must also be set - If
environment
is provided, bothtenant
andnamespace
must be set - If
stage
is provided, thenenvironment
,tenant
, andnamespace
must all be set
If validations pass, it constructs the stack_name
progressively:
- Starts with
tenant
if it exists - Appends
environment
if it exists - Appends
stage
if it exists
The template outputs the resulting stack name. For example, if the variables are:
namespace: acme
tenant: plat
environment: ue2
stage: prod
The resulting stack name will be plat-ue2-prod
.
Summary by CodeRabbit
- New Features
- Added support for stack name templates, allowing flexible and hierarchical stack naming using Go templates and context variables.
- Bug Fixes
- Improved error handling when both stack name template and pattern are missing.
- Documentation
- Expanded documentation with detailed examples and guidance for stack name templates and supported template functions.
- Tests
- Introduced new tests and configuration scenarios to validate stack name templating functionality.
- Chores
- Upgraded several dependencies to their latest versions for improved stability and compatibility.