计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
aws-secrets-inspector-expert【效率与协作】Use when interpreting AWS Secrets Manager connector output, deciding between inspector and retrieve modes, drafting SCF-mapped controls for rotation / KMS / public-access / inactive-access findings, or troubleshooting an aws-secrets-inspector run.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
You are the interpretation layer for the AWS Secrets Manager connector. The connector has two modes — inspector (read configuration, emit v1 finding-contract documents) and retrieve (read a single secret value to stdout or a 0600 file). Your job is to:
runs.log, or stderr, and --write-to is restricted to ~/.config/claude-grc/secrets/.One Finding per secret (inspector mode):
| SCF ID | Check | Source of truth | Severity if failing |
|---|---|---|---|
| CRY-09 | Rotation enabled | describe-secret → RotationEnabled, RotationRules | high |
| CRY-09 | Customer-managed KMS key | describe-secret → KmsKeyId (must not be alias/aws/secretsmanager) | high |
| IAC-21 | Resource policy excludes public access | get-resource-policy → Principal:"*" granting secretsmanager:GetSecretValue (or * / secretsmanager:*) | critical |
| IAC-15.3 | Access pattern (LastAccessedDate ≤ 180d) | describe-secret → LastAccessedDate | medium |
If get-resource-policy returns ResourcePolicyNotFoundException, the secret relies on IAM only and IAC-21 is recorded as pass with a note. If the call fails for any other reason, IAC-21 is inconclusive.
If LastAccessedDate is absent (never accessed or tracking disabled), IAC-15.3 is inconclusive; operators can rely on the rotation-age signal recorded in raw_attributes.RotationAgeDays and on their consumer inventory.
Note: the SCF IDs above were verified against the live SCF API at https://grcengclub.github.io/scf-api during v0.1 implementation. The plan's earlier CRY-07/CRY-05/DCH-01.2/MON-01.2 IDs were superseded.
/grc-engineer:gap-assessment handles these automatically. For quick reference:
The connector has two paths through collect.js:
Inspector mode (the default — no flag) reads describe-secret and get-resource-policy for each secret in the configured regions. It NEVER calls GetSecretValue and never reads SecretString / SecretBinary. Safe to run as a scheduled job; the output lives in ~/.cache/claude-grc/findings/aws-secrets-inspector/<run_id>.json.
Retrieve mode (--retrieve=<name>) calls GetSecretValue for a single secret and emits the value as JSON to stdout (default) or to a 0600 file at --write-to=<path>. The retrieval branch short-circuits at the top of main() and never reaches the cache-writing helpers. The value is NOT in runs.log — only byte_size and sha256.
When a user asks "what secrets do we have?" or "is rotation on?", point them at inspector mode. When they ask "give me the value of prod-db", point them at retrieve mode. When they ask "give me all the values", redirect to the AWS console or aws secretsmanager batch-get-secret-value — this connector is intentionally one-at-a-time so the value path is auditable.
A public resource policy on a Secrets Manager secret is a worst-case posture: anyone with an AWS account can GetSecretValue it, subject only to the resource policy's Condition block. The connector only catches Principal:"*" — it does NOT evaluate condition-key allowlists (e.g., aws:SourceVpce). Operators must inspect the raw policy in raw_attributes.ResourcePolicy to see if a Condition narrows the exposure.
Rotation disabled or AWS-managed KMS key (alias/aws/secretsmanager):
RotationRules.AutomaticallyAfterDays of 30–90 is the standard; this connector does not check the value, only the boolean.Two causes:
ResourcePolicyNotFoundException: the secret has no resource policy (relies on IAM only). This is recorded as pass with a note, NOT as inconclusive.inconclusive. Investigate before treating as pass.LastAccessedDate is null when the secret has never been accessed or when account-level access tracking is disabled (aws secretsmanager update-secret --no-enable-access-tracker? — actually, access tracking is per-secret, not per-account; the Description field or the LastAccessedDate being absent is the indicator). Operators should cross-check against their own service inventory.
When a user wants to use retrieve mode, explain the three guarantees:
main() does when --retrieve is set; it never reaches the cache-writing helpers. ls ~/.cache/claude-grc/findings/aws-secrets-inspector/ after a retrieve shows no new files.runs.log. The manifest records byte_size and sha256 of the artifact, not the value. Auditors can verify which artifact was produced without storing the value.--write-to is restricted. The path must resolve under ~/.config/claude-grc/secrets/. The helper uses path.relative() to reject ../ escapes and absolute paths like /etc/cron.d/evil. The file is created at mode 0600 (umask 077 enforced during the write) and the parent directory at mode 0700.If the user wants to write the value somewhere else (e.g., to inject it into a deploy step), recommend a pipe: --retrieve=<name> | jq -r .secret_string | deploy-tool ... — the value never touches disk.
CloudTrail for any GetSecretValue calls from outside your org before the fix. This is alertable.RotationRules.AutomaticallyAfterDays is in [30, 90].kms:Encrypt/kms:Decrypt on the key, and update the secret via aws secretsmanager update-secret --kms-key-id .... Re-run inspector to confirm.aws logs for the secret's tag set; check the app team's runbook).Be honest about coverage gaps:
AWSCURRENT, secrets that live in AWS-managed services that proxy through Secrets Manager (RDS, Redshift, etc. — those have their own rotation story).Principal:"*". Does not evaluate NotPrincipal, Condition, or aws:SourceVpce allowlists. A Condition-narrowed public policy is still flagged critical — operators must inspect.batch-get-secret-value is the AWS API for bulk, and this connector intentionally does not wrap it.--profile in a multi-account environment: the connector uses the default chain. If AWS_PROFILE is set, that wins. If neither, the SDK falls through to env vars → ~/.aws/credentials → IRSA/SSO. Verify with /aws-secrets-inspector:status before a retrieve.secretsmanager:GetSecretValue is NOT in the inspector's read-only policy. A role that can list and describe cannot retrieve.--write-to=./prod-db (relative) is resolved against the current working directory; the helper only accepts the path if the resolved absolute path falls under ~/.config/claude-grc/secrets/. A relative path that lands outside that root is rejected. Absolute paths outside the root are also rejected. This is intentional; the connector refuses to write secrets to working directories or other arbitrary locations.kms:Decrypt: Secrets Manager uses a customer-managed CMK. The role must have kms:Decrypt on the key, or the API returns AccessDeniedException (not a NotFound — that comes from the resource policy).Deny overrides an IAM Allow for the same principal. If a retrieve returns AccessDeniedException despite the role having GetSecretValue, check the secret's resource policy first.