2021-03-10 18:30:06 +00:00
|
|
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
2020-09-23 13:53:21 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
// Package dynamiccertauthority implements a x509 certificate authority capable of issuing
|
|
|
|
// certificates from a dynamically updating CA keypair.
|
|
|
|
package dynamiccertauthority
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
2021-03-10 18:30:06 +00:00
|
|
|
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
|
|
|
|
2020-09-23 13:53:21 +00:00
|
|
|
"go.pinniped.dev/internal/certauthority"
|
2021-03-15 16:24:07 +00:00
|
|
|
"go.pinniped.dev/internal/issuer"
|
2020-09-23 13:53:21 +00:00
|
|
|
)
|
|
|
|
|
2021-03-15 16:24:07 +00:00
|
|
|
// ca is a type capable of issuing certificates.
|
|
|
|
type ca struct {
|
2021-03-10 18:30:06 +00:00
|
|
|
provider dynamiccertificates.CertKeyContentProvider
|
2020-09-23 13:53:21 +00:00
|
|
|
}
|
|
|
|
|
2021-03-15 16:24:07 +00:00
|
|
|
// 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{
|
2020-09-23 13:53:21 +00:00
|
|
|
provider: provider,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:24:07 +00:00
|
|
|
func (c *ca) Name() string {
|
|
|
|
return c.provider.Name()
|
|
|
|
}
|
|
|
|
|
2021-03-13 00:09:16 +00:00
|
|
|
// IssueClientCertPEM issues a new client certificate for the given identity and duration, returning it as a
|
2020-10-23 19:34:25 +00:00
|
|
|
// pair of PEM-formatted byte slices for the certificate and private key.
|
2021-03-15 16:24:07 +00:00
|
|
|
func (c *ca) IssueClientCertPEM(username string, groups []string, ttl time.Duration) ([]byte, []byte, error) {
|
2020-09-23 13:53:21 +00:00
|
|
|
caCrtPEM, caKeyPEM := c.provider.CurrentCertKeyContent()
|
2021-03-15 16:24:07 +00:00
|
|
|
// 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.
|
2020-09-23 13:53:21 +00:00
|
|
|
ca, err := certauthority.Load(string(caCrtPEM), string(caKeyPEM))
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2021-03-13 00:09:16 +00:00
|
|
|
return ca.IssueClientCertPEM(username, groups, ttl)
|
2020-09-23 13:53:21 +00:00
|
|
|
}
|