Atmos Pro Logo

Atmos Pro

ProductPricingDocsBlogChangelog
⌘K
Create Workspace
Atmos Pro Logo

Atmos Pro

ProductPricingDocsBlogChangelog
What is Atmos Pro?
Installation
How it Works
Workspaces
Team Members
Authentication
Ordered Deployments
Deployment Approvals
Deployment Locking
Drift Detection
Event Triggers
Workflow Dispatches
Repository Permissions
Audit Log
MCP Server
AI Credits
Troubleshooting
Workspaces
Atmos Stacks
Atmos CI
Atmos Toolchain
Cloud Authentication
GitHub Repository
GitHub Workflows
Commit From CI
Upload Instances
GitHub Environments
Deployment Locking
Drift Detection
CODEOWNERS Validation
Audit Log Webhooks
MCP Server
AWS
Private Cross-Repo Modules
Reference
Atmos Docs
Example Repository

Pull Private Cross-Repo Modules in CI

Use Atmos Pro STS to mint short-lived, read-only GitHub tokens so CI can pull private Terraform modules and components from your other repos — no PATs, no second GitHub App, and no Terraform code changes.


When a stack vendors a component or references a Terraform module that lives in a different private repository, CI needs credentials to read that repo. The usual options — a Personal Access Token or a dedicated GitHub App — are long-lived and almost always scoped broader than "read these modules." That is exactly the credential a leak weaponizes: a PAT that surfaces in a build log, a compromised dependency, or a misconfigured runner keeps working indefinitely and reaches everything it was granted, which an attacker can use to pivot. Storing and rotating it is the visible cost; the standing blast radius is the real one.
Atmos Pro STS removes that entirely. Your CI run exchanges its GitHub Actions OIDC identity for a short-lived, read-only GitHub token scoped only to the source repositories that have explicitly opted in. The Atmos CLI injects that token as a git credential for the duration of the run, so atmos vendor pull, source:-provisioned components, and terraform init of a private module all resolve with no changes to your Terraform code.
A source repo only becomes readable when it opts in. STS is deny-by-default: each source repo grants access by committing a small trust policy (.atmos/pro/sts/default.yaml) that says which CI identities may mint a token for it. A repo with no policy is never mintable — even read access. This keeps consent where it belongs: in the source repo, as reviewable, branch-protectable code its own owners merged, rather than a switch someone flips elsewhere. Making access "effortless" is still one small file away (see the match-all example).
Requirements. This needs an Atmos CLI release that includes the atmos/pro auth provider and the github/sts integration; the Atmos Pro STS entitlement on your plan; the feature enabled on the workspace Security tab (Workspace → Settings → Security → Cross-Repo Token Broker); the Atmos Pro GitHub App installed on both the repo running CI and every source repo you want to read; and a committed trust policy in each source repo.
  1. 1
    Grant the consuming repo permission — In Atmos Pro, on the repository that runs CI, add the ws:sts:create permission (Repository Permissions page), just as you would ws:commits:create for autocommit.
  2. 2
    Configure Atmos auth — Add an Atmos Pro provider and a github/sts integration to your atmos.yaml.
  3. 3
    Grant the workflow an OIDC token — Add id-token: write to the workflow permissions.
  4. 4
    Run Atmos as usual — Vendoring and Terraform module fetches now authenticate automatically.
The atmos/pro provider authenticates the CLI to Atmos Pro (not to GitHub). The github/sts integration consumes that identity to broker GitHub tokens — the same pattern as the AWS provider's aws/ecr and aws/eks integrations.
auth:
  providers:
    atmos-pro:
      kind: atmos/pro # authenticate the CLI to Atmos Pro (via GitHub Actions OIDC)
      base_url: https://atmos-pro.com
  identities:
    atmos-pro:
      kind: atmos/pro
      via:
        provider: atmos-pro
  integrations:
    github-sts:
      kind: github/sts # mint read-only git credentials for private sources
      via:
        identity: atmos-pro
      spec:
        # Optional narrowing allowlist. Omit to request every repo where Atmos
        # Pro is installed; list repos to request only those. Either way, a repo
        # is minted only if it has a matching trust policy committed (see below).
        repos:
          - acme/terraform-modules
          - acme-labs/components
