Azure / Azure/azure-cli-extensions
[bastion] Concurrent tunnel connections overwrite last_token; only last session is cleaned up
- Dominant language
- Python
- Stars
- 454
- Forks
- 1.7k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 64
Description
### Describe the bug
With concurrent local TCP accepts on `az network bastion tunnel`, each connection requests a Bastion token via `POST /api/tokens` and stores it in a single instance field `self.last_token`. When `active_connections` reaches 0, `cleanup()` only `DELETE`s that last token.
Browsers / SOCKS clients that open multiple connections therefore create multiple Bastion active sessions (often with the same start time). After the tunnel stops, earlier sessions can remain visible in `getActiveSessions` / Portal until idle timeout.
### Related command
az network bastion tunnel
### Errors
no error but does not close all opened connections
### Issue script & Debug output
the script does not error it just doesn't close all sessions
### Expected behavior
When I close the tunnel I expect all sessions created to be closed.
### Environment Summary
azure-cli 2.88.0
core 2.88.0
telemetry 1.1.0
Extensions:
account 0.2.5
ad 0.1.0
amg 3.0.0
azure-devops 1.0.6
bastion 1.4.3
databricks 1.3.2
datadog 3.0.0
front-door 2.3.0
resource-graph 2.1.1
ssh 2.0.9
stream-analytics 1.0.5
Dependencies:
msal 1.36.0
azure-mgmt-resource 24.0.0
### Additional context
### Summary
With concurrent local TCP accepts on `az network bastion tunnel`, each connection requests a Bastion token via `POST /api/tokens` and stores it in a single instance field `self.last_token`. When `active_connections` reaches 0, `cleanup()` only `DELETE`s that last token.
Browsers / SOCKS clients that open multiple connections therefore create multiple Bastion active sessions (often with the same start time). After the tunnel stops, earlier sessions can remain visible in `getActiveSessions` / Portal until idle timeout.
### Related
- Concurrent connections were added to fix https://github.com/Azure/azure-cli/issues/24600 (bastion extension ≥ 1.0.1)
- Adjacent: https://github.com/Azure/azure-cli/issues/28367 (tunnel drop / cleanup races)
### Environment
- azure-cli 2.88.0
- bastion extension **1.4.3**
- Observed while using a local SOCKS5 proxy through `az network bastion tunnel` (multiple concurrent local accepts)
### Code path (`azext_bastion/tunnel.py`)
1. Each accept → `_handle_client` → `_get_auth_token()` overwrites `self.last_token` / `self.node_id`
2. On client exit, when `active_connections == 0`, `cleanup()` deletes only `self.last_token`
So if connections A/B/C obtained tokens T1/T2/T3, only T3 is deleted when the last client leaves. T1/T2 are never deleted by this path.
### Steps to reproduce
1. Start `az network bastion tunnel` to a TCP/SOCKS resource port
2. Open 2–3 concurrent local connections to the local tunnel port (or drive traffic through a browser SOCKS proxy)
3. Check Bastion active sessions (`getActiveSessions` / Portal) — expect multiple sessions for the same user, same/near start time
4. Stop the tunnel (`Ctrl+C` / kill the process)
5. Re-check active sessions — earlier sessions may still appear
### Expected
All tokens/sessions created by this tunnel process are cleaned up when their connections close and/or when the tunnel process exits.
### Ask
Track tokens **per connection** (or a set of outstanding tokens) and `DELETE` each on close / process exit, instead of a single overwritten `last_token`.
Contributor guide
Assessment
This issue has not been assessed yet.