WIP on the safely rotate of root and federated certificates.

Fixes #23
This commit is contained in:
Mariano Cano 2019-01-22 19:54:12 -08:00
parent bacbf85aa3
commit 25eba1a96c
4 changed files with 286 additions and 74 deletions

View file

@ -10,16 +10,18 @@ type TLSOption func(ctx *TLSOptionCtx) error
// TLSOptionCtx is the context modified on TLSOption methods.
type TLSOptionCtx struct {
Client *Client
Config *tls.Config
OnRenewFunc []TLSOption
Client *Client
Config *tls.Config
OnRenewFunc []TLSOption
mutableConfig *mutableTLSConfig
}
// newTLSOptionCtx creates the TLSOption context.
func newTLSOptionCtx(c *Client, config *tls.Config) *TLSOptionCtx {
return &TLSOptionCtx{
Client: c,
Config: config,
Client: c,
Config: config,
mutableConfig: newMutableTLSConfig(),
}
}
@ -29,6 +31,23 @@ func (ctx *TLSOptionCtx) apply(options []TLSOption) error {
return err
}
}
// Initialize mutable config with the fully configured tls.Config
ctx.mutableConfig.Init(ctx.Config)
// Update tls.Config with mutable data
if ctx.Config.RootCAs == nil && len(ctx.mutableConfig.mutRootCerts) > 0 {
ctx.Config.RootCAs = x509.NewCertPool()
}
if ctx.Config.ClientCAs == nil && len(ctx.mutableConfig.mutClientCerts) > 0 {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range ctx.mutableConfig.mutRootCerts {
ctx.Config.RootCAs.AddCert(cert)
}
for _, cert := range ctx.mutableConfig.mutClientCerts {
ctx.Config.ClientCAs.AddCert(cert)
}
ctx.mutableConfig.Reload()
return nil
}
@ -38,6 +57,8 @@ func (ctx *TLSOptionCtx) applyRenew() error {
return err
}
}
// Reload mutable config with the changes
ctx.mutableConfig.Reload()
return nil
}
@ -68,6 +89,7 @@ func AddRootCA(cert *x509.Certificate) TLSOption {
ctx.Config.RootCAs = x509.NewCertPool()
}
ctx.Config.RootCAs.AddCert(cert)
ctx.mutableConfig.AddInmutableRootCACert(cert)
return nil
}
}
@ -81,6 +103,7 @@ func AddClientCA(cert *x509.Certificate) TLSOption {
ctx.Config.ClientCAs = x509.NewCertPool()
}
ctx.Config.ClientCAs.AddCert(cert)
ctx.mutableConfig.AddInmutableClientCACert(cert)
return nil
}
}
@ -91,16 +114,21 @@ func AddClientCA(cert *x509.Certificate) TLSOption {
//
// BootstrapServer and BootstrapClient methods include this option by default.
func AddRootsToRootCAs() TLSOption {
// var once sync.Once
fn := func(ctx *TLSOptionCtx) error {
certs, err := ctx.Client.Roots()
if err != nil {
return err
}
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddRootCAs(certs.Certificates)
}
return nil
}
@ -117,16 +145,21 @@ func AddRootsToRootCAs() TLSOption {
//
// BootstrapServer method includes this option by default.
func AddRootsToClientCAs() TLSOption {
// var once sync.Once
fn := func(ctx *TLSOptionCtx) error {
certs, err := ctx.Client.Roots()
if err != nil {
return err
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddClientCAs(certs.Certificates)
}
return nil
}
@ -145,11 +178,15 @@ func AddFederationToRootCAs() TLSOption {
if err != nil {
return err
}
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddRootCAs(certs.Certificates)
}
return nil
}
@ -169,11 +206,15 @@ func AddFederationToClientCAs() TLSOption {
if err != nil {
return err
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddClientCAs(certs.Certificates)
}
return nil
}
@ -192,15 +233,20 @@ func AddRootsToCAs() TLSOption {
if err != nil {
return err
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
ctx.Config.RootCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
ctx.Config.ClientCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddRootCAs(certs.Certificates)
ctx.mutableConfig.AddClientCAs(certs.Certificates)
}
return nil
}
@ -219,15 +265,20 @@ func AddFederationToCAs() TLSOption {
if err != nil {
return err
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.ClientCAs.AddCert(cert.Certificate)
ctx.Config.RootCAs.AddCert(cert.Certificate)
if ctx.mutableConfig == nil {
if ctx.Config.RootCAs == nil {
ctx.Config.RootCAs = x509.NewCertPool()
}
if ctx.Config.ClientCAs == nil {
ctx.Config.ClientCAs = x509.NewCertPool()
}
for _, cert := range certs.Certificates {
ctx.Config.RootCAs.AddCert(cert.Certificate)
ctx.Config.ClientCAs.AddCert(cert.Certificate)
}
} else {
ctx.mutableConfig.AddRootCAs(certs.Certificates)
ctx.mutableConfig.AddClientCAs(certs.Certificates)
}
return nil
}