1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Add libtrust key identity management

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2014-09-26 14:24:04 -07:00
parent a049ac32d1
commit ea6a480128
6 changed files with 96 additions and 24 deletions

View file

@ -13,6 +13,7 @@ import (
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/registry"
"github.com/docker/libtrust"
)
type DockerCli struct {
@ -22,6 +23,7 @@ type DockerCli struct {
in io.ReadCloser
out io.Writer
err io.Writer
key libtrust.PrivateKey
tlsConfig *tls.Config
scheme string
// inFd holds file descriptor of the client's STDIN, if it's a valid file
@ -98,7 +100,7 @@ func (cli *DockerCli) LoadConfigFile() (err error) {
return err
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
inFd uintptr
outFd uintptr
@ -135,6 +137,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsC
in: in,
out: out,
err: err,
key: key,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,

View file

@ -79,6 +79,7 @@ func mainDaemon() {
job.Setenv("TlsCa", *flCa)
job.Setenv("TlsCert", *flCert)
job.Setenv("TlsKey", *flKey)
job.Setenv("TrustKey", *flTrustKey)
job.SetenvBool("BufferRequests", true)
if err := job.Run(); err != nil {
log.Fatal(err)

View file

@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"os"
"path"
"strings"
"github.com/docker/docker/api"
@ -15,9 +16,11 @@ import (
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/reexec"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
const (
defaultTrustKeyFile = "key.json"
defaultCaFile = "ca.pem"
defaultKeyFile = "key.pem"
defaultCertFile = "cert.pem"
@ -61,6 +64,20 @@ func main() {
}
protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
err := os.MkdirAll(path.Dir(*flTrustKey), 0700)
if err != nil {
log.Fatal(err)
}
trustKey, keyErr := libtrust.LoadKeyFile(*flTrustKey)
if keyErr == libtrust.ErrKeyFileDoesNotExist {
trustKey, keyErr = libtrust.GenerateECP256PrivateKey()
if keyErr == nil {
keyErr = libtrust.SaveKey(*flTrustKey, trustKey)
}
}
if keyErr != nil {
log.Fatal(keyErr)
}
var (
cli *client.DockerCli
tlsConfig tls.Config
@ -95,9 +112,9 @@ func main() {
}
if *flTls || *flTlsVerify {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
} else {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], nil)
}
if err := cli.Cmd(flag.Args()...); err != nil {

View file

@ -29,6 +29,7 @@ var (
flTlsVerify = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)")
// these are initialized in init() below since their default values depend on dockerCertPath which isn't fully initialized until init() runs
flTrustKey *string
flCa *string
flCert *string
flKey *string
@ -36,6 +37,10 @@ var (
)
func init() {
// placeholder for trust key flag
trustKeyDefault := filepath.Join(dockerCertPath, defaultTrustKeyFile)
flTrustKey = &trustKeyDefault
flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust only remotes providing a certificate signed by the CA given here")
flCert = flag.String([]string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file")
flKey = flag.String([]string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file")

View file

@ -14,6 +14,7 @@ import (
"github.com/docker/docker/pkg/log"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
func closeWrap(args ...io.Closer) error {
@ -117,8 +118,12 @@ func TestRunDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c1 := make(chan struct{})
@ -163,8 +168,12 @@ func TestRunDisconnectTty(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c1 := make(chan struct{})
@ -213,8 +222,12 @@ func TestRunDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@ -260,8 +273,12 @@ func TestRunDetach(t *testing.T) {
func TestAttachDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@ -294,7 +311,7 @@ func TestAttachDetach(t *testing.T) {
stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe()
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
ch = make(chan struct{})
go func() {
@ -341,8 +358,12 @@ func TestAttachDetach(t *testing.T) {
func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
// Discard the CmdRun output
@ -360,7 +381,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe()
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
ch := make(chan struct{})
go func() {
@ -406,8 +427,12 @@ func TestAttachDetachTruncatedID(t *testing.T) {
func TestAttachDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
go func() {
@ -461,7 +486,7 @@ func TestAttachDisconnect(t *testing.T) {
// We closed stdin, expect /bin/cat to still be running
// Wait a little bit to make sure container.monitor() did his thing
_, err := container.WaitStop(500 * time.Millisecond)
_, err = container.WaitStop(500 * time.Millisecond)
if err == nil || !container.IsRunning() {
t.Fatalf("/bin/cat is not running after closing stdin")
}
@ -476,7 +501,11 @@ func TestAttachDisconnect(t *testing.T) {
func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe()
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -512,8 +541,12 @@ func TestRunAutoRemove(t *testing.T) {
// Expected behaviour: error out when attempting to bind mount non-existing source paths
func TestRunErrorBindNonExistingSource(t *testing.T) {
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, nil, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})

View file

@ -9,6 +9,7 @@ import (
"time"
"github.com/docker/docker/api/client"
"github.com/docker/libtrust"
)
const (
@ -37,7 +38,11 @@ func getTlsConfig(certFile, keyFile string, t *testing.T) *tls.Config {
// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint
func TestHttpsInfo(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@ -50,7 +55,11 @@ func TestHttpsInfo(t *testing.T) {
// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint
// by using a rogue client certificate and checks that it fails with the expected error.
func TestHttpsInfoRogueCert(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@ -67,7 +76,11 @@ func TestHttpsInfoRogueCert(t *testing.T) {
// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint
// which provides a rogue server certificate and checks that it fails with the expected error
func TestHttpsInfoRogueServerCert(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {