Skip to content

Add credential_cache_location setting for role profiles - #10854

Draft
GarrettBeatty wants to merge 5 commits into
credential-cache-settingfrom
credential-cache-location
Draft

GarrettBeatty wants to merge 5 commits into
credential-cache-settingfrom
credential-cache-location

Conversation

@GarrettBeatty

@GarrettBeatty GarrettBeatty commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #10849. This PR is stacked on it; the diff below starts after
its commits.

Problem

Role credentials from AssumeRole / AssumeRoleWithWebIdentity are always
cached in ~/.aws/cli/cache, and there is no way to choose another folder.
Some users need the cache outside the home directory, for example a
per-session or tmpfs directory, or a read-only home (#1804, also asked in
#7376 and #6628).

Solution

A new optional profile setting, read by the assume role and the assume role
with web identity credential providers, next to credential_cache from
#10849:

Setting Values Default
credential_cache_location an absolute directory, or a path that starts with ~ ~/.aws/cli/cache
  • credential_cache_location = <dir> stores the file cache in that
    directory. ~ is expanded; environment variables aren't. With
    credential_cache = memory, the location is ignored and isn't read.
  • Each hop of a role chain reads its own profile's setting. For web
    identity, the setting of the profile in use applies even when the token
    file or role ARN comes from the environment, as for credential_cache.
  • A web identity source_profile hop with a location caches there.

Example ~/.aws/config

# Cache this role's credentials outside the home directory.
[profile ci]
role_arn = arn:aws:iam::123456789012:role/CI
web_identity_token_file = /var/run/secrets/token
credential_cache_location = /run/user/1000/aws-cache

Cache folder

The folder is used like the default cache folder: it's created if missing, and files are written with 0600. Choosing a location is up to the user.

Errors

All are InvalidConfigError, raised when the profile is loaded, before any
STS call. Reads and writes of the cache files behave as in the default
cache folder.

Setting Message
credential_cache_location = (empty) The credential_cache_location in profile "ci" is empty. Set it to a directory or remove it.
credential_cache_location = cache (relative) The credential_cache_location "cache" in profile "ci" is not an absolute path. Use an absolute path or a path that starts with ~/.
credential_cache_location = ~nouser/cache The credential_cache_location "~nouser/cache" in profile "ci" could not be expanded: the home directory for that user can't be found. Use an absolute path or a path that starts with ~/.
credential_cache_location = $HOME/cache The credential_cache_location "$HOME/cache" in profile "ci" is not an absolute path. Use an absolute path or a path that starts with ~/. Environment variables aren't expanded.

A relative path is rejected rather than resolved against the current
directory, so the cache never moves with the working directory. With
credential_cache = memory, the location isn't read, so it can't cause an
error.

Limits

  • Only a profile setting; there is no environment variable for it.
  • Role profiles only. IAM Identity Center (SSO) tokens and credentials, and
    credential_process, are not covered by this change.
  • Only the AWS CLI reads this key. The AWS SDKs and other tools that read
    the shared config file ignore it.

Testing

Run on the top commit with a temporary home directory and config, no
AWS_* environment variables, and Python 3.12:

Tests Result
tests/unit/botocore/test_credentials.py 250 passed
tests/functional/botocore/test_credentials.py 60 passed
tests/functional/configure/test_exportcreds.py 2 passed
tests/unit/customizations/test_assumerole.py 4 passed
tests/functional/docs/test_help_output.py, tests/unit/test_clidocs.py, tests/unit/test_help.py, tests/unit/test_topictags.py 149 passed, 3 skipped
Total 465 passed, 3 skipped, 0 failed

The JSONFileCache tests (TestJSONCache, and test_utils.py -k Cache)
pass unchanged.

25 new tests on top of #10849:

  • Settings: ~ and ~user expansion, empty and relative locations (and
    the environment variable note), a relative location writes nothing to the
    current directory, and memory with a location (also empty or relative)
    set.
  • The folder: a missing folder and its parents are created on the first
    write, a cached file is reused by the next command, and a cache file is
    0600, as in the default folder.
  • Role chains: each hop caches in its own profile's location, a location
    on the source hop only, and memory on the top hop with a location on
    the source hop.
  • Web identity: a location from the profile, with the token file from the
    environment, and on a web identity source hop (and a relative one).
  • Explicit credential_cache = file with no location uses the injected
    cache, and on a web identity source hop, where no cache is injected, it
    writes to ~/.aws/cli/cache.
  • End to end against real STS (one account, a read-only target role, on
    an earlier revision without the directory checks):
    credential_cache_location cached only in the given directory; cache
    files are mode 600; a relative location fails before any STS call, and no
    directory is created.
  • aws help config-vars renders the new paragraph.
  • ruff check and ruff format --check are clean on the changed lines.
    The import order finding ruff reports in
    tests/functional/botocore/test_credentials.py (the import block at line
    13) is already on v2 and isn't touched here.

Changelog

.changes/next-release/feature-credentials-44796.json, type feature,
category credentials.

Merge order

Merge #10849 first. The commits can be squashed or kept.

This PR was generated by AI tools, and reviewed by @GarrettBeatty.

Some users need role credentials cached somewhere other than
~/.aws/cli/cache, for example on a different volume or in a directory
their tooling manages. Add an optional profile setting, read by the
assume role and the assume role with web identity providers:

* credential_cache_location = <dir> stores the file cache in that
  directory. ~ is expanded. An empty, relative or unexpandable (~user)
  value is an InvalidConfigError, so nothing is resolved against the
  current directory; the error notes that environment variables aren't
  expanded when the value contains $ or %. With credential_cache =
  memory, the location is ignored.

The directory is checked when the profile loads, before the STS call. A
missing directory and each missing parent is created with mode 0700;
existing parents are left alone. It must be a real directory (not a
symbolic link, whose target the error names) and writable. On Linux and
macOS it must also be owned by the current user with no group or other
write permission.

Cache files there go through _PrivateCredentialFileCache, which checks
the directory again on every read and write. Where dir_fd is supported,
the directory is opened once without following links and all I/O is
relative to that handle. Cache file symlinks are never followed. Files
owned by another user, group or other writable, with more than one hard
link, invalid JSON or missing credential keys are a cache miss. Writes
go to a new 0600 temporary file renamed into place. A failed write after
the STS call logs a warning and the command continues. File descriptors
are closed if fdopen fails.

The default ~/.aws/cli/cache isn't checked, whether the profile sets
credential_cache = file or neither setting, so existing setups behave as
before.
The owner and mode checks don't apply on Windows, which has no POSIX
owner or mode bits. Rely on the default permissions of the user profile
folder instead: on Windows, a credential_cache_location must be
%USERPROFILE% or a folder under it, after following junctions and
symbolic links. Network (UNC) paths are refused, and so is every
location when the user profile folder can't be found or is the root of
a drive or share. The check runs before the directory is created, so a
refused location leaves nothing behind.

The path logic is tested with ntpath on every OS, and the wiring with
os.name patched.
Describe credential_cache_location for assume role and assume role with
web identity profiles in the config-vars topic: accepted values, the
default, and that memory ignores it. Explain the directory checks: a
missing directory is created with mode 700, symbolic links and
unwritable directories are refused before the STS call, cache file links
are replaced rather than followed, and a failed cache write only logs a
warning. Describe the extra owner, permission and hard link checks on
Linux and macOS, and the Windows rule that the directory must be under
the user profile folder, with network paths refused. Note that the
default ~/.aws/cli/cache isn't checked.
A credential_cache_location folder is now used like the default
~/.aws/cli/cache: a JSONFileCache that creates the folder if it's
missing and writes each file with mode 0600. Choosing the folder is up
to the user, so the CLI no longer checks its owner, mode or links, and
no longer refuses Windows locations outside the user profile.

The setting itself is unchanged: an absolute path or one starting with
~, a relative path is a config error, and memory ignores it.
@GarrettBeatty
GarrettBeatty force-pushed the credential-cache-location branch from 5e35984 to 215c135 Compare November 9, 2026 15:57

This branch has not been deployed

No deployments
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.

1 participant