diff --git a/project_setup/scripts/terraform-to-secrets b/project_setup/scripts/terraform-to-secrets index 7bf3eba..e97297c 100755 --- a/project_setup/scripts/terraform-to-secrets +++ b/project_setup/scripts/terraform-to-secrets @@ -98,6 +98,64 @@ def get_terraform_state(filename: str = None) -> Dict: return json_state +def find_tagged_secret( + resource_name: str, resource_data: Dict +) -> Generator[Tuple[str, str], None, None]: + """Extract a tagged secret from a resource.""" + # Ensure "tags" key exists in resource_data and if it does, make sure + # its value is not None. Both of these cases can occur. + tags: Dict[str, str] + if "tags" not in resource_data or resource_data.get("tags") is None: + tags = dict() + else: + tags = resource_data["tags"] + + secret_name: Optional[str] = tags.get(GITHUB_SECRET_NAME_TAG) + lookup_tag: Optional[str] = tags.get(GITHUB_SECRET_TERRAFORM_LOOKUP_TAG) + secret_value: Optional[str] + if secret_name: + logging.debug( + f"Found {GITHUB_SECRET_NAME_TAG} on {resource_name} " + f"with value {secret_name}" + ) + if lookup_tag: + logging.debug( + f"Found {GITHUB_SECRET_TERRAFORM_LOOKUP_TAG} on " + f"{resource_name} with value {lookup_tag}" + ) + secret_value = resource_data.get(lookup_tag) + if secret_value is None: + logging.warning(f"Could not lookup value with key {lookup_tag}") + else: + logging.debug(f"Looked up value: {secret_value}") + yield secret_name, secret_value + else: + logging.warning( + f"Missing {GITHUB_SECRET_TERRAFORM_LOOKUP_TAG} on " f"{resource_name}." + ) + return + + +def find_outputs(terraform_state: Dict) -> Generator[Dict, None, None]: + """Search for resources with outputs in the Terraform state.""" + for resource in terraform_state["values"]["root_module"]["resources"]: + if resource.get("values", dict()).get("outputs", dict()): + yield resource["values"]["outputs"] + + +def parse_tagged_outputs( + terraform_state: Dict, +) -> Generator[Tuple[str, str], None, None]: + """Search all outputs for tags requesting the creation of a secret.""" + for outputs in find_outputs(terraform_state): + for output_name, output_data in outputs.items(): + for secret_name, secret_value in find_tagged_secret( + output_name, output_data + ): + yield secret_name, secret_value + return + + def find_resources( terraform_state: Dict, resource_type: Optional[str] ) -> Generator[Dict, None, None]: @@ -129,37 +187,10 @@ def parse_tagged_resources( ) -> Generator[Tuple[str, str], None, None]: """Search all resources for tags requesting the creation of a secret.""" for resource in find_resources(terraform_state, None): - # Ensure "tags" key exists in resource["values"] and if it does, - # make sure its value is not None. Both of these cases can occur. - tags: Dict[str, str] - if "tags" not in resource["values"] or resource["values"].get("tags") is None: - tags = dict() - else: - tags = resource["values"]["tags"] - secret_name: Optional[str] = tags.get(GITHUB_SECRET_NAME_TAG) - lookup_tag: Optional[str] = tags.get(GITHUB_SECRET_TERRAFORM_LOOKUP_TAG) - secret_value: str - if secret_name: - logging.debug( - f"Found {GITHUB_SECRET_NAME_TAG} on {resource['address']} " - f"with value {secret_name}" - ) - if lookup_tag: - logging.debug( - f"Found {GITHUB_SECRET_TERRAFORM_LOOKUP_TAG} on " - f"{resource['address']} with value {lookup_tag}" - ) - secret_value = resource["values"].get(lookup_tag) - if secret_value is None: - logging.warning(f"Could not lookup value with key {lookup_tag}") - else: - logging.debug(f"Looked up value: {secret_value}") - yield secret_name, secret_value - else: - logging.warning( - f"Missing {GITHUB_SECRET_TERRAFORM_LOOKUP_TAG} on " - f"{resource['address']}." - ) + for secret_name, secret_value in find_tagged_secret( + resource["address"], resource["values"] + ): + yield secret_name, secret_value return @@ -249,6 +280,9 @@ def get_resource_secrets(terraform_state: Dict) -> Dict[str, str]: for secret_name, secret_value in parse_tagged_resources(terraform_state): logging.info(f"Found secret: {secret_name}") secrets[secret_name] = secret_value + for secret_name, secret_value in parse_tagged_outputs(terraform_state): + logging.info(f"Found secret: {secret_name}") + secrets[secret_name] = secret_value return secrets