Skip to main content

Centralizing Developer Cloud Access

This guide shows you how to define your organization's cloud authentication configuration once, in a private central repository, and have it "just work" for every developer who clones any project repo that imports it — no manually copy-pasted ~/.aws/config profile blocks, no per-developer setup docs to keep in sync, no risk of someone hand-typing the wrong account ID.

The pattern is the same regardless of cloud — Atmos supports AWS, Azure, and GCP as first-class auth providers. The example below shows all three side by side.

If you've only used Atmos in Terraform repositories, using it here may be unexpected. But Atmos isn't a Terraform wrapper—it's a general-purpose task runner and configuration platform with best-in-class support for Terraform. We recommend using it in every repository to give teams one consistent way to manage commands, toolchains, authentication, secrets, and workflows, whether that repository contains infrastructure code or not.

The Problem

A common way teams distribute AWS SSO access today is a [profile] block passed around in Slack or a wiki page:

[profile corp-nonprod]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = us-east-1
sso_account_id = 111111111111
sso_role_name = ReadOnlyAccess

This works, but it doesn't scale or govern well:

  • Every developer's ~/.aws/config is a hand-rolled, ungoverned copy — nothing catches copy-paste mistakes (and it costs your team time supporting it).
  • Every new team member goes through the same onboarding song-and-dance, usually capped off with a Slack message asking how to configure their AWS credentials.
  • Making any changes requires coordinating the updates across the entire team (unsustainable)
  • There's no single source of truth to audit or version-control.
  • If your organization is multi-cloud, this ad hoc pattern doesn't generalize — AWS profiles, az login conventions, and gcloud configurations all look different, so you end up maintaining a separate, differently-shaped solution per cloud instead of one consistent pattern.

The Solution: One Central, Private Config Repo

Atmos lets you define your auth: configuration once in a private repository and import: it from the atmos.yaml of every project repo. Developers only need to clone a project and run atmos auth login — they never see or manage the SSO block themselves.

1. Create the central config repo

Create a private repository — for example github.com/acme-corp/atmos-config — and organize it by cloud, then by the group of developers (or team) the file grants access to. A simple starting layout:

atmos-config/
├── aws/
│ └── developers/
│ └── auth.yaml
├── azure/
│ └── developers/
│ └── auth.yaml
└── gcp/
└── developers/
└── auth.yaml

The import syntax, private-repo access, and atmos auth workflow are identical across tabs — only the path (aws/, azure/, or gcp/) and the providers:/identities: block inside auth.yaml change. Use the path and block for the cloud you're setting up:

# aws/developers/auth.yaml (in the private acme-corp/atmos-config repo)
auth:
providers:
acme-sso:
kind: aws/iam-identity-center
region: us-east-1
start_url: https://d-xxxxxxxxxx.awsapps.com/start

identities:
nonprod:
kind: aws/permission-set
default: true # makes this the default identity
via:
provider: acme-sso
principal:
name: ReadOnlyAccess # the SSO permission set / role name
account:
id: "111111111111" # quote it — it's a string, not a number

Tag releases (e.g. v1.0.0) so downstream repos can pin to a known-good version instead of tracking a moving branch. A repo that needs more than one cloud isn't limited to a single provider — it can import multiple provider files side by side (e.g. aws.yaml and azure.yaml).

2. Import it from every project repo

In each project's own atmos.yaml, add a remote import: pointing at that file, pinned to a tag:

# atmos.yaml (in any project repo)
import:
- "git::https://github.com/acme-corp/atmos-config.git//aws/developers/auth.yaml?ref=v1.0.0"

That's the entire integration. Every project that adds this one line inherits the same providers and identities — add an account or rotate a role name once in the central repo, tag a new release, and bump the ref across projects (or leave them tracking a branch if you'd rather changes roll out immediately).

By default this import is re-resolved (a fresh shallow clone) on every single atmos command in the project, not just auth commands — so every command depends on network reachability to the central repo. Set imports: { ttl: ... } once in atmos.yaml to cache the clone across commands instead (see Caching Remote Imports).

Import only what a project needs

A project doesn't have to pull in the entire org's auth: config just to get one identity. Extend the same <cloud>/<team>/auth.yaml layout with more teams as they need their own identities:

atmos-config/
└── aws/
├── developers/auth.yaml # broad, mostly-read access — imported by most repos
├── platform/auth.yaml # platform team's more privileged identities
└── data/auth.yaml # data team's identities

A platform-team repo then imports only its own file, not the whole org's config:

