Skip to content

NIFI-15911 Add proxy support to StandardSnowflakeIngestManagerProviderService#11314

Open
rakesh-rsky wants to merge 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15911-proxy-support-snowflake-ingest
Open

NIFI-15911 Add proxy support to StandardSnowflakeIngestManagerProviderService#11314
rakesh-rsky wants to merge 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15911-proxy-support-snowflake-ingest

Conversation

@rakesh-rsky

Copy link
Copy Markdown
Contributor

NIFI-15911 Add proxy support to StandardSnowflakeIngestManagerProviderService

StandardSnowflakeIngestManagerProviderService uses SnowpipeIngestClient to send data to Snowflake via the Snowpipe REST API. Previously, the HTTP client had no proxy configuration, causing failures for NiFi deployments running behind a corporate or network proxy.

This change adds proxy support by wiring ProxyConfigurationService into the controller service.

Changes:

  • Added PROXY_CONFIGURATION_SERVICE property to StandardSnowflakeIngestManagerProviderService
  • Used a custom ProxySelector that correctly handles HTTP, SOCKS, and DIRECT proxy types
  • Added scoped Authenticator for proxy username/password credentials
  • Extended SnowpipeIngestClient with a constructor accepting ProxySelector and Authenticator

SnowpipeIngestClient

  • Added a constructor accepting ProxySelector and Authenticator, applied to the underlying HttpClient
  • Existing 3-arg constructor delegates to the new one with nulls (backward compatible)

Summary

NIFI-15911

Tracking

Please complete the following tracking steps prior to pull request creation.

Issue Tracking

Pull Request Tracking

  • Pull Request title starts with Apache NiFi Jira issue number, such as NIFI-00000
  • Pull Request commit message starts with Apache NiFi Jira issue number, as such NIFI-00000
  • Pull request contains commits signed with a registered key indicating Verified status

Pull Request Formatting

  • Pull Request based on current revision of the main branch
  • Pull Request refers to a feature branch with one commit containing changes

Verification

Please indicate the verification steps performed prior to pull request creation.

Build

  • Build completed using ./mvnw clean install -P contrib-check
    • JDK 21
    • JDK 25

Licensing

  • New dependencies are compatible with the Apache License 2.0 according to the License Policy
  • New dependencies are documented in applicable LICENSE and NOTICE files

Documentation

  • Documentation formatting appears as expected in rendered files

SCHEMA,
PIPE
PIPE,
ProxyConfigurationService.PROXY_CONFIGURATION_SERVICE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use ProxyConfiguration.createProxyConfigPropertyDescriptor(...) here and add a customValidate that calls ProxyConfiguration.validateProxySpec(...), like other proxy aware components, so an unsupported proxy type is rejected at configuration time instead of failing silently at runtime?

return null;
}
final Proxy proxy = proxyConfigurationService.getConfiguration().createProxy();
// Use a custom ProxySelector so that the Proxy.Type (HTTP or SOCKS) is preserved,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JDK java.net.http.HttpClient only applies HTTP proxies and ignores a SOCKS Proxy, so a configured SOCKS proxy would silently fall back to a direct connection. Should we drop the SOCKS handling claim or validate that only HTTP proxy types are configured?

if (proxyConfigurationService == null) {
return null;
}
final Proxy proxy = proxyConfigurationService.getConfiguration().createProxy();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use ProxyConfiguration.getConfiguration(context), which returns DIRECT when the service is unset, and ProxyConfiguration.hasCredential() to simplify this code and remove the two null returning helper methods?

};
}

private Authenticator buildProxyAuthenticator(final ProxyConfigurationService proxyConfigurationService) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Snowpipe endpoint is HTTPS, and the JDK disables Basic proxy authentication over CONNECT tunneling by default via jdk.http.auth.tunneling.disabledSchemes. Was the username and password path tested against a real authenticated HTTPS proxy?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. The Authenticator is the correct Java API for proxy credentials, but there's a JDK limitation — Basic authentication over CONNECT tunneling is disabled by default via jdk.http.auth.tunneling.disabledSchemes=Basic. There's no way to override this per HttpClient instance since it's a JVM-wide setting. So authenticated proxy won't work out of the box for HTTPS targets like Snowflake. To handle this, I've added a note directly in the property description telling users to add -Djdk.http.auth.tunneling.disabledSchemes="" to their bootstrap.conf if they need proxy credentials with Snowflake.

}

@Test
void testInsertFilesViaProxy() throws InterruptedException, NoSuchAlgorithmException {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test uses an HTTP base URI and a null authenticator, so it does not cover HTTPS tunneling or proxy credentials, which are the parts most likely to break. Can we add coverage for the authenticated proxy and HTTPS cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the proxy test, it now points the base URI to a different host (http://fake-snowflake.example.com) while the proxy selector points to MockWebServer. When Java's HttpClient routes through an HTTP proxy, it sends the request target in absolute form, so we assert the recorded request starts with http://fake-snowflake.example.com. This proves the proxy selector is actually being used. For the HTTPS + credentials case as mentioned in the comment above, this hits the JDK limitation with CONNECT tunneling and would need a full TLS proxy setup to test properly, which is more of an integration test scenario. The property description now documents what users need to configure to make it work.

…rService

Without this change, SnowpipeIngestClient always connects to Snowflake directly,
which fails in environments behind a corporate proxy. This adds proxy support by
wiring ProxyConfigurationService into the service's HTTP client.

Changes:
- Added PROXY_CONFIGURATION_SERVICE property to StandardSnowflakeIngestManagerProviderService
- Used a custom ProxySelector that correctly handles HTTP, SOCKS, and DIRECT proxy types
- Added scoped Authenticator for proxy username/password credentials
- Extended SnowpipeIngestClient with a constructor accepting ProxySelector and Authenticator
@rakesh-rsky rakesh-rsky force-pushed the fix/NIFI-15911-proxy-support-snowflake-ingest branch from baeeac2 to 3baff7d Compare June 12, 2026 10:57
@rakesh-rsky rakesh-rsky requested a review from pvillard31 June 12, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants