Skip to content

Honor secure Functions host URIs in Java worker#872

Open
larohra wants to merge 14 commits into
Azure:devfrom
larohra:swarm/83f39e36/integration
Open

Honor secure Functions host URIs in Java worker#872
larohra wants to merge 14 commits into
Azure:devfrom
larohra:swarm/83f39e36/integration

Conversation

@larohra
Copy link
Copy Markdown

@larohra larohra commented May 12, 2026

Summary

JavaWorkerClient always builds ManagedChannelBuilder.forAddress(...).usePlaintext(), so the Java worker ignores the already-parsed --functions-uri and can never join a secure host/worker gRPC channel.

Findings

  • Fix necessary: Yes. Today the worker guarantees plaintext and blocks any host-side TLS rollout, leaving any non-local transport exposed to MITM tampering.
  • Historical context: Plaintext dates back to the early 2018 same-machine child-process design. In 2023 the worker added prefixed startup args, including functions-uri, plus fallback to legacy args, but JavaWorkerClient was not updated; this looks like an old assumption that became a gap once URI-based startup existed.
  • TLS behavior clarification: The fix should honor TLS, not ignore it. When functions-uri uses https, the worker should build a TLS gRPC channel and fail if handshake, certificate, or hostname validation fails. Only http URIs, or legacy startup that supplies just host+port, should continue to use plaintext.
  • Regression / breaking change: No new CLI or protocol contract. Existing http and legacy host+port launches keep their current behavior. The only observable behavior change is that a previously ignored or misconfigured https endpoint will stop connecting insecurely and instead fail closed.
  • Customer contract: No new flags are required. Trust still comes from the JVM trust configuration already available via existing Java options, so hosts using private CAs do not need a new worker-specific switch.
  • Testing today: mvn test currently passes (63 tests, 0 failures/errors/skips). Repo CI also runs build plus emulated, docker, and end-to-end matrices, but there is no direct secure gRPC transport coverage.

Plan

  1. Expose the parsed functions-uri through IApplication in a compatibility-safe way.
  2. Make JavaWorkerClient choose transport from the URI scheme: https => TLS with no plaintext downgrade, http or legacy host+port => plaintext.
  3. Add focused plaintext/TLS transport tests and rerun mvn test.

Issue describing the changes in this PR

resolves #issue_for_this_pr

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Additional PR information

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Java worker to honor the scheme of the already-parsed --functions-uri when building the gRPC channel to the Functions host, enabling TLS when https is provided and preserving plaintext behavior for legacy host/port startup.

Changes:

  • Add IApplication#getFunctionsUri() (defaulting to null) and expose the parsed Functions URI from Application.
  • Update JavaWorkerClient to select useTransportSecurity() vs usePlaintext() based on the Functions URI scheme.
  • Add unit + functional tests for transport selection, including TLS test assets and a TLS-capable in-process test host.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/main/java/com/microsoft/azure/functions/worker/JavaWorkerClient.java Selects TLS vs plaintext based on functions-uri scheme; adds scheme parsing/validation helper.
src/main/java/com/microsoft/azure/functions/worker/IApplication.java Adds compatibility-safe default getFunctionsUri() accessor.
src/main/java/com/microsoft/azure/functions/worker/Application.java Exposes parsed functions-uri via getFunctionsUri(); keeps getUri() delegating for compatibility.
src/test/java/com/microsoft/azure/functions/worker/JavaWorkerClientTest.java Unit tests for scheme -> transport decision and invalid scheme handling.
src/test/java/com/microsoft/azure/functions/worker/ApplicationTest.java Tests precedence of prefixed args vs legacy args and compatibility behavior.
src/test/java/com/microsoft/azure/functions/worker/functional/tests/GrpcTransportTest.java Functional coverage for plaintext legacy, TLS success (trusted), and no plaintext downgrade on TLS failure.
src/test/java/com/microsoft/azure/functions/worker/test/utilities/FunctionsTestHost.java Adds TLS-capable gRPC test server and URI-driven client transport selection for tests.
src/test/resources/grpc-tls/localhost-cert.pem Adds test TLS certificate for localhost.
src/test/resources/grpc-tls/localhost-key.pem Adds test TLS private key for localhost.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

String scheme = parseFunctionsUriScheme(functionsUri);
switch (scheme.toLowerCase(Locale.ROOT)) {
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.

Consolidate URI parsing into Application.parseUri as the single source of truth. Validate the scheme there, default the port from the scheme, and decompose host/port. JavaWorkerClient.useTransportSecurity then collapses to a one-line scheme check. Today there are two parsers (URL in Application, URI in JavaWorkerClient) with different acceptance rules, and https://host/ without an explicit port is rejected by URL.getPort() == -1. Both go away with the consolidation. Small change, fits naturally with the rest of this PR.

return this.uri;
}

public String getUri() {
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 isn't being called, can it be removed?

Copy link
Copy Markdown
Contributor

@ahmedmuhsin ahmedmuhsin left a comment

Choose a reason for hiding this comment

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

What's the host-side timeline for emitting https:// URIs? The current host hardcodes http://127.0.0.1:port/ in AspNetCoreGrpcServer.cs, so this PR's TLS branch is dormant in production today. Is there a tracked host-side change to enable TLS that this PR is gating, or is this defense-in-depth ahead of any host plans? Either is fine, just helps reviewers calibrate.

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.

4 participants