# atmos.yaml (in a platform-team project repo)
import:
- "git::https://github.com/acme-corp/atmos-config.git//aws/platform/auth.yaml?ref=v1.0.0"

This composes the same way whether the split is by team, by environment (nonprod/auth.yaml/ prod/auth.yaml), or by cloud provider — you're not limited to one monolithic file imported everywhere.

3. Private repo access — no token setup needed

Because atmos-config is private, fetching it needs authentication. This git:: import is cloned by Git itself under the hood, and Atmos resolves a token for that clone in this order:

  1. ATMOS_PRO_GITHUB_TOKEN environment variable (set automatically if you use Atmos Pro's GitHub integration)
  2. ATMOS_GITHUB_TOKEN environment variable
  3. GITHUB_TOKEN environment variable
  4. gh auth token, if the GitHub CLI is installed and the developer has already run gh auth login

For most developers, step 4 means there's nothing to configure at all — gh auth login is already a common onboarding step, and Atmos reuses that session automatically for this import too.

Developer Workflow

With the import wired up, a new developer's entire setup is:

git clone git@github.com:acme-corp/some-project.git
cd some-project
atmos auth login # auto-uses the default identity; pass a bare --identity to force a selector

Then, to actually use the credentials:

# Option A: isolated subshell — credential env vars are scoped to this child
# shell and go away when it exits (the underlying credential files on disk
# aren't revoked; they just expire on their own normal schedule)
atmos auth shell

# Option B: run one command with credentials injected
atmos auth exec -- aws s3 ls

# Option C: make credentials ambient in the current shell
eval $(atmos auth env)

atmos auth env is safe to add to ~/.zshrc/~/.bashrc unconditionally — it only prints (and, via eval, exports) environment variables from cached credentials; it never triggers a login prompt on its own. A new shell starts in $HOME, though, not inside your project checkout, so Atmos won't find the atmos.yaml (and its import) unless you point it there explicitly with --chdir:

eval $(atmos auth env --chdir=/path/to/your/checkout)

What's Actually Zero-Setup (and What's Optional)

Install Atmos once; use it on every repo in the organization. For a private central repo, that also means being authenticated with GitHub — most developers already are, via gh auth login (see step 3 above for the exact resolution order). From there: clone a repo, run atmos auth login, then atmos auth shell or atmos auth exec — no profile block to copy, no account ID to transcribe.

The one thing that isn't automatic is ambient parity with a manually managed [profile] block — a bare aws s3 ls, or an IDE extension finding credentials, with no atmos auth wrapper involved at all. Atmos deliberately doesn't write to ~/.aws/credentials/~/.aws/config; credentials go to Atmos-managed files instead, exposed only to processes that inherit AWS_SHARED_CREDENTIALS_FILE/AWS_CONFIG_FILE/ AWS_PROFILE. This is a security default, not an oversight — it avoids silently overwriting a developer's own credentials, and it means a tool (or an AI agent) isn't automatically signed in to AWS just by existing in your shell; it only gets credentials if something explicitly runs atmos auth exec/shell or has eval'd atmos auth env.

Want that ambient parity anyway? Add eval $(atmos auth env --chdir=...) to your shell profile (see Developer Workflow) — optional, and most repo-scoped work doesn't need it.

Either way, updates are centrally managed rather than re-broadcast: add an account or rotate a role once in the central repo and tag a release. Projects tracking a branch pick up the change immediately; projects pinned to a tag (the pattern this guide recommends) pick it up the next time they bump their ref — still a one-line change in one file, not a wiki post and a round of developers hand-editing ~/.aws/config.

Troubleshooting

atmos auth login doesn't find the identity — a failed import is non-fatal by design: a typo'd ref, an unreachable repo, or a private repo Git can't authenticate to all produce an empty auth: section and exit 0, not an error. Run atmos auth list first to confirm the import actually resolved anything. If it's empty, look for a WARN failed to resolve import line in the command's output — Atmos logs it at the default log level, so it shows up without setting ATMOS_LOGS_LEVEL. That line names the real reason (bad ref, 403, DNS failure, etc.).

That warning shows an authentication error — confirm gh auth status shows an active session (or that ATMOS_PRO_GITHUB_TOKEN/ATMOS_GITHUB_TOKEN/GITHUB_TOKEN is set — see step 3 for the full resolution order), and that the account has read access to the central config repo.

AWS CLI/Terraform outside of Atmos can't find credentials — you're missing eval $(atmos auth env) in your shell profile, or the tool was launched before you ran it in that shell session.

See Also