Skip to content

Tag managed secrets to prevent cleanup of unmanaged secrets#32

Open
paul-watkins-croud wants to merge 1 commit intomainfrom
feature/tag-managed-secrets
Open

Tag managed secrets to prevent cleanup of unmanaged secrets#32
paul-watkins-croud wants to merge 1 commit intomainfrom
feature/tag-managed-secrets

Conversation

@paul-watkins-croud
Copy link
Copy Markdown
Contributor

Summary

  • Adds a ManagedBy: croudtech-bootstrap tag to secrets created/updated by the pipeline
  • Changes cleanup_secrets() to only delete secrets that have the ManagedBy tag
  • Independently-added secrets (without the tag) are no longer removed during put-config
  • Existing pipeline-managed secrets get backfill-tagged on the next put-config run via _ensure_managed_by_tag()
  • Also adds CLAUDE.md for project context

Test plan

  • Run put-config against a test environment and verify new secrets are created with the ManagedBy: croudtech-bootstrap tag
  • Verify existing pipeline-managed secrets get the ManagedBy tag added on update
  • Add an unmanaged secret manually (without the tag) and confirm it survives a put-config run
  • Remove a secret from the local .secret.yaml and confirm it is cleaned up (since it has the ManagedBy tag)

🤖 Generated with Claude Code

…nmanaged secrets

The put-config cleanup was deleting independently-added secrets that shared
the same Environment/App tag prefix. Now secrets created by the pipeline are
tagged with ManagedBy: croudtech-bootstrap, and cleanup only targets secrets
with that tag — leaving unmanaged secrets untouched.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -502,6 +520,17 @@ def remote_secret_filters(self):

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (secret)
as clear text.

Copilot Autofix

AI 4 days ago

In general, to fix clear-text logging of sensitive data, you should avoid including sensitive values (or their directly identifying metadata) in log messages. If some context is needed for troubleshooting, prefer high-level descriptors (like environment or app name) or redacted/hashed versions that do not allow reconstructing or directly identifying the secret.

In this specific case, the vulnerable sink is logger.debug(f"Could not ensure ManagedBy tag on {secret_id}") in _ensure_managed_by_tag. The simplest, least intrusive fix is to stop interpolating secret_id into the log message. We can still log that something went wrong, potentially including non-sensitive context such as the exception itself (which may already be logged elsewhere) or a generic message. To keep behavior close to current functionality, we’ll change the message to drop the secret identifier and optionally log the exception with logger.debug("Could not ensure ManagedBy tag on a secret.", exc_info=True) so stack trace is available when debug logs are enabled. This avoids logging the tainted secret_id while maintaining useful diagnostics.

Concretely:

  • In croudtech_bootstrap_app/bootstrap.py, in _ensure_managed_by_tag, replace the except block’s logging line to not reference secret_id.
  • No new helper methods are required; we just modify the log message.
  • No new imports are needed, as logger is already initialized and logging is already imported.

Suggested changeset 1
croudtech_bootstrap_app/bootstrap.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/croudtech_bootstrap_app/bootstrap.py b/croudtech_bootstrap_app/bootstrap.py
--- a/croudtech_bootstrap_app/bootstrap.py
+++ b/croudtech_bootstrap_app/bootstrap.py
@@ -417,7 +417,7 @@
                     Tags=[self.MANAGED_BY_TAG],
                 )
         except Exception:
-            logger.debug(f"Could not ensure ManagedBy tag on {secret_id}")
+            logger.debug("Could not ensure ManagedBy tag on a secret.", exc_info=True)
 
     def backoff_with_custom_exception(self, func, exception, message_prefix="", max_attempts=5, base_delay=1, max_delay=10, factor=2, *args, **kwargs):
         attempts = 0
EOF
@@ -417,7 +417,7 @@
Tags=[self.MANAGED_BY_TAG],
)
except Exception:
logger.debug(f"Could not ensure ManagedBy tag on {secret_id}")
logger.debug("Could not ensure ManagedBy tag on a secret.", exc_info=True)

def backoff_with_custom_exception(self, func, exception, message_prefix="", max_attempts=5, base_delay=1, max_delay=10, factor=2, *args, **kwargs):
attempts = 0
Copilot is powered by AI and may make mistakes. Always verify output.
@paul-watkins-croud
Copy link
Copy Markdown
Contributor Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants