Repository navigation
Conversation
The STS simulator returned one canned assertion, for Administrator@VSPHERE.LOCAL, whose signature no key held by vcsim could check. vAPI session login accepted any "SIGN" header and recorded the session user as "TODO"; SOAP LoginByToken accepted any NameID. The STS simulator now issues an assertion per request, signed with its own key (generated on first use): - the subject is the UsernameToken user, a solution user named by its certificate's CN, the ActAs token's subject, or, for Renew, the subject of the token being renewed; a name without a domain gets "@<domain>" - a holder-of-key token confirms the request's certificate; a bearer token is issued when none is given, or KeyType is Bearer - the lifetime is the one requested, 5m by default - group membership is the default Administrator's, or Users and Everyone (and SolutionUsers for a solution user) - a token presented to Renew, ActAs or the request header must be one it issued, or the request fails with a SOAP fault - passwords are still not checked The assertion is written in exclusive canonical form, so the digest is taken over its bytes; the simulator only validates the form it writes. The STS simulator sets SessionManager.ValidToken. When set: - vAPI session login with a "SIGN" header requires a valid token, and a holder-of-key token requires a request signature by the confirmed key; the session user is the token's subject - SOAP LoginByToken requires a valid token; its request signature is not checked Without an STS simulator, both still accept any token, and vAPI records the token's NameID rather than "TODO". Handler.Minted returns every issued token, for tests that scan logs for leaked credentials. No token is logged. The session.loginbytoken bats test used hand-written tokens, which vcsim now rejects; it uses a token issued by the STS simulator instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: George Hicken <george.hicken@broadcom.com>
Simulate POST /rest/vcenter/tokenservice/token-exchange, which exchanges a SAML token issued by the STS simulator for a JWT, per TokenExchange.exchange and the claims vCenter writes for the vmware-tes:vc:vns:k8s audience: - RS256, signed with the STS simulator's key; kid is the hex SHA-1 thumbprint of its certificate - iss is https://<host>/openidconnect/<domain> - aud is the requested audience, in lower case - sub, username and domain are the SAML subject, with the domain in lower case; group_names are its groups, as name@domain - exp is 10h after iat; the response is issued_token_type id_token, token_type N_A and scope openid, wrapped in "value" Errors follow the TES client in wcpsvc: - a subject token that is not valid is a 500 whose body carries com.vmware.vcenter.tokenservice.exceptions.InvalidGrant - an unknown audience, grant type or token type, a missing audience, or a subject token that is not base64 is a 400 invalid_request - the request requires a vAPI session (401 otherwise), via the vapi simulator's handler Only the vns audience and the SAML to id_token exchange are supported. Handler.InjectInvalidGrant fails the next n exchanges with InvalidGrant, as vCenter does when the session's own token is no longer valid, so a client's session renewal can be tested. Minted JWTs are included in Handler.Minted. Neither requests nor responses are logged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: George Hicken <george.hicken@broadcom.com>
Serve the SSO server's OpenID Connect provider metadata and JWKS, so that a JWT issued by the Token Exchange Service simulator can be verified by, for example, a Kubernetes API server configured with the issuer https://<host>/openidconnect/<domain>: - GET /openidconnect/<domain>/.well-known/openid-configuration, and /openidconnect/.well-known/openid-configuration for the default domain; the issuer and endpoint URLs are laid out as vCenter's are (jwks_uri is /openidconnect/jwks/<domain>) - GET /openidconnect/jwks/<domain> and /openidconnect/jwks: the STS simulator's RSA key, with its kid and certificate chain Both are served on vcsim's listener, so over its TLS, and require no session. The authorize, token and logout endpoints are advertised in the metadata but not served. TestTokenChain follows a holder-of-key SAML token through the JWT TES issues for it to verification against the served discovery and JWKS, trusting only vcsim's certificate, and checks that no minted token appears in the simulator's log or in an error response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: George Hicken <george.hicken@broadcom.com>
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.
Description
Makes the vcsim token chain real enough for a client to go from a SAML token to a JWT that a Kubernetes apiserver can verify.
SessionManager.ValidTokenhook (followingValidLogin) lets STS validate tokens: vAPISIGNlogin checks the token signature and the HoK request signature and records the token subject as the session user (instead of"TODO"); SOAPLoginByTokenvalidates the token (not the request signature). Without the STS simulator both stay lenient.restexample output are updated accordingly. Happy to gate this behind an option if reviewers prefer.POST /rest/vcenter/tokenservice/token-exchange,com.vmware.vcenter.tokenservice.TokenExchange, released 1.18): exchanges an issued SAML token for an RS256 JWT (iss,sub,aud,group_names,exp,iat,jti,kid), requires a vAPI session, returns 500 withInvalidGrantfor a bad subject token, andHandler.InjectInvalidGrant(n)allows fault injection./openidconnect/<domain>/.well-known/openid-configurationand/openidconnect/jwks/<domain>.No token is logged, and error bodies never echo the request.
Handler.Minted()returns every issued assertion and JWT, for tests that scan logs for leaked credentials.Closes: n/a (no upstream issue yet)
How Has This Been Tested?
TestTokenChain: SAML from STS, then TES, then JWT verification against the served JWKS trusting only vcsim's certificate; it also scans captured logs and error bodies for leaked tokens.go test ./sts/... ./vapi/... ./session/... ./lookup/... ./ssoadmin/... ./simulator/passes; govc and vcsim build;make lintreports 0 issues.session.loginbytokenbats flow run by hand against the built govc and vcsim (bats not installed).session/keepalive ExampleHandlerRESTfailed once under parallel load (timing-based, basic auth), and passed 3 of 3 alone.