Files
Andrew Martinez 948735d86c fixes openziti/ziti#4094 accept first-party certs issued by a separat… (#4140)
* fixes openziti/ziti#4094 accept first-party certs issued by a separate edge signing CA

- adds FirstPartyX509CertValidation and ThirdPartyX509CertValidation usages and an
  intermediates field to the router data model public keys, deprecating
  ClientX509CertValidation
- publishes config CA bundle roots as first-party anchors with their intermediates and
  Ca store entries as third-party anchors; controller certs carry JWT validation only,
  since a controller identity is never a CA and anchors no client cert chains
- builds router first-party and client cert trust pools from the published usages,
  falling back to the deprecated usage against older controllers
- propagates the full signing cert chain between controllers via a new mesh
  SigningCertChainHeader and persists whole chains in controller records
- removes the orphaned InstantStrategy.AddPublicKey, dead since public key sync moved
  to controller list data
- gives each command dispatcher its own decoder registry so multiple in-process
  controllers no longer decode into the last-started controller's managers
- adds a three-controller in-process HA test harness with a split signing PKI,
  cluster formation and first-party cert integration tests
- trusts the edge signing CA when verifying router control channel certs
- adds a variadic additionalRoots parameter to VerifyLeafCertChain, applied to a
  clone of the caller's pool so an identity's live tls.Configs are unaffected
- passes the edge enrollment signing CA bundle as additional roots when admitting
  a router control channel connection, so a deployment whose signing CA sits
  outside the controller's own trust bundle no longer has every router refused
- leaves the fingerprint check bound to the verified leaf, so the wider anchor set
  changes which chains verify, not which routers are admitted
- covers the split-root case and the caller-pool guarantee in common/cert tests
2026-08-26 14:07:31 -04:00
..

Test Configuration Sets

This directory contains named configuration sets used by the integration tests in ziti/tests/. Each subdirectory is a self-contained set of YAML config files for a specific test scenario.

How Configuration Sets Work

Each config set has a corresponding ConfigSet variable declared in tests/configsets.go. Most tests use DefaultATS implicitly via NewTestContext(t). Tests that need a different configuration call NewTestContextWithConfigSet(t, <ConfigSet>), passing one of the package-level vars defined in configsets.go.

All paths inside config files are relative to the tests/ working directory (the standard Go test working directory for this package), so cert and key paths such as testdata/pki/... resolve correctly regardless of which config set is active.

Test PKI

All config sets share one PKI under testdata/pki/, generated by tests/testdata/create-pki.sh (and the equivalent create-pki.ps1). It is built with ziti pki and is SPIFFE-capable so the raft/HA config sets work:

  • A single root CA, Ziti Test Root CA, under pki/root/.
  • Three controller intermediates (ctrl1, ctrl2, ctrl3), each signing its own server and client certs with a spiffe://ziti.test/controller/<id> URI SAN.
  • Fabric routers 001 and 002, signed by the ctrl1 intermediate, each with a shared key backing its server and client certs and a spiffe://ziti.test/router/<id> URI SAN.
  • A ctrl1 wildcard alt server cert (ctrl1-wildcard.chain.pem / ctrl1-wildcard.key) whose only SAN is *.wildcard.test, used by the wildcard-oidc-server config set.
  • A separate edge signing PKI: a second self-signed root, Ziti Test Edge Signing Root CA, under pki/signing-root/, with per-controller signing intermediates (signing1, signing2, signing3) and a shared bundle (pki/signing-root/certs/signing-bundle.pem, root + all three intermediates). Used by the ha-3 config set to model networks whose edge.enrollment.signingCert root differs from the ctrl-channel root CA.

The single-controller config sets use the ctrl1 material. In the identity blocks:

  • cert / server_cert point at the full chain files (*.chain.pem, leaf → intermediate → root) so peers can build the chain from what is presented on the wire.
  • ca is the root cert only (testdata/pki/root/certs/root.cert); the trust anchor is the root, and intermediates arrive in the presented chains.
  • the controller's client and server certs use separate keys, so key and server_key are both set.

