Skip to content

fix(transport): Fixes fetching new access token on every use of Service Account transport#71

Open
cveticm wants to merge 2 commits into
masterfrom
CLOUDP-418568-sa-token
Open

fix(transport): Fixes fetching new access token on every use of Service Account transport#71
cveticm wants to merge 2 commits into
masterfrom
CLOUDP-418568-sa-token

Conversation

@cveticm

@cveticm cveticm commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Proposed changes

JIRA ticket: CLOUDP-418568

Summary

When authenticating with an SA, the Atlas CLI minted a new access token on every command. Service accounts are capped at 100 active tokens per hour, so any workflow that runs many CLI commands (e.g. an automated agent using a GSA) quickly exhausts the limit and fails with:
oauth2: "access_denied" "Access Token limit reached. Please use the existing Access Tokens or create a new Service Account"

This PR persists the SA access token and reuses it until it expires (~1 token/hour instead of 1/command).

Root cause

transport.NewServiceAccountClientWithHost built the client via clientcredentials.Config.Client(ctx). Each CLI command is a new process, so the OAuth2 client-credentials source minted and cached a token only in-process, then discarded it on exit. Nothing was written to disk, unlike the UserAccount flow which already persists its token.

Fix

NewServiceAccountClientWithHost now composes token sources:

  • Seeds an oauth2.ReuseTokenSource from the token persisted on disk (loaded via the new config.ServiceAccountToken() accessor — returns the access token + JWT-derived expiry, no refresh token, leaving Token()/UserAccount behavior untouched).
  • Wraps it in a small persisting TokenSource that writes any newly minted token back through the existing SetAccessToken + Save accessors (stored in the existing access_token field).

Result: a valid persisted token is reused across invocations; a new one is minted (and saved) only when none exists or the current one has expired. UserAccount, API-key, and no-auth paths are unchanged. Logout already clears access_token, so the persisted SA token is cleaned up on logout.

Note: SA profiles will now also have an access token attriute:

> atlas config describe sa-profile
SETTING         VALUE
access_token    [redacted - source: secure storage]  << new field for SA profiles
auth_type       service_account
client_id       [redacted - source: secure storage]
client_secret   [redacted - source: secure storage]
output          plaintext
service         cloud

Reproduction (before the fix)

Ran the CLI with an SA profile in a loop:

for i in $(seq 1 120); do atlas projects list --profile sa -o json; done

Fails at call 101 with Access Token limit reached, confirming one token minted per command.

Verification (after the fix)

  • Unit tests (transport, config): reuse (valid seed , no mint, no save), mint-and-persist (no seed, 1 mint saved), expired-seed (1 mint and save), and persistingTokenSource only saving on change; plus ServiceAccountToken() accessor tests including the non-JWT/no-expiry fallback.
  • E2E (test/e2e): TestServiceAccountTokenReuse creates a real SA, then constructs a fresh client per "invocation" seeded from the persisted token across 6 calls. Asserts exactly 1 token minted total.
  • Live CLI: reran the 120-call loop against a fresh SA profile with the fixed binary and got 0 token-limit errors (previously failed at 101). Debug tracing (temporary, not in this PR) confirmed the same access-token fingerprint reused across separate invocations until its expiry.

@coveralls

coveralls commented Jul 15, 2026

Copy link
Copy Markdown

Coverage Status

Coverage is 61.765%CLOUDP-418568-sa-token into master. No base build found for master.

@cveticm
cveticm force-pushed the CLOUDP-418568-sa-token branch from dd5ddcc to 3fca99b Compare July 15, 2026 14:52
@cveticm
cveticm marked this pull request as ready for review July 15, 2026 15:20
@cveticm
cveticm requested a review from a team as a code owner July 15, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants