cloudfoundry / gorouter

CF Router
Apache License 2.0
441 stars 226 forks source link

Optional mTLS client certificate metadata verification #367

Closed peanball closed 1 year ago

peanball commented 1 year ago

We want to add optional mTLS client certificate metadata verification in addition to the issuer CA validity checks.

Given a particular signing CA (identified by its subject) we want to limit the allowed client certificate subjects that are allowed to send requests.

While the underlying issue is better solved with changes to the PKI and trust relationship between CAs, the PKI or its use by other sub-entities is not always under the control of the operator.

The use case is an upstream proxy managed by a different entity that uses a widely spread private CA for issuing its certificates.

We want to avoid that every user of that CA is able to issue requests to Gorouter, while still explicitly allowing the upstream proxy and its CA certificates, which are short-lived and need rotation.

In the specific use case, we have a CA that controls, which certificates are issued for specific sub-entities, which are clearly identified in the certificate's subject DN.

e.g. configuration in routing-release:

router:
  verify_client_certificate_metadata:
    - issuer_in_chain:
        common_name: Some Root CA
        country:
          - DE
      valid_cert_subjects:
        - common_name: Awesome Service 1
          organizational_unit:
            - sub-entity4
          organization:
            - Acme, Inc.
          country:
            - US
        - common_name: Awesome Service 2
          organizational_unit:
            - sub-entity7
          organization:
            - Acme, Inc.
          country:
            - US
  1. Send a request using a client certificate that is signed by a CA that is configured in client_ca_certs: but not in the explicit allowed subjects, configured in verify_client_certificate_metadata::
    curl --cacert other-department-5.pem https://app.cf.example.com
  2. Send a request using a client certificate that is signed by a CA that is configured in client_ca_certs: and in the allowed subjects, configured in verify_client_certificate_metadata::
    curl --cacert awesome-service-2.pem https://app.cf.example.com
  1. The request fails with a TLS handshake error. Gorouter logs the certificate subject and the fact that this certificate was not allowed.
  2. succeeds, as desired.
  1. The request passes through without TLS handshake errors, allows access to a different party that should not have access.
  2. succeeds, as desired.
peanball commented 1 year ago

@ameowlia thanks so much for this thoughtful and thorough review. We'll address the points. Fully agree on having a check in the spec ERB template / at template generation time.

peanball commented 1 year ago

@ameowlia Could you have another look?

I've updated this PR addressing all comments and provided the companion PR for routing release: https://github.com/cloudfoundry/routing-release/pull/355