config: include IsFedramp in Forwarder.Hash - #1724
Open
nileshpatil6 wants to merge 1 commit into
Open
Conversation
Forwarder.Hash hashes five of the struct's six fields. IsFedramp is
never mixed into the digest, so two forwarders that differ only in that
setting produce an identical hash.
The hash is the identity function for live config reload. When the
config file changes, AppService.handleConfigUpdate builds a
ForwarderService per forwarders entry and calls overwatch
AppManager.Add, which does:
if currentService.Hash() == service.Hash() {
return // the exact same service, no changes, so move along
}
currentService.Shutdown()
ForwarderService.Hash delegates to Forwarder.Hash, so flipping
isFedramp on an existing forwarder makes Add early-return: the running
listener is never shut down and the new one never starts. The change is
silently discarded with no log line until the process restarts.
The setting is not cosmetic. Forwarder.IsFedramp reaches
carrier.StartOptions in access.StartForwarder and is passed to
token.FetchTokenWithRedirect, which selects the FedRAMP or the
commercial Access endpoint for the token exchange.
IsFedramp was added to the struct in 8825cee, which also rewrote the
body of Forwarder.Hash line by line without adding it, while the
sibling Hash in that same commit did mix in its bool.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Forwarder.Hash()hashes five of the struct's six fields.IsFedrampis never mixed into the digest, so two forwarders that differ only in that setting hash identically.Why it matters
The hash is the identity function for live config reload, not a display value. When the config file changes,
AppService.handleConfigUpdatebuilds aForwarderServiceperforwarders:entry and hands it tooverwatch.AppManager.Add:ForwarderService.Hash()delegates straight toForwarder.Hash(). So an operator who edits an existing forwarder to flipisFedrampgets a byte-identical hash,Addearly-returns, the running listener is never shut down and the replacement never starts. The edit is silently discarded, with no log line, until the process is restarted.The setting is not cosmetic.
Forwarder.IsFedrampis carried intocarrier.StartOptionsinaccess.StartForwarder:and
carrier.StartForwarderpasses it totoken.FetchTokenWithRedirect(req.URL, options.AppInfo, options.AutoCloseInterstitial, options.IsFedramp, log), which selects the FedRAMP or the commercial Cloudflare Access endpoint for the token exchange. So the daemon reports success while continuing to authenticate against the previous endpoint.How it happened
IsFedrampwas added to the struct in 8825cee ("AUTH-7480 update fed callback url for login helper"). That same commit rewrote the body ofForwarder.Hash()line by line, switching md5 to sha256 and adding_, _ =, without adding the new field:The sibling
Hash()immediately below it in that same commit did mix in its bool, with_, _ = io.WriteString(h, fmt.Sprintf("%v", r.Enabled)), so this looks like an oversight rather than a deliberate exclusion. I have used that same idiom here.Scope, stated plainly
This only affects the file-watching config reload path used when
cloudflaredruns with no subcommand.cloudflared access ssh/tcpread the flag fresh per invocation and are unaffected, and anyone who restarts the process after editing config is unaffected. I verified the hash collision and traced the call chain by reading; I did not run a live daemon reload end to end.Testing
Without the change the same test fails, and the message shows both structs producing one digest:
go build ./...,go vet ./config/..., andgo test ./config/... ./overwatch/...all pass.gofmt -lreports nothing for the two touched files, so thewhole-files: truelint rule is not triggered.Possible follow-up, not included here
Hash()concatenates fields with no delimiter, so in principle{URL: "ab", Listener: "c"}and{URL: "a", Listener: "bc"}collide. Realistic URL and listener formats make that hard to hit, and fixing it would widen this diff, so I have left it alone. Happy to send it separately if you want it.