Skip to content

Add Python toolkit with IAM auth token generator - #1

Merged
mwaisaida-13 merged 5 commits into
mainfrom
add-python-and-java-libraries
Aug 14, 2026
Merged

mwaisaida-13 merged 5 commits into
mainfrom
add-python-and-java-libraries

Conversation

@mwaisaida-13

Copy link
Copy Markdown
Collaborator

What

Adds the python/ package of the Developer Toolkit for Amazon ElastiCache, with its first tool: ElastiCache IAM authentication tokens, available as a library and as a CLI.

This PR is Python-only. The java/ package will follow in a separate PR.

Why

IAM auth requires presenting a short-lived SigV4-signed token as the connection password. The signing has several non-obvious details that otherwise surface only as an opaque WRONGPASS at connect time, so the tool encapsulates them:

  • The token is signed against the cache name (or replication group id), not the connection endpoint DNS.
  • Serverless caches sign ResourceType=ServerlessCache; node-based replication groups omit it. It is part of the signature, so it cannot be corrected after the fact.
  • Cache names are lowercased at creation, so they must be signed in lowercase.

Design notes

Token readiness. Tokens are signed on demand, Credentials are re-read from the default AWS credential chain on every call, so rotated credentials (SSO, assume-role, container, instance metadata) are picked up automatically.

Region resolution is explicit argument → AWS_REGION → session (AWS_DEFAULT_REGION or config profile). AWS_REGION is handled by this package because botocore does not read it — the aws CLI and the JS, Go, and Java SDKs all do, so without this a user whose region is set only there would have a working aws CLI and an inexplicably failing toolkit.

ToolkitUserError is the contract between the tools and the CLI. Raising a subclass reports a single-line message and exit 1; anything else keeps its traceback as a toolkit bug. A second tool therefore needs only a subparser, with no CLI change.

Packaging and CI

  • requires-python >= 3.10; tested on 3.10–3.13 across Linux, macOS, and Windows (8 test jobs + lint)
  • setuptools >= 77 for the PEP 639 license expression
  • py.typed so the annotations are visible to consumers
  • Path-filtered workflow, so the Python package builds standalone in the monorepo
  • Private :: Do Not Upload — this is not ready to publish, and that classifier makes PyPI reject any upload

Testing

  • 40 tests, passing on Python 3.10, 3.12, and 3.13
  • ruff check and ruff format --check clean
  • The suite injects credentials and severs the credential environment, so it never reads the real AWS credential chain and needs no AWS account
  • Wheel and sdist build; twine check passes on both
  • py.typed verified end-to-end: mypy in a separate venv resolves the annotations from the installed wheel

Status

Proof of concept — not yet ready for production use.

Licensed under Apache-2.0.

Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/examples/connect_redis.py Outdated
Comment thread python/examples/connect_valkey.py Outdated
Comment thread python/src/developer_toolkit_elasticache/errors.py
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
@mwaisaida-13
mwaisaida-13 requested a review from cziheng-aws July 30, 2026 14:27
Comment thread python/pyproject.toml
Comment thread python/pyproject.toml Outdated
Comment thread python/pyproject.toml
Comment thread python/examples/connect_redis.py
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/tests/test_token_generator.py
…kage

- Add Python 3.14 to the supported/tested versions (classifier + CI matrix).
- Rename provider class ElastiCacheIAMAuth -> ElastiCacheIAMAuthTokenProvider
  for clarity and parity with the Java package.
- Validate user_id against the ElastiCache user-id format (allowing the
  service-managed default.iam-user), and lowercase it before signing so a
  mixed-case id no longer yields a token the server rejects as WRONGPASS.
- Consolidate bad-value validation into a single InvalidParameterError that
  names the offending parameter (botocore-style), keep TargetRequiredError
  distinct as a missing-required error, and collapse the region/credentials
  cases into one ConfigurationError.
- Add known-answer signature tests asserting the exact signed token for both
  serverless and node-based caches, with the signing clock frozen; signatures
  cross-checked against botocore independently.
