"trust_pool" directive behavior

Hello Caddy community! I’m looking for some clarification about the behavior of the “trust_pool file” directive. I’ve read over the relevant documentation which I’ve linked in section #4 and the behavior is still unclear to me. I’m hoping a Caddy expert can help me get to the bottom of this.

1. The problem:

I’m upgrading my Caddy deployment by a few major versions and replacing the deprecated trusted_ca_cert_file directive with the new trust_pool file syntax. My original configuration looks like this:

tls /etc/caddy/certs/dev-pub-wildcard-cert.cert /etc/caddy/certs/dev-pub-wildcard-cert.key {
    client_auth {
        mode require_and_verify
        # Intermediate then Root (order is important here)
        trusted_ca_cert_file /etc/caddy/certs/new_dev_int_ca_combo.pem
        trusted_ca_cert_file /etc/caddy/certs/wildstar_combo.cert
    }
}

Both new_dev_int_ca_combo.pem and wildstar_combo.cert are “combo” files that include an intermediate CA and its corresponding root CA. I’ve rewritten this as:

tls /etc/caddy/certs/dev-pub-wildcard-cert.cert /etc/caddy/certs/dev-pub-wildcard-cert.key {
    client_auth {
        mode require_and_verify
        # Intermediate then Root (order is important here)
        trust_pool file {
            pem_file /etc/caddy/certs/new_dev_int_ca_combo.pem
            pem_file /etc/caddy/certs/wildstar_combo.cert
        }
    }
}

What I really need help with is understanding the behavior of the new trust_pool directive. I am assuming that this config will behave in the exact same way that the previous config does. Can someone please confirm or deny my assumption?

My understanding is that, just like two trusted_ca_cert_file entries, this trust_pool file block should accept a client whose certificate chain is signed by either of those bundled CAs. If instead it requires both CAs to be presented in the same chain, what’s the correct way to configure trust_pool so that a single combo-CA bundle will suffice?

2. Caddy version:

v2.10.0

3. How I installed and ran Caddy:

a. System environment:

RHEL 8 w/ FIPS Mode enabled

Running as systemd service

b. Command:

sudo systemctl enable caddy --now

c. Relevant Caddy config:

tls /etc/caddy/certs/dev-pub-wildcard-cert.cert /etc/caddy/certs/dev-pub-wildcard-cert.key {
    client_auth {
        mode require_and_verify
        # Intermediate then Root (order is important here)
        trust_pool file {
            pem_file /etc/caddy/certs/new_dev_int_ca_combo.pem
            pem_file /etc/caddy/certs/wildstar_combo.cert
        }
    }
}

4. Links to relevant resources:

Official documentation about “trust_pool file”
tls (Caddyfile directive) — Caddy Documentation

Client cert auth using trust_pool - Help - Caddy Community

That is correct.

This is also correct.

For this sort of validation, you need a verifier module.

However, there isn’t any module (at the time of writing) that verifies the entire chain, as you request. The module must implement the ClientCertificateVerifier interface.

You can try implementing it yourself. It’s fun :slight_smile:

3 Likes

@Mohammed90
Hello Mohammed! Thank you so much for your reply! I really appreciate it. You’ve verified all the information I was concerned about.

To your point of the custom verifier module, I actually have written a custom verifier module that will validate the OU of an x509 certificate. You can pass in a single OU name to trust and then multiple CNs. If the certificate uses the same OU and one of the CNs, then it passes validation.

This is actually my full TLS directive:

tls /etc/caddy/certs/dev-pub-wildcard-cert.cert /etc/caddy/certs/dev-pub-wildcard-cert.key {
  client_auth {
      mode require_and_verify
      trust_pool file {
          pem_file /etc/caddy/certs/dev_int_ca_combo.cert
          pem_file /etc/caddy/certs/wildstar_combo.cert
      }
      verifier ou_validator {
          ou_match_string "CA"
          trusted_common_names "INTERNAL-Policy-Issuing-CA" "Second-INTERNAL-Policy-Issuing-CA"
      }
      verifier revocation {
          mode require_and_verify
          crl_config {
              work_dir "/var/lib/caddy/crlworkdir/test"
              storage_type memory
              update_interval 1m
              signature_validation_mode verify
              trusted_signature_cert_file "/etc/caddy/certs/dev_int.pem"
              crl_file "/var/lib/caddy/crlworkdir/test/ca.crl"
              cdp_config {
                  crl_fetch_mode fetch_actively
                  crl_cdp_strict true
              }
          }
      }
  }
}
2 Likes