codeant-ai-for-open-source[bot] commented on code in PR #38269:
URL: https://github.com/apache/superset/pull/38269#discussion_r3600394070
##########
superset/db_engine_specs/aws_iam.py:
##########
@@ -54,9 +53,14 @@
# Cache STS credentials: key = (role_arn, region, external_id), TTL = 10 min
# Using a TTL shorter than the minimum supported session duration (900s) avoids
# reusing expired STS credentials when a short session_duration is configured.
-_credentials_cache: TTLCache[tuple[str, str, str | None], dict[str, Any]] =
TTLCache(
- maxsize=100, ttl=600
-)
+try:
+ from cachetools import TTLCache
+
+ _credentials_cache: MutableMapping[
+ tuple[str, str, str | None], dict[str, Any]
+ ] = TTLCache(maxsize=100, ttl=600)
+except ImportError:
+ _credentials_cache = {}
Review Comment:
**Suggestion:** Falling back to a plain dictionary removes TTL eviction, but
`get_iam_credentials` returns any cached entry without checking credential
expiration. After the first STS token expires, stale credentials will be
returned indefinitely, causing repeated AWS auth failures until process restart
or manual cache clear. Use a fallback cache that still enforces expiration (or
validate `Expiration` before returning cached credentials) instead of a
non-expiring dict. [cache]
<details>
<summary><b>Severity Level:</b> Critical 🚨</summary>
```mdx
- ❌ AWS IAM auth fails after STS token expiry.
- ⚠️ Postgres/MySQL RDS connections using IAM become unreliable.
- ⚠️ Requires Superset restart to recover AWS IAM access.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Install Superset from `pyproject.toml` without `cachetools` so that
importing
`TTLCache` fails in `superset/db_engine_specs/aws_iam.py:56-61`; the
`try/except` block at
lines 56-63 catches `ImportError` and sets `_credentials_cache = {}` (plain
dict) instead
of a `TTLCache`.
2. Configure a Postgres or MySQL database with AWS IAM authentication by
setting
`database.encrypted_extra` to include an `aws_iam` block with `"enabled":
true` (as
documented in `AWSIAMAuthMixin` at
`superset/db_engine_specs/aws_iam.py:83-102`). When
Superset builds a SQLAlchemy engine, `Database._get_sqla_engine` in
`superset/models/core.py:590-629` calls
`self.update_params_from_encrypted_extra(engine_kwargs)` (line 608), which
dispatches to
the engine spec’s `update_params_from_encrypted_extra` method.
3. For Postgres, `PostgresEngineSpec.update_params_from_encrypted_extra` in
`superset/db_engine_specs/postgres.py:670-738` loads `encrypted_extra`, pops
the `aws_iam`
config, and when `iam_config.get("enabled")` is true, calls
`AWSIAMAuthMixin._apply_iam_authentication` at
`superset/db_engine_specs/postgres.py:693-29`. `_apply_iam_authentication`
(defined in
`superset/db_engine_specs/aws_iam.py:395-66`) in turn calls
`AWSIAMAuthMixin.get_iam_credentials` at
`superset/db_engine_specs/aws_iam.py:127-153`.
4. On the first query, `get_iam_credentials` uses `boto3.client("sts")` to
call
`assume_role` at `superset/db_engine_specs/aws_iam.py:169-181`, stores
`response["Credentials"]` (including `AccessKeyId`, `SecretAccessKey`,
`SessionToken`, and
`Expiration`) in `_credentials_cache[cache_key]` inside the `with
_credentials_lock` block
at lines 183-184, and returns these credentials to
`_apply_iam_authentication`, which
generates an RDS auth token in `generate_rds_auth_token` at
`superset/db_engine_specs/aws_iam.py:44-89`. After the configured
`session_duration`
(default 3600 seconds at line 132) elapses and the STS credentials expire, a
subsequent
query to the same database follows the same call chain;
`get_iam_credentials` checks
`_credentials_cache.get(cache_key)` at lines 150-153, finds the cached entry
from the
plain dict (no TTL eviction), and returns it without checking the
`Expiration` field or
re-calling `assume_role`. `generate_rds_auth_token` then uses these expired
credentials
(lines 76-82), causing AWS to respond with an expired-token error and
raising a
`SupersetSecurityException`, and because the dict cache never evicts the
entry, all future
connections for that database keep reusing the same expired credentials
until the Superset
process is restarted.
```
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=a93cc6a9d4e34eba883ba8f279ad231c&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=a93cc6a9d4e34eba883ba8f279ad231c&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset/db_engine_specs/aws_iam.py
**Line:** 62:63
**Comment:**
*Cache: Falling back to a plain dictionary removes TTL eviction, but
`get_iam_credentials` returns any cached entry without checking credential
expiration. After the first STS token expires, stale credentials will be
returned indefinitely, causing repeated AWS auth failures until process restart
or manual cache clear. Use a fallback cache that still enforces expiration (or
validate `Expiration` before returning cached credentials) instead of a
non-expiring dict.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38269&comment_hash=21510b6093bac59d252164bfea3a490524b31789e452950315926ede87199eb2&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38269&comment_hash=21510b6093bac59d252164bfea3a490524b31789e452950315926ede87199eb2&reaction=dislike'>👎</a>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]