By default the minted token is read-only (contents: read). The consumer never requests scopes itself — a source repo grants access (and any additional scopes) to matched consumers via its trust policy (see below), always bounded by what the Atmos Pro GitHub App holds. repos only narrows the request; it cannot grant access to a repo that hasn't opted in.
The only thing your workflow declares is permission to mint an OIDC token. There is no GitHub Action to add — the Atmos CLI does the exchange, injection, and cleanup natively.
permissions:
  id-token: write # required: lets the runner mint the OIDC token Atmos Pro verifies
  contents: read
 
jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cloudposse/github-action-setup-atmos@v2
      - run: atmos vendor pull
      - run: atmos terraform plan my-component -s my-stack
That's it. When atmos vendor pull or atmos terraform runs, Atmos resolves the github/sts integration, mints the scoped token, and exports it as a git URL rewrite into the child process — so go-getter and Terraform's module installer both authenticate transparently.
  1. 1
    The CLI mints a GitHub Actions OIDC token and exchanges it with Atmos Pro for a short-lived session.
  2. 2
    Atmos Pro verifies the OIDC token, confirms the calling repo belongs to your workspace, and checks the STS entitlement.
  3. 3
    For each requested source repo, Atmos Pro reads its required trust policy and checks the caller against it. Repos with no policy — or no matching rule — are excluded; the rest get a read-only (or policy-granted), repository-scoped GitHub App installation token (one per installation).
  4. 4
    The CLI injects the token as a per-owner git credential (GIT_CONFIG_* URL rewrite) for the run, and revokes it when the command finishes.
