Do not require authority for UNIX domain sockets#487
Do not require authority for UNIX domain sockets#487saschagrunert wants to merge 1 commit intohyperium:masterfrom
Conversation
c4b2913 to
86979b3
Compare
95a0d59 to
69444f5
Compare
|
Test are failing now for sure. In case of an unix socket, we would only get a path and nothing else. Do you see any feasible way to implement this in h2? |
|
The description mentions not requiring an authority, but it looks like this changes it to stop checking if the provided authority is valid. So, in the Unix socket case, does it send an |
Unfortunately not, the authority would be the complete path, like |
|
Would it be okay to early exit the validation path if the parsed URI is a path? Not sure how to classify a “path” though… |
0447e60 to
7482820
Compare
|
@seanmonstar I checked for a path. If this exists locally, then we assume that the connection through the UDS should work. |
7482820 to
1fc278f
Compare
|
Is there anyone over here to give this a review? 😇 |
seanmonstar
left a comment
There was a problem hiding this comment.
As I mentioned in grpc/grpc-go#3854 (comment), I think it's fine to ignore the :authority if it's a blank value. I would expect a client to not send an invalid authority.
src/server.rs
Outdated
| // When connecting to a UNIX Domain Socket (UDS), then we might get a path for the | ||
| // authority field. If it's a local path and exists, then we do not error in that case | ||
| // and assume an UDS. | ||
| if !Path::new(authority.as_str()).exists() { |
There was a problem hiding this comment.
This will do a blocking IO call, which we wouldn't want to do in an async environment.
There was a problem hiding this comment.
Removed in favor of a check for a .sock suffix.
c993b8c to
1fc278f
Compare
Yes, but in case of a unix domain socket the authority is not blank. It's the socket path. |
1fc278f to
3a7d79b
Compare
812e70d to
3354233
Compare
This fixes connections where a local UNIX domain socket path is provided, where the authority contains the full path to the *.sock file or is empty. Signed-off-by: Sascha Grunert <sgrunert@suse.com>
3354233 to
1f99ad3
Compare
|
PTAL @seanmonstar I changed the check to either exclude |
|
Has 0.4.0 solved the problem? |
|
Just want to add that I am facing a similar issue using h2 to process gRPC requests using tonic. I am using h2 v0.3.1. I have fixed the problem by just sending a warning when Maybe we should find another more elegant solution than just ignoring |
|
Didn't grpc-go change to not emit those malformed authority headers? |
|
For anyone trying to get that working, the workaround is to simply send a dummy authority field from the client side:
|
|
Changing this on the client side is currently not an option as I can't patch every kubelet. Currently this issue is preventig me from properly implementing a Kubernetes Device plugin in Rust using Tonic. |
|
I am exactly in the same situation: kubelet is the client and patch it is not an option for me either. This is why few month ago I have fork this repository to disable panic if authority field is Moreover, from k8s point of view, authority field is not invalid. It represent namespace from where the request came from. This is not just a valid http authority but it still contains meaningful network information. In my case, forking unlock me and I have been able to make k8s extension works correctly. But from my point of view this is too bad request fail because an optional field cannot be parsed. |
|
@saschagrunert I think only checking for @seanmonstar What would be the harm if we just ignore an invalid authority instead of failing with an error? So the change would essentially become bachp@0a3f73b |
|
Totally agree on the fact there is nothing that enforce a socket file ending with A better check for that would be to check file descriptor exists and check it is a valid socket file (but it will still not works for unnamed unix socket). The patch you have made is exactly the same I have suggest around 1 year ago 😉 2c26eda . If any maintainers want I would be happy to make a PR for this or you could take the solution of @bachp without the log. |
|
@arthurlm I think logging it makes a lot of sense. |
|
Before creating any PR, I have done more investigation to understand clearly what is happening. In my extension service k8s case the Looking at RFCs:
So, from my understanding:
NOTE: I have not read the whole RFCs but just read in details the mentioned sections. If anyone have better understanding of this RFCs, please feel free to comment 😉 ! Looking at current code:
I now think we are here in a corner case.
@seanmonstar / hyperium maintainers: what is your point on view on this ? Should we consider Should we fail request if Any other ideas or comments ? |
|
@arthurlm I like your proposal to only ignore the malformed |
mingliangli-lml
left a comment
There was a problem hiding this comment.
I encountered the same problem, this solution can be applied to the scenario of UDS address.
Copy from hyperium#487 Thanks for the help from Sascha Grunert.
|
Hi, this issue is still present, is there any plan to fix? |
|
@seanmonstar I'm not sure how you would prefer this be tackled, so I'll leave the review to you here. |
|
I encountered the same problem. I'm writing a rust grpc server that implements bazel remote cache protocol. Bazel reports "PROTOCOL ERROR" when unix domain socket used. Port is fine. Are we going to fix that? |
|
I've come across the same issue. I've implemented a Would be fantastic to get a fix here. |
…ibility Go gRPC clients connecting over Unix domain sockets send the URL-encoded socket path as the :authority pseudo-header (e.g. %2Fvar%2Frun%2Fisol8%2Fcri.sock). This is rejected by http::uri::Authority as invalid, causing RST_STREAM PROTOCOL_ERROR. Instead of rejecting the request, log a warning and skip setting the authority. This matches the intent of hyperium#487 which has been open since 2020.
Replace SMAppService.daemon() with osascript admin password prompt. SMAppService.daemon() is unreliable on macOS 15 — it registers the helper as disabled without notifying the user, and System Settings provides no separate toggle to enable it (see hyperium/tonic#742, hyperium/h2#487, Apple FB13206906). The new approach runs `abctl _install --no-daemon --no-shell` via osascript's 'with administrator privileges', which triggers the standard macOS password dialog. Only prompts on first install; subsequent launches detect the helper socket and skip silently. Also fix gRPC Unix socket connectivity: - Switch from Posix to TransportServices transport - Set http2.authority = "arcbox.local" to avoid RST_STREAM caused by grpc-swift sending the percent-encoded socket path as :authority
…y layer (#57) * refactor: remove Swift ArcBoxHelper privileged helper Privileged host mutations (DNS resolver, Docker socket, routes) are now handled by the Rust arcbox-helper daemon invoked by arcbox-daemon's self-setup or by `arcbox install`. The desktop app no longer manages these operations. Deleted: - ArcBoxHelper/ (XPC daemon target, 6 files) - HelperManager.swift, HelperProtocol.swift (client-side XPC) - LoginItemApprovalSheet.swift (approval UI) - LaunchDaemons/com.arcboxlabs.desktop.helper.plist Cleaned: - ArcBoxApp.swift: remove helperManager lifecycle - ContentView.swift: remove approval sheet - StartupOrchestrator.swift: remove setupHelper step Note: ArcBoxHelper target in project.pbxproj needs manual removal via Xcode (Delete Target). * chore(proto): regenerate from updated api.proto Adds DOWNLOADING_ASSETS phase, docker_tools_installed field, and GetSetupStatus/WatchSetupStatus RPC methods. * refactor(client): remove BootAssetManager, CLIRunner, DockerToolSetupManager These responsibilities are now handled by the daemon: - Boot assets: auto-provisioned during daemon startup - Docker CLI tools: installed during daemon recovery phase - CLI runner: no longer needed, desktop doesn't shell out * refactor(desktop): pure gRPC display layer DaemonManager: Replace /_ping polling with WatchSetupStatus gRPC stream. Daemon liveness is now derived from stream connectivity. Setup phase, infrastructure flags, and status messages are all pushed by the daemon. StartupOrchestrator: Reduce to 2 steps (enableDaemon + connectAndWatch). All provisioning (boot assets, runtime binaries, Docker tools) is handled by the daemon. ArcBoxApp: Remove BootAssetManager, DockerToolSetupManager state. Orchestrator init simplified to daemonManager + onClientsNeeded. * feat(desktop): install helper via SMAppService.daemon() Register the privileged helper as a system-level LaunchDaemon using SMAppService.daemon(). macOS handles the authorization prompt natively (password / Touch ID). This eliminates the need for desktop users to run `abctl install`. Startup sequence is now 3 steps: 1. installHelper — SMAppService.daemon() (one-time, non-critical) 2. enableDaemon — SMAppService.agent() 3. connectAndWatch — gRPC WatchSetupStatus stream The helper plist uses BundleProgram to reference the binary embedded in the app bundle at Contents/Library/HelperTools/ArcBoxHelper. * chore: add Makefile for local DMG builds + helper plist Makefile wraps the existing package-dmg.sh with dependency targets: make build-rust — cargo build release make prefetch — download boot assets + Docker tools make dmg — unsigned DMG (local testing) make dmg-signed — Developer ID signed DMG Also creates the helper LaunchDaemon plist template for SMAppService.daemon() registration (BundleProgram format). * refactor(ci): use Makefile targets in release workflow Replace inline prefetch/build-dmg steps with `make prefetch` and `make dmg-release`. Build logic lives in one place (Makefile + package-dmg.sh); the workflow only handles CI-specific concerns (secrets, artifact upload, Sparkle signing). Local dev and CI now share the exact same build path: Local: make dmg-signed CI: make dmg-release SIGN_IDENTITY="..." NOTARIZE=1 * refactor(xcode): remove Swift ArcBoxHelper target The Swift ArcBoxHelper was replaced by the Rust arcbox-helper in v0.3.0 but the Xcode target and build configurations were left behind. This removes all remnants: - ArcBoxHelper native target + build configurations - Copy Helper Tool build phase (referenced Swift target product) - Target dependency from ArcBox → ArcBoxHelper - Product reference in Products group The Rust helper binary is embedded by fetch-arcbox-binaries.sh and registered via SMAppService.daemon() at runtime. The Generate Helper LaunchDaemon Plist build phase is preserved (it processes the plist template for the Rust helper). * fix: inline docker socket path after DaemonManager cleanup DaemonManager.dockerSocketPath was removed when stripping the polling logic. Inline the path directly since it's a fixed convention. * fix(build): embed arcbox-helper as com.arcboxlabs.desktop.helper Copy Rust arcbox-helper binary to Contents/Library/HelperTools/ with reverse-DNS name matching the plist Label, consistent with the daemon naming convention. Fix BundleProgram path in helper plist. * fix(build): include agent cross-compilation in build-rust build-rust now runs `make build-agent` (aarch64-unknown-linux-musl) so the Linux guest agent binary is available for bundle embedding. Without this, package-dmg.sh embeds a macOS binary that the guest VM can't execute. * fix(desktop): adjust timeouts for single gRPC server gRPC no longer restarts mid-boot, so 30s timeout is sufficient. Reconnect backoff reduced to 500ms for faster recovery if the daemon restarts. * fix(desktop): use osascript for helper install, fix gRPC authority Replace SMAppService.daemon() with osascript admin password prompt. SMAppService.daemon() is unreliable on macOS 15 — it registers the helper as disabled without notifying the user, and System Settings provides no separate toggle to enable it (see hyperium/tonic#742, hyperium/h2#487, Apple FB13206906). The new approach runs `abctl _install --no-daemon --no-shell` via osascript's 'with administrator privileges', which triggers the standard macOS password dialog. Only prompts on first install; subsequent launches detect the helper socket and skip silently. Also fix gRPC Unix socket connectivity: - Switch from Posix to TransportServices transport - Set http2.authority = "arcbox.local" to avoid RST_STREAM caused by grpc-swift sending the percent-encoded socket path as :authority * fix(desktop): replace SMAppService.daemon() with osascript admin prompt SMAppService.daemon() is unreliable on macOS 15 — it registers the helper as disabled in BTM without notifying the user, and System Settings provides no separate toggle to enable it. Replace with osascript 'do shell script ... with administrator privileges' calling `abctl _install --helper-path <bundle-path>`. This triggers the standard macOS password dialog on first launch only. Changes: - DaemonManager: osascript-based installHelper(), checks socket existence - install.rs: add --helper-path flag for custom helper binary location - fetch-arcbox-binaries.sh: copy helper to MacOS/bin/ (next to abctl) - Remove SMAppService.daemon() infrastructure: - LaunchDaemons/com.arcboxlabs.desktop.helper.plist - Xcode "Generate Helper LaunchDaemon Plist" build phase - HelperTools copy in fetch-arcbox-binaries.sh * fix(desktop): use single-quote shell escaping for osascript Paths with spaces (e.g. "ArcBox Desktop.app") were not properly escaped in the do shell script command. Use single-quote wrapping instead of backslash escaping. * chore: delete stale PLAN.helper.md (describes removed Swift SMAppService implementation) * fix: address review comments (copilot + codex) - Sign arcbox-helper in fetch-arcbox-binaries.sh (required for notarization) - Guard helper binary exists before triggering osascript password prompt - Fix misleading log dir comment (plist uses /tmp/, create run/ instead) - Use throwing Task.sleep for cancellation support in connect wait loop - Add TODO for helper version check on app update * fix(desktop): auto-upgrade helper via --version comparison Compare installed vs bundled helper version using `--version` output instead of SHA256 hashing. On app update, if the bundled helper has a newer version, re-run _install with admin prompt. Uses existing Cargo version infrastructure (env!("CARGO_PKG_VERSION")), no build-time preparation needed. * fix: address review round 3 (copilot) - Fix stale docstring on installHelper (socket → version check) - Fix stale comment on applySetupStatusSync - Remove duplicate installedHelperPath / dead helperSocket constant - Makefile: guard prefetch against missing ABCTL, guard clean against missing ARCBOX_DIR - Add --timestamp to helper codesign for notarization consistency
This fixes connections where paths to UNIX domain sockets (
*.sock) are provided or the authority is empty.Refers to hyperium/tonic#243, containers/containrs#34