wolfstudy opened a new pull request, #25575:
URL: https://github.com/apache/pulsar/pull/25575

   
   ### Motivation
   
   Currently, the Pulsar Admin client (`PulsarAdmin`) built on top of Jersey + 
async-http-client does
   not honor the SOCKS5 proxy settings that are already supported by the Pulsar 
data-plane client
   (`PulsarClient`). In environments where brokers are only reachable through a 
SOCKS5 gateway
   (for example, cross-region bastion hosts, isolated VPCs, or corporate egress 
proxies), users are
   forced to expose brokers directly or maintain separate tunneling tooling 
just for admin
   operations. This leads to inconsistent networking configuration between the 
producer/consumer
   path and the admin path, and is surprising for users who already configured
   `socks5ProxyAddress` / `socks5ProxyUsername` / `socks5ProxyPassword` on 
their client
   configuration.
   
   This PR makes `PulsarAdmin` reuse the existing SOCKS5 configuration on
   `ClientConfigurationData`, so that admin HTTP traffic transparently flows 
through the same
   SOCKS5 proxy as the binary protocol traffic.
   
   ### Modifications
   
   - 
`pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnector.java`
       - Added a new private static helper `configureSocks5ProxyIfNeeded(...)` 
that inspects the
         `socks5ProxyAddress` / `socks5ProxyUsername` / `socks5ProxyPassword` 
fields on
         `ClientConfigurationData` and, when an address is present, installs a
         `ProxyServer` of type `ProxyType.SOCKS_V5` on the async-http-client
         `DefaultAsyncHttpClientConfig.Builder`. async-http-client wires this 
into Netty's
         `Socks5ProxyHandler` at channel-initialization time, so both plain 
HTTP and HTTPS admin
         requests are tunneled through the proxy.
       - When a non-blank username is provided, a `Realm` with 
`AuthScheme.BASIC` is attached to
         the proxy so that username/password authentication is performed 
against the SOCKS5 server.
         Blank usernames are treated as "no credentials" to avoid sending empty 
authentication
         frames.
       - Invoked the new helper at the end of 
`configureAsyncHttpClientConfig(...)`, so the proxy
         is configured for every `AsyncHttpConnector` instance regardless of 
HTTP vs HTTPS.
       - Added the required imports (`StringUtils`, `Realm`, `ProxyServer`, 
`ProxyType`).
       - No changes to the public API, configuration keys, or connector 
lifecycle.
   
   - 
`pulsar-client-admin/src/test/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnectorSocks5Test.java`
 (new)
       - Unit tests that cover the following scenarios of 
`configureSocks5ProxyIfNeeded`:
           - `null` configuration: helper is a no-op, no proxy is set.
           - Configuration without `socks5ProxyAddress`: no proxy is set.
           - Only `socks5ProxyAddress`: a `SOCKS_V5` `ProxyServer` is 
configured with the correct
             host and port and no realm.
           - `socks5ProxyAddress` + username/password: a `SOCKS_V5` 
`ProxyServer` with a BASIC
             `Realm` carrying the expected principal/password is configured.
           - Blank username: treated the same as no credentials; proxy is 
configured without a
             realm.
           - End-to-end construction of `AsyncHttpConnector` with SOCKS5 
enabled, to verify that
             the full wiring path does not throw and that the underlying 
`AsyncHttpClient` is
             created and can be closed cleanly.
   
   ### Verifying this change
   
   This change added tests and can be verified as follows:
   
   - Unit tests in `AsyncHttpConnectorSocks5Test` verify that the SOCKS5 proxy 
is correctly
     configured on the async-http-client builder for all combinations of 
address/credentials, and
     that `AsyncHttpConnector` can be constructed and closed with SOCKS5 
enabled.
   - Manual verification: start a local SOCKS5 server (e.g. `ssh -D 1080` or 
`dante-server`),
     configure a `PulsarAdmin` instance with
     `.socks5ProxyAddress(new InetSocketAddress("127.0.0.1", 1080))` (plus 
optional
     username/password), and confirm that admin operations such as 
`admin.tenants().getTenants()`
     succeed while direct network access to the broker HTTP endpoint is blocked.
   
   ### Does this pull request potentially affect one of the following parts:
   
   - [ ] Dependencies (add or upgrade a dependency)
   - [ ] The public API
   - [ ] The schema
   - [ ] The default values of configurations
   - [ ] The threading model
   - [ ] The binary protocol
   - [ ] The REST endpoints
   - [ ] The admin CLI options
   - [ ] The metrics
   - [ ] Anything that affects deployment
   
   No box is checked:
   
   - No new dependencies are introduced. `async-http-client`, `commons-lang3`, 
and the Netty SOCKS5
     handler are already on the admin client's classpath.
   - No public API, configuration keys, REST endpoints, CLI options, metrics, 
or default values are
     changed. The feature reuses the existing `socks5ProxyAddress` / 
`socks5ProxyUsername` /
     `socks5ProxyPassword` fields on `ClientConfigurationData`, which are 
already part of the
     client configuration; the behavior is strictly opt-in and defaults to "no 
proxy" when the
     address is not set.
   


-- 
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