GitHub installation tokens live at most ~1 hour; the CLI revokes them at the end of the run, so the credential effectively lives only for the lifecycle of the job.
STS is deny-by-default: a source repo is mintable only if it has committed a trust policy that the calling CI identity matches. No file → not mintable. The workspace toggle turns the feature on; it does not consent on a source repo's behalf — that authority lives only in the source repo's own .atmos/pro/sts/*.yaml, so the people who own the code (and their CODEOWNERS reviewers) are the ones who grant access, in a reviewable, version-controlled file.
Let Atmos Pro open the PR for you. If you use the Atmos Pro MCP (in the in-product chat or any connected client), just ask — e.g. "let acme/app read this repo via STS". The agent checks the source repo is imported, generates the policy below, and opens a pull request adding it (defaulting you as the reviewer). It will not touch a repo that isn't imported into your workspace.
A policy file lives at .atmos/pro/sts/default.yaml in the repo being read. It is a versioned Atmos Pro manifest — apiVersion: atmos-pro.com/v1alpha1, kind: TrustPolicy, a metadata.name, and a spec.rules list. The caller need match any one rule. Within a rule, the caller must satisfy every entry in its match block, and the block must specify at least one claim (an empty match never matches). Start the file with the # yaml-language-server line so your editor gives you autocomplete and validates against the published schema:
# yaml-language-server: $schema=https://atmos-pro.com/schemas/v1alpha1/trust-policy.json
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default # = the file name (.atmos/pro/sts/<name>.yaml)
spec:
  rules:
    - match:
        # one or more claim → matcher entries (see below)
      permissions:
        # optional, owner-granted (see below)
Each match entry maps a GitHub OIDC claim to a matcher. A matcher is a glob string (the safe default — * matches any run of characters, ? matches one character, and every other character is literal, so . : / - are matched literally, not as wildcards) or an explicit { regex: "…" } opt-in (an anchored full-string regex, for when a glob can't express the intent). Prefer globs; reach for regex only when you must.
The supported claims (a typo like repositoryowner: fails validation rather than silently never matching):
ClaimMatches
subjectThe OIDC sub (e.g. repo:acme/app:ref:refs/heads/main)
repositoryowner/repo of the calling repo
repository_ownerThe owner (org or user) of the calling repo
refThe git ref (e.g. refs/heads/main)
ref_typebranch or tag
actorThe GitHub login that triggered the run
workflow_refThe calling workflow's ref
environmentThe GitHub Environment the job runs in
shaThe commit SHA
The OIDC issuer is always enforced to GitHub Actions (https://token.actions.githubusercontent.com) — you don't (and can't) match on it.
A rule's optional permissions map grants scopes beyond the read-only default. Scopes are owner-granted — the consumer can never request them. Each key is a GitHub App permission name and each value is read, write, or admin. Omit permissions for the read-only default (contents: read + the always-present metadata: read). Grants are capped at what the Atmos Pro GitHub App actually holds (GitHub enforces that ceiling).
The "effortless" opt-in — one committed file restores the zero-config feel, but the grant is now explicit and reviewable. Any caller Atmos Pro verifies gets a read-only token:
# .atmos/pro/sts/default.yaml — broad opt-in, read-only
# yaml-language-server: $schema=https://atmos-pro.com/schemas/v1alpha1/trust-policy.json
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        subject: "*"
# only callers in repos owned by `acme` may read this repo
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        repository_owner: "acme"
Prefer a narrow subject over a broad one when you know the consumer. A glob with no wildcards is effectively an exact match:
# only acme/infra's main-branch workflows may read this repo
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        subject: "repo:acme/infra:ref:refs/heads/main" # exact; for any branch use "repo:acme/infra:*"
# any acme repo, but only from the protected `production` environment
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        repository_owner: "acme"
        environment: "production"
The caller need match any one rule:
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        subject: "repo:acme/infra:ref:refs/heads/main"
    - match:
        repository: "acme/platform-*"
    - match:
        repository_owner: "acme-labs"
Add a permissions map to a rule to grant beyond the read-only default:
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: default
spec:
  rules:
    - match:
        repository_owner: "acme"
      permissions:
        contents: read
        pull_requests: write # e.g. let a matched consumer open PRs
The policy file name defaults to default (→ .atmos/pro/sts/default.yaml), and metadata.name matches it. The github/sts integration can request a different name, selecting .atmos/pro/sts/<name>.yaml instead — useful for auditing distinct consumer classes ("federated as ci"):
# .atmos/pro/sts/ci.yaml
apiVersion: atmos-pro.com/v1alpha1
kind: TrustPolicy
metadata:
  name: ci
spec:
  rules:
    - match:
        repository: "acme/*"
The named (or default) file must exist, or the source is excluded with no_trust_policy.
Because the policy lives in the source repo, protect it. Branch protection on the default branch plus a CODEOWNERS rule for /.atmos/pro/sts/ lets you require designated reviewers (e.g. org/security admins) to approve any change to who may mint tokens and what scopes they get:
# CODEOWNERS — require admin review for trust-policy changes
/.atmos/pro/sts/  @your-org/security-admins
Prefer exact subject matches over broad patterns, and grant the narrowest permissions that the consuming workflow needs.
The minted token can only reach source repositories that have explicitly opted in with a matching trust policy, is read-only by default, and is gone within the hour (sooner, on run completion). It can never reach another organization's code, a repo that hasn't opted in, or anything beyond what the source repo's trust policy grants — capped by what the Atmos Pro GitHub App holds, so it can never exceed the App's own scopes. Every token issued is recorded in your audit log with the verified run identity — repository, ref, actor, the repos it was scoped to, and the permissions granted — while the token value itself is never logged.
That inverts the PAT risk above. If this token leaks from the runner, an attacker gets read access to a fixed set of opted-in repos for the few minutes until the job revokes it — not standing, broadly scoped access that lives until someone notices. The window and the reach are both small by construction.
If a source repo isn't resolving, check the response from the exchange: repos are reported as excluded with a reason:
  • no_trust_policy — the source repo has no .atmos/pro/sts/default.yaml (or the named file). Commit a trust policy that matches your CI identity (see the examples). This is the most common reason on first setup, since STS is deny-by-default.
  • trust_policy_denied — the repo has a policy, but your workflow's verified identity matched no rule. Compare your OIDC subject/claims against the policy's matchers.
  • trust_policy_invalid — the policy file is present but doesn't parse: bad YAML, a wrong apiVersion, an unknown kind, or a spec that violates the schema (e.g. a misspelled claim, or a permissions value that isn't read/write/admin). STS fails closed, so fix the file before access resumes.
  • not_installed_in_workspace — the Atmos Pro GitHub App isn't installed on that repo for this workspace.
Confirm the Atmos Pro GitHub App is installed on the source repo, the STS entitlement and workspace toggle are enabled, and the source repo has a committed trust policy your subject/claims match.

AWSAtmos Docs
Atmos Pro Logo

Atmos Pro

The fastest way to deploy your apps on AWS with Terraform and GitHub Actions.

GitHubTwitterLinkedInYouTubeSlack

For Developers

  • Quick Start
  • Example Workflows
  • Atmos Documentation

Community

  • Register for Office Hours
  • Join the Slack Community
  • Try our Newsletter

Company

  • About Cloud Posse
  • Security
  • Pricing
  • Blog
  • Media Kit

Legal

  • SaaS Agreement
  • Terms of Use
  • Privacy Policy
  • Disclaimer
  • Cookie Policy

© 2026 Cloud Posse, LLC. All rights reserved.

Checking status...