only create ca and client cert once; create server keys each time; add serverAuth to ext usage

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
Evan Hazlett 2015-01-23 21:27:29 -05:00
parent 97e164e7a2
commit 74f9bcebc7
10 changed files with 113 additions and 84 deletions

View File

@ -27,6 +27,7 @@ import (
_ "github.com/docker/machine/drivers/vmwarevcloudair"
_ "github.com/docker/machine/drivers/vmwarevsphere"
"github.com/docker/machine/state"
"github.com/docker/machine/utils"
)
type hostListItem struct {
@ -156,7 +157,7 @@ var Commands = []cli.Command{
func cmdActive(c *cli.Context) {
name := c.Args().First()
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("auth-ca"), c.GlobalString("auth-key"))
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
if name == "" {
host, err := store.GetActive()
@ -221,10 +222,9 @@ func cmdConfig(c *cli.Context) {
log.Fatalf("Error loading machine config: %s", err)
}
storeDir := store.Path
caCert := filepath.Join(storeDir, name, "ca.pem")
clientCert := filepath.Join(storeDir, name, "cert.pem")
clientKey := filepath.Join(storeDir, name, "key.pem")
caCert := filepath.Join(utils.GetMachineDir(), "ca.pem")
clientCert := filepath.Join(utils.GetMachineDir(), "client.pem")
clientKey := filepath.Join(utils.GetMachineDir(), "client-key.pem")
machineUrl, err := host.GetURL()
if err != nil {
log.Fatalf("Error getting machine url: %s", err)

View File

@ -4,22 +4,12 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/docker/machine/utils"
)
func GetHomeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}
func GetDockerDir() string {
return fmt.Sprintf(filepath.Join(GetHomeDir(), ".docker"))
}
func PublicKeyPath() string {
return filepath.Join(GetHomeDir(), ".docker", "public-key.json")
return filepath.Join(utils.GetHomeDir(), ".docker", "public-key.json")
}
func AddPublicKeyToAuthorizedHosts(d Driver, authorizedKeysPath string) error {

View File

@ -143,7 +143,7 @@ func (d *Driver) Create() error {
}
// todo: use real constant for .docker
rootPath := filepath.Join(drivers.GetHomeDir(), ".docker")
rootPath := filepath.Join(utils.GetHomeDir(), ".docker")
imgPath := filepath.Join(rootPath, "images")
commonIsoPath := filepath.Join(imgPath, "boot2docker.iso")
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {

View File

@ -151,7 +151,7 @@ func (d *Driver) Create() error {
}
// todo: use real constant for .docker
rootPath := filepath.Join(drivers.GetHomeDir(), ".docker")
rootPath := filepath.Join(utils.GetHomeDir(), ".docker")
imgPath := filepath.Join(rootPath, "images")
commonIsoPath := filepath.Join(imgPath, "boot2docker.iso")
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {

View File

@ -244,8 +244,7 @@ func (d *Driver) Create() error {
return err
}
// todo: use real constant for .docker
rootPath := filepath.Join(drivers.GetHomeDir(), ".docker")
rootPath := utils.GetDockerDir()
imgPath := filepath.Join(rootPath, "images")
commonIsoPath := filepath.Join(imgPath, "boot2docker.iso")
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {

76
host.go
View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"net"
"os"
"path"
"path/filepath"
"regexp"
"time"
@ -83,59 +84,15 @@ func ValidateHostName(name string) (string, error) {
return name, nil
}
func (h *Host) GenerateCertificates() error {
func GenerateClientCertificate(caCertPath, privateKeyPath string) error {
var (
caPathExists bool
privateKeyExists bool
org = "docker-machine"
bits = 2048
org = "docker-machine"
bits = 2048
)
ip, err := h.Driver.GetIP()
if err != nil {
return err
}
clientCertPath := filepath.Join(utils.GetMachineDir(), "cert.pem")
clientKeyPath := filepath.Join(utils.GetMachineDir(), "key.pem")
caCertPath := filepath.Join(h.storePath, "ca.pem")
privateKeyPath := filepath.Join(h.storePath, "private.pem")
if _, err := os.Stat(h.CaCertPath); os.IsNotExist(err) {
caPathExists = false
} else {
caPathExists = true
}
if _, err := os.Stat(h.PrivateKeyPath); os.IsNotExist(err) {
privateKeyExists = false
} else {
privateKeyExists = true
}
if !caPathExists && !privateKeyExists {
log.Debugf("generating self-signed CA cert: %s", caCertPath)
if err := utils.GenerateCACert(caCertPath, privateKeyPath, org, bits); err != nil {
return fmt.Errorf("error generating self-signed CA cert: %s", err)
}
} else {
if err := utils.CopyFile(h.CaCertPath, caCertPath); err != nil {
return fmt.Errorf("unable to copy CA cert: %s", err)
}
if err := utils.CopyFile(h.PrivateKeyPath, privateKeyPath); err != nil {
return fmt.Errorf("unable to copy private key: %s", err)
}
}
serverCertPath := filepath.Join(h.storePath, "server.pem")
serverKeyPath := filepath.Join(h.storePath, "server-key.pem")
log.Debugf("generating server cert: %s", serverCertPath)
if err := utils.GenerateCert([]string{ip}, serverCertPath, serverKeyPath, caCertPath, privateKeyPath, org, bits); err != nil {
return fmt.Errorf("error generating server cert: %s", err)
}
clientCertPath := filepath.Join(h.storePath, "cert.pem")
clientKeyPath := filepath.Join(h.storePath, "key.pem")
log.Debugf("generating client cert: %s", clientCertPath)
if err := utils.GenerateCert([]string{""}, clientCertPath, clientKeyPath, caCertPath, privateKeyPath, org, bits); err != nil {
return fmt.Errorf("error generating client cert: %s", err)
@ -151,14 +108,23 @@ func (h *Host) ConfigureAuth() error {
return nil
}
log.Debugf("generating certificates for %s", h.Name)
if err := h.GenerateCertificates(); err != nil {
ip, err := h.Driver.GetIP()
if err != nil {
return err
}
caCertPath := filepath.Join(utils.GetMachineDir(), "ca.pem")
caKeyPath := filepath.Join(utils.GetMachineDir(), "key.pem")
serverCertPath := filepath.Join(h.storePath, "server.pem")
caCertPath := filepath.Join(h.storePath, "ca.pem")
serverKeyPath := filepath.Join(h.storePath, "server-key.pem")
org := "docker"
bits := 2048
log.Debugf("generating server cert: %s", serverCertPath)
if err := utils.GenerateCert([]string{ip}, serverCertPath, serverKeyPath, caCertPath, caKeyPath, org, bits); err != nil {
return fmt.Errorf("error generating server cert: %s", err)
}
if err := d.StopDocker(); err != nil {
return err
@ -180,19 +146,19 @@ func (h *Host) ConfigureAuth() error {
// due to windows clients, we cannot use filepath.Join as the paths
// will be mucked on the linux hosts
machineCaCertPath := fmt.Sprintf("%s/ca.pem", d.GetDockerConfigDir())
machineCaCertPath := path.Join(d.GetDockerConfigDir(), "ca.pem")
serverCert, err := ioutil.ReadFile(serverCertPath)
if err != nil {
return err
}
machineServerCertPath := fmt.Sprintf("%s/server.pem", d.GetDockerConfigDir())
machineServerCertPath := path.Join(d.GetDockerConfigDir(), "server.pem")
serverKey, err := ioutil.ReadFile(serverKeyPath)
if err != nil {
return err
}
machineServerKeyPath := fmt.Sprintf("%s/server-key.pem", d.GetDockerConfigDir())
machineServerKeyPath := path.Join(d.GetDockerConfigDir(), "server-key.pem")
cmd, err = d.GetSSHCommand(fmt.Sprintf("echo \"%s\" | sudo tee -a %s", string(caCert), machineCaCertPath))
if err != nil {

63
main.go
View File

@ -3,11 +3,51 @@ package main
import (
"os"
"path"
"path/filepath"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/machine/utils"
)
func before(c *cli.Context) error {
caCertPath := c.GlobalString("tls-ca-cert")
caKeyPath := c.GlobalString("tls-ca-key")
clientCertPath := c.GlobalString("tls-client-cert")
clientKeyPath := c.GlobalString("tls-client-key")
org := "docker"
bits := 2048
if _, err := os.Stat(caCertPath); os.IsNotExist(err) {
log.Debugf("Creating CA: %s", caCertPath)
// check if the key path exists; if so, error
if _, err := os.Stat(caKeyPath); err == nil {
log.Fatalf("The CA key already exists. Please remove it or specify a different key/cert.")
}
if err := utils.GenerateCACertificate(caCertPath, caKeyPath, org, bits); err != nil {
log.Fatalf("Error generating CA certificate: %s", err)
}
}
if _, err := os.Stat(clientCertPath); os.IsNotExist(err) {
log.Debugf("Creating client certificate: %s", clientCertPath)
// check if the key path exists; if so, error
if _, err := os.Stat(clientKeyPath); err == nil {
log.Fatalf("The client key already exists. Please remove it or specify a different key/cert.")
}
if err := utils.GenerateCert([]string{""}, clientCertPath, clientKeyPath, caCertPath, caKeyPath, org, bits); err != nil {
log.Fatalf("Error generating client certificate: %s", err)
}
}
return nil
}
func main() {
for _, f := range os.Args {
if f == "-D" || f == "--debug" || f == "-debug" {
@ -21,6 +61,7 @@ func main() {
app.Commands = Commands
app.CommandNotFound = cmdNotFound
app.Usage = "Create and manage machines running Docker."
app.Before = before
app.Version = VERSION
app.Flags = []cli.Flag{
@ -34,14 +75,28 @@ func main() {
Usage: "Configures storage path",
},
cli.StringFlag{
EnvVar: "MACHINE_AUTH_CA",
Name: "auth-ca",
EnvVar: "MACHINE_TLS_CA_CERT",
Name: "tls-ca-cert",
Usage: "CA to verify remotes against",
Value: filepath.Join(utils.GetMachineDir(), "ca.pem"),
},
cli.StringFlag{
EnvVar: "MACHINE_AUTH_PRIVATE_KEY",
Name: "auth-key",
EnvVar: "MACHINE_TLS_CA_KEY",
Name: "tls-ca-key",
Usage: "Private key to generate certificates",
Value: filepath.Join(utils.GetMachineDir(), "key.pem"),
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CLIENT_CERT",
Name: "tls-client-cert",
Usage: "Client cert to use for TLS",
Value: filepath.Join(utils.GetMachineDir(), "client.pem"),
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CLIENT_KEY",
Name: "tls-client-key",
Usage: "Private key used in client TLS auth",
Value: filepath.Join(utils.GetMachineDir(), "client-key.pem"),
},
}

View File

@ -8,6 +8,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/machine/drivers"
"github.com/docker/machine/utils"
)
// Store persists hosts on the filesystem
@ -19,7 +20,7 @@ type Store struct {
func NewStore(rootPath string, caCert string, privateKey string) *Store {
if rootPath == "" {
rootPath = filepath.Join(drivers.GetHomeDir(), ".docker", "machines")
rootPath = utils.GetMachineDir()
}
return &Store{Path: rootPath, CaCertPath: caCert, PrivateKeyPath: privateKey}

View File

@ -40,10 +40,10 @@ func newCertificate(org string) (*x509.Certificate, error) {
}
// GenerateCACert generates a new certificate authority from the specified org
// GenerateCACertificate generates a new certificate authority from the specified org
// and bit size and stores the resulting certificate and key file
// in the arguments.
func GenerateCACert(certFile, keyFile, org string, bits int) error {
func GenerateCACertificate(certFile, keyFile, org string, bits int) error {
template, err := newCertificate(org)
if err != nil {
return err

View File

@ -1,10 +1,28 @@
package utils
import (
"fmt"
"io"
"os"
"path/filepath"
"runtime"
)
func GetHomeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}
func GetDockerDir() string {
return fmt.Sprintf(filepath.Join(GetHomeDir(), ".docker"))
}
func GetMachineDir() string {
return fmt.Sprintf(filepath.Join(GetDockerDir(), "machines"))
}
func CopyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {