Skip to content

Commit 8a9754b

Browse files
ostermanclaudeaknysh
authored
Fix AWS store auth and add Floci E2E coverage (#2625)
* Fix AWS store auth and add Floci E2E coverage * Polish AWS secrets examples and Floci toolchain * Address floci review feedback * De-risk store auth resolver injection * Fix acceptance CI failures * Pass GitHub token to Floci toolchain CI * Auto-start Floci emulators for local E2E tests; store auth/endpoint fixes Add testcontainers-based auto-start for the opt-in Floci cloud-emulator E2E tests. When ATMOS_TEST_FLOCI=true and the FLOCI_* endpoints are unset, the suite detects the container runtime (Docker or Podman, via pkg/container), wires Podman's API socket into testcontainers, and brings the AWS/GCP/Azure emulators up on dynamic ports, tearing them down afterward. CI keeps its service containers (pre-set endpoints make auto-start a no-op), and tests skip cleanly with an actionable message when no runtime is available. Also includes this branch's AWS SSM / Secrets Manager / Azure Key Vault / GCP Secret Manager store auth and endpoint changes and their tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Cover decodeNodeWithYamlFunctions error and alias branches Add a focused test for the error-propagation paths (failing scalar decode inside a mapping and a sequence) and the default/alias branch of decodeNodeWithYamlFunctions, raising it from ~73% to ~97%. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Move AWS resolver endpoint into auth context * Address CodeRabbit review feedback on test quality - aws_ssm_param_store_test: assert applied option behavior (region, endpoint, profile, config/creds files) not just option count, so auth precedence can't regress silently - precondition_cached_tools_test: use OS-agnostic temp-dir PATH fixture instead of hardcoded /usr/bin - cli_test: bound Floci auto-start with a 3m timeout context so a hung Podman/Docker call can't block TestMain indefinitely Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add perf.Track to SetAuthContext and cover lowercase identity fallback - setup.go: add the required perf.Track defer to the public SetAuthContext function, matching the package convention (nil atmosConfig) - setup_test: make TestSetAuthContext_WithIdentityResolverEndpoint table-driven to also exercise the strings.ToLower identity-name fallback in endpointURLFromManager (mixed-case input, lowercase-keyed identity) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add store integration coverage * Fix Vault test HTTP handler --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Andriy Knysh <aknysh@users.noreply.github.com>
1 parent d21327f commit 8a9754b

119 files changed

Lines changed: 4886 additions & 488 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yml

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ permissions:
3131
pull-requests: read
3232

3333
env:
34-
TERRAFORM_VERSION: "1.9.7"
35-
OPEN_TOFU_VERSION: "1.9.1"
34+
TERRAFORM_VERSION: "1.15.6"
35+
OPEN_TOFU_VERSION: "1.12.2"
3636
HELM_VERSION: "v3.19.2"
3737
HELMFILE_VERSION: "v1.1.0"
3838
PACKER_VERSION: "1.14.2"
@@ -281,7 +281,7 @@ jobs:
281281
run: make testacc
282282

283283
- name: Upload coverage report to Codecov
284-
if: matrix.flavor.target == 'linux' && (success() || failure())
284+
if: matrix.flavor.target == 'linux' && hashFiles('coverage.out') != ''
285285
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
286286
with:
287287
token: ${{ secrets.CODECOV_TOKEN }}
@@ -408,6 +408,77 @@ jobs:
408408
exit "${status}"
409409
}
410410
411+
# Run Go E2E tests against Floci. These cover store/secrets workflows that are
412+
# easier to assert directly from Go than through the demo `atmos test` runner.
413+
floci-go:
414+
name: "[floci] go e2e"
415+
needs: build
416+
runs-on: ubuntu-latest
417+
418+
services:
419+
floci:
420+
# Pin by immutable digest for reproducibility/supply-chain safety (matches our SHA-pinned actions). Comment tracks the human-readable tag.
421+
image: floci/floci@sha256:c88ec20bf221630dd195d38a14eeb0ac52ddfa72c37ebb3c8aa17f63ae27c5f2 # 1.5.23
422+
ports:
423+
- 4566:4566
424+
floci-gcp:
425+
# Pin by immutable digest for reproducibility/supply-chain safety. Comment tracks the human-readable tag.
426+
image: floci/floci-gcp@sha256:a6420f308ad721fa4a203b70658563eab9c8fbc8d091feca2d95016239f5854a # latest
427+
ports:
428+
- 4588:4588
429+
floci-az:
430+
# Pin by immutable digest for reproducibility/supply-chain safety. Comment tracks the human-readable tag.
431+
image: floci/floci-az@sha256:1e514c57db14dc41938f7925bbc1aca0293aa4da272c7014d98f1fba378cedb2 # latest
432+
ports:
433+
- 4577:4577
434+
435+
timeout-minutes: 30
436+
steps:
437+
- name: Download build artifacts
438+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
439+
with:
440+
name: build-artifacts-linux
441+
path: /usr/local/bin
442+
443+
- name: Set execute permissions on atmos
444+
run: chmod +x /usr/local/bin/atmos
445+
446+
- name: Check out code into the Go module directory
447+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
448+
with:
449+
persist-credentials: false
450+
451+
- name: Set up Go
452+
# setup-go v6 requires runner v2.327.1+ and can affect toolchain handling.
453+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
454+
with:
455+
go-version-file: "go.mod"
456+
cache: false
457+
458+
- name: Install OpenTofu with Atmos toolchain
459+
env:
460+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
461+
run: |
462+
atmos toolchain install --default opentofu/opentofu@${{ env.OPEN_TOFU_VERSION }}
463+
atmos toolchain env --format=github
464+
465+
- name: Verify OpenTofu
466+
run: tofu version
467+
468+
- name: Install Linux build dependencies
469+
run: |
470+
sudo apt-get update
471+
sudo apt-get install -y --no-install-recommends libudev-dev pkg-config
472+
473+
- name: Run Floci Go E2E tests
474+
env:
475+
ATMOS_TEST_FLOCI: "true"
476+
FLOCI_ENDPOINT_URL: "http://localhost:4566"
477+
FLOCI_GCP_ENDPOINT: "http://localhost:4588"
478+
FLOCI_AZURE_ENDPOINT: "http://localhost:4577"
479+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
480+
run: go test ./tests -run 'Test(AWS(StoreHooks|Secrets)|GCPSecrets|AzureSecrets)FlociE2E' -count=1 -timeout 15m -v
481+
411482
# run k3s demo tests
412483
k3s:
413484
name: "[k3s] ${{ matrix.demo-folder }}"
@@ -681,7 +752,7 @@ jobs:
681752
}
682753
683754
release:
684-
needs: [test, lint, mock, k3s, floci, docker, validate]
755+
needs: [test, lint, mock, k3s, floci, floci-go, docker, validate]
685756
if: github.event_name == 'push'
686757
uses: cloudposse/.github/.github/workflows/shared-go-auto-release.yml@8244c7c9142e92281e7841f655fa48e9ceb9b454 # main
687758
with:

agent-skills/skills/atmos-config/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ auth:
179179
180180
stores:
181181
ssm/dev:
182-
type: aws-ssm-parameter-store
182+
kind: aws/ssm
183183
options:
184184
region: us-east-1
185185
identity: dev-admin

agent-skills/skills/atmos-config/references/sections-reference.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,19 +271,19 @@ Configures external key-value store backends.
271271
```yaml
272272
stores:
273273
ssm/dev:
274-
type: aws-ssm-parameter-store
274+
kind: aws/ssm
275+
identity: dev-admin
275276
options:
276277
region: us-east-1
277-
identity: dev-admin
278278
279279
secrets:
280-
type: azure-key-vault
280+
kind: azure/keyvault
281281
options:
282282
vault_url: https://my-vault.vault.azure.net/
283283
```
284284

285-
Supported types: `aws-ssm-parameter-store`, `azure-key-vault`, `google-secret-manager` (alias: `gsm`),
286-
`redis`, `artifactory`.
285+
Supported kinds: `aws/ssm`, `aws/asm`, `azure/keyvault`, `gcp/secretmanager`, `redis`, `artifactory`.
286+
Legacy `type` aliases are still supported for backward compatibility.
287287

288288
For complete store configuration, see the `atmos-stores` skill.
289289

agent-skills/skills/atmos-stores/SKILL.md

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
name: atmos-stores
3-
description: "Store backends: AWS SSM, Azure Key Vault, Google Secret Manager, Redis, Artifactory configuration, hooks integration, cross-component data sharing"
3+
description: "Store backends: AWS SSM, AWS Secrets Manager, Azure Key Vault, Google Secret Manager, Redis, Artifactory configuration, hooks integration, cross-component data sharing"
44
metadata:
55
copyright: Copyright Cloud Posse, LLC 2026
66
version: "1.0.0"
77
---
88

