Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions factory/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,25 @@ func GenCA() (*x509.Certificate, crypto.Signer, error) {
return caCert, caKey, nil
}

// Deprecated: Use LoadOrGenCAChain instead as it supports intermediate CAs
func LoadOrGenCA() (*x509.Certificate, crypto.Signer, error) {
cert, key, err := loadCA()
chain, signer, err := LoadOrGenCAChain()
return chain[0], signer, err
}

func LoadOrGenCAChain() ([]*x509.Certificate, crypto.Signer, error) {
certs, key, err := loadCA()
if err == nil {
return cert, key, nil
return certs, key, nil
}

cert, key, err = GenCA()
cert, key, err := GenCA()
if err != nil {
return nil, nil, err
}
certs = []*x509.Certificate{cert}

certBytes, keyBytes, err := Marshal(cert, key)
certBytes, keyBytes, err := MarshalChain(key, certs...)
if err != nil {
return nil, nil, err
}
Expand All @@ -53,14 +60,19 @@ func LoadOrGenCA() (*x509.Certificate, crypto.Signer, error) {
return nil, nil, err
}

return cert, key, nil
return certs, key, nil
}

func loadCA() (*x509.Certificate, crypto.Signer, error) {
return LoadCerts("./certs/ca.pem", "./certs/ca.key")
func loadCA() ([]*x509.Certificate, crypto.Signer, error) {
return LoadCertsChain("./certs/ca.pem", "./certs/ca.key")
}

func LoadCA(caPem, caKey []byte) (*x509.Certificate, crypto.Signer, error) {
chain, signer, err := LoadCAChain(caPem, caKey)
return chain[0], signer, err
}

func LoadCAChain(caPem, caKey []byte) ([]*x509.Certificate, crypto.Signer, error) {
key, err := cert.ParsePrivateKeyPEM(caKey)
if err != nil {
return nil, nil, err
Expand All @@ -70,15 +82,21 @@ func LoadCA(caPem, caKey []byte) (*x509.Certificate, crypto.Signer, error) {
return nil, nil, fmt.Errorf("key is not a crypto.Signer")
}

cert, err := ParseCertPEM(caPem)
certs, err := cert.ParseCertsPEM(caPem)
if err != nil {
return nil, nil, err
}

return cert, signer, nil
return certs, signer, nil
}

// Deprecated: Use LoadCertsChain instead as it supports intermediate CAs
func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, error) {
chain, signer, err := LoadCertsChain(certFile, keyFile)
return chain[0], signer, err
}

func LoadCertsChain(certFile, keyFile string) ([]*x509.Certificate, crypto.Signer, error) {
caPem, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, nil, err
Expand All @@ -88,5 +106,5 @@ func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, erro
return nil, nil, err
}

return LoadCA(caPem, caKey)
return LoadCAChain(caPem, caKey)
}
10 changes: 6 additions & 4 deletions factory/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var (
)

type TLS struct {
CACert *x509.Certificate
CACert []*x509.Certificate
CAKey crypto.Signer
CN string
Organization []string
Expand Down Expand Up @@ -178,7 +178,7 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
return nil, false, err
}

keyBytes, certBytes, err := MarshalChain(privateKey, newCert, t.CACert)
keyBytes, certBytes, err := MarshalChain(privateKey, append([]*x509.Certificate{newCert}, t.CACert...)...)
if err != nil {
return nil, false, err
}
Expand Down Expand Up @@ -226,14 +226,16 @@ func (t *TLS) Verify(secret *v1.Secret) error {
x509.ExtKeyUsageAny,
},
}
verifyOpts.Roots.AddCert(t.CACert)
for _, c := range t.CACert {
verifyOpts.Roots.AddCert(c)
}

_, err = certificates[0].Verify(verifyOpts)
return err
}

func (t *TLS) newCert(domains []string, ips []net.IP, privateKey crypto.Signer) (*x509.Certificate, error) {
return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips)
return NewSignedCert(privateKey, t.CACert[0], t.CAKey, t.CN, t.Organization, domains, ips)
}

func populateCN(secret *v1.Secret, cn ...string) *v1.Secret {
Expand Down
5 changes: 5 additions & 0 deletions listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ type SetFactory interface {
SetFactory(tls TLSFactory)
}

// Deprecated: Use NewListener2 instead as it supports intermediate CAs
func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, caKey crypto.Signer, config Config) (net.Listener, http.Handler, error) {
return NewListener2(l, storage, []*x509.Certificate{caCert}, caKey, config)
}

func NewListener2(l net.Listener, storage TLSStorage, caCert []*x509.Certificate, caKey crypto.Signer, config Config) (net.Listener, http.Handler, error) {
if config.CN == "" {
config.CN = "dynamic"
}
Expand Down
18 changes: 12 additions & 6 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
)

type ListenOpts struct {
CAChain []*x509.Certificate
// Deprecated: Use CAChain instead
CA *x509.Certificate
CAKey crypto.Signer
Storage dynamiclistener.TLSStorage
Expand Down Expand Up @@ -132,21 +134,25 @@ func getTLSListener(ctx context.Context, tcp net.Listener, handler http.Handler,
return nil, nil, err
}

listener, dynHandler, err := dynamiclistener.NewListener(tcp, storage, caCert, caKey, opts.TLSListenerConfig)
listener, dynHandler, err := dynamiclistener.NewListener2(tcp, storage, caCert, caKey, opts.TLSListenerConfig)
if err != nil {
return nil, nil, err
}

return listener, wrapHandler(dynHandler, handler), nil
}

func getCA(opts ListenOpts) (*x509.Certificate, crypto.Signer, error) {
if opts.CA != nil && opts.CAKey != nil {
return opts.CA, opts.CAKey, nil
func getCA(opts ListenOpts) ([]*x509.Certificate, crypto.Signer, error) {
if opts.CAKey != nil {
if opts.CAChain != nil {
return opts.CAChain, opts.CAKey, nil
} else if opts.CA != nil {
return []*x509.Certificate{opts.CA}, opts.CAKey, nil
}
}

if opts.Secrets == nil {
return factory.LoadOrGenCA()
return factory.LoadOrGenCAChain()
}

if opts.CAName == "" {
Expand All @@ -161,7 +167,7 @@ func getCA(opts ListenOpts) (*x509.Certificate, crypto.Signer, error) {
opts.CANamespace = "kube-system"
}

return kubernetes.LoadOrGenCA(opts.Secrets, opts.CANamespace, opts.CAName)
return kubernetes.LoadOrGenCAChain(opts.Secrets, opts.CANamespace, opts.CAName)
}

func newStorage(ctx context.Context, opts ListenOpts) dynamiclistener.TLSStorage {
Expand Down
8 changes: 7 additions & 1 deletion storage/kubernetes/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Deprecated: Use LoadOrGenCAChain instead as it supports intermediate CAs
func LoadOrGenCA(secrets v1controller.SecretClient, namespace, name string) (*x509.Certificate, crypto.Signer, error) {
chain, signer, err := LoadOrGenCAChain(secrets, namespace, name)
return chain[0], signer, err
}

func LoadOrGenCAChain(secrets v1controller.SecretClient, namespace, name string) ([]*x509.Certificate, crypto.Signer, error) {
secret, err := getSecret(secrets, namespace, name)
if err != nil {
return nil, nil, err
}
return factory.LoadCA(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
return factory.LoadCAChain(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
}

func LoadOrGenClient(secrets v1controller.SecretClient, namespace, name, cn string, ca *x509.Certificate, key crypto.Signer) (*x509.Certificate, crypto.Signer, error) {
Expand Down