Skip to content

Commit 00c4efe

Browse files
authored
Merge pull request #113 from cisagov/improvement/add-remote-state-switch
Add option to `terraform-to-secrets` to search for secrets in remote state resources
2 parents 10e7067 + 7ae8646 commit 00c4efe

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

project_setup/scripts/terraform-to-secrets

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Options:
4444
-l --log-level=LEVEL If specified, then the log level will be set to
4545
the specified value. Valid values are "debug", "info",
4646
"warning", "error", and "critical". [default: info]
47+
-m --remote-state Look for secrets in remote state resources also.
4748
-r --repo=REPONAME Use provided repository name instead of detecting it.
4849
-s --state=JSONFILE Read state from a file instead of asking Terraform.
4950
-t --token=PAT Specify a GitHub personal access token (PAT).
@@ -137,18 +138,27 @@ def find_tagged_secret(
137138
return
138139

139140

140-
def find_outputs(terraform_state: Dict) -> Generator[Dict, None, None]:
141+
def find_outputs(
142+
terraform_state: Dict, include_remote_state: bool
143+
) -> Generator[Dict, None, None]:
141144
"""Search for resources with outputs in the Terraform state."""
142145
for resource in terraform_state["values"]["root_module"].get("resources", []):
146+
# Exclude remote state resources unless requested
147+
if (
148+
not include_remote_state
149+
and resource.get("type") == "terraform_remote_state"
150+
):
151+
continue
143152
if resource.get("values", dict()).get("outputs", dict()):
144153
yield resource["values"]["outputs"]
145154

146155

147156
def parse_tagged_outputs(
148157
terraform_state: Dict,
158+
include_remote_state: bool,
149159
) -> Generator[Tuple[str, str], None, None]:
150160
"""Search all outputs for tags requesting the creation of a secret."""
151-
for outputs in find_outputs(terraform_state):
161+
for outputs in find_outputs(terraform_state, include_remote_state):
152162
for output_name, output_data in outputs.items():
153163
yield from find_tagged_secret(output_name, output_data)
154164
return
@@ -207,9 +217,16 @@ def parse_creds(terraform_state: Dict) -> Generator[Tuple[str, str, str], None,
207217

208218
def parse_tagged_resources(
209219
terraform_state: Dict,
220+
include_remote_state: bool,
210221
) -> Generator[Tuple[str, str], None, None]:
211222
"""Search all resources for tags requesting the creation of a secret."""
212223
for resource in find_resources(terraform_state, None):
224+
# Exclude remote state resources unless requested
225+
if (
226+
not include_remote_state
227+
and resource.get("type") == "terraform_remote_state"
228+
):
229+
continue
213230
yield from find_tagged_secret(resource["address"], resource["values"])
214231
return
215232

@@ -309,14 +326,20 @@ def get_users(terraform_state: Dict) -> Dict[str, Tuple[str, str]]:
309326
return user_creds
310327

311328

312-
def get_resource_secrets(terraform_state: Dict) -> Dict[str, str]:
329+
def get_resource_secrets(
330+
terraform_state: Dict, include_remote_state: bool
331+
) -> Dict[str, str]:
313332
"""Collect secrets from tagged Terraform resources."""
314333
secrets: Dict[str, str] = dict()
315334
logging.info("Searching Terraform state for tagged resources.")
316-
for secret_name, secret_value in parse_tagged_resources(terraform_state):
335+
for secret_name, secret_value in parse_tagged_resources(
336+
terraform_state, include_remote_state
337+
):
317338
logging.info(f"Found secret: {secret_name}")
318339
secrets[secret_name] = secret_value
319-
for secret_name, secret_value in parse_tagged_outputs(terraform_state):
340+
for secret_name, secret_value in parse_tagged_outputs(
341+
terraform_state, include_remote_state
342+
):
320343
logging.info(f"Found secret: {secret_name}")
321344
secrets[secret_name] = secret_value
322345
return secrets
@@ -425,6 +448,7 @@ def main() -> int:
425448
github_env: str = validated_args["--env"]
426449
github_token_to_save: str = validated_args["<github-personal-access-token>"]
427450
log_level: str = validated_args["--log-level"]
451+
include_remote_state: bool = validated_args["--remote-state"]
428452
repo_name: str = validated_args["--repo"]
429453
state_filename: str = validated_args["--state"]
430454
github_token: str = validated_args["--token"]
@@ -467,7 +491,9 @@ def main() -> int:
467491
user_secrets: Dict[str, str] = create_user_secrets(user_creds)
468492

469493
# Secrets created from tagged resources. Names mapped to value.
470-
resource_secrets: Dict[str, str] = get_resource_secrets(terraform_state)
494+
resource_secrets: Dict[str, str] = get_resource_secrets(
495+
terraform_state, include_remote_state
496+
)
471497

472498
# Check if there are overlaps in the keys.
473499
if not user_secrets.keys().isdisjoint(resource_secrets.keys()):

0 commit comments

Comments
 (0)