diff --git a/proposals/2027_opt_out_of_self_signed_certificate_authorities/README.md b/proposals/2027_opt_out_of_self_signed_certificate_authorities/README.md new file mode 100644 index 0000000000..951ff50d61 --- /dev/null +++ b/proposals/2027_opt_out_of_self_signed_certificate_authorities/README.md @@ -0,0 +1,134 @@ +--- +title: "Opt-Out of self-signed CAs (and their certs)" +authors: [ "@joshuatcasey" ] +status: "proposed" +sponsor: [ "@cfryanr", "@ashish-amarnath" ] +approval_date: "TBD" +--- + +*Disclaimer*: Proposals are point-in-time designs and decisions. +Once approved and implemented, they become historical documents. +If you are reading an old proposal, please be aware that the +features described herein might have continued to evolve since. + +# Opt-Out of self-signed CAs (and their certs) + +## Problem Statement + +Pinniped's Concierge, Supervisor, and Local-User-Authenticator today require the use of self-signed certificate +authorities (CAs). These self-signed CAs are used for a variety of purposes, but generally are used to sign leaf +certificates used to serve TLS or sign leaf certificates for client authentication (mTLS). + +Using self-signed certificates can mean that custom CA bundles need to be installed on client machines so that clients +can perform TLS verification with a Pinniped endpoint. As of Pinniped v0.32.0, any endpoints that are meant to be +visited by a client machine can use external certificates. In particular, each Supervisor `FederationDomain` serves +OIDC discovery and web endpoints that are meant to be visited by client machines, and each Concierge `ImpersonationProxy` +is an endpoint meant to be visited by client machines. This proposal will not change configuration for those endpoints. + +However, Pinniped does expose various endpoints for Kubernetes-internal use, such as to serve a `/healthz` endpoint +or an endpoint that backs an `APIService` (only the Kubernetes API Service will call an `APIService`), as well as +create certificates for client authentication (when the impersonation proxy is enabled). Today, Pinniped will generate +its own CA certificate and any leaf certificates that it needs. + +TBD: explain if/why this is bad + +## Terminology / Concepts + +* Self-signed certificate: A certificate not signed by a publicly-trusted CA authority. +* Certificate Authority (CA): A certificate (with `isCA: true`) used to issue intermediate certificates or leaf +certificates, such as certificates for serving TLS or certificates for client authentication (mTLS). +* Generated certificate: A certificate generated by Pinniped, from its own CAs. By definition these generated certificates +are not themselves self-signed, since they are always signed by a CA (even if that CA is self-signed). +* External certificate: A certificate provided by something outside of Pinniped, such as `cert-manager`. Usually this +is a leaf certificate (to serve TLS, for example), but could be a CA certificate. +* Secret type `kubernetes.io/tls`: Secrets that must have keys `tls.crt` and `tls.key` that can contain either a CA, +intermediate, or leaf certificate. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets. +* `cert-manager`: A [tool](https://cert-manager.io/) to manage certificates used within a cluster. Generally outputs +secrets of type `kubernetes.io/tls`, and may populate an additional data field `ca.crt` with a higher-level certificate +if available. +* CA Bundle: A collection of certificates used to verify TLS or some other certificate signature. Usually should only +contain CA or intermediate certificates (not leaf certificates that should be rotated frequently), and should never +contain private keys. + +## Proposal + +TBD + +### Goals and Non-goals + +Goal: +* Pinniped should provide enough configuration options for Pinniped administrators to completely avoid using self-signed CAs +* Pinniped should generally expect external certificates to be leaf certificates (to serve TLS, for example). Pinniped +will need a CA certificate when the impersonation proxy is enabled, in order to issue client certificates for mTLS. +* Pinniped should rely on Kubernetes standards such as secrets with type `kubernetes.io/tls`, instead of coupling itself +to any specific tool such as `cert-manager`. However, Pinniped will defer to a `ca.crt` field for CA bundles if that +field is available. + +Non-goals: +* It is not a goal of this proposal to remove Pinniped's self-signed CAs (and require the user to configure all CAs and +certificates). Pinniped should continue to generate any necessary CAs and certificates that are not externally provided. +* It is not a goal of this proposal to change how the Supervisor signs the ID tokens that it issues. Those tokens are +signed by ECDSA private keys specific to each `FederationDomain`. Clients that need to validate tokens issued by the +Pinniped Supervisor can obtain the public keys through OIDC discovery, not through PKI distribution. +* It is not a goal of this proposal to change configuration for `FederationDomain` or `ImpersonationProxy` resources +that already accept external certificates as of v0.32.0 + +#### API Changes + +TBD + +#### Configuration Changes + +TBD + +#### Upgrades + +TBD + +#### Tests + +TBD + +#### New Dependencies + +No. + +#### Performance Considerations + +No. + +#### Observability Considerations + +TBD + +#### Security Considerations + +TBD + +#### Usability Considerations + +TBD + +#### Documentation Considerations + +TBD + +### Other Approaches Considered + +TBD + +## Open Questions + +TBD + +## Answered Questions + +TBD + +## Implementation Plan + +TBD + +## Implementation PRs + +* TBD diff --git a/proposals/2027_opt_out_of_self_signed_certificate_authorities/fail_test.go b/proposals/2027_opt_out_of_self_signed_certificate_authorities/fail_test.go new file mode 100644 index 0000000000..843055fc07 --- /dev/null +++ b/proposals/2027_opt_out_of_self_signed_certificate_authorities/fail_test.go @@ -0,0 +1,16 @@ +// Copyright 2024 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package fail_test + +// TODO: remove this file before merging. + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test(t *testing.T) { + require.Fail(t, "fail this test so that unit tests fail and integration tests do not run in CI") +}