Skip to content

Commit f80d7a3

Browse files
committed
improve restrict-remote-state policy
1 parent bd3b016 commit f80d7a3

8 files changed

+58
-44
lines changed

governance/third-generation/cloud-agnostic/restrict-remote-state.sentinel

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# This policy uses the Sentinel tfstate import to restrict the
1+
# This policy uses the Sentinel tfstate and tfrun imports to restrict the
22
# workspaces from which remote state can be retrieved using the
33
# terraform_remote_state data source. It provides a map between
4-
# substrings of names of workspaces that want to read remote state
4+
# prefixes and suffixes of names of workspaces that want to read remote state
55
# and specific workspaces from which they can read it.
66

77

@@ -12,41 +12,44 @@ import "tfstate-functions" as state
1212
# Use standard tfrun import
1313
import "tfrun"
1414

15-
# workspace mapping
16-
# We use "invalid-workspace-name" to represent workspaces with names that do not
17-
# match any of the allowed workspace naming patterns. These workspace names are
18-
# allowed, but the workspaces with these names are not allowed to access remote
19-
# state.
15+
# Mapping between environments and lists of workspaces from which remote state
16+
# can be retrieved. The keys should be strings which will be the prefixes or
17+
# suffixes of workspace names.
18+
# Be sure to include the key "invalid" to represent workspaces with names that
19+
# do not match any of the allowed workspace naming patterns and to set its value
20+
# to the empty list, []. These workspace names are allowed, but the workspaces
21+
# with these names are not allowed to access remote state.
2022
param allowed_workspaces default {
2123
"dev": ["vpc-dev", "s3-dev", "sec-group-dev"],
2224
"qa": ["vpc-qa", "s3-qa", "sec-group-qa"],
2325
"prod": ["vpc-prod", "s3-prod", "sec-group-prod"],
24-
"invalid-workspace-name": [],
26+
"invalid": [],
2527
}
2628

27-
# Get workspace name
29+
# Get the workspace name from the tfrun import
2830
workspace_name = tfrun.workspace.name
29-
# print("workspace_name:", workspace_name)
3031

31-
# Determine environment of workspace name
32-
# If workspace does not start or end with "dev", "qa", or "prod", then set it
33-
# to "invalid-workspace-name"
32+
# Determine the workspace environment (key of allowed_workspaces list)
33+
matching_env_found = false
3434
workspace_env = ""
35-
case {
36-
when workspace_name matches "^(.+)-dev$" or workspace_name matches "^dev-(.+)$":
37-
workspace_env = "dev"
38-
when workspace_name matches "^(.+)-qa$" or workspace_name matches "^qa-(.+)$":
39-
workspace_env = "qa"
40-
when workspace_name matches "^(.+)-prod$" or workspace_name matches "^prod-(.+)$":
41-
workspace_env = "prod"
42-
else:
43-
workspace_env = "invalid-workspace-name"
35+
for allowed_workspaces as env, workspaces {
36+
if workspace_name matches "(.+)-" + env + "$" or
37+
workspace_name matches "^" + env + "-(.+)$" {
38+
workspace_env = env
39+
matching_env_found = true
40+
break
41+
}
42+
}
43+
44+
# Deal with workspaces names that do not match patterns
45+
if not matching_env_found {
46+
workspace_env = "invalid"
4447
}
4548

4649
# Find instances of remote state data sources
4750
remoteStates = state.find_datasources("terraform_remote_state")
4851

49-
# Filter remote state data sources
52+
# Filter remote state data sources to violations
5053
violatingRemoteStates = state.filter_attribute_not_in_list(remoteStates,
5154
"config.workspaces.name",
5255
allowed_workspaces[workspace_env], false)
@@ -55,8 +58,19 @@ violatingRemoteStates = state.filter_attribute_not_in_list(remoteStates,
5558
validated = true
5659
if length(violatingRemoteStates["messages"]) is not 0 {
5760
validated = false
61+
# Special processing for workspace names that do not match an environment
62+
if workspace_env is "invalid" {
63+
# delete the "invalid" key from allowed_workspaces to improve message
64+
delete(allowed_workspaces, "invalid")
65+
print("The current workspace", workspace_name, "is not allowed to access",
66+
"remote state from other workspaces because its name does not match",
67+
"any of the allowed regular expressions in", keys(allowed_workspaces))
68+
}
69+
# Print generic violation message
5870
print("This workspace tried to access remote state from workspaces",
5971
"it is not allowed to access.")
72+
# Print specific violation messages for instances of the terraform_remote_state
73+
# data source
6074
state.print_violations(violatingRemoteStates["messages"], "Data source")
6175
}
6276

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-fail-dev.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-dev": {
23+
"address": "terraform_remote_state.ec2-dev",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-dev",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-fail-invalid-workspace-name.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-for-production": {
23+
"address": "terraform_remote_state.ec2-for-production",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-for-production",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-fail-prod.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-prod": {
23+
"address": "terraform_remote_state.ec2-prod",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-prod",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-fail-qa.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-qa": {
23+
"address": "terraform_remote_state.ec2-qa",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-qa",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-pass-dev.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-dev": {
23+
"address": "terraform_remote_state.ec2-dev",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-dev",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-pass-prod.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-prod": {
23+
"address": "terraform_remote_state.ec2-prod",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-prod",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

governance/third-generation/cloud-agnostic/test/restrict-remote-state/mock-tfstate-pass-qa.sentinel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ outputs = {
1919
}
2020

2121
resources = {
22-
"terraform_remote_state.pets": {
23-
"address": "terraform_remote_state.pets",
22+
"terraform_remote_state.ec2-qa": {
23+
"address": "terraform_remote_state.ec2-qa",
2424
"depends_on": [],
2525
"deposed_key": "",
2626
"index": null,
2727
"mode": "data",
2828
"module_address": "",
29-
"name": "pets",
29+
"name": "ec2-qa",
3030
"provider_name": "terraform.io/builtin/terraform",
3131
"tainted": false,
3232
"type": "terraform_remote_state",

0 commit comments

Comments
 (0)