99
# Atmos External Stores
1010

11-
Stores are external key-value backends configured in `atmos.yaml` that enable components to share data outside of Terraform state. Atmos supports five store providers: AWS SSM Parameter Store, Azure Key Vault, Google Secret Manager, Redis, and JFrog Artifactory.
11+
Stores are external key-value backends configured in `atmos.yaml` that enable components to share data outside of Terraform state. Atmos supports store providers including AWS SSM Parameter Store, AWS Secrets Manager, Azure Key Vault, Google Secret Manager, Redis, and JFrog Artifactory.
1212

1313
## When to Use Stores
1414

@@ -23,23 +23,28 @@ For Terraform-managed outputs, prefer `!terraform.state` (fastest) or `!terrafor
2323

2424
## Configuring Stores in atmos.yaml
2525

26-
All stores are declared under the top-level `stores:` key in `atmos.yaml`. Each store has a unique name, a `type`, and provider-specific `options`:
26+
All stores are declared under the top-level `stores:` key in `atmos.yaml`. Each store has a unique name, a `kind`, and provider-specific `options`. The legacy `type` field remains supported for compatibility, but `kind` is canonical:
2727

2828
```yaml
2929
# atmos.yaml
3030
stores:
3131
prod/ssm:
32-
type: aws-ssm-parameter-store
32+
kind: aws/ssm
33+
options:
34+
region: us-east-1
35+
36+
prod/asm:
37+
kind: aws/asm
3338
options:
3439
region: us-east-1
3540

3641
prod/azure:
37-
type: azure-key-vault
42+
kind: azure/keyvault
3843
options:
3944
vault_url: "https://my-keyvault.vault.azure.net/"
4045

4146
prod/gcp:
42-
type: google-secret-manager
47+
kind: gcp/secretmanager
4348
options:
4449
project_id: my-project
4550

@@ -77,13 +82,13 @@ Stores that support identity-based authentication accept an `identity` field at
7782
```yaml
7883
stores:
7984
prod/ssm:
80-
type: aws-ssm-parameter-store
85+
kind: aws/ssm
8186
identity: prod-aws # References an identity defined in the auth section
8287
options:
8388
region: us-east-1
8489
```
8590

86-
Identity-based auth is supported by AWS SSM, Azure Key Vault, and Google Secret Manager. It is not supported by Redis or Artifactory (a warning is logged if configured).
91+
Identity-based auth is supported by AWS SSM, AWS Secrets Manager, Azure Key Vault, and Google Secret Manager. It is not supported by Redis or Artifactory (a warning is logged if configured).
8792

8893
## Store Provider Configuration
8994

