Commit Graph

9 Commits

Author SHA1 Message Date
Paul Lorenz e38970803c Merge commit from fork
fixes GHSA-whjr-3j94-gw3c constrain external jwt signer JWKS fetching
2026-08-20 15:27:56 -04:00
Andrew Martinez 9cf98a1dc9 fixes GHSA-4h58-w989-xgg4 enforce issuer and audience in ext-jwt token enrollment
- enforces issuer and audience claims inside TokenIssuerExtJwt.VerifyToken, which
  previously verified only the token signature and resolved the signing key by kid
- closes the ziti-token-issuer-id header enrollment path accepting a validly-signed
  token minted for a different audience or issuer that shares signing keys
- mirrors the runtime ext-jwt authentication and by-inspection enrollment paths so
  all paths validate claims consistently
- adds a controller/model unit test covering foreign-audience, foreign-issuer, and
  missing-audience rejection
2026-08-20 15:15:26 -04:00
Andrew Martinez f64b6879cf fixes GHSA-whjr-3j94-gw3c constrain external jwt signer JWKS fetching
- adds HardenedJwksResolver, a jwks.Resolver that fetches an external jwt signer's
  jwksEndpoint with an http/https-only scheme check, a total timeout and a redirect cap
- adds JwksFetchPolicy, gating a fetch on both the URL hostname and the address being
  connected to, applied to the first request and to every redirect hop
- hostname gate: deniedHostnames blocks, allowedHostnames is exclusive when set; entries
  are an exact hostname or a '*.suffix' wildcard that matches subdomains at any depth but
  never the suffix itself, normalized to lower case punycode without a trailing dot
- address gate: built-in blocked (metadata, link-local, link-local multicast,
  unspecified), then deniedIPs, then allowedIPs, then blockPrivateAddresses,
  first-match-wins with deny over allow
- keeps the gates independent, so neither can authorize what the other refuses; the
  address check runs in the dialer against the resolved address, so a hostname that
  resolves to a blocked address is refused
- adds the [edge.externalJwtSigners.jwksFetch] config section with compatible defaults:
  empty hostname lists, blockPrivateAddresses false, timeout 5s, maxRedirects 5
- takes IP lists as a flat address or a CIDR block, hostname lists as names only, and
  rejects an entry belonging to the other list at startup
- rejects a jwksEndpoint the policy refuses when an external jwt signer is created or
  updated, and logs an existing signer whose endpoint the configuration now refuses
  when the token issuer cache loads
- documents both gates, their deny-wins precedence, the accepted entry forms and the
  wildcard matching rules in etc/ctrl.with.edge.yml and CHANGELOG.md
2026-08-20 15:12:56 -04:00
Andrew Martinez 9abb347bb2 fixes openziti/ziti#4118 disambiguate overlapping ext-jwt-signer kids… (#4120)
* fixes openziti/ziti#4118 disambiguate overlapping ext-jwt-signer kids by issuer

- binds external JWT tokens to signers by exact issuer claim rather than by key ID, so signers drawing from a shared signing-key pool resolve deterministically
- binds controller-issued tokens by key ID first, preserving controller token resolution and preventing an external signer configured with a controller's issuer from capturing controller access tokens
- removes the external key-ID fallback so a token whose issuer matches no configured signer is not bound to an unrelated signer that happens to share its kid
- adds GetControllerIssuerByKid to the TokenIssuerCache interface and implementation
- skips disabled external signers in GetIssuerByKid so a disabled signer sharing a kid cannot poison resolution for an enabled one
- adds an integration test with two HTTPS JWKS providers sharing a key and kid, covering the enabled-collision and disabled-poison cases
- documents that controller issuers are keyed by controller id and that a controller issuer's key ID is the fingerprint of its TLS certificate
- documents that an external kid match is ambiguous because signers can share a signing-key pool, and that a definitive binding requires resolving by issuer claim
- clarifies the overlapping-kid test comment covering why issuer-claim binding is required when a disabled signer shares a kid
2026-08-06 10:55:46 -04:00
Andrew Martinez e1a431b6b4 fixes openziti/ziti#4063 enroll with empty roles when ext-jwt attribu… (#4064)
* fixes openziti/ziti#4063 enroll with empty roles when ext-jwt attribute claim is absent

- treats an absent enrollment attribute claim as no role attributes rather than
  rejecting the token; a failed jsonPointer.Get means the claim is not present,
  since pointer syntax is already validated at jsonpointer.New
- matches the existing unset-selector and empty-claim cases, which already
  enroll with an empty attribute set; a present-but-wrong-type claim still errors
- adds unit coverage for resolveStringSliceClaimProperty
- moves the two ext-jwt enrollment integration subtests that asserted the old
  failure behavior to success cases asserting an empty role-attribute set

* fixes openziti/ziti#4063 treat a null attribute claim as no role attributes

- treats an attribute claim sent as JSON null as no role attributes, logging a
  warning, matching the behavior of an absent claim
- logs at debug when the attribute claim selector does not resolve
- prints the offending value in the wrong-type error rather than the always-nil
  result of the failed array assertion
- corrects the godoc and inline comment: a pointer can fail to resolve through
  traversal as well as absence, and the malformed-pointer error is unreachable
- adds unit coverage for null and nested null claims, and asserts the wrong-type
  error names the value
- adds enrollment tests for a null attribute claim enrolling with no role
  attributes, and for a null name claim rejecting enrollment
2026-08-06 10:42:32 -04:00
Paul Lorenz 4df6ae564d Update package paths for newly imported storage and ziti-db-explorer packages 2026-04-16 09:18:55 -04:00
Andrew Martinez fb2034245d fixes openziti/ziti#3356 adds www-authenticate headers (#3561)
* fixes openziti/ziti#3356 adds www-authenticate headers

- www-authenticate headers are returned on 401s from API requests
- www-authenticate headers are returned during authentication to signal
  addtional JWT bearer tokens needed (secondary ext jwt)
- adds support for additional headers on API errors
- adds SecurityTokenCtx for centralized security header processing
  (legacy, jwt, etc.)
- adds SecurityCtx for centralized identity, auth policy, MFA handling
- refactors existing JWT authentication methods (oidc, legacy) to use
  centralized processing where possible
2026-02-24 10:01:36 -05:00
Paul Lorenz 2ffc6e1151 Update ziti version to 2.0 2026-01-28 12:34:10 -05:00
Andrew Martinez ce83c0fb7c fixes openziti/ziti#2324 add token based enrollment (#3342)
* fixes openziti/ziti#2324 add token based enrollment

- allows enrollment to certificate auth
- allows enrollment to ext jwt token auth
- alters ext jwt claimsProperty (maps identity id) to support JSON
  pointers, defaults to `/sub`
- adds ext jwt enrollToCert, enrollToToken to controller  valid
  enrollment end-authenticator state
- adds ext jwt enrollAuthPolicyId to map end identity auth policy to,
  defaults to `default`
- adds ext jwt enrollAttributeSelector, supports single field name or
  JSON pointer to point to a single string or array of string attributes
  to give the identity, defaults to no selector
- adds ext jwt enrollNameSelector, supports single field name or JSON
  pointer to a string field to use as the name, defaults to `/sub`
- add enrollment errors to determine if enrollment has occurred
- adds CLI support for ext jwt signer enroll flags
2025-11-05 15:43:49 -05:00