fix(jwt): name the issuing instance in every signed token - #7113
geovannewashington wants to merge 1 commit into
Conversation
|
Claude finished @geovannewashington's task in 10m 12s —— View job Code Review CompleteReviewed 14 files. 4 inline issues posted. Standards: 0 violations, 2 judgement calls. Spec: 1. Correctness: 1. StandardsNo documented rule is broken. The worst judgement call is CorrectnessNo security, access-control, concurrency or context defects. The one finding is that the Cross-repo check is clean. Spec
Additional notes
If you've addressed the feedback and want a new review, tag |
3d7695f to
a8ed328
Compare
|
Documentation preview: https://6a6aeaa1.shellhub-docs.pages.dev |
927451f to
aed7cbb
Compare
|
/review |
|
Claude finished @otavio's task in 7m 35s —— View job Code Review CompleteReviewed 16 files. 2 inline issues posted. Standards: 1 violation, 1 judgement call. Spec: 0 new. Correctness: 0 new. StandardsThe doc comment added to CorrectnessNo new defects. Verified directly: the only JWT signing sites in the repo are Cross-repo check is clean. SpecEvery requirement in issue #7111 is met, with one partial that is not new: Met: all three encoders set the issuer, Additional notes
If you've addressed the feedback and want a new review, tag |
Tokens were signed with an empty iss claim, and the enrollment callback token carried none at all. That is free while one system mints tokens, and ambiguous as soon as a second issuer exists. The issuer is the instance's own URL, derived from SHELLHUB_DOMAIN and SHELLHUB_AUTO_SSL by the rule the SSH approval banner already used, now exported so there is one copy of it. That rule describes the bundled gateway rather than how the instance is reached, so a deployment whose TLS terminates upstream is named http while served over https. Left as it stands: the claim is unread until issuer validation exists, and that is when the value has to be right. The service takes the issuer as an option rather than a constructor argument: that constructor has one production call site against 129 in tests. Decoding still ignores iss, since validating it would reject every token already in circulation. The SSH web session token is groundwork. Its signed form never leaves the process today, the handler returning the token id while nothing reads Data, so the claim it now carries is for whoever wires that up. Fixes: #7111
aed7cbb to
1dc16f4
Compare
|
/review |
|
Claude finished @otavio's task in 14m 17s —— View job Code Review CompleteReviewed 16 files on all three axes: Standards (repo rules, Go conventions, tests, code smells), Spec (does it implement issue #7111?) and Correctness (security and runtime defects). No new issues found, and no inline comments were posted. The code looks good as-is. StandardsNo violations. Every comment the diff adds is a doc comment on an exported declaration and each states a contract rather than restating a signature — including CorrectnessVerified and clean. Cross-repo is clean. SpecEvery requirement in #7111 is met, with one partial that is not new: Met: all three encoders set the issuer, Additional notesTwo things surfaced and were dropped in validation, recorded because they are useful to whoever picks up issuer validation.
No caps dropped anything. Nothing was committed; this run only read the branch. If you've addressed the feedback and want a new review, tag |
What
Every JWT ShellHub signs now names the instance that signed it, derived from
SHELLHUB_DOMAINandSHELLHUB_AUTO_SSL.Why
isswas empty on user and device tokens (both carried a TODO asking how to get the value) and absent entirely on enrollment callback and SSH web session tokens. It costs nothing while one system mints tokens and one key signs them, and becomes ambiguous as soon as there is a second issuer, which is what embedding Dex brings. Doing it now is the cheap ordering: every token in circulation is blank, so whatever validation lands later must tolerate blanks, and the sooner we stop minting them the shorter that window stays open.Changes
jwttokenencoders take anissuerand write it.EncodeEnrollmentDecisionClaimsgains the field it never had.*rsa.PrivateKeyparameter is dropped.WithIssueroption, set once inSetup. An option rather than a constructor argument because that constructor has 1 production call site against 129 in tests.session.ConsoleURL, so there is one copy of it rather than two.jwt.WithIssuerwould reject all of them, so it needs a transition window and its own issue.Testing
TestEncodedClaimsCarryTheIssuercovers all three encoders,TestNewTokenCarriesTheIssuerthe SSH web signer,TestInstanceIssuerthe scheme decision and the wiring.go build,gofmt -s -landgolangci-lint runare clean../api/... ./app/... ./ssh/...pass exceptTestInstallScriptRendersAValidShellScript, which fails identically on master (it cannot findinstall.shfrom the container's working directory).Two limitations, both recorded in the commit message rather than fixed here. The scheme is derived from
SHELLHUB_AUTO_SSL, which describes the bundled gateway, so an instance terminating TLS upstream is namedhttpwhile served overhttps; the claim is unread until issuer validation exists, which is when the value has to be right. And the SSH web session token's signed form never leaves the process today, so that claim is groundwork.Closes #7111