Skip to content

fix(secrets): store SSM scalar secrets without JSON quotes#2797

Merged
Andriy Knysh (aknysh) merged 9 commits into
mainfrom
osterman/fix-ssm-scalar-secrets
Jul 25, 2026
Merged

fix(secrets): store SSM scalar secrets without JSON quotes#2797
Andriy Knysh (aknysh) merged 9 commits into
mainfrom
osterman/fix-ssm-scalar-secrets

Conversation

@osterman

@osterman Erik Osterman (Cloud Posse) (osterman) commented Jul 24, 2026

Copy link
Copy Markdown
Member

what

  • Write string values to secret: true AWS SSM stores without JSON quoting.
  • Preserve JSON encoding for structured secrets and regular SSM stores, with regression coverage.
  • Document absolute SSM parameter prefixes.

why

  • AWS-native consumers need the raw SecureString value rather than a JSON-wrapped scalar.

references

Summary by CodeRabbit

  • Bug Fixes

    • Improved AWS SSM secret handling to preserve raw string values (including number-like, boolean, and null text) without unwanted formatting or type changes.
    • Added/strengthened round-trip behavior for structured secret values (maps and lists), plus correct handling of empty secret strings.
    • Updated retrieval behavior to decode stored values consistently (including for GetKey).
  • Documentation

    • Clarified AWS SSM prefix must start with /.
    • Documented secret: true read/write behavior and related decoding ambiguity.
  • Tests

    • Expanded SSM secret set/get/get-key coverage for both raw and legacy formats.
    • Updated Terraform-compatible tooling test isolation to cover both terraform and tofu.

@atmos-pro

atmos-pro Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@github-actions github-actions Bot added the size/s Small size PR label Jul 24, 2026
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.80%. Comparing base (dc9aa44) to head (6d0b859).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2797      +/-   ##
==========================================
+ Coverage   81.78%   81.80%   +0.01%     
==========================================
  Files        1793     1793              
  Lines      173025   173037      +12     
==========================================
+ Hits       141507   141551      +44     
+ Misses      23707    23678      -29     
+ Partials     7811     7808       -3     
Flag Coverage Δ
unittests 81.80% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/store/aws_ssm_param_store.go 85.71% <100.00%> (+2.18%) ⬆️

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@osterman, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 009bb0ad-7884-4931-a004-faf84c18048b

📥 Commits

Reviewing files that changed from the base of the PR and between 92a78a7 and 6d0b859.

📒 Files selected for processing (1)
  • tests/cli_jit_source_oci_test.go
📝 Walkthrough

Walkthrough

SSM secret storage now preserves raw string values while retaining JSON encoding for structured values, with expanded round-trip tests and corrected prefix documentation. Terraform and OpenTofu tests now resolve and isolate compatible executables per test.

Changes

AWS SSM secret storage

Layer / File(s) Summary
Secret serialization and decoding
pkg/store/aws_ssm_param_store.go
SSMStore centralizes encoding and decoding, preserves raw secret strings, supports structured secrets, and routes Set, Get, and GetKey through the helpers.
Secret behavior coverage
pkg/store/aws_ssm_param_store_test.go
Tests cover SecureString writes, raw and structured values, serialization failures, and byte-exact secret retrieval.
SSM prefix configuration
website/docs/cli/configuration/stores.mdx
The SSM prefix example and guidance now require a leading / and describe secret serialization behavior.

Terraform-compatible test isolation

Layer / File(s) Summary
Binary lookup and isolation
internal/exec/terraform_test.go, internal/exec/yaml_func_terraform_output_test.go
Terraform and OpenTofu tests select binaries with exec.LookPath, copy them into per-test directories, prepend those directories to PATH, and validate the isolation helper.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SecretCaller
  participant SSMStore
  participant AWS_SSM
  SecretCaller->>SSMStore: Set secret value
  SSMStore->>AWS_SSM: PutParameter with encoded value
  SecretCaller->>SSMStore: Get or GetKey
  SSMStore->>AWS_SSM: GetParameter
  AWS_SSM-->>SSMStore: Stored parameter value
  SSMStore-->>SecretCaller: Decoded value
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Terraform test changes in internal/exec are unrelated to the SSM secrets and docs objectives. Move the Terraform test updates into a separate PR unless they are required for this SSM secret-storage fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main change: storing scalar SSM secrets without JSON quotes.
Linked Issues check ✅ Passed Meets #2795: scalar secrets are stored raw, structured values stay JSON, reads still accept both, and the docs note the absolute SSM prefix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch osterman/fix-ssm-scalar-secrets

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/store/aws_ssm_param_store_test.go (1)

111-142: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a raw-string case containing JSON-sensitive characters.