- Raise the botocore floor to >=1.43.0 so the advertised minimum matches the
  API the test suite relies on.
Comment thread python/src/developer_toolkit_elasticache/errors.py Outdated

print("Token generated successfully!\n")
print(f"Token length: {len(token)} chars")
print(f"Token preview: {token[:80]}...")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - I think it would be useful to display details from the resolved credentials in one of the examples. Could be a followup.

Comment thread python/src/developer_toolkit_elasticache/errors.py Outdated
Comment thread python/src/developer_toolkit_elasticache/cli.py Outdated
Comment thread python/src/developer_toolkit_elasticache/errors.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/src/developer_toolkit_elasticache/token_generator.py
- Rename the base exception to ToolkitInputError so the name fits both CLI and
  programmatic use, and consolidate user errors to two: InvalidParameterError
  (bad value or parameter combination) and ConfigurationError (missing region
  or credentials), both inheriting the base.
- Unify cache-name and user-id checks into one validate-and-normalize helper so
  every validator normalizes and returns consistently; derive the failure
  message from the accepted pattern instead of a hand-maintained description.
- Trim comments that restated the code, keeping the ones that explain why.
Comment thread python/src/developer_toolkit_elasticache/token_generator.py Outdated
Comment thread python/README.md Outdated
Install from source:

```bash
python3 -m pip install -e ".[dev]"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add here the install from github instructions while we are working on publishing to pip?

Comment thread python/README.md Outdated
Comment on lines +18 to +34
IAM authentication for ElastiCache requires presenting a short-lived
SigV4-signed token (valid for 15 minutes) as the connection password. This tool
handles the signing, eliminating the boilerplate and the several non-obvious
details that otherwise surface as an opaque `WRONGPASS` at connect time:

- The token is signed against the **cache name** (or replication group id), not
the connection endpoint DNS.
- Serverless caches sign `ResourceType=ServerlessCache`; node-based replication
groups omit it. The resource type is part of the signature, so it cannot be
corrected after the fact.
- Cache names are lowercased at creation time, so they must be signed in
lowercase.

A fresh token is signed on demand each time one is requested, so there is no
background refresh thread to manage and no stale-token window. Credentials are
re-read from the default AWS credential chain on every call, so rotated
credentials are picked up automatically.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first paragraph as well as the bullet points are specific to implementation details, and IMO not relevant as part of a user-facing documentation. I'd rather explain the required input arguments, where the credentials are coming from, how the credentials provider prioritizes credentials, etc.

Comment thread python/README.md Outdated
```

The token is a bearer credential. Pass it via the client's password parameter or
`VALKEYCLI_AUTH` / `REDISCLI_AUTH`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we specify which Valkey client version supports VALKEYCLI_AUTH?

Comment thread python/README.md Outdated
Comment on lines +78 to +80
## Status

Proof of concept

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this as well

- Accept an optional "default." prefix on the user_id pattern rather than the
  single literal "default.iam-user", so a new service-managed default.* user
  needs no code change.
- Stop echoing the caller's value in InvalidParameterError; name the parameter
  and the accepted pattern only. Add a test that the value is never in the
  message.
- Rewrite the README for a customer audience: separate install requirements
  from runtime requirements, document the arguments and the credential
  resolution order, note that VALKEYCLI_AUTH needs valkey-cli 9.0+ while
  REDISCLI_AUTH works with both clients, and drop implementation detail.
Comment thread python/README.md
- IAM-enabled user that has access to to the cache.
- AWS credentials on the default credential chain (environment variables, shared
config files, or an instance/container role), for an identity with the
`elasticache:Connect` permission to the cache.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Connect requires cache and user as resources in the policy.

@ChristophKoerner ChristophKoerner left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM

@mwaisaida-13
mwaisaida-13 merged commit 139c939 into main Aug 14, 2026
10 checks passed
@mwaisaida-13
mwaisaida-13 deleted the add-python-and-java-libraries branch October 13, 2026 15:55
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.

3 participants