mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-05 13:07:14 +00:00
dynamiccert: split into serving cert and CA providers
Signed-off-by: Monis Khan <mok@vmware.com>
This commit is contained in:
@@ -19,6 +19,8 @@ import (
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"go.pinniped.dev/internal/constable"
|
||||
)
|
||||
|
||||
// certBackdate is the amount of time before time.Now() that will be used to set
|
||||
@@ -71,7 +73,7 @@ func secureEnv() env {
|
||||
}
|
||||
|
||||
// ErrInvalidCACertificate is returned when the contents of the loaded CA certificate do not meet our assumptions.
|
||||
var ErrInvalidCACertificate = fmt.Errorf("invalid CA certificate")
|
||||
const ErrInvalidCACertificate = constable.Error("invalid CA certificate")
|
||||
|
||||
// Load a certificate authority from an existing certificate and private key (in PEM format).
|
||||
func Load(certPEM string, keyPEM string) (*CA, error) {
|
||||
@@ -82,6 +84,13 @@ func Load(certPEM string, keyPEM string) (*CA, error) {
|
||||
if certCount := len(cert.Certificate); certCount != 1 {
|
||||
return nil, fmt.Errorf("%w: expected a single certificate, found %d certificates", ErrInvalidCACertificate, certCount)
|
||||
}
|
||||
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse key pair as x509 cert: %w", err)
|
||||
}
|
||||
if !x509Cert.IsCA {
|
||||
return nil, fmt.Errorf("%w: passed in key pair is not a CA", ErrInvalidCACertificate)
|
||||
}
|
||||
return &CA{
|
||||
caCertBytes: cert.Certificate[0],
|
||||
signer: cert.PrivateKey.(crypto.Signer),
|
||||
|
||||
@@ -11,25 +11,33 @@ import (
|
||||
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
||||
|
||||
"go.pinniped.dev/internal/certauthority"
|
||||
"go.pinniped.dev/internal/issuer"
|
||||
)
|
||||
|
||||
// CA is a type capable of issuing certificates.
|
||||
type CA struct {
|
||||
// ca is a type capable of issuing certificates.
|
||||
type ca struct {
|
||||
provider dynamiccertificates.CertKeyContentProvider
|
||||
}
|
||||
|
||||
// New creates a new CA, ready to issue certs whenever the provided provider has a keypair to
|
||||
// provide.
|
||||
func New(provider dynamiccertificates.CertKeyContentProvider) *CA {
|
||||
return &CA{
|
||||
// New creates a ClientCertIssuer, ready to issue certs whenever
|
||||
// the given CertKeyContentProvider has a keypair to provide.
|
||||
func New(provider dynamiccertificates.CertKeyContentProvider) issuer.ClientCertIssuer {
|
||||
return &ca{
|
||||
provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ca) Name() string {
|
||||
return c.provider.Name()
|
||||
}
|
||||
|
||||
// IssueClientCertPEM issues a new client certificate for the given identity and duration, returning it as a
|
||||
// pair of PEM-formatted byte slices for the certificate and private key.
|
||||
func (c *CA) IssueClientCertPEM(username string, groups []string, ttl time.Duration) ([]byte, []byte, error) {
|
||||
func (c *ca) IssueClientCertPEM(username string, groups []string, ttl time.Duration) ([]byte, []byte, error) {
|
||||
caCrtPEM, caKeyPEM := c.provider.CurrentCertKeyContent()
|
||||
// in the future we could split dynamiccert.Private into two interfaces (Private and PrivateRead)
|
||||
// and have this code take PrivateRead as input. We would then add ourselves as a listener to
|
||||
// the PrivateRead. This would allow us to only reload the CA contents when they actually change.
|
||||
ca, err := certauthority.Load(string(caCrtPEM), string(caKeyPEM))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -10,13 +10,14 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/internal/dynamiccert"
|
||||
"go.pinniped.dev/internal/issuer"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
)
|
||||
|
||||
func TestCAIssuePEM(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
provider := dynamiccert.New(t.Name())
|
||||
provider := dynamiccert.NewCA(t.Name())
|
||||
ca := New(provider)
|
||||
|
||||
goodCACrtPEM0, goodCAKeyPEM0, err := testutil.CreateCertificate(
|
||||
@@ -115,7 +116,7 @@ func TestCAIssuePEM(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func issuePEM(provider dynamiccert.Provider, ca *CA, caCrt, caKey []byte) ([]byte, []byte, error) {
|
||||
func issuePEM(provider dynamiccert.Provider, ca issuer.ClientCertIssuer, caCrt, caKey []byte) ([]byte, []byte, error) {
|
||||
// if setting fails, look at that error
|
||||
if caCrt != nil || caKey != nil {
|
||||
if err := provider.SetCertKeyContent(caCrt, caKey); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user