Skip to content
Snippets Groups Projects
Unverified Commit 94cec121 authored by Tomasz Maczukin's avatar Tomasz Maczukin
Browse files

Add command for base TLS Certificates regeneration

parent a6084657
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/docker/machine/commands/mcndirs" "github.com/docker/machine/commands/mcndirs"
"github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/crashreport" "github.com/docker/machine/libmachine/crashreport"
...@@ -320,6 +321,23 @@ var Commands = []cli.Command{ ...@@ -320,6 +321,23 @@ var Commands = []cli.Command{
}, },
}, },
}, },
{
Name: "regenerate-base-certs",
Usage: "Regenerate the base TLS Certificates only",
Description: "No arguments expected",
Action: runCommand(cmdRegenerateBaseCerts),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "force, f",
Usage: "Force rebuild and do not prompt",
},
cli.IntFlag{
Name: "regenerate-before",
Usage: "Number of hours defining regeneration window. Existing certificates will be regenerated if current time exceeds `notAfter - regenerate-before`",
Value: 672, // 4 weeks * 7 days * 24 hours
},
},
},
{ {
Name: "restart", Name: "restart",
Usage: "Restart a machine", Usage: "Restart a machine",
......
package commands package commands
import ( import (
"errors"
"time"
"github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/cert"
"github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/log"
) )
...@@ -24,3 +29,32 @@ func cmdRegenerateCerts(c CommandLine, api libmachine.API) error { ...@@ -24,3 +29,32 @@ func cmdRegenerateCerts(c CommandLine, api libmachine.API) error {
} }
return runAction("configureAuth", c, api) return runAction("configureAuth", c, api)
} }
type authOptionsProvider interface {
AuthOptions() *auth.Options
}
func cmdRegenerateBaseCerts(c CommandLine, api libmachine.API) error {
if !c.Bool("force") {
ok, err := confirmInput("Regenerate base TLS certificates? Warning: this is irreversible.")
if err != nil {
return err
}
if !ok {
return nil
}
}
log.Infof("Regenerating base TLS certificates")
aop, ok := api.(authOptionsProvider)
if !ok {
return errors.New("can't typecast API to authOptionsProvider")
}
regenerateBeforeHours := c.Int("regenerate-before")
regenerateWindow := time.Duration(-1*regenerateBeforeHours) * time.Hour
return cert.BootstrapCertificatesWithRegenerationWindow(aop.AuthOptions(), regenerateWindow)
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"time"
"github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/log"
...@@ -72,6 +73,14 @@ func createCert(authOptions *auth.Options, org string, bits int) error { ...@@ -72,6 +73,14 @@ func createCert(authOptions *auth.Options, org string, bits int) error {
} }
func BootstrapCertificates(authOptions *auth.Options) error { func BootstrapCertificates(authOptions *auth.Options) error {
return bootstrapCertificates(authOptions, time.Duration(0))
}
func BootstrapCertificatesWithRegenerationWindow(authOptions *auth.Options, regenerationWindow time.Duration) error {
return bootstrapCertificates(authOptions, regenerationWindow)
}
func bootstrapCertificates(authOptions *auth.Options, regenerationWindow time.Duration) error {
certDir := authOptions.CertDir certDir := authOptions.CertDir
caCertPath := authOptions.CaCertPath caCertPath := authOptions.CaCertPath
clientCertPath := authOptions.ClientCertPath clientCertPath := authOptions.ClientCertPath
...@@ -101,7 +110,7 @@ func BootstrapCertificates(authOptions *auth.Options) error { ...@@ -101,7 +110,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
return err return err
} }
} else { } else {
current, err := CheckCertificateDate(caCertPath) current, err := CheckCertificateDate(caCertPath, regenerationWindow)
if err != nil { if err != nil {
return err return err
} }
...@@ -119,7 +128,7 @@ func BootstrapCertificates(authOptions *auth.Options) error { ...@@ -119,7 +128,7 @@ func BootstrapCertificates(authOptions *auth.Options) error {
return err return err
} }
} else { } else {
current, err := CheckCertificateDate(clientCertPath) current, err := CheckCertificateDate(clientCertPath, regenerationWindow)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -7,14 +7,13 @@ import ( ...@@ -7,14 +7,13 @@ import (
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"errors"
"io/ioutil" "io/ioutil"
"math/big" "math/big"
"net" "net"
"os" "os"
"time" "time"
"errors"
"github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/log"
) )
...@@ -268,7 +267,7 @@ func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth ...@@ -268,7 +267,7 @@ func (xcg *X509CertGenerator) ValidateCertificate(addr string, authOptions *auth
return true, nil return true, nil
} }
func CheckCertificateDate(certPath string) (bool, error) { func CheckCertificateDate(certPath string, regenerationWindow time.Duration) (bool, error) {
log.Debugf("Reading certificate data from %s", certPath) log.Debugf("Reading certificate data from %s", certPath)
certBytes, err := ioutil.ReadFile(certPath) certBytes, err := ioutil.ReadFile(certPath)
if err != nil { if err != nil {
...@@ -286,7 +285,14 @@ func CheckCertificateDate(certPath string) (bool, error) { ...@@ -286,7 +285,14 @@ func CheckCertificateDate(certPath string) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
if time.Now().After(cert.NotAfter) {
notAfter := cert.NotAfter
log.Debugf("Valid Not After: %s", notAfter)
log.Debugf("Regeneration window: %s", regenerationWindow)
regenerationTime := notAfter.Add(regenerationWindow)
log.Debugf("Regeneration time: %s", regenerationTime)
if time.Now().After(regenerationTime) {
return false, nil return false, nil
} }
......
...@@ -2,9 +2,8 @@ package libmachine ...@@ -2,9 +2,8 @@ package libmachine
import ( import (
"fmt" "fmt"
"path/filepath"
"io" "io"
"path/filepath"
"github.com/docker/machine/drivers/errdriver" "github.com/docker/machine/drivers/errdriver"
"github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/auth"
...@@ -65,15 +64,7 @@ func (api *Client) NewHost(driverName string, rawDriver []byte) (*host.Host, err ...@@ -65,15 +64,7 @@ func (api *Client) NewHost(driverName string, rawDriver []byte) (*host.Host, err
Driver: driver, Driver: driver,
DriverName: driver.DriverName(), DriverName: driver.DriverName(),
HostOptions: &host.Options{ HostOptions: &host.Options{
AuthOptions: &auth.Options{ AuthOptions: api.AuthOptions(),
CertDir: api.certsDir,
CaCertPath: filepath.Join(api.certsDir, "ca.pem"),
CaPrivateKeyPath: filepath.Join(api.certsDir, "ca-key.pem"),
ClientCertPath: filepath.Join(api.certsDir, "cert.pem"),
ClientKeyPath: filepath.Join(api.certsDir, "key.pem"),
ServerCertPath: filepath.Join(api.GetMachinesDir(), "server.pem"),
ServerKeyPath: filepath.Join(api.GetMachinesDir(), "server-key.pem"),
},
EngineOptions: &engine.Options{ EngineOptions: &engine.Options{
InstallURL: drivers.DefaultEngineInstallURL, InstallURL: drivers.DefaultEngineInstallURL,
StorageDriver: "overlay2", StorageDriver: "overlay2",
...@@ -88,6 +79,18 @@ func (api *Client) NewHost(driverName string, rawDriver []byte) (*host.Host, err ...@@ -88,6 +79,18 @@ func (api *Client) NewHost(driverName string, rawDriver []byte) (*host.Host, err
}, nil }, nil
} }
func (api *Client) AuthOptions() *auth.Options {
return &auth.Options{
CertDir: api.certsDir,
CaCertPath: filepath.Join(api.certsDir, "ca.pem"),
CaPrivateKeyPath: filepath.Join(api.certsDir, "ca-key.pem"),
ClientCertPath: filepath.Join(api.certsDir, "cert.pem"),
ClientKeyPath: filepath.Join(api.certsDir, "key.pem"),
ServerCertPath: filepath.Join(api.GetMachinesDir(), "server.pem"),
ServerKeyPath: filepath.Join(api.GetMachinesDir(), "server-key.pem"),
}
}
func (api *Client) Load(name string) (*host.Host, error) { func (api *Client) Load(name string) (*host.Host, error) {
h, err := api.Filestore.Load(name) h, err := api.Filestore.Load(name)
if err != nil { if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment