State whether ssm-get is deliberately interactive-only, or give it a callable form #1308

Closed
opened 2026-08-27 04:00:25 +00:00 by coilyco-ops · 1 comment
Owner

Carries settling condition 3 and Finding 2 from #1137, which closed on the gpg.program mechanism fix and would otherwise bury this.

The observation

ssm-get is a shell function in shell/common.sh, not a binary on PATH. It works as designed in an interactive zsh or bash session and resolves to nothing in a non-interactive shell, a script, or an agent tool call.

Confirmed again while working #1137: fetching /forgejo/coilyco-ops/api-token from an agent shell fell back to a raw aws ssm get-parameter --name ... --with-decryption --query Parameter.Value --output text, which is the exact body of the function. That restatement is the duplication the single-owning-source convention exists to prevent, and it is the second time the same fallback has been written down.

#1137 was explicit that this may be entirely intentional and did not claim a defect.

The decision

Either:

  • Interactive-only, deliberately. Say so, and the note belongs next to the function so the next agent stops reaching for it. Agents and scripts keep writing the raw AWS call.
  • Give it a callable form. A thin scripts/ssm-get holding the logic, with the shell function delegating to it, so both surfaces share one implementation. apply-shell-links already owns ~/.local/bin links and would carry it with no new machinery.

Worth weighing against the second option: a PATH-resolvable secret reader is reachable by anything running as the user, where a shell function is not. Whether that widens the surface enough to matter is part of the call.

What settles it

A stated answer. If it is the second option, the build belongs in this repo and the ~/.local/bin link rollout belongs to infrastructure/ansible.

Carries settling condition 3 and Finding 2 from #1137, which closed on the `gpg.program` mechanism fix and would otherwise bury this. ## The observation `ssm-get` is a shell function in `shell/common.sh`, not a binary on `PATH`. It works as designed in an interactive zsh or bash session and resolves to nothing in a non-interactive shell, a script, or an agent tool call. Confirmed again while working #1137: fetching `/forgejo/coilyco-ops/api-token` from an agent shell fell back to a raw `aws ssm get-parameter --name ... --with-decryption --query Parameter.Value --output text`, which is the exact body of the function. That restatement is the duplication the single-owning-source convention exists to prevent, and it is the second time the same fallback has been written down. #1137 was explicit that this may be entirely intentional and did not claim a defect. ## The decision Either: * **Interactive-only, deliberately.** Say so, and the note belongs next to the function so the next agent stops reaching for it. Agents and scripts keep writing the raw AWS call. * **Give it a callable form.** A thin `scripts/ssm-get` holding the logic, with the shell function delegating to it, so both surfaces share one implementation. `apply-shell-links` already owns `~/.local/bin` links and would carry it with no new machinery. Worth weighing against the second option: a `PATH`-resolvable secret reader is reachable by anything running as the user, where a shell function is not. Whether that widens the surface enough to matter is part of the call. ## What settles it A stated answer. If it is the second option, the build belongs in this repo and the `~/.local/bin` link rollout belongs to infrastructure/ansible.
Author
Owner

Answered by Kai: give it a callable form. Landed in #1314.

scripts/ssm-get holds the logic, with the same <name> [profile] [region] shape and the same default / us-east-1 defaults, plus the Git Bash MSYS_NO_PATHCONV carve-out the other wrappers carry so leading-slash SSM names survive intact. It reaches PATH through the same ~/.local/bin link as gpg-ssm, carried by apply-shell-links here and by the ansible shell role fleet-wide (coilyco-flight-deck/infrastructure#960).

The shell function stays as a thin delegator rather than being deleted. It prefers the converged link and falls back to the checkout, so a host that has not run just apply-shell-links yet keeps the helper working and there is no window where ssm-get is missing from an interactive shell. One implementation, two surfaces.

On the surface-area point raised in the filing: a PATH-resolvable secret reader is reachable by anything running as the user where a shell function is not. That is real, and it is not a new exposure. Anything that could call ssm-get can already call aws ssm get-parameter --with-decryption directly with the same credentials, which is exactly what agents were doing in its absence. The script adds convenience rather than access.

Verified with bash -n and zsh -n on shell/common.sh and a live fetch of /forgejo/coilyco-ops/api-token through the function.

Answered by Kai: **give it a callable form.** Landed in #1314. `scripts/ssm-get` holds the logic, with the same `<name> [profile] [region]` shape and the same `default` / `us-east-1` defaults, plus the Git Bash `MSYS_NO_PATHCONV` carve-out the other wrappers carry so leading-slash SSM names survive intact. It reaches `PATH` through the same `~/.local/bin` link as `gpg-ssm`, carried by `apply-shell-links` here and by the ansible `shell` role fleet-wide (`coilyco-flight-deck/infrastructure#960`). The shell function stays as a thin delegator rather than being deleted. It prefers the converged link and falls back to the checkout, so a host that has not run `just apply-shell-links` yet keeps the helper working and there is no window where `ssm-get` is missing from an interactive shell. One implementation, two surfaces. On the surface-area point raised in the filing: a `PATH`-resolvable secret reader is reachable by anything running as the user where a shell function is not. That is real, and it is not a new exposure. Anything that could call `ssm-get` can already call `aws ssm get-parameter --with-decryption` directly with the same credentials, which is exactly what agents were doing in its absence. The script adds convenience rather than access. Verified with `bash -n` and `zsh -n` on `shell/common.sh` and a live fetch of `/forgejo/coilyco-ops/api-token` through the function.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1308
No description provided.