Docker-DCO-1.1-Signed-off-by: Johannes 'fish' Ziemke <github@freigeist.org> (github: discordianfish)
| ... | ... |
@@ -3,6 +3,7 @@ package api |
| 3 | 3 |
import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"bytes" |
| 6 |
+ "crypto/tls" |
|
| 6 | 7 |
"encoding/base64" |
| 7 | 8 |
"encoding/json" |
| 8 | 9 |
"errors" |
| ... | ... |
@@ -57,8 +58,8 @@ func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) {
|
| 57 | 57 |
return method.Interface().(func(...string) error), true |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
-func ParseCommands(proto, addr string, args ...string) error {
|
|
| 61 |
- cli := NewDockerCli(os.Stdin, os.Stdout, os.Stderr, proto, addr) |
|
| 60 |
+func ParseCommands(proto, addr string, tlsConfig *tls.Config, args ...string) error {
|
|
| 61 |
+ cli := NewDockerCli(os.Stdin, os.Stdout, os.Stderr, proto, addr, tlsConfig) |
|
| 62 | 62 |
|
| 63 | 63 |
if len(args) > 0 {
|
| 64 | 64 |
method, exists := cli.getMethod(args[0]) |
| ... | ... |
@@ -2026,6 +2027,13 @@ func (cli *DockerCli) CmdLoad(args ...string) error {
|
| 2026 | 2026 |
return nil |
| 2027 | 2027 |
} |
| 2028 | 2028 |
|
| 2029 |
+func (cli *DockerCli) dial() (net.Conn, error) {
|
|
| 2030 |
+ if cli.tlsConfig != nil && cli.proto != "unix" {
|
|
| 2031 |
+ return tls.Dial(cli.proto, cli.addr, cli.tlsConfig) |
|
| 2032 |
+ } |
|
| 2033 |
+ return net.Dial(cli.proto, cli.addr) |
|
| 2034 |
+} |
|
| 2035 |
+ |
|
| 2029 | 2036 |
func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) {
|
| 2030 | 2037 |
params := bytes.NewBuffer(nil) |
| 2031 | 2038 |
if data != nil {
|
| ... | ... |
@@ -2078,7 +2086,7 @@ func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo b
|
| 2078 | 2078 |
} else if method == "POST" {
|
| 2079 | 2079 |
req.Header.Set("Content-Type", "plain/text")
|
| 2080 | 2080 |
} |
| 2081 |
- dial, err := net.Dial(cli.proto, cli.addr) |
|
| 2081 |
+ dial, err := cli.dial() |
|
| 2082 | 2082 |
if err != nil {
|
| 2083 | 2083 |
if strings.Contains(err.Error(), "connection refused") {
|
| 2084 | 2084 |
return nil, -1, ErrConnectionRefused |
| ... | ... |
@@ -2140,7 +2148,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h |
| 2140 | 2140 |
} |
| 2141 | 2141 |
} |
| 2142 | 2142 |
|
| 2143 |
- dial, err := net.Dial(cli.proto, cli.addr) |
|
| 2143 |
+ dial, err := cli.dial() |
|
| 2144 | 2144 |
if err != nil {
|
| 2145 | 2145 |
if strings.Contains(err.Error(), "connection refused") {
|
| 2146 | 2146 |
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
|
| ... | ... |
@@ -2196,7 +2204,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea |
| 2196 | 2196 |
req.Header.Set("Content-Type", "plain/text")
|
| 2197 | 2197 |
req.Host = cli.addr |
| 2198 | 2198 |
|
| 2199 |
- dial, err := net.Dial(cli.proto, cli.addr) |
|
| 2199 |
+ dial, err := cli.dial() |
|
| 2200 | 2200 |
if err != nil {
|
| 2201 | 2201 |
if strings.Contains(err.Error(), "connection refused") {
|
| 2202 | 2202 |
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
|
| ... | ... |
@@ -2388,7 +2396,7 @@ func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, err |
| 2388 | 2388 |
return body, statusCode, nil |
| 2389 | 2389 |
} |
| 2390 | 2390 |
|
| 2391 |
-func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli {
|
|
| 2391 |
+func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
|
|
| 2392 | 2392 |
var ( |
| 2393 | 2393 |
isTerminal = false |
| 2394 | 2394 |
terminalFd uintptr |
| ... | ... |
@@ -2412,6 +2420,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *Doc |
| 2412 | 2412 |
err: err, |
| 2413 | 2413 |
isTerminal: isTerminal, |
| 2414 | 2414 |
terminalFd: terminalFd, |
| 2415 |
+ tlsConfig: tlsConfig, |
|
| 2415 | 2416 |
} |
| 2416 | 2417 |
} |
| 2417 | 2418 |
|
| ... | ... |
@@ -2424,4 +2433,5 @@ type DockerCli struct {
|
| 2424 | 2424 |
err io.Writer |
| 2425 | 2425 |
isTerminal bool |
| 2426 | 2426 |
terminalFd uintptr |
| 2427 |
+ tlsConfig *tls.Config |
|
| 2427 | 2428 |
} |
| ... | ... |
@@ -4,6 +4,8 @@ import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"bytes" |
| 6 | 6 |
"code.google.com/p/go.net/websocket" |
| 7 |
+ "crypto/tls" |
|
| 8 |
+ "crypto/x509" |
|
| 7 | 9 |
"encoding/base64" |
| 8 | 10 |
"encoding/json" |
| 9 | 11 |
"expvar" |
| ... | ... |
@@ -1129,9 +1131,8 @@ func changeGroup(addr string, nameOrGid string) error {
|
| 1129 | 1129 |
|
| 1130 | 1130 |
// ListenAndServe sets up the required http.Server and gets it listening for |
| 1131 | 1131 |
// each addr passed in and does protocol specific checking. |
| 1132 |
-func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string, socketGroup string) error {
|
|
| 1133 |
- r, err := createRouter(eng, logging, enableCors, dockerVersion) |
|
| 1134 |
- |
|
| 1132 |
+func ListenAndServe(proto, addr string, job *engine.Job) error {
|
|
| 1133 |
+ r, err := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
|
|
| 1135 | 1134 |
if err != nil {
|
| 1136 | 1135 |
return err |
| 1137 | 1136 |
} |
| ... | ... |
@@ -1151,17 +1152,43 @@ func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors |
| 1151 | 1151 |
return err |
| 1152 | 1152 |
} |
| 1153 | 1153 |
|
| 1154 |
+ if proto != "unix" && (job.GetenvBool("Tls") || job.GetenvBool("TlsVerify")) {
|
|
| 1155 |
+ tlsCert := job.Getenv("TlsCert")
|
|
| 1156 |
+ tlsKey := job.Getenv("TlsKey")
|
|
| 1157 |
+ cert, err := tls.LoadX509KeyPair(tlsCert, tlsKey) |
|
| 1158 |
+ if err != nil {
|
|
| 1159 |
+ return fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?",
|
|
| 1160 |
+ tlsCert, tlsKey, err) |
|
| 1161 |
+ } |
|
| 1162 |
+ tlsConfig := &tls.Config{
|
|
| 1163 |
+ NextProtos: []string{"http/1.1"},
|
|
| 1164 |
+ Certificates: []tls.Certificate{cert},
|
|
| 1165 |
+ } |
|
| 1166 |
+ if job.GetenvBool("TlsVerify") {
|
|
| 1167 |
+ certPool := x509.NewCertPool() |
|
| 1168 |
+ file, err := ioutil.ReadFile(job.Getenv("TlsCa"))
|
|
| 1169 |
+ if err != nil {
|
|
| 1170 |
+ return fmt.Errorf("Couldn't read CA certificate: %s", err)
|
|
| 1171 |
+ } |
|
| 1172 |
+ certPool.AppendCertsFromPEM(file) |
|
| 1173 |
+ |
|
| 1174 |
+ tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert |
|
| 1175 |
+ tlsConfig.ClientCAs = certPool |
|
| 1176 |
+ } |
|
| 1177 |
+ l = tls.NewListener(l, tlsConfig) |
|
| 1178 |
+ } |
|
| 1179 |
+ |
|
| 1154 | 1180 |
// Basic error and sanity checking |
| 1155 | 1181 |
switch proto {
|
| 1156 | 1182 |
case "tcp": |
| 1157 |
- if !strings.HasPrefix(addr, "127.0.0.1") {
|
|
| 1183 |
+ if !strings.HasPrefix(addr, "127.0.0.1") && !job.GetenvBool("TlsVerify") {
|
|
| 1158 | 1184 |
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
| 1159 | 1185 |
} |
| 1160 | 1186 |
case "unix": |
| 1161 | 1187 |
if err := os.Chmod(addr, 0660); err != nil {
|
| 1162 | 1188 |
return err |
| 1163 | 1189 |
} |
| 1164 |
- |
|
| 1190 |
+ socketGroup := job.Getenv("SocketGroup")
|
|
| 1165 | 1191 |
if socketGroup != "" {
|
| 1166 | 1192 |
if err := changeGroup(addr, socketGroup); err != nil {
|
| 1167 | 1193 |
if socketGroup == "docker" {
|
| ... | ... |
@@ -1197,7 +1224,7 @@ func ServeApi(job *engine.Job) engine.Status {
|
| 1197 | 1197 |
protoAddrParts := strings.SplitN(protoAddr, "://", 2) |
| 1198 | 1198 |
go func() {
|
| 1199 | 1199 |
log.Printf("Listening for HTTP on %s (%s)\n", protoAddrParts[0], protoAddrParts[1])
|
| 1200 |
- chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"), job.Getenv("SocketGroup"))
|
|
| 1200 |
+ chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job) |
|
| 1201 | 1201 |
}() |
| 1202 | 1202 |
} |
| 1203 | 1203 |
|
| ... | ... |
@@ -70,7 +70,7 @@ func main() {
|
| 70 | 70 |
bufErr := bytes.NewBuffer(nil) |
| 71 | 71 |
|
| 72 | 72 |
// Instanciate the Docker CLI |
| 73 |
- cli := docker.NewDockerCli(nil, bufOut, bufErr, "unix", "/var/run/docker.sock") |
|
| 73 |
+ cli := docker.NewDockerCli(nil, bufOut, bufErr, "unix", "/var/run/docker.sock", false, nil) |
|
| 74 | 74 |
// Retrieve the container info |
| 75 | 75 |
if err := cli.CmdInspect(flag.Arg(0)); err != nil {
|
| 76 | 76 |
// As of docker v0.6.3, CmdInspect always returns nil |
| ... | ... |
@@ -1,7 +1,10 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "crypto/tls" |
|
| 5 |
+ "crypto/x509" |
|
| 4 | 6 |
"fmt" |
| 7 |
+ "io/ioutil" |
|
| 5 | 8 |
"log" |
| 6 | 9 |
"os" |
| 7 | 10 |
"strings" |
| ... | ... |
@@ -16,6 +19,16 @@ import ( |
| 16 | 16 |
"github.com/dotcloud/docker/utils" |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 |
+const ( |
|
| 20 |
+ defaultCaFile = "ca.pem" |
|
| 21 |
+ defaultKeyFile = "key.pem" |
|
| 22 |
+ defaultCertFile = "cert.pem" |
|
| 23 |
+) |
|
| 24 |
+ |
|
| 25 |
+var ( |
|
| 26 |
+ dockerConfDir = os.Getenv("HOME") + "/.docker/"
|
|
| 27 |
+) |
|
| 28 |
+ |
|
| 19 | 29 |
func main() {
|
| 20 | 30 |
if selfPath := utils.SelfPath(); strings.Contains(selfPath, ".dockerinit") {
|
| 21 | 31 |
// Running in init mode |
| ... | ... |
@@ -43,6 +56,11 @@ func main() {
|
| 43 | 43 |
flExecDriver = flag.String([]string{"e", "-exec-driver"}, "native", "Force the docker runtime to use a specific exec driver")
|
| 44 | 44 |
flHosts = opts.NewListOpts(api.ValidateHost) |
| 45 | 45 |
flMtu = flag.Int([]string{"#mtu", "-mtu"}, 0, "Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available")
|
| 46 |
+ flTls = flag.Bool([]string{"-tls"}, false, "Use TLS; implied by tls-verify flags")
|
|
| 47 |
+ flTlsVerify = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)")
|
|
| 48 |
+ flCa = flag.String([]string{"-tlscacert"}, dockerConfDir+defaultCaFile, "Trust only remotes providing a certificate signed by the CA given here")
|
|
| 49 |
+ flCert = flag.String([]string{"-tlscert"}, dockerConfDir+defaultCertFile, "Path to TLS certificate file")
|
|
| 50 |
+ flKey = flag.String([]string{"-tlskey"}, dockerConfDir+defaultKeyFile, "Path to TLS key file")
|
|
| 46 | 51 |
) |
| 47 | 52 |
flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers")
|
| 48 | 53 |
flag.Var(&flHosts, []string{"H", "-host"}, "tcp://host:port, unix://path/to/socket, fd://* or fd://socketfd to use in daemon mode. Multiple sockets can be specified")
|
| ... | ... |
@@ -73,6 +91,7 @@ func main() {
|
| 73 | 73 |
if *flDebug {
|
| 74 | 74 |
os.Setenv("DEBUG", "1")
|
| 75 | 75 |
} |
| 76 |
+ |
|
| 76 | 77 |
if *flDaemon {
|
| 77 | 78 |
if flag.NArg() != 0 {
|
| 78 | 79 |
flag.Usage() |
| ... | ... |
@@ -140,6 +159,12 @@ func main() {
|
| 140 | 140 |
job.SetenvBool("EnableCors", *flEnableCors)
|
| 141 | 141 |
job.Setenv("Version", dockerversion.VERSION)
|
| 142 | 142 |
job.Setenv("SocketGroup", *flSocketGroup)
|
| 143 |
+ |
|
| 144 |
+ job.SetenvBool("Tls", *flTls)
|
|
| 145 |
+ job.SetenvBool("TlsVerify", *flTlsVerify)
|
|
| 146 |
+ job.Setenv("TlsCa", *flCa)
|
|
| 147 |
+ job.Setenv("TlsCert", *flCert)
|
|
| 148 |
+ job.Setenv("TlsKey", *flKey)
|
|
| 143 | 149 |
if err := job.Run(); err != nil {
|
| 144 | 150 |
log.Fatal(err) |
| 145 | 151 |
} |
| ... | ... |
@@ -148,14 +173,53 @@ func main() {
|
| 148 | 148 |
log.Fatal("Please specify only one -H")
|
| 149 | 149 |
} |
| 150 | 150 |
protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2) |
| 151 |
- if err := api.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
|
|
| 152 |
- if sterr, ok := err.(*utils.StatusError); ok {
|
|
| 151 |
+ |
|
| 152 |
+ var ( |
|
| 153 |
+ errc error |
|
| 154 |
+ tlsConfig tls.Config |
|
| 155 |
+ ) |
|
| 156 |
+ tlsConfig.InsecureSkipVerify = true |
|
| 157 |
+ |
|
| 158 |
+ // If we should verify the server, we need to load a trusted ca |
|
| 159 |
+ if *flTlsVerify {
|
|
| 160 |
+ *flTls = true |
|
| 161 |
+ certPool := x509.NewCertPool() |
|
| 162 |
+ file, err := ioutil.ReadFile(*flCa) |
|
| 163 |
+ if err != nil {
|
|
| 164 |
+ log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err)
|
|
| 165 |
+ } |
|
| 166 |
+ certPool.AppendCertsFromPEM(file) |
|
| 167 |
+ tlsConfig.RootCAs = certPool |
|
| 168 |
+ tlsConfig.InsecureSkipVerify = false |
|
| 169 |
+ } |
|
| 170 |
+ |
|
| 171 |
+ // If tls is enabled, try to load and send client certificates |
|
| 172 |
+ if *flTls || *flTlsVerify {
|
|
| 173 |
+ _, errCert := os.Stat(*flCert) |
|
| 174 |
+ _, errKey := os.Stat(*flKey) |
|
| 175 |
+ if errCert == nil && errKey == nil {
|
|
| 176 |
+ *flTls = true |
|
| 177 |
+ cert, err := tls.LoadX509KeyPair(*flCert, *flKey) |
|
| 178 |
+ if err != nil {
|
|
| 179 |
+ log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err)
|
|
| 180 |
+ } |
|
| 181 |
+ tlsConfig.Certificates = []tls.Certificate{cert}
|
|
| 182 |
+ } |
|
| 183 |
+ } |
|
| 184 |
+ |
|
| 185 |
+ if *flTls || *flTlsVerify {
|
|
| 186 |
+ errc = api.ParseCommands(protoAddrParts[0], protoAddrParts[1], &tlsConfig, flag.Args()...) |
|
| 187 |
+ } else {
|
|
| 188 |
+ errc = api.ParseCommands(protoAddrParts[0], protoAddrParts[1], nil, flag.Args()...) |
|
| 189 |
+ } |
|
| 190 |
+ if errc != nil {
|
|
| 191 |
+ if sterr, ok := errc.(*utils.StatusError); ok {
|
|
| 153 | 192 |
if sterr.Status != "" {
|
| 154 | 193 |
log.Println(sterr.Status) |
| 155 | 194 |
} |
| 156 | 195 |
os.Exit(sterr.StatusCode) |
| 157 | 196 |
} |
| 158 |
- log.Fatal(err) |
|
| 197 |
+ log.Fatal(errc) |
|
| 159 | 198 |
} |
| 160 | 199 |
} |
| 161 | 200 |
} |
| 162 | 201 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,126 @@ |
| 0 |
+:title: Docker HTTPS Setup |
|
| 1 |
+:description: How to setup docker with https |
|
| 2 |
+:keywords: docker, example, https, daemon |
|
| 3 |
+ |
|
| 4 |
+.. _running_docker_https: |
|
| 5 |
+ |
|
| 6 |
+Running Docker with https |
|
| 7 |
+========================= |
|
| 8 |
+ |
|
| 9 |
+By default, Docker runs via a non-networked Unix socket. It can also optionally |
|
| 10 |
+communicate using a HTTP socket. |
|
| 11 |
+ |
|
| 12 |
+If you need Docker reachable via the network in a safe manner, you can enable |
|
| 13 |
+TLS by specifying the `tlsverify` flag and pointing Docker's `tlscacert` flag to a |
|
| 14 |
+trusted CA certificate. |
|
| 15 |
+ |
|
| 16 |
+In daemon mode, it will only allow connections from clients authenticated by a |
|
| 17 |
+certificate signed by that CA. In client mode, it will only connect to servers |
|
| 18 |
+with a certificate signed by that CA. |
|
| 19 |
+ |
|
| 20 |
+.. warning:: |
|
| 21 |
+ |
|
| 22 |
+ Using TLS and managing a CA is an advanced topic. Please make you self familiar |
|
| 23 |
+ with openssl, x509 and tls before using it in production. |
|
| 24 |
+ |
|
| 25 |
+Create a CA, server and client keys with OpenSSL |
|
| 26 |
+------------------------------------------------ |
|
| 27 |
+ |
|
| 28 |
+First, initialize the CA serial file and generate CA private and public keys: |
|
| 29 |
+ |
|
| 30 |
+.. code-block:: bash |
|
| 31 |
+ |
|
| 32 |
+ $ echo 01 > ca.srl |
|
| 33 |
+ $ openssl genrsa -des3 -out ca-key.pem |
|
| 34 |
+ $ openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem |
|
| 35 |
+ |
|
| 36 |
+Now that we have a CA, you can create a server key and certificate signing request. |
|
| 37 |
+Make sure that `"Common Name (e.g. server FQDN or YOUR name)"` matches the hostname you will use |
|
| 38 |
+to connect to Docker or just use '*' for a certificate valid for any hostname: |
|
| 39 |
+ |
|
| 40 |
+.. code-block:: bash |
|
| 41 |
+ |
|
| 42 |
+ $ openssl genrsa -des3 -out server-key.pem |
|
| 43 |
+ $ openssl req -new -key server-key.pem -out server.csr |
|
| 44 |
+ |
|
| 45 |
+Next we're going to sign the key with our CA: |
|
| 46 |
+ |
|
| 47 |
+.. code-block:: bash |
|
| 48 |
+ |
|
| 49 |
+ $ openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem \ |
|
| 50 |
+ -out server-cert.pem |
|
| 51 |
+ |
|
| 52 |
+For client authentication, create a client key and certificate signing request: |
|
| 53 |
+ |
|
| 54 |
+.. code-block:: bash |
|
| 55 |
+ |
|
| 56 |
+ $ openssl genrsa -des3 -out client-key.pem |
|
| 57 |
+ $ openssl req -new -key client-key.pem -out client.csr |
|
| 58 |
+ |
|
| 59 |
+ |
|
| 60 |
+To make the key suitable for client authentication, create a extensions config file: |
|
| 61 |
+ |
|
| 62 |
+.. code-block:: bash |
|
| 63 |
+ |
|
| 64 |
+ $ echo extendedKeyUsage = clientAuth > extfile.cnf |
|
| 65 |
+ |
|
| 66 |
+Now sign the key: |
|
| 67 |
+ |
|
| 68 |
+.. code-block:: bash |
|
| 69 |
+ |
|
| 70 |
+ $ openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem \ |
|
| 71 |
+ -out client-cert.pem -extfile extfile.cnf |
|
| 72 |
+ |
|
| 73 |
+Finally you need to remove the passphrase from the client and server key: |
|
| 74 |
+ |
|
| 75 |
+.. code-block:: bash |
|
| 76 |
+ |
|
| 77 |
+ $ openssl rsa -in server-key.pem -out server-key.pem |
|
| 78 |
+ $ openssl rsa -in client-key.pem -out client-key.pem |
|
| 79 |
+ |
|
| 80 |
+Now you can make the Docker daemon only accept connections from clients providing |
|
| 81 |
+a certificate trusted by our CA: |
|
| 82 |
+ |
|
| 83 |
+.. code-block:: bash |
|
| 84 |
+ |
|
| 85 |
+ $ sudo docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem \ |
|
| 86 |
+ -H=0.0.0.0:4243 |
|
| 87 |
+ |
|
| 88 |
+To be able to connect to Docker and validate its certificate, you now need to provide your client keys, |
|
| 89 |
+certificates and trusted CA: |
|
| 90 |
+ |
|
| 91 |
+.. code-block:: bash |
|
| 92 |
+ |
|
| 93 |
+ $ docker --tlsverify --tlscacert=ca.pem --tlscert=client-cert.pem --tlskey=client-key.pem \ |
|
| 94 |
+ -H=dns-name-of-docker-host:4243 |
|
| 95 |
+ |
|
| 96 |
+.. warning:: |
|
| 97 |
+ |
|
| 98 |
+ As shown in the example above, you don't have to run the ``docker`` |
|
| 99 |
+ client with ``sudo`` or the ``docker`` group when you use |
|
| 100 |
+ certificate authentication. That means anyone with the keys can |
|
| 101 |
+ give any instructions to your Docker daemon, giving them root |
|
| 102 |
+ access to the machine hosting the daemon. Guard these keys as you |
|
| 103 |
+ would a root password! |
|
| 104 |
+ |
|
| 105 |
+Other modes |
|
| 106 |
+----------- |
|
| 107 |
+If you don't want to have complete two-way authentication, you can run Docker in |
|
| 108 |
+various other modes by mixing the flags. |
|
| 109 |
+ |
|
| 110 |
+Daemon modes |
|
| 111 |
+~~~~~~~~~~~~ |
|
| 112 |
+- tlsverify, tlscacert, tlscert, tlskey set: Authenticate clients |
|
| 113 |
+- tls, tlscert, tlskey: Do not authenticate clients |
|
| 114 |
+ |
|
| 115 |
+Client modes |
|
| 116 |
+~~~~~~~~~~~~ |
|
| 117 |
+- tls: Authenticate server based on public/default CA pool |
|
| 118 |
+- tlsverify, tlscacert: Authenticate server based on given CA |
|
| 119 |
+- tls, tlscert, tlskey: Authenticate with client certificate, do not authenticate |
|
| 120 |
+ server based on given CA |
|
| 121 |
+- tlsverify, tlscacert, tlscert, tlskey: Authenticate with client certificate, |
|
| 122 |
+ authenticate server based on given CA |
|
| 123 |
+ |
|
| 124 |
+The client will send its client certificate if found, so you just need to drop |
|
| 125 |
+your keys into `~/.docker/<ca, cert or key>.pem` |
| ... | ... |
@@ -86,6 +86,11 @@ Commands |
| 86 | 86 |
-s, --storage-driver="": Force the docker runtime to use a specific storage driver |
| 87 | 87 |
-e, --exec-driver="native": Force the docker runtime to use a specific exec driver |
| 88 | 88 |
-v, --version=false: Print version information and quit |
| 89 |
+ --tls=false: Use TLS; implied by tls-verify flags |
|
| 90 |
+ --tlscacert="~/.docker/ca.pem": Trust only remotes providing a certificate signed by the CA given here |
|
| 91 |
+ --tlscert="~/.docker/cert.pem": Path to TLS certificate file |
|
| 92 |
+ --tlskey="~/.docker/key.pem": Path to TLS key file |
|
| 93 |
+ --tlsverify=false: Use TLS and verify the remote (daemon: verify client, client: verify daemon) |
|
| 89 | 94 |
--mtu=0: Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available |
| 90 | 95 |
|
| 91 | 96 |
The Docker daemon is the persistent process that manages containers. Docker uses the same binary for both the |
| ... | ... |
@@ -120,7 +120,7 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error |
| 120 | 120 |
func TestRunHostname(t *testing.T) {
|
| 121 | 121 |
stdout, stdoutPipe := io.Pipe() |
| 122 | 122 |
|
| 123 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 123 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 124 | 124 |
defer cleanup(globalEngine, t) |
| 125 | 125 |
|
| 126 | 126 |
c := make(chan struct{})
|
| ... | ... |
@@ -165,7 +165,7 @@ func TestRunHostname(t *testing.T) {
|
| 165 | 165 |
func TestRunWorkdir(t *testing.T) {
|
| 166 | 166 |
stdout, stdoutPipe := io.Pipe() |
| 167 | 167 |
|
| 168 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 168 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 169 | 169 |
defer cleanup(globalEngine, t) |
| 170 | 170 |
|
| 171 | 171 |
c := make(chan struct{})
|
| ... | ... |
@@ -210,7 +210,7 @@ func TestRunWorkdir(t *testing.T) {
|
| 210 | 210 |
func TestRunWorkdirExists(t *testing.T) {
|
| 211 | 211 |
stdout, stdoutPipe := io.Pipe() |
| 212 | 212 |
|
| 213 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 213 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 214 | 214 |
defer cleanup(globalEngine, t) |
| 215 | 215 |
|
| 216 | 216 |
c := make(chan struct{})
|
| ... | ... |
@@ -255,7 +255,7 @@ func TestRunExit(t *testing.T) {
|
| 255 | 255 |
stdin, stdinPipe := io.Pipe() |
| 256 | 256 |
stdout, stdoutPipe := io.Pipe() |
| 257 | 257 |
|
| 258 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 258 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 259 | 259 |
defer cleanup(globalEngine, t) |
| 260 | 260 |
|
| 261 | 261 |
c1 := make(chan struct{})
|
| ... | ... |
@@ -308,7 +308,7 @@ func TestRunDisconnect(t *testing.T) {
|
| 308 | 308 |
stdin, stdinPipe := io.Pipe() |
| 309 | 309 |
stdout, stdoutPipe := io.Pipe() |
| 310 | 310 |
|
| 311 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 311 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 312 | 312 |
defer cleanup(globalEngine, t) |
| 313 | 313 |
|
| 314 | 314 |
c1 := make(chan struct{})
|
| ... | ... |
@@ -354,7 +354,7 @@ func TestRunDisconnectTty(t *testing.T) {
|
| 354 | 354 |
stdin, stdinPipe := io.Pipe() |
| 355 | 355 |
stdout, stdoutPipe := io.Pipe() |
| 356 | 356 |
|
| 357 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 357 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 358 | 358 |
defer cleanup(globalEngine, t) |
| 359 | 359 |
|
| 360 | 360 |
c1 := make(chan struct{})
|
| ... | ... |
@@ -406,7 +406,7 @@ func TestRunAttachStdin(t *testing.T) {
|
| 406 | 406 |
stdin, stdinPipe := io.Pipe() |
| 407 | 407 |
stdout, stdoutPipe := io.Pipe() |
| 408 | 408 |
|
| 409 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 409 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 410 | 410 |
defer cleanup(globalEngine, t) |
| 411 | 411 |
|
| 412 | 412 |
ch := make(chan struct{})
|
| ... | ... |
@@ -470,7 +470,7 @@ func TestRunDetach(t *testing.T) {
|
| 470 | 470 |
stdin, stdinPipe := io.Pipe() |
| 471 | 471 |
stdout, stdoutPipe := io.Pipe() |
| 472 | 472 |
|
| 473 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 473 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 474 | 474 |
defer cleanup(globalEngine, t) |
| 475 | 475 |
|
| 476 | 476 |
ch := make(chan struct{})
|
| ... | ... |
@@ -517,7 +517,7 @@ func TestAttachDetach(t *testing.T) {
|
| 517 | 517 |
stdin, stdinPipe := io.Pipe() |
| 518 | 518 |
stdout, stdoutPipe := io.Pipe() |
| 519 | 519 |
|
| 520 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 520 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 521 | 521 |
defer cleanup(globalEngine, t) |
| 522 | 522 |
|
| 523 | 523 |
ch := make(chan struct{})
|
| ... | ... |
@@ -550,7 +550,7 @@ func TestAttachDetach(t *testing.T) {
|
| 550 | 550 |
|
| 551 | 551 |
stdin, stdinPipe = io.Pipe() |
| 552 | 552 |
stdout, stdoutPipe = io.Pipe() |
| 553 |
- cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 553 |
+ cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 554 | 554 |
|
| 555 | 555 |
ch = make(chan struct{})
|
| 556 | 556 |
go func() {
|
| ... | ... |
@@ -598,7 +598,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
|
| 598 | 598 |
stdin, stdinPipe := io.Pipe() |
| 599 | 599 |
stdout, stdoutPipe := io.Pipe() |
| 600 | 600 |
|
| 601 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 601 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 602 | 602 |
defer cleanup(globalEngine, t) |
| 603 | 603 |
|
| 604 | 604 |
// Discard the CmdRun output |
| ... | ... |
@@ -616,7 +616,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
|
| 616 | 616 |
|
| 617 | 617 |
stdin, stdinPipe = io.Pipe() |
| 618 | 618 |
stdout, stdoutPipe = io.Pipe() |
| 619 |
- cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 619 |
+ cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 620 | 620 |
|
| 621 | 621 |
ch := make(chan struct{})
|
| 622 | 622 |
go func() {
|
| ... | ... |
@@ -663,7 +663,7 @@ func TestAttachDisconnect(t *testing.T) {
|
| 663 | 663 |
stdin, stdinPipe := io.Pipe() |
| 664 | 664 |
stdout, stdoutPipe := io.Pipe() |
| 665 | 665 |
|
| 666 |
- cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 666 |
+ cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 667 | 667 |
defer cleanup(globalEngine, t) |
| 668 | 668 |
|
| 669 | 669 |
go func() {
|
| ... | ... |
@@ -732,7 +732,7 @@ func TestAttachDisconnect(t *testing.T) {
|
| 732 | 732 |
func TestRunAutoRemove(t *testing.T) {
|
| 733 | 733 |
t.Skip("Fixme. Skipping test for now, race condition")
|
| 734 | 734 |
stdout, stdoutPipe := io.Pipe() |
| 735 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 735 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 736 | 736 |
defer cleanup(globalEngine, t) |
| 737 | 737 |
|
| 738 | 738 |
c := make(chan struct{})
|
| ... | ... |
@@ -768,7 +768,7 @@ func TestRunAutoRemove(t *testing.T) {
|
| 768 | 768 |
|
| 769 | 769 |
func TestCmdLogs(t *testing.T) {
|
| 770 | 770 |
t.Skip("Test not impemented")
|
| 771 |
- cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 771 |
+ cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 772 | 772 |
defer cleanup(globalEngine, t) |
| 773 | 773 |
|
| 774 | 774 |
if err := cli.CmdRun(unitTestImageID, "sh", "-c", "ls -l"); err != nil {
|
| ... | ... |
@@ -786,7 +786,7 @@ func TestCmdLogs(t *testing.T) {
|
| 786 | 786 |
// Expected behaviour: error out when attempting to bind mount non-existing source paths |
| 787 | 787 |
func TestRunErrorBindNonExistingSource(t *testing.T) {
|
| 788 | 788 |
|
| 789 |
- cli := api.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 789 |
+ cli := api.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 790 | 790 |
defer cleanup(globalEngine, t) |
| 791 | 791 |
|
| 792 | 792 |
c := make(chan struct{})
|
| ... | ... |
@@ -806,7 +806,7 @@ func TestRunErrorBindNonExistingSource(t *testing.T) {
|
| 806 | 806 |
func TestImagesViz(t *testing.T) {
|
| 807 | 807 |
stdout, stdoutPipe := io.Pipe() |
| 808 | 808 |
|
| 809 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 809 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 810 | 810 |
defer cleanup(globalEngine, t) |
| 811 | 811 |
|
| 812 | 812 |
image := buildTestImages(t, globalEngine) |
| ... | ... |
@@ -856,7 +856,7 @@ func TestImagesViz(t *testing.T) {
|
| 856 | 856 |
func TestImagesTree(t *testing.T) {
|
| 857 | 857 |
stdout, stdoutPipe := io.Pipe() |
| 858 | 858 |
|
| 859 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 859 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 860 | 860 |
defer cleanup(globalEngine, t) |
| 861 | 861 |
|
| 862 | 862 |
image := buildTestImages(t, globalEngine) |
| ... | ... |
@@ -939,7 +939,7 @@ func TestRunCidFile(t *testing.T) {
|
| 939 | 939 |
} |
| 940 | 940 |
tmpCidFile := path.Join(tmpDir, "cid") |
| 941 | 941 |
|
| 942 |
- cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 942 |
+ cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 943 | 943 |
defer cleanup(globalEngine, t) |
| 944 | 944 |
|
| 945 | 945 |
c := make(chan struct{})
|
| ... | ... |
@@ -989,7 +989,7 @@ func TestContainerOrphaning(t *testing.T) {
|
| 989 | 989 |
defer os.RemoveAll(tmpDir) |
| 990 | 990 |
|
| 991 | 991 |
// setup a CLI and server |
| 992 |
- cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 992 |
+ cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 993 | 993 |
defer cleanup(globalEngine, t) |
| 994 | 994 |
srv := mkServerFromEngine(globalEngine, t) |
| 995 | 995 |
|
| ... | ... |
@@ -1049,8 +1049,8 @@ func TestCmdKill(t *testing.T) {
|
| 1049 | 1049 |
var ( |
| 1050 | 1050 |
stdin, stdinPipe = io.Pipe() |
| 1051 | 1051 |
stdout, stdoutPipe = io.Pipe() |
| 1052 |
- cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 1053 |
- cli2 = api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr) |
|
| 1052 |
+ cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 1053 |
+ cli2 = api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 1054 | 1054 |
) |
| 1055 | 1055 |
defer cleanup(globalEngine, t) |
| 1056 | 1056 |
|
| 1057 | 1057 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+-----BEGIN CERTIFICATE----- |
|
| 1 |
+MIID0TCCAzqgAwIBAgIJAP2r7GqEJwSnMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD |
|
| 2 |
+VQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMG |
|
| 3 |
+A1UEChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMI |
|
| 4 |
+Y2hhbmdlbWUxETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWls |
|
| 5 |
+QGhvc3QuZG9tYWluMB4XDTEzMTIwMzE2NTYzMFoXDTIzMTIwMTE2NTYzMFowgaIx |
|
| 6 |
+CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2Nv |
|
| 7 |
+MRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYD |
|
| 8 |
+VQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEW |
|
| 9 |
+EG1haWxAaG9zdC5kb21haW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALAn |
|
| 10 |
+0xDw+5y7ZptQacq66pUhRu82JP2WU6IDgo5QUtNU6/CX5PwQATe/OnYTZQFbksxp |
|
| 11 |
+AU9boG0FCkgxfsgPYXEuZxVEGKI2fxfKHOZZI8mrkWmj6eWU/0cvCjGVc9rTITP5 |
|
| 12 |
+sNQvg+hORyVDdNp2IdsbMJayiB3AQYMFx3vSDOMTAgMBAAGjggELMIIBBzAdBgNV |
|
| 13 |
+HQ4EFgQUZu7DFz09q0QBa2+ymRm9qgK1NPswgdcGA1UdIwSBzzCBzIAUZu7DFz09 |
|
| 14 |
+q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD |
|
| 15 |
+QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x |
|
| 16 |
+ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI |
|
| 17 |
+Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq |
|
| 18 |
+hCcEpzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAF8fJKKM+/oOdnNi |
|
| 19 |
+zEd0M1+PmZOyqvjYQn/2ZR8UHH6Imgc/OPQKZXf0bVE1Txc/DaUNn9Isd1SuCuaE |
|
| 20 |
+ic3vAIYYU7PmgeNN6vwec48V96T7jr+GAi6AVMhQEc2hHCfVtx11Xx+x6aHDZzJt |
|
| 21 |
+Zxtf5lL6KSO9Y+EFwM+rju6hm5hW |
|
| 22 |
+-----END CERTIFICATE----- |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,73 @@ |
| 0 |
+Certificate: |
|
| 1 |
+ Data: |
|
| 2 |
+ Version: 3 (0x2) |
|
| 3 |
+ Serial Number: 3 (0x3) |
|
| 4 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 5 |
+ Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 6 |
+ Validity |
|
| 7 |
+ Not Before: Dec 4 14:17:54 2013 GMT |
|
| 8 |
+ Not After : Dec 2 14:17:54 2023 GMT |
|
| 9 |
+ Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=client/name=changeme/emailAddress=mail@host.domain |
|
| 10 |
+ Subject Public Key Info: |
|
| 11 |
+ Public Key Algorithm: rsaEncryption |
|
| 12 |
+ Public-Key: (1024 bit) |
|
| 13 |
+ Modulus: |
|
| 14 |
+ 00:ca:c9:05:d0:09:4e:3e:a4:fc:d5:14:f4:a5:e8: |
|
| 15 |
+ 34:d3:6b:51:e3:f3:62:ea:a1:f0:e8:ed:c4:2a:bc: |
|
| 16 |
+ f0:4f:ca:07:df:e3:88:fa:f4:21:99:35:0e:3d:ea: |
|
| 17 |
+ b0:86:e7:c4:d2:8a:83:2b:42:b8:ec:a3:99:62:70: |
|
| 18 |
+ 81:46:cc:fc:a5:1d:d2:63:e8:eb:07:25:9a:e2:25: |
|
| 19 |
+ 6d:11:56:f2:1a:51:a1:b6:3e:1c:57:32:e9:7b:2c: |
|
| 20 |
+ aa:1b:cc:97:2d:89:2d:b1:c9:5e:35:28:4d:7c:fa: |
|
| 21 |
+ 65:31:3e:f7:70:dd:6e:0b:3c:58:af:a8:2e:24:c0: |
|
| 22 |
+ 7e:4e:78:7d:0a:9e:8f:42:43 |
|
| 23 |
+ Exponent: 65537 (0x10001) |
|
| 24 |
+ X509v3 extensions: |
|
| 25 |
+ X509v3 Basic Constraints: |
|
| 26 |
+ CA:FALSE |
|
| 27 |
+ Netscape Comment: |
|
| 28 |
+ Easy-RSA Generated Certificate |
|
| 29 |
+ X509v3 Subject Key Identifier: |
|
| 30 |
+ DE:42:EF:2D:98:A3:6C:A8:AA:E0:8C:71:2C:9D:64:23:A9:E2:7E:81 |
|
| 31 |
+ X509v3 Authority Key Identifier: |
|
| 32 |
+ keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB |
|
| 33 |
+ DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 34 |
+ serial:FD:AB:EC:6A:84:27:04:A7 |
|
| 35 |
+ |
|
| 36 |
+ X509v3 Extended Key Usage: |
|
| 37 |
+ TLS Web Client Authentication |
|
| 38 |
+ X509v3 Key Usage: |
|
| 39 |
+ Digital Signature |
|
| 40 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 41 |
+ 1c:44:26:ea:e1:66:25:cb:e4:8e:57:1c:f6:b9:17:22:62:40: |
|
| 42 |
+ 12:90:8f:3b:b2:61:7a:54:94:8f:b1:20:0b:bf:a3:51:e3:fa: |
|
| 43 |
+ 1c:a1:be:92:3a:d0:76:44:c0:57:83:ab:6a:e4:1a:45:49:a4: |
|
| 44 |
+ af:39:0d:60:32:fc:3a:be:d7:fb:5d:99:7a:1f:87:e7:d5:ab: |
|
| 45 |
+ 84:a2:5e:90:d8:bf:fa:89:6d:32:26:02:5e:31:35:68:7f:31: |
|
| 46 |
+ f5:6b:51:46:bc:af:70:ed:5a:09:7d:ec:b2:48:4f:fe:c5:2f: |
|
| 47 |
+ 56:04:ad:f6:c1:d2:2a:e4:6a:c4:87:fe:08:35:c5:38:cb:5e: |
|
| 48 |
+ 4a:c4 |
|
| 49 |
+-----BEGIN CERTIFICATE----- |
|
| 50 |
+MIIEFTCCA36gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx |
|
| 51 |
+CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv |
|
| 52 |
+cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l |
|
| 53 |
+MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv |
|
| 54 |
+bWFpbjAeFw0xMzEyMDQxNDE3NTRaFw0yMzEyMDIxNDE3NTRaMIGgMQswCQYDVQQG |
|
| 55 |
+EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE |
|
| 56 |
+ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEPMA0GA1UEAxMGY2xp |
|
| 57 |
+ZW50MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0 |
|
| 58 |
+LmRvbWFpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyskF0AlOPqT81RT0 |
|
| 59 |
+peg002tR4/Ni6qHw6O3EKrzwT8oH3+OI+vQhmTUOPeqwhufE0oqDK0K47KOZYnCB |
|
| 60 |
+Rsz8pR3SY+jrByWa4iVtEVbyGlGhtj4cVzLpeyyqG8yXLYktscleNShNfPplMT73 |
|
| 61 |
+cN1uCzxYr6guJMB+Tnh9Cp6PQkMCAwEAAaOCAVkwggFVMAkGA1UdEwQCMAAwLQYJ |
|
| 62 |
+YIZIAYb4QgENBCAWHkVhc3ktUlNBIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV |
|
| 63 |
+HQ4EFgQU3kLvLZijbKiq4IxxLJ1kI6nifoEwgdcGA1UdIwSBzzCBzIAUZu7DFz09 |
|
| 64 |
+q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD |
|
| 65 |
+QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x |
|
| 66 |
+ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI |
|
| 67 |
+Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq |
|
| 68 |
+hCcEpzATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcN |
|
| 69 |
+AQEFBQADgYEAHEQm6uFmJcvkjlcc9rkXImJAEpCPO7JhelSUj7EgC7+jUeP6HKG+ |
|
| 70 |
+kjrQdkTAV4OrauQaRUmkrzkNYDL8Or7X+12Zeh+H59WrhKJekNi/+oltMiYCXjE1 |
|
| 71 |
+aH8x9WtRRryvcO1aCX3sskhP/sUvVgSt9sHSKuRqxIf+CDXFOMteSsQ= |
|
| 72 |
+-----END CERTIFICATE----- |
| 0 | 73 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+-----BEGIN PRIVATE KEY----- |
|
| 1 |
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMrJBdAJTj6k/NUU |
|
| 2 |
+9KXoNNNrUePzYuqh8OjtxCq88E/KB9/jiPr0IZk1Dj3qsIbnxNKKgytCuOyjmWJw |
|
| 3 |
+gUbM/KUd0mPo6wclmuIlbRFW8hpRobY+HFcy6XssqhvMly2JLbHJXjUoTXz6ZTE+ |
|
| 4 |
+93Ddbgs8WK+oLiTAfk54fQqej0JDAgMBAAECgYBOFEzKp2qbMEexe9ofL2N3rDDh |
|
| 5 |
+xkrl8OijpzkLA6i78BxMFn4dsnZlWUpciMrjhsYAExkiRRSS+QMMJimAq1jzQqc3 |
|
| 6 |
+FAQV2XGYwkd0cUn7iZGvfNnEPysjsfyYQM+m+sT0ATj4BZjVShC6kkSjTdm1leLN |
|
| 7 |
+OSvcHdcu3Xxg9ufF0QJBAPYdnNt5sIndt2WECePuRVi+uF4mlxTobFY0fjn26yhC |
|
| 8 |
+4RsnhhD3Vldygo9gvnkwrAZYaALGSPBewes2InxvjA8CQQDS7erKiNXpwoqz5XiU |
|
| 9 |
+SVEsIIVTdWzBjGbIqMOu/hUwM5FK4j6JTBks0aTGMyh0YV9L1EzM0X79J29JahCe |
|
| 10 |
+iQKNAkBKNMOGqTpBV0hko1sYDk96YobUXG5RL4L6uvkUIQ7mJMQam+AgXXL7Ctuy |
|
| 11 |
+v0iu4a38e8tgisiTMP7nHHtpaXihAkAOiN54/lzfMsykANgCP9scE1GcoqbP34Dl |
|
| 12 |
+qttxH4kOPT9xzY1JoLjLYdbc4YGUI3GRpBt2sajygNkmUey7P+2xAkBBsVCZFvTw |
|
| 13 |
+qHvOpPS2kX5ml5xoc/QAHK9N7kR+X7XFYx82RTVSqJEK4lPb+aEWn+CjiIewO4Q5 |
|
| 14 |
+ksDFuNxAzbhl |
|
| 15 |
+-----END PRIVATE KEY----- |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,73 @@ |
| 0 |
+Certificate: |
|
| 1 |
+ Data: |
|
| 2 |
+ Version: 3 (0x2) |
|
| 3 |
+ Serial Number: 2 (0x2) |
|
| 4 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 5 |
+ Issuer: C=US, ST=CA, L=SanFrancisco, O=Evil Inc, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 6 |
+ Validity |
|
| 7 |
+ Not Before: Feb 24 17:54:59 2014 GMT |
|
| 8 |
+ Not After : Feb 22 17:54:59 2024 GMT |
|
| 9 |
+ Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=client/name=changeme/emailAddress=mail@host.domain |
|
| 10 |
+ Subject Public Key Info: |
|
| 11 |
+ Public Key Algorithm: rsaEncryption |
|
| 12 |
+ Public-Key: (1024 bit) |
|
| 13 |
+ Modulus: |
|
| 14 |
+ 00:e8:e2:2c:b8:d4:db:89:50:4f:47:1e:68:db:f7: |
|
| 15 |
+ e4:cc:47:41:63:75:03:37:50:7a:a8:4d:27:36:d5: |
|
| 16 |
+ 15:01:08:b6:cf:56:f7:56:6d:3d:f9:e2:8d:1a:5d: |
|
| 17 |
+ bf:a0:24:5e:07:55:8e:d0:dc:f1:fa:19:87:1d:d6: |
|
| 18 |
+ b6:58:82:2e:ba:69:6d:e9:d9:c8:16:0d:1d:59:7f: |
|
| 19 |
+ f4:8e:58:10:01:3d:21:14:16:3c:ec:cd:8c:b7:0e: |
|
| 20 |
+ e6:7b:77:b4:f9:90:a5:17:01:bb:84:c6:b2:12:87: |
|
| 21 |
+ 70:eb:9f:6d:4f:d0:68:8b:96:c0:e7:0b:51:b4:9d: |
|
| 22 |
+ 1d:7b:6c:7b:be:89:6b:88:8b |
|
| 23 |
+ Exponent: 65537 (0x10001) |
|
| 24 |
+ X509v3 extensions: |
|
| 25 |
+ X509v3 Basic Constraints: |
|
| 26 |
+ CA:FALSE |
|
| 27 |
+ Netscape Comment: |
|
| 28 |
+ Easy-RSA Generated Certificate |
|
| 29 |
+ X509v3 Subject Key Identifier: |
|
| 30 |
+ 9E:F8:49:D0:A2:76:30:5C:AB:2B:8A:B5:8D:C6:45:1F:A7:F8:CF:85 |
|
| 31 |
+ X509v3 Authority Key Identifier: |
|
| 32 |
+ keyid:DC:A5:F1:76:DB:4E:CD:8E:EF:B1:23:56:1D:92:80:99:74:3B:EA:6F |
|
| 33 |
+ DirName:/C=US/ST=CA/L=SanFrancisco/O=Evil Inc/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 34 |
+ serial:E7:21:1E:18:41:1B:96:83 |
|
| 35 |
+ |
|
| 36 |
+ X509v3 Extended Key Usage: |
|
| 37 |
+ TLS Web Client Authentication |
|
| 38 |
+ X509v3 Key Usage: |
|
| 39 |
+ Digital Signature |
|
| 40 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 41 |
+ 48:76:c0:18:fa:0a:ee:4e:1a:ec:02:9d:d4:83:ca:94:54:a1: |
|
| 42 |
+ 3f:51:2f:3e:4b:95:c3:42:9b:71:a0:4b:d9:af:47:23:b9:1c: |
|
| 43 |
+ fb:85:ba:76:e2:09:cb:65:bb:d2:7d:44:3d:4b:67:ba:80:83: |
|
| 44 |
+ be:a8:ed:c4:b9:ea:1a:1b:c7:59:3b:d9:5c:0d:46:d8:c9:92: |
|
| 45 |
+ cb:10:c5:f2:1a:38:a4:aa:07:2c:e3:84:16:79:c7:95:09:e3: |
|
| 46 |
+ 01:d2:15:a2:77:0b:8b:bf:94:04:e9:7f:c0:cd:e6:2e:64:cd: |
|
| 47 |
+ 1e:a3:32:ec:11:cc:62:ce:c7:4e:cd:ad:48:5c:b1:b8:e9:76: |
|
| 48 |
+ b3:f9 |
|
| 49 |
+-----BEGIN CERTIFICATE----- |
|
| 50 |
+MIIEDTCCA3agAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx |
|
| 51 |
+CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2 |
|
| 52 |
+aWwgSW5jMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAP |
|
| 53 |
+BgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWlu |
|
| 54 |
+MB4XDTE0MDIyNDE3NTQ1OVoXDTI0MDIyMjE3NTQ1OVowgaAxCzAJBgNVBAYTAlVT |
|
| 55 |
+MQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxG |
|
| 56 |
+b3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMQ8wDQYDVQQDEwZjbGllbnQx |
|
| 57 |
+ETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9t |
|
| 58 |
+YWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo4iy41NuJUE9HHmjb9+TM |
|
| 59 |
+R0FjdQM3UHqoTSc21RUBCLbPVvdWbT354o0aXb+gJF4HVY7Q3PH6GYcd1rZYgi66 |
|
| 60 |
+aW3p2cgWDR1Zf/SOWBABPSEUFjzszYy3DuZ7d7T5kKUXAbuExrISh3Drn21P0GiL |
|
| 61 |
+lsDnC1G0nR17bHu+iWuIiwIDAQABo4IBVTCCAVEwCQYDVR0TBAIwADAtBglghkgB |
|
| 62 |
+hvhCAQ0EIBYeRWFzeS1SU0EgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW |
|
| 63 |
+BBSe+EnQonYwXKsrirWNxkUfp/jPhTCB0wYDVR0jBIHLMIHIgBTcpfF2207Nju+x |
|
| 64 |
+I1YdkoCZdDvqb6GBpKSBoTCBnjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRUw |
|
| 65 |
+EwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2aWwgSW5jMREwDwYDVQQL |
|
| 66 |
+EwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAPBgNVBCkTCGNoYW5nZW1l |
|
| 67 |
+MR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWluggkA5yEeGEEbloMwEwYD |
|
| 68 |
+VR0lBAwwCgYIKwYBBQUHAwIwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GB |
|
| 69 |
+AEh2wBj6Cu5OGuwCndSDypRUoT9RLz5LlcNCm3GgS9mvRyO5HPuFunbiCctlu9J9 |
|
| 70 |
+RD1LZ7qAg76o7cS56hobx1k72VwNRtjJkssQxfIaOKSqByzjhBZ5x5UJ4wHSFaJ3 |
|
| 71 |
+C4u/lATpf8DN5i5kzR6jMuwRzGLOx07NrUhcsbjpdrP5 |
|
| 72 |
+-----END CERTIFICATE----- |
| 0 | 73 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+-----BEGIN PRIVATE KEY----- |
|
| 1 |
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOjiLLjU24lQT0ce |
|
| 2 |
+aNv35MxHQWN1AzdQeqhNJzbVFQEIts9W91ZtPfnijRpdv6AkXgdVjtDc8foZhx3W |
|
| 3 |
+tliCLrppbenZyBYNHVl/9I5YEAE9IRQWPOzNjLcO5nt3tPmQpRcBu4TGshKHcOuf |
|
| 4 |
+bU/QaIuWwOcLUbSdHXtse76Ja4iLAgMBAAECgYADs+TmI2xCKKa6CL++D5jxrohZ |
|
| 5 |
+nnionnz0xBVFh+nHlG3jqgxQsXf0yydXLfpn/2wHTdLxezHVuiYt0UYg7iD0CglW |
|
| 6 |
++IjcgMebzyjLeYqYOE5llPlMvhp2HoEMYJNb+7bRrZ1WCITbu+Su0w1cgA7Cs+Ej |
|
| 7 |
+VlfvGzN+qqnDThRUYQJBAPY0sMWZJKly8QhUmUvmcXdPczzSOf6Mm7gc5LR6wzxd |
|
| 8 |
+vW7syuqk50qjqVqFpN81vCV7GoDxRUWbTM9ftf7JGFkCQQDyJc/1RMygE2o+enU1 |
|
| 9 |
+6UBxJyclXITEYtDn8aoEpLNc7RakP1WoPUKjZOnjkcoKcIkFNkSPeCfQujrb5f3F |
|
| 10 |
+MkuDAkByAI/hzzmkpK5rFxEsjfX4Mve/L/DepyjrpaVY1IdWimlO1aJX6CeY7hNa |
|
| 11 |
+8QsYt/74s/nfvtg+lNyKIV1aLq9xAkB+WSSNgfyTeg3x08vc+Xxajmdqoz/TiQwg |
|
| 12 |
+OoTQL3A3iK5LvZBgXLasszcnOycFE3srcQmNItEDpGiZ3QPxJTEpAkEA45EE9NMJ |
|
| 13 |
+SA7EGWSFlbz4f4u4oBeiDiJRJbGGfAyVxZlpCWUjPpg9+swsWoFEOjnGYaChAMk5 |
|
| 14 |
+nrOdMf15T6QF7Q== |
|
| 15 |
+-----END PRIVATE KEY----- |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,76 @@ |
| 0 |
+Certificate: |
|
| 1 |
+ Data: |
|
| 2 |
+ Version: 3 (0x2) |
|
| 3 |
+ Serial Number: 4 (0x4) |
|
| 4 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 5 |
+ Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 6 |
+ Validity |
|
| 7 |
+ Not Before: Dec 4 15:01:20 2013 GMT |
|
| 8 |
+ Not After : Dec 2 15:01:20 2023 GMT |
|
| 9 |
+ Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=*/name=changeme/emailAddress=mail@host.domain |
|
| 10 |
+ Subject Public Key Info: |
|
| 11 |
+ Public Key Algorithm: rsaEncryption |
|
| 12 |
+ Public-Key: (1024 bit) |
|
| 13 |
+ Modulus: |
|
| 14 |
+ 00:c1:ff:7d:30:6f:64:4a:b1:92:b1:71:d1:c1:74: |
|
| 15 |
+ e2:1d:db:2d:11:24:e1:00:d4:00:ae:6f:c8:9e:ae: |
|
| 16 |
+ 67:b3:4a:bd:f7:e6:9e:57:6d:19:4c:3c:23:94:2d: |
|
| 17 |
+ 3d:d6:63:84:d8:fa:76:2b:38:12:c1:ed:20:9d:32: |
|
| 18 |
+ e0:e8:c2:bf:9a:77:70:04:3f:7f:ca:8c:2c:82:d6: |
|
| 19 |
+ 3d:25:5c:02:1a:4f:64:93:03:dd:9c:42:97:5e:09: |
|
| 20 |
+ 49:af:f0:c2:e1:30:08:0e:21:46:95:d1:13:59:c0: |
|
| 21 |
+ c8:76:be:94:0d:8b:43:67:21:33:b2:08:60:9d:76: |
|
| 22 |
+ a8:05:32:1e:f9:95:09:14:75 |
|
| 23 |
+ Exponent: 65537 (0x10001) |
|
| 24 |
+ X509v3 extensions: |
|
| 25 |
+ X509v3 Basic Constraints: |
|
| 26 |
+ CA:FALSE |
|
| 27 |
+ Netscape Cert Type: |
|
| 28 |
+ SSL Server |
|
| 29 |
+ Netscape Comment: |
|
| 30 |
+ Easy-RSA Generated Server Certificate |
|
| 31 |
+ X509v3 Subject Key Identifier: |
|
| 32 |
+ 14:02:FD:FD:DD:13:38:E0:71:EA:D1:BE:C0:0E:89:1A:2D:B6:19:06 |
|
| 33 |
+ X509v3 Authority Key Identifier: |
|
| 34 |
+ keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB |
|
| 35 |
+ DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 36 |
+ serial:FD:AB:EC:6A:84:27:04:A7 |
|
| 37 |
+ |
|
| 38 |
+ X509v3 Extended Key Usage: |
|
| 39 |
+ TLS Web Server Authentication |
|
| 40 |
+ X509v3 Key Usage: |
|
| 41 |
+ Digital Signature, Key Encipherment |
|
| 42 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 43 |
+ 40:0f:10:39:c4:b7:0f:0d:2f:bf:d2:16:cc:8e:d3:9a:fb:8b: |
|
| 44 |
+ ce:4b:7b:0d:48:77:ce:f1:fe:d5:8f:ea:b1:71:ed:49:1d:9f: |
|
| 45 |
+ 23:3a:16:d4:70:7c:c5:29:bf:e4:90:34:d0:f0:00:24:f4:e4: |
|
| 46 |
+ df:2c:c3:83:01:66:61:c9:a8:ab:29:e7:98:6d:27:89:4a:76: |
|
| 47 |
+ c9:2e:19:8e:fe:6e:d5:f8:99:11:0e:97:67:4b:34:e3:1e:e3: |
|
| 48 |
+ 9f:35:00:a5:32:f9:b5:2c:f2:e0:c5:2e:cc:81:bd:18:dd:5c: |
|
| 49 |
+ 12:c8:6b:fa:0c:17:74:30:55:f6:6e:20:9a:6c:1e:09:b4:0c: |
|
| 50 |
+ 15:42 |
|
| 51 |
+-----BEGIN CERTIFICATE----- |
|
| 52 |
+MIIEKjCCA5OgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx |
|
| 53 |
+CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv |
|
| 54 |
+cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l |
|
| 55 |
+MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv |
|
| 56 |
+bWFpbjAeFw0xMzEyMDQxNTAxMjBaFw0yMzEyMDIxNTAxMjBaMIGbMQswCQYDVQQG |
|
| 57 |
+EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE |
|
| 58 |
+ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEKMAgGA1UEAxQBKjER |
|
| 59 |
+MA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21h |
|
| 60 |
+aW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMH/fTBvZEqxkrFx0cF04h3b |
|
| 61 |
+LREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y4OjCv5p3 |
|
| 62 |
+cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+lA2LQ2ch |
|
| 63 |
+M7IIYJ12qAUyHvmVCRR1AgMBAAGjggFzMIIBbzAJBgNVHRMEAjAAMBEGCWCGSAGG |
|
| 64 |
++EIBAQQEAwIGQDA0BglghkgBhvhCAQ0EJxYlRWFzeS1SU0EgR2VuZXJhdGVkIFNl |
|
| 65 |
+cnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUFAL9/d0TOOBx6tG+wA6JGi22GQYw |
|
| 66 |
+gdcGA1UdIwSBzzCBzIAUZu7DFz09q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJ |
|
| 67 |
+BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUw |
|
| 68 |
+EwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQD |
|
| 69 |
+EwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1h |
|
| 70 |
+aWxAaG9zdC5kb21haW6CCQD9q+xqhCcEpzATBgNVHSUEDDAKBggrBgEFBQcDATAL |
|
| 71 |
+BgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEAQA8QOcS3Dw0vv9IWzI7TmvuL |
|
| 72 |
+zkt7DUh3zvH+1Y/qsXHtSR2fIzoW1HB8xSm/5JA00PAAJPTk3yzDgwFmYcmoqynn |
|
| 73 |
+mG0niUp2yS4Zjv5u1fiZEQ6XZ0s04x7jnzUApTL5tSzy4MUuzIG9GN1cEshr+gwX |
|
| 74 |
+dDBV9m4gmmweCbQMFUI= |
|
| 75 |
+-----END CERTIFICATE----- |
| 0 | 76 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+-----BEGIN PRIVATE KEY----- |
|
| 1 |
+MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMH/fTBvZEqxkrFx |
|
| 2 |
+0cF04h3bLREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y |
|
| 3 |
+4OjCv5p3cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+ |
|
| 4 |
+lA2LQ2chM7IIYJ12qAUyHvmVCRR1AgMBAAECgYAmwckb9RUfSwyYgLm8IYLPHiuJ |
|
| 5 |
+wkllZfVg5Bo7gXJcQnFjZmJ56uTj8xvUjZlODIHM63TSO5ibv6kFXtXKCqZGd2M+ |
|
| 6 |
+wGbhZ0f+2GvKcwMmJERnIQjuoNaYSQLT0tM0VB9Iz0rJlZC+tzPZ+5pPqEumRdsS |
|
| 7 |
+IzWNXfF42AhcbwAQYQJBAPVXtMYIJc9EZsz86ZcQiMPWUpCX5vnRmtwL8kKyR8D5 |
|
| 8 |
+4KfYeiowyFffSRMMcclwNHq7TgSXN+nIXM9WyzyzwikCQQDKbNA28AgZp9aT54HP |
|
| 9 |
+WnbeE2pmt+uk/zl/BtxJSoK6H+69Jec+lf7EgL7HgOWYRSNot4uQWu8IhsHLTiUq |
|
| 10 |
++0FtAkEAqwlRxRy4/x24bP+D+QRV0/D97j93joFJbE4Hved7jlSlAV4xDGilwlyv |
|
| 11 |
+HNB4Iu5OJ6Gcaibhm+FKkmD3noHSwQJBAIpu3fokLzX0bS+bDFBU6qO3HXX/47xj |
|
| 12 |
++tsfQvkwZrSI8AkU6c8IX0HdVhsz0FBRQAT2ORDQz1XCarfxykNZrwUCQQCGCBIc |
|
| 13 |
+BBCWzhHlswlGidWJg3HqqO6hPPClEr3B5G87oCsdeYwiO23XT6rUnoJXfJHp6oCW |
|
| 14 |
+5nCwDu5ZTP+khltg |
|
| 15 |
+-----END PRIVATE KEY----- |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,76 @@ |
| 0 |
+Certificate: |
|
| 1 |
+ Data: |
|
| 2 |
+ Version: 3 (0x2) |
|
| 3 |
+ Serial Number: 3 (0x3) |
|
| 4 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 5 |
+ Issuer: C=US, ST=CA, L=SanFrancisco, O=Evil Inc, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 6 |
+ Validity |
|
| 7 |
+ Not Before: Feb 28 18:49:31 2014 GMT |
|
| 8 |
+ Not After : Feb 26 18:49:31 2024 GMT |
|
| 9 |
+ Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=localhost/name=changeme/emailAddress=mail@host.domain |
|
| 10 |
+ Subject Public Key Info: |
|
| 11 |
+ Public Key Algorithm: rsaEncryption |
|
| 12 |
+ Public-Key: (1024 bit) |
|
| 13 |
+ Modulus: |
|
| 14 |
+ 00:d1:08:58:24:60:a1:69:65:4b:76:46:8f:88:75: |
|
| 15 |
+ 7c:49:3a:d8:03:cc:5b:58:c5:d1:bb:e5:f9:54:b9: |
|
| 16 |
+ 75:65:df:7e:bb:fb:54:d4:b2:e9:6f:58:a2:a4:84: |
|
| 17 |
+ 43:94:77:24:81:38:36:36:f0:66:65:26:e5:5b:2a: |
|
| 18 |
+ 14:1c:a9:ae:57:7f:75:00:23:14:4b:61:58:e4:82: |
|
| 19 |
+ aa:15:97:94:bd:50:35:0d:5d:18:18:ed:10:6a:bb: |
|
| 20 |
+ d3:64:5a:eb:36:98:5b:58:a7:fe:67:48:c1:6c:3f: |
|
| 21 |
+ 51:2f:02:65:96:54:77:9b:34:f9:a7:d2:63:54:6a: |
|
| 22 |
+ 9e:02:5c:be:65:98:a4:b4:b5 |
|
| 23 |
+ Exponent: 65537 (0x10001) |
|
| 24 |
+ X509v3 extensions: |
|
| 25 |
+ X509v3 Basic Constraints: |
|
| 26 |
+ CA:FALSE |
|
| 27 |
+ Netscape Cert Type: |
|
| 28 |
+ SSL Server |
|
| 29 |
+ Netscape Comment: |
|
| 30 |
+ Easy-RSA Generated Server Certificate |
|
| 31 |
+ X509v3 Subject Key Identifier: |
|
| 32 |
+ 1F:E0:57:CA:CB:76:C9:C4:86:B9:EA:69:17:C0:F3:51:CE:95:40:EC |
|
| 33 |
+ X509v3 Authority Key Identifier: |
|
| 34 |
+ keyid:DC:A5:F1:76:DB:4E:CD:8E:EF:B1:23:56:1D:92:80:99:74:3B:EA:6F |
|
| 35 |
+ DirName:/C=US/ST=CA/L=SanFrancisco/O=Evil Inc/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain |
|
| 36 |
+ serial:E7:21:1E:18:41:1B:96:83 |
|
| 37 |
+ |
|
| 38 |
+ X509v3 Extended Key Usage: |
|
| 39 |
+ TLS Web Server Authentication |
|
| 40 |
+ X509v3 Key Usage: |
|
| 41 |
+ Digital Signature, Key Encipherment |
|
| 42 |
+ Signature Algorithm: sha1WithRSAEncryption |
|
| 43 |
+ 04:93:0e:28:01:94:18:f0:8c:7c:d3:0c:ad:e9:b7:46:b1:30: |
|
| 44 |
+ 65:ed:68:7c:8c:91:cd:1a:86:66:87:4a:4f:c0:97:bc:f7:85: |
|
| 45 |
+ 4b:38:79:31:b2:65:88:b1:76:16:9e:80:93:38:f4:b9:eb:65: |
|
| 46 |
+ 00:6d:bb:89:e0:a1:bf:95:5e:80:13:8e:01:73:d3:f1:08:73: |
|
| 47 |
+ 85:a5:33:75:0b:42:8a:a3:07:09:35:ef:d7:c6:58:eb:60:a3: |
|
| 48 |
+ 06:89:a0:53:99:e2:aa:41:90:e0:1a:d2:12:4b:48:7d:c3:9c: |
|
| 49 |
+ ad:bd:0e:5e:5f:f7:09:0c:5d:7c:86:24:dd:92:d5:b3:14:06: |
|
| 50 |
+ c7:9f |
|
| 51 |
+-----BEGIN CERTIFICATE----- |
|
| 52 |
+MIIEKjCCA5OgAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx |
|
| 53 |
+CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2 |
|
| 54 |
+aWwgSW5jMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAP |
|
| 55 |
+BgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWlu |
|
| 56 |
+MB4XDTE0MDIyODE4NDkzMVoXDTI0MDIyNjE4NDkzMVowgaMxCzAJBgNVBAYTAlVT |
|
| 57 |
+MQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxG |
|
| 58 |
+b3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMRIwEAYDVQQDEwlsb2NhbGhv |
|
| 59 |
+c3QxETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3Qu |
|
| 60 |
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRCFgkYKFpZUt2Ro+I |
|
| 61 |
+dXxJOtgDzFtYxdG75flUuXVl3367+1TUsulvWKKkhEOUdySBODY28GZlJuVbKhQc |
|
| 62 |
+qa5Xf3UAIxRLYVjkgqoVl5S9UDUNXRgY7RBqu9NkWus2mFtYp/5nSMFsP1EvAmWW |
|
| 63 |
+VHebNPmn0mNUap4CXL5lmKS0tQIDAQABo4IBbzCCAWswCQYDVR0TBAIwADARBglg |
|
| 64 |
+hkgBhvhCAQEEBAMCBkAwNAYJYIZIAYb4QgENBCcWJUVhc3ktUlNBIEdlbmVyYXRl |
|
| 65 |
+ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFB/gV8rLdsnEhrnqaRfA81HO |
|
| 66 |
+lUDsMIHTBgNVHSMEgcswgciAFNyl8XbbTs2O77EjVh2SgJl0O+pvoYGkpIGhMIGe |
|
| 67 |
+MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNj |
|
| 68 |
+bzERMA8GA1UEChMIRXZpbCBJbmMxETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQD |
|
| 69 |
+EwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1h |
|
| 70 |
+aWxAaG9zdC5kb21haW6CCQDnIR4YQRuWgzATBgNVHSUEDDAKBggrBgEFBQcDATAL |
|
| 71 |
+BgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEABJMOKAGUGPCMfNMMrem3RrEw |
|
| 72 |
+Ze1ofIyRzRqGZodKT8CXvPeFSzh5MbJliLF2Fp6Akzj0uetlAG27ieChv5VegBOO |
|
| 73 |
+AXPT8QhzhaUzdQtCiqMHCTXv18ZY62CjBomgU5niqkGQ4BrSEktIfcOcrb0OXl/3 |
|
| 74 |
+CQxdfIYk3ZLVsxQGx58= |
|
| 75 |
+-----END CERTIFICATE----- |
| 0 | 76 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+-----BEGIN PRIVATE KEY----- |
|
| 1 |
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANEIWCRgoWllS3ZG |
|
| 2 |
+j4h1fEk62APMW1jF0bvl+VS5dWXffrv7VNSy6W9YoqSEQ5R3JIE4NjbwZmUm5Vsq |
|
| 3 |
+FByprld/dQAjFEthWOSCqhWXlL1QNQ1dGBjtEGq702Ra6zaYW1in/mdIwWw/US8C |
|
| 4 |
+ZZZUd5s0+afSY1RqngJcvmWYpLS1AgMBAAECgYAJXh9dGfuB1qlIFqduDR3RxlJR |
|
| 5 |
+8UGSu+LHUeoXkuwg8aAjWoMVuSLe+5DmYIsKx0AajmNXmPRtyg1zRXJ7SltmubJ8 |
|
| 6 |
+6qQVDsRk6biMdkpkl6a9Gk2av40psD9/VPGxagEoop7IKYhf3AeKPvPiwVB2qFrl |
|
| 7 |
+1aYMZm0aMR55pgRajQJBAOk8IsJDf0beooDZXVdv/oe4hcbM9fxO8Cn3qzoGImqD |
|
| 8 |
+37LL+PCzDP7AEV3fk43SsZDeSk+LDX+h0o9nPyhzHasCQQDlb3aDgcQY9NaGLUWO |
|
| 9 |
+moOCB3148eBVcAwCocu+OSkf7sbQdvXxgThBOrZl11wwRIMQqh99c2yeUwj+tELl |
|
| 10 |
+3VcfAkBZTiNpCvtDIaBLge9RuZpWUXs3wec2cutWxnSTxSGMc25GQf/R+l0xdk2w |
|
| 11 |
+ChmvpktDUzpU9sN2aXn8WuY+EMX9AkEApbLpUbKPUELLB958RLA819TW/lkZXjrs |
|
| 12 |
+wZ3eSoR3ufM1rOqtVvyvBxUDE+wETWu9iHSFB5Ir2PA5J9JCGkbPmwJAFI1ndfBj |
|
| 13 |
+iuyU93nFX0p+JE2wVHKx4dMzKCearNKiJh/lGDtUq3REGgamTNUnG8RAITUbxFs+ |
|
| 14 |
+Z1hrIq8xYl2LOQ== |
|
| 15 |
+-----END PRIVATE KEY----- |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,82 @@ |
| 0 |
+package docker |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "crypto/tls" |
|
| 4 |
+ "crypto/x509" |
|
| 5 |
+ "github.com/dotcloud/docker/api" |
|
| 6 |
+ "io/ioutil" |
|
| 7 |
+ "testing" |
|
| 8 |
+ "time" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+const ( |
|
| 12 |
+ errBadCertificate = "remote error: bad certificate" |
|
| 13 |
+ errCaUnknown = "x509: certificate signed by unknown authority" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func getTlsConfig(certFile, keyFile string, t *testing.T) *tls.Config {
|
|
| 17 |
+ certPool := x509.NewCertPool() |
|
| 18 |
+ file, err := ioutil.ReadFile("fixtures/https/ca.pem")
|
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ t.Fatal(err) |
|
| 21 |
+ } |
|
| 22 |
+ certPool.AppendCertsFromPEM(file) |
|
| 23 |
+ |
|
| 24 |
+ cert, err := tls.LoadX509KeyPair("fixtures/https/"+certFile, "fixtures/https/"+keyFile)
|
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ t.Fatalf("Couldn't load X509 key pair: %s", err)
|
|
| 27 |
+ } |
|
| 28 |
+ tlsConfig := &tls.Config{
|
|
| 29 |
+ RootCAs: certPool, |
|
| 30 |
+ Certificates: []tls.Certificate{cert},
|
|
| 31 |
+ } |
|
| 32 |
+ return tlsConfig |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint |
|
| 36 |
+func TestHttpsInfo(t *testing.T) {
|
|
| 37 |
+ cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, |
|
| 38 |
+ testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
|
|
| 39 |
+ |
|
| 40 |
+ setTimeout(t, "Reading command output time out", 10*time.Second, func() {
|
|
| 41 |
+ if err := cli.CmdInfo(); err != nil {
|
|
| 42 |
+ t.Fatal(err) |
|
| 43 |
+ } |
|
| 44 |
+ }) |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint |
|
| 48 |
+// by using a rogue client certificate and checks that it fails with the expected error. |
|
| 49 |
+func TestHttpsInfoRogueCert(t *testing.T) {
|
|
| 50 |
+ cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, |
|
| 51 |
+ testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t))
|
|
| 52 |
+ |
|
| 53 |
+ setTimeout(t, "Reading command output time out", 10*time.Second, func() {
|
|
| 54 |
+ err := cli.CmdInfo() |
|
| 55 |
+ if err == nil {
|
|
| 56 |
+ t.Fatal("Expected error but got nil")
|
|
| 57 |
+ } |
|
| 58 |
+ if err.Error() != errBadCertificate {
|
|
| 59 |
+ t.Fatalf("Expected error: %s, got instead: %s", errBadCertificate, err)
|
|
| 60 |
+ } |
|
| 61 |
+ }) |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint |
|
| 65 |
+// which provides a rogue server certificate and checks that it fails with the expected error |
|
| 66 |
+func TestHttpsInfoRogueServerCert(t *testing.T) {
|
|
| 67 |
+ cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, |
|
| 68 |
+ testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
|
|
| 69 |
+ |
|
| 70 |
+ setTimeout(t, "Reading command output time out", 10*time.Second, func() {
|
|
| 71 |
+ err := cli.CmdInfo() |
|
| 72 |
+ if err == nil {
|
|
| 73 |
+ t.Fatal("Expected error but got nil")
|
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ if err.Error() != errCaUnknown {
|
|
| 77 |
+ t.Fatalf("Expected error: %s, got instead: %s", errBadCertificate, err)
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ }) |
|
| 81 |
+} |
| ... | ... |
@@ -24,21 +24,26 @@ import ( |
| 24 | 24 |
) |
| 25 | 25 |
|
| 26 | 26 |
const ( |
| 27 |
- unitTestImageName = "docker-test-image" |
|
| 28 |
- unitTestImageID = "83599e29c455eb719f77d799bc7c51521b9551972f5a850d7ad265bc1b5292f6" // 1.0 |
|
| 29 |
- unitTestImageIDShort = "83599e29c455" |
|
| 30 |
- unitTestNetworkBridge = "testdockbr0" |
|
| 31 |
- unitTestStoreBase = "/var/lib/docker/unit-tests" |
|
| 32 |
- testDaemonAddr = "127.0.0.1:4270" |
|
| 33 |
- testDaemonProto = "tcp" |
|
| 27 |
+ unitTestImageName = "docker-test-image" |
|
| 28 |
+ unitTestImageID = "83599e29c455eb719f77d799bc7c51521b9551972f5a850d7ad265bc1b5292f6" // 1.0 |
|
| 29 |
+ unitTestImageIDShort = "83599e29c455" |
|
| 30 |
+ unitTestNetworkBridge = "testdockbr0" |
|
| 31 |
+ unitTestStoreBase = "/var/lib/docker/unit-tests" |
|
| 32 |
+ testDaemonAddr = "127.0.0.1:4270" |
|
| 33 |
+ testDaemonProto = "tcp" |
|
| 34 |
+ testDaemonHttpsProto = "tcp" |
|
| 35 |
+ testDaemonHttpsAddr = "localhost:4271" |
|
| 36 |
+ testDaemonRogueHttpsAddr = "localhost:4272" |
|
| 34 | 37 |
) |
| 35 | 38 |
|
| 36 | 39 |
var ( |
| 37 | 40 |
// FIXME: globalRuntime is deprecated by globalEngine. All tests should be converted. |
| 38 |
- globalRuntime *docker.Runtime |
|
| 39 |
- globalEngine *engine.Engine |
|
| 40 |
- startFds int |
|
| 41 |
- startGoroutines int |
|
| 41 |
+ globalRuntime *docker.Runtime |
|
| 42 |
+ globalEngine *engine.Engine |
|
| 43 |
+ globalHttpsEngine *engine.Engine |
|
| 44 |
+ globalRogueHttpsEngine *engine.Engine |
|
| 45 |
+ startFds int |
|
| 46 |
+ startGoroutines int |
|
| 42 | 47 |
) |
| 43 | 48 |
|
| 44 | 49 |
// FIXME: nuke() is deprecated by Runtime.Nuke() |
| ... | ... |
@@ -117,8 +122,10 @@ func init() {
|
| 117 | 117 |
// (no tests are run directly in the base) |
| 118 | 118 |
setupBaseImage() |
| 119 | 119 |
|
| 120 |
- // Create the "global runtime" with a long-running daemon for integration tests |
|
| 120 |
+ // Create the "global runtime" with a long-running daemons for integration tests |
|
| 121 | 121 |
spawnGlobalDaemon() |
| 122 |
+ spawnLegitHttpsDaemon() |
|
| 123 |
+ spawnRogueHttpsDaemon() |
|
| 122 | 124 |
startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine() |
| 123 | 125 |
} |
| 124 | 126 |
|
| ... | ... |
@@ -170,6 +177,61 @@ func spawnGlobalDaemon() {
|
| 170 | 170 |
} |
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 |
+func spawnLegitHttpsDaemon() {
|
|
| 174 |
+ if globalHttpsEngine != nil {
|
|
| 175 |
+ return |
|
| 176 |
+ } |
|
| 177 |
+ globalHttpsEngine = spawnHttpsDaemon(testDaemonHttpsAddr, "fixtures/https/ca.pem", |
|
| 178 |
+ "fixtures/https/server-cert.pem", "fixtures/https/server-key.pem") |
|
| 179 |
+} |
|
| 180 |
+ |
|
| 181 |
+func spawnRogueHttpsDaemon() {
|
|
| 182 |
+ if globalRogueHttpsEngine != nil {
|
|
| 183 |
+ return |
|
| 184 |
+ } |
|
| 185 |
+ globalRogueHttpsEngine = spawnHttpsDaemon(testDaemonRogueHttpsAddr, "fixtures/https/ca.pem", |
|
| 186 |
+ "fixtures/https/server-rogue-cert.pem", "fixtures/https/server-rogue-key.pem") |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+func spawnHttpsDaemon(addr, cacert, cert, key string) *engine.Engine {
|
|
| 190 |
+ t := log.New(os.Stderr, "", 0) |
|
| 191 |
+ root, err := newTestDirectory(unitTestStoreBase) |
|
| 192 |
+ if err != nil {
|
|
| 193 |
+ t.Fatal(err) |
|
| 194 |
+ } |
|
| 195 |
+ // FIXME: here we don't use NewTestEngine because it calls initserver with Autorestart=false, |
|
| 196 |
+ // and we want to set it to true. |
|
| 197 |
+ |
|
| 198 |
+ eng := newTestEngine(t, true, root) |
|
| 199 |
+ |
|
| 200 |
+ // Spawn a Daemon |
|
| 201 |
+ go func() {
|
|
| 202 |
+ utils.Debugf("Spawning https daemon for integration tests")
|
|
| 203 |
+ listenURL := &url.URL{
|
|
| 204 |
+ Scheme: testDaemonHttpsProto, |
|
| 205 |
+ Host: addr, |
|
| 206 |
+ } |
|
| 207 |
+ job := eng.Job("serveapi", listenURL.String())
|
|
| 208 |
+ job.SetenvBool("Logging", true)
|
|
| 209 |
+ job.SetenvBool("Tls", true)
|
|
| 210 |
+ job.SetenvBool("TlsVerify", true)
|
|
| 211 |
+ job.Setenv("TlsCa", cacert)
|
|
| 212 |
+ job.Setenv("TlsCert", cert)
|
|
| 213 |
+ job.Setenv("TlsKey", key)
|
|
| 214 |
+ if err := job.Run(); err != nil {
|
|
| 215 |
+ log.Fatalf("Unable to spawn the test daemon: %s", err)
|
|
| 216 |
+ } |
|
| 217 |
+ }() |
|
| 218 |
+ |
|
| 219 |
+ // Give some time to ListenAndServer to actually start |
|
| 220 |
+ time.Sleep(time.Second) |
|
| 221 |
+ |
|
| 222 |
+ if err := eng.Job("acceptconnections").Run(); err != nil {
|
|
| 223 |
+ log.Fatalf("Unable to accept connections for test api: %s", err)
|
|
| 224 |
+ } |
|
| 225 |
+ return eng |
|
| 226 |
+} |
|
| 227 |
+ |
|
| 173 | 228 |
// FIXME: test that ImagePull(json=true) send correct json output |
| 174 | 229 |
|
| 175 | 230 |
func GetTestImage(runtime *docker.Runtime) *docker.Image {
|