AaronCoquet-Easypark opened a new issue, #70519:
URL: https://github.com/apache/airflow/issues/70519
### Airflow CTL Version
Latest stable version
### Airflow CTL Command
airflowctl auth login --env staging --api-url <staging-url> --api-token
<token>; airflowctl dags list --env staging
### Keyring Backend / Version
macOS Keychain (`keyring.backends.macOS.Keyring`) 25.7.0
### Auth Type
Token
### What is the current behaviour?
`--env`/`-e` is accepted by every non-auth command (`dags list`, `dags
trigger`, `connections list`, etc. — anything routed through
`output_command_list` / `ARG_AUTH_ENVIRONMENT`) and parses fine into
`args.env`. But it's never actually used.
`provide_api_client`'s wrapper only forwards `api_token` to `get_client()`:
```python
# airflow-ctl/src/airflowctl/api/client.py
def wrapper(*args, **kwargs) -> RT:
if "api_client" not in kwargs:
api_token = getattr(args[0], "api_token", None) if args else None
with get_client(kind=kind, api_token=api_token) as api_client:
return func(*args, api_client=api_client, **kwargs)
```
and `get_client()` constructs `Credentials` with no `api_environment`:
```python
def get_client(kind=ClientKind.CLI, api_token=None):
...
credentials = Credentials(client_kind=kind, api_token=api_token).load()
```
`Credentials.__init__` defaults `api_environment` to `"production"`. Since
it's never overridden here, **every non-auth command silently operates against
the `production` environment** — reading `production.json` for the API URL and
the `api_token_production` keychain entry — no matter what `--env` you pass.
`auth login` doesn't go through this path; it builds `Credentials(...,
api_environment=args.env)` directly, so login correctly targets the requested
environment and stores the token under the right keychain key. The net effect:
`auth login --env staging` succeeds and looks correct, but every subsequent
command (`dags list --env staging`, etc.) silently talks to `production`
instead, using a stale/unrelated production token — surfacing as `{'detail':
'Token Expired'}` or `{'detail': 'Invalid JWT token'}` with no indication that
the wrong environment was ever contacted.
Reproduced: I confirmed by instrumenting
`Credentials(client_kind=ClientKind.CLI, api_token=None).load()` exactly as
`get_client` calls it — with `sys.argv` set to `dags list --env staging`, it
resolves `api_environment="production"`, `api_url` to the production URL, and
`api_token` to the production keychain entry.
Workaround: setting `AIRFLOW_CLI_ENVIRONMENT=staging` in the environment
(read directly via `os.getenv` in `Credentials.__init__`, independent of the
CLI arg) makes commands correctly target the intended environment.
`--api-token` alone does **not** work around this, since it only overrides the
token, not the URL — you end up sending the right token to the wrong server.
### What is the expected results?
`--env`/`-e` passed to any `airflowctl` command should resolve the API URL
and stored credentials for that environment, consistently with what `auth login
--env <x>` stores. `provide_api_client`/`get_client` should read `args.env` (or
`AIRFLOW_CLI_ENVIRONMENT`) and pass it through as
`Credentials(api_environment=...)`.
### Anything else?
This is especially dangerous when a user manages multiple environments
(staging/prod/etc.) via `--env`: commands *appear* to target the environment
you specified, but silently execute against production instead. A `dags trigger
--env staging ...` would actually trigger a DAG in production.
Related: #58230 added `--api-token` to non-auth commands for headless use
but didn't wire `--env`/`api_environment` through the same path, which is
effectively what left this gap open.
### Are you willing to submit PR?
- [ ] Yes I am willing to submit a PR!
### Code of Conduct
- [x] I agree to follow this project's [Code of
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
--
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]