To regenerate the PKI, run create-pki.sh (or create-pki.ps1) from anywhere; it anchors itself to tests/testdata/ and writes to pki/.

Directory Layout

testdata/configs/
  <config-set-name>/
    ctrl.yml                      # controller config
    edge-router.yml               # edge router, when the set needs one
    tunneler-router.yml           # tunneler-enabled edge router
    transit-router.yml            # transit router
    fabric-router-N.yml           # fabric-only routers, when the set needs them

Config Sets

  • default-ats (DefaultATS) — The standard full-stack config used by the majority of the integration test suite. Starts the controller on 127.0.0.1:1281 with edge, OIDC, management, fabric, and health-check APIs; edge router on 127.0.0.1:3022; transit router on tls:0.0.0.0:7098. Also includes the fabric-only router pair used by link-management tests (router 1 on tls:127.0.0.1:6004, router 2 on tls:127.0.0.1:6005).

  • no-explicit-oidc (NoExplicitOIDC) — Controller-only config identical to default-ats/ctrl.yml except the edge-oidc binding is omitted from the web listener. Used to verify that the controller's ensureOidcOnClientApiServer validator automatically adds the OIDC API when it is not explicitly configured.

  • disabled-oidc-auto-binding (DisabledOidcAutoBinding) — Controller-only config with the edge-oidc binding omitted from the web listener AND disableOidcAutoBinding: true set in the edge: section. Used to verify that the auto-binding behaviour is suppressed when the operator opts out, leaving OIDC absent from the running controller.

  • dual-oidc-servers (DualOidcServers) — Controller-only config with two web server entries on different ports (127.0.0.1:1281 and 127.0.0.1:1282), each hosting the edge-oidc API. Used to verify that the OIDC discovery document returns issuer-specific endpoint URLs reflecting the port the client connected to.

  • single-raft (SingleRaft) — Controller-only config that runs a single controller in raft/cluster mode (cluster.dataDir set instead of db). Used to exercise the raft self-registration path, where the controller records itself in the Controller store on leadership rather than relying on the non-raft synthesized-self fallback. Requires the SPIFFE-capable PKI described above.

  • ha-3 (Ha3) — Three-controller raft cluster whose edge signing CA root (pki/signing-root) is distinct from the ctrl-channel root CA (pki/root). Each controller signs identity certs with its own intermediate under the shared signing root (signing1/2/3), and all three point edge.enrollment.signingCert.ca at the shared signing bundle. Controllers listen on 1281/1282/1283 (web), 6262/6363/6464 (ctrl), 10000/10001/10002 (mgmt); raft data lives under testdata/ha-3-data/ctrl{1,2,3}. Includes an edge router config listing all three ctrl endpoints. Started with StartHaCluster. Used to exercise first-party client cert validation when the signing CA and ctrl-channel CA differ, including certs issued by a controller other than the one a router is subscribed to.

  • dual-oidc-servers (DualOidcServers) — Controller config with two web servers on different ports, each hosting the edge-oidc API. Used by Test_OidcDiscoveryEndpoints_DualServers to verify the OIDC discovery document returns endpoint URLs that reflect the port the client connected to.

  • wildcard-oidc-server (WildcardOidcServer) — Ordinary primary server_cert plus an alt_server_certs entry whose only SAN is the wildcard *.wildcard.test, with the edge-oidc binding setting allowedHostnames: [ctrl.wildcard.test]. Used by Test_OidcDiscoveryEndpoints_WildcardIssuer.

Adding a New Config Set

  1. Create a subdirectory with a short, descriptive name (kebab-case).
  2. Add a ctrl.yml and/or router configs as needed, using paths relative to tests/.
  3. Add a ConfigSet var for it in tests/configsets.go.
  4. Write your test using NewTestContextWithConfigSet(t, <YourNewConfigSet>).
  5. Add an entry for the new set to the list above.