@@ -92,7 +97,7 @@ Identity-based auth is supported by AWS SSM, Azure Key Vault, and Google Secret
9297
```yaml
9398
stores:
9499
prod/ssm:
95-
type: aws-ssm-parameter-store
100+
kind: aws/ssm
96101
options:
97102
region: us-east-1 # Required
98103
prefix: myapp # Optional: prepended to all key paths
@@ -105,12 +110,26 @@ Authentication uses the AWS default credential chain (environment variables, sha
105110

106111
Key format: `/<prefix>/<stack-parts>/<component-parts>/<key>` (segments joined by `/`).
107112

113+
### AWS Secrets Manager
114+
115+
```yaml
116+
stores:
117+
prod/asm:
118+
kind: aws/asm
119+
options:
120+
region: us-east-1
121+
prefix: myapp
122+
stack_delimiter: "/"
123+
```
124+
125+
Use `secret: true` with `kind: aws/asm` for declared secrets managed through `atmos secret` and `!secret`.
126+
108127
### Azure Key Vault
109128

110129
```yaml
111130
stores:
112131
prod/azure:
113-
type: azure-key-vault
132+
kind: azure/keyvault
114133
options:
115134
vault_url: "https://my-keyvault.vault.azure.net/" # Required
116135
prefix: myapp # Optional
@@ -126,7 +145,7 @@ Key format: `<prefix>-<stack-parts>-<component-parts>-<key>` (segments joined by
126145
```yaml
127146
stores:
128147
prod/gcp:
129-
type: google-secret-manager # Also accepts "gsm"
148+
kind: gcp/secretmanager
130149
options:
131150
project_id: my-project # Required
132151
prefix: myapp # Optional
@@ -312,7 +331,7 @@ Atmos merges these into a complete hook definition at resolution time.
312331
```yaml
313332
stores:
314333
prod/ssm:
315-
type: aws-ssm-parameter-store
334+
kind: aws/ssm
316335
options:
317336
region: us-east-1
318337
read_role_arn: arn:aws:iam::123456789012:role/SSMReader
@@ -328,12 +347,12 @@ Define separate stores per region:
328347
```yaml
329348
stores:
330349
prod-us/ssm:
331-
type: aws-ssm-parameter-store
350+
kind: aws/ssm
332351
options:
333352
region: us-east-1
334353
335354
prod-eu/ssm:
336-
type: aws-ssm-parameter-store
355+
kind: aws/ssm
337356
options:
338357
region: eu-west-1
339358
```
@@ -347,7 +366,7 @@ Reference the appropriate store in each stack's configuration.
347366
```yaml
348367
stores:
349368
prod/ssm:
350-
type: aws-ssm-parameter-store
369+
kind: aws/ssm
351370
options:
352371
region: us-east-1
353372
```
@@ -381,7 +400,7 @@ components:
381400

382401
## Security Best Practices
383402

384-
- **Secrets exposure**: `!store` values appear in stdout when running `atmos describe stacks` or `atmos describe component`. Avoid storing highly sensitive secrets in stores that are frequently described.
403+
- **Secrets exposure**: `!store`, `!store.get`, and `atmos.Store` read values in cleartext and reject stores marked `secret: true`. Use `secret: true` plus `!secret` and `atmos secret` for sensitive values.
385404
- **Least privilege**: Use `read_role_arn`/`write_role_arn` to separate read and write permissions. Grant only the permissions each operation needs.
386405
- **Environment variables for tokens**: Never hardcode access tokens. Use `!env` or environment variables (`ARTIFACTORY_ACCESS_TOKEN`, `JFROG_ACCESS_TOKEN`, `ATMOS_REDIS_URL`).
387406
- **Cold-start handling**: Always provide `| default` values for store lookups that may reference unprovisioned components.
@@ -392,7 +411,7 @@ components:
392411

393412
| Problem | Cause | Solution |
394413
|---------|-------|----------|
395-
| `store type not found` | Invalid `type` in store config | Use one of: `aws-ssm-parameter-store`, `azure-key-vault`, `google-secret-manager`, `gsm`, `redis`, `artifactory` |
414+
| `store type not found` | Invalid `kind`/`type` in store config | Use one of: `aws/ssm`, `aws/asm`, `azure/keyvault`, `gcp/secretmanager`, `redis`, `artifactory` |
396415
| `region is required` | Missing `region` for SSM store | Add `region` to store options |
397416
| `vault_url is required` | Missing `vault_url` for Azure | Add `vault_url` to store options |
398417
| `project_id is required` | Missing `project_id` for GCP | Add `project_id` to store options |

0 commit comments

Comments
 (0)