The current test only uses "test-value". Add a table case containing quotes, backslashes, and/or a newline, then assert the exact PutParameterInput.Value; this protects the promised byte-preserving behavior from future escaping regressions.

As per coding guidelines, new features should have comprehensive behavior-focused tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/store/aws_ssm_param_store_test.go` around lines 111 - 142, Extend the
table-driven tests around the secret_string_is_stored_raw case with a raw string
containing JSON-sensitive characters such as quotes, backslashes, or a newline.
Configure the mock PutParameter expectation to assert the exact unchanged Value
while retaining SecureString and overwrite settings, verifying byte-preserving
behavior separately from secret_structured_value_is_json_encoded.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/store/aws_ssm_param_store_test.go`:
- Around line 111-142: Extend the table-driven tests around the
secret_string_is_stored_raw case with a raw string containing JSON-sensitive
characters such as quotes, backslashes, or a newline. Configure the mock
PutParameter expectation to assert the exact unchanged Value while retaining
SecureString and overwrite settings, verifying byte-preserving behavior
separately from secret_structured_value_is_json_encoded.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 276197b0-fa23-445e-85b8-ceca66df8d8c

📥 Commits

Reviewing files that changed from the base of the PR and between 2fe07c7 and f803c64.

📒 Files selected for processing (3)
  • pkg/store/aws_ssm_param_store.go
  • pkg/store/aws_ssm_param_store_test.go
  • website/docs/cli/configuration/stores.mdx

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 24, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 24, 2026
@atmos-pro
atmos-pro Bot temporarily deployed to screengrabs July 24, 2026 19:21 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/exec/yaml_func_terraform_output_test.go`:
- Around line 182-187: Update isolateTerraformTestBinary and its failure-path
error messages to use tool-neutral wording such as “Terraform-compatible
executable,” rather than “OpenTofu executable.” Ensure all reported failures in
this helper accurately cover both Terraform and OpenTofu without changing the
existing behavior.
- Around line 210-217: In TestIsolateTerraformTestBinary, replace assert.NoError
with require.NoError for both os.Executable and exec.LookPath results so
executable discovery failures stop the test immediately before subsequent
operations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bb5be992-252e-4c3b-8e5d-bef9ae5c3812

📥 Commits

Reviewing files that changed from the base of the PR and between cd4ad3f and 898a3f6.

📒 Files selected for processing (2)
  • internal/exec/terraform_test.go
  • internal/exec/yaml_func_terraform_output_test.go

Comment thread internal/exec/yaml_func_terraform_output_test.go
Comment thread internal/exec/yaml_func_terraform_output_test.go Outdated
@github-actions github-actions Bot removed the size/s Small size PR label Jul 24, 2026
@github-actions github-actions Bot added the size/m Medium size PR label Jul 24, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 24, 2026
@aknysh

Copy link
Copy Markdown
Member

CodeRabbit (@coderabbitai) review please

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

@aknysh Understood. Reviewing PR #2797 now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/store/aws_ssm_param_store.go`:
- Around line 291-329: Document the raw-value/JSON ambiguity in the secret read
paths that use SSMStore.decodeParameterValue, covering !secret and atmos secret
get/env/exec plus the relevant store documentation. State that Set writes
strings raw, but Get/GetKey decode JSON objects, arrays, and quoted strings, so
secrets containing JSON blobs or literal surrounding quotes may not return
byte-exactly; note that distinguishing these cases requires a type marker.
- Around line 279-289: Update SSMStore.encodeParameterValue so secret string
values bypass JSON encoding only when non-empty; route an empty secret string
through json.Marshal to produce the JSON representation "\"\"". Preserve the
existing raw-value behavior for non-empty secret strings and existing
serialization error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 94357095-fa41-46b7-bb57-fa89d6c47f07

📥 Commits

Reviewing files that changed from the base of the PR and between 41d901e and cca6e44.

📒 Files selected for processing (2)
  • pkg/store/aws_ssm_param_store.go
  • pkg/store/aws_ssm_param_store_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/store/aws_ssm_param_store_test.go

Comment thread pkg/store/aws_ssm_param_store.go
Comment thread pkg/store/aws_ssm_param_store.go
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 25, 2026
@aknysh
Andriy Knysh (aknysh) merged commit 1b965ac into main Jul 25, 2026
84 checks passed
@atmos-pro

atmos-pro Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@aknysh
Andriy Knysh (aknysh) deleted the osterman/fix-ssm-scalar-secrets branch July 25, 2026 22:34
@github-actions

Copy link
Copy Markdown

These changes were released in v1.224.1-rc.1.

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

Labels

patch A minor, backward compatible change size/m Medium size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

atmos secret (aws/ssm store) JSON-encodes scalar secrets, so string values are stored double-quoted and break external consumers

2 participants