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]

Reply via email to