Propagate the swarm cluster and node TLS info provided by the swarm

objects into the REST API responses.  In the CLI, display only
whether the nodes' TLS info matches the cluster's TLS info, or
whether the node needs cert rotation.

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2017-04-26 19:46:20 -07:00
parent a762ceace4
commit 64cccedbce
8 changed files with 101 additions and 1 deletions

View file

@ -1716,6 +1716,8 @@ definitions:
type: "string" type: "string"
Name: Name:
type: "string" type: "string"
TLSInfo:
$ref: "#/definitions/SwarmSpec"
example: example:
ID: "24ifsmvkjbyhk" ID: "24ifsmvkjbyhk"
Version: Version:
@ -1756,6 +1758,47 @@ definitions:
Leader: true Leader: true
Reachability: "reachable" Reachability: "reachable"
Addr: "172.17.0.2:2377" Addr: "172.17.0.2:2377"
TLSInfo:
TrustRoot: |
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUbYqrLSOSQHoxD8CwG6Bi2PJi9c8wCgYIKoZIzj0EAwIw
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwNDI0MjE0MzAwWhcNMzcwNDE5MjE0
MzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABJk/VyMPYdaqDXJb/VXh5n/1Yuv7iNrxV3Qb3l06XD46seovcDWs3IZNV1lf
3Skyr0ofcchipoiHkXBODojJydSjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBRUXxuRcnFjDfR/RIAUQab8ZV/n4jAKBggqhkjO
PQQDAgNIADBFAiAy+JTe6Uc3KyLCMiqGl2GyWGQqQDEcO3/YG36x7om65AIhAJvz
pxv6zFeVEkAEEkqIYi0omA9+CjanB/6Bz4n1uw8H
-----END CERTIFICATE-----
CertIssuerSubject: "MBMxETAPBgNVBAMTCHN3YXJtLWNh"
CertIssuerPublicKey: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmT9XIw9h1qoNclv9VeHmf/Vi6/uI2vFXdBveXTpcPjqx6i9wNazchk1XWV/dKTKvSh9xyGKmiIeRcE4OiMnJ1A=="
TLSInfo:
description: "Information about the issuer of leaf TLS certificates and the trusted root CA certificate"
type: "object"
properties:
TrustRoot:
description: "The root CA certificate(s) that are used to validate leaf TLS certificates"
type: "string"
CertIssuerSubject:
description: "The base64-url-safe-encoded raw subject bytes of the issuer"
type: "string"
CertIssuerPublicKey:
description: "The base64-url-safe-encoded raw public key bytes of the issuer"
type: "string"
example:
TrustRoot: |
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUbYqrLSOSQHoxD8CwG6Bi2PJi9c8wCgYIKoZIzj0EAwIw
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwNDI0MjE0MzAwWhcNMzcwNDE5MjE0
MzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABJk/VyMPYdaqDXJb/VXh5n/1Yuv7iNrxV3Qb3l06XD46seovcDWs3IZNV1lf
3Skyr0ofcchipoiHkXBODojJydSjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBRUXxuRcnFjDfR/RIAUQab8ZV/n4jAKBggqhkjO
PQQDAgNIADBFAiAy+JTe6Uc3KyLCMiqGl2GyWGQqQDEcO3/YG36x7om65AIhAJvz
pxv6zFeVEkAEEkqIYi0omA9+CjanB/6Bz4n1uw8H
-----END CERTIFICATE-----
CertIssuerSubject: "MBMxETAPBgNVBAMTCHN3YXJtLWNh"
CertIssuerPublicKey: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmT9XIw9h1qoNclv9VeHmf/Vi6/uI2vFXdBveXTpcPjqx6i9wNazchk1XWV/dKTKvSh9xyGKmiIeRcE4OiMnJ1A=="
SwarmSpec: SwarmSpec:
description: "User modifiable swarm configuration." description: "User modifiable swarm configuration."
type: "object" type: "object"
@ -1903,6 +1946,11 @@ definitions:
format: "dateTime" format: "dateTime"
Spec: Spec:
$ref: "#/definitions/SwarmSpec" $ref: "#/definitions/SwarmSpec"
TLSInfo:
$ref: "#/definitions/TLSInfo"
RootRotationInProgress:
description: "Whether there is currently a root CA rotation in progress for the swarm"
type: "boolean"
TaskSpec: TaskSpec:
description: "User modifiable task configuration." description: "User modifiable task configuration."
type: "object" type: "object"
@ -7205,6 +7253,21 @@ paths:
UpdatedAt: "2016-08-15T16:32:09.623207604Z" UpdatedAt: "2016-08-15T16:32:09.623207604Z"
Version: Version:
Index: 51 Index: 51
RootRotationInProgress: false
TLSInfo:
TrustRoot: |
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUbYqrLSOSQHoxD8CwG6Bi2PJi9c8wCgYIKoZIzj0EAwIw
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwNDI0MjE0MzAwWhcNMzcwNDE5MjE0
MzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABJk/VyMPYdaqDXJb/VXh5n/1Yuv7iNrxV3Qb3l06XD46seovcDWs3IZNV1lf
3Skyr0ofcchipoiHkXBODojJydSjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBRUXxuRcnFjDfR/RIAUQab8ZV/n4jAKBggqhkjO
PQQDAgNIADBFAiAy+JTe6Uc3KyLCMiqGl2GyWGQqQDEcO3/YG36x7om65AIhAJvz
pxv6zFeVEkAEEkqIYi0omA9+CjanB/6Bz4n1uw8H
-----END CERTIFICATE-----
CertIssuerSubject: "MBMxETAPBgNVBAMTCHN3YXJtLWNh"
CertIssuerPublicKey: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmT9XIw9h1qoNclv9VeHmf/Vi6/uI2vFXdBveXTpcPjqx6i9wNazchk1XWV/dKTKvSh9xyGKmiIeRcE4OiMnJ1A=="
404: 404:
description: "no such swarm" description: "no such swarm"
schema: schema:

View file

@ -25,3 +25,16 @@ type Driver struct {
Name string `json:",omitempty"` Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"` Options map[string]string `json:",omitempty"`
} }
// TLSInfo represents the TLS information about what CA certificate is trusted,
// and who the issuer for a TLS certificate is
type TLSInfo struct {
// TrustRoot is the trusted CA root certificate in PEM format
TrustRoot string `json:",omitempty"`
// CertIssuer is the raw subject bytes of the issuer
CertIssuerSubject []byte `json:",omitempty"`
// CertIssuerPublicKey is the raw public key bytes of the issuer
CertIssuerPublicKey []byte `json:",omitempty"`
}

View file

@ -52,6 +52,7 @@ type NodeDescription struct {
Platform Platform `json:",omitempty"` Platform Platform `json:",omitempty"`
Resources Resources `json:",omitempty"` Resources Resources `json:",omitempty"`
Engine EngineDescription `json:",omitempty"` Engine EngineDescription `json:",omitempty"`
TLSInfo TLSInfo `json:",omitempty"`
} }
// Platform represents the platform (Arch/OS). // Platform represents the platform (Arch/OS).

View file

@ -7,7 +7,9 @@ import "time"
type ClusterInfo struct { type ClusterInfo struct {
ID string ID string
Meta Meta
Spec Spec Spec Spec
TLSInfo TLSInfo
RootRotationInProgress bool
} }
// Swarm represents a swarm. // Swarm represents a swarm.

View file

@ -50,6 +50,11 @@ func NodeFromGRPC(n swarmapi.Node) types.Node {
node.Description.Engine.Plugins = append(node.Description.Engine.Plugins, types.PluginDescription{Type: plugin.Type, Name: plugin.Name}) node.Description.Engine.Plugins = append(node.Description.Engine.Plugins, types.PluginDescription{Type: plugin.Type, Name: plugin.Name})
} }
} }
if n.Description.TLSInfo != nil {
node.Description.TLSInfo.TrustRoot = string(n.Description.TLSInfo.TrustRoot)
node.Description.TLSInfo.CertIssuerPublicKey = n.Description.TLSInfo.CertIssuerPublicKey
node.Description.TLSInfo.CertIssuerSubject = n.Description.TLSInfo.CertIssuerSubject
}
} }
//Manager //Manager

View file

@ -7,6 +7,7 @@ import (
types "github.com/docker/docker/api/types/swarm" types "github.com/docker/docker/api/types/swarm"
swarmapi "github.com/docker/swarmkit/api" swarmapi "github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/ca"
gogotypes "github.com/gogo/protobuf/types" gogotypes "github.com/gogo/protobuf/types"
) )
@ -30,6 +31,10 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
AutoLockManagers: c.Spec.EncryptionConfig.AutoLockManagers, AutoLockManagers: c.Spec.EncryptionConfig.AutoLockManagers,
}, },
}, },
TLSInfo: types.TLSInfo{
TrustRoot: string(c.RootCA.CACert),
},
RootRotationInProgress: c.RootCA.RootRotation != nil,
}, },
JoinTokens: types.JoinTokens{ JoinTokens: types.JoinTokens{
Worker: c.RootCA.JoinTokens.Worker, Worker: c.RootCA.JoinTokens.Worker,
@ -37,6 +42,12 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
}, },
} }
issuerInfo, err := ca.IssuerFromAPIRootCA(&c.RootCA)
if err == nil && issuerInfo != nil {
swarm.TLSInfo.CertIssuerSubject = issuerInfo.Subject
swarm.TLSInfo.CertIssuerPublicKey = issuerInfo.PublicKey
}
heartbeatPeriod, _ := gogotypes.DurationFromProto(c.Spec.Dispatcher.HeartbeatPeriod) heartbeatPeriod, _ := gogotypes.DurationFromProto(c.Spec.Dispatcher.HeartbeatPeriod)
swarm.Spec.Dispatcher.HeartbeatPeriod = heartbeatPeriod swarm.Spec.Dispatcher.HeartbeatPeriod = heartbeatPeriod

View file

@ -18,7 +18,11 @@ keywords: "API, Docker, rcli, REST, documentation"
[Docker Engine API v1.30](https://docs.docker.com/engine/api/v1.30/) documentation [Docker Engine API v1.30](https://docs.docker.com/engine/api/v1.30/) documentation
* `GET /info` now returns the list of supported logging drivers, including plugins. * `GET /info` now returns the list of supported logging drivers, including plugins.
* `GET /info` and `GET /swarm` now returns the cluster-wide swarm CA info if the node is in a swarm: the cluster root CA certificate, and the cluster TLS
leaf certificate issuer's subject and public key.
* `POST /build/` now (when not silent) produces an `Aux` message in the JSON output stream with payload `types.BuildResult` for each image produced. The final such message will reference the image resulting from the build. * `POST /build/` now (when not silent) produces an `Aux` message in the JSON output stream with payload `types.BuildResult` for each image produced. The final such message will reference the image resulting from the build.
* `GET /nodes` and `GET /nodes/{id}` now returns additional information about swarm TLS info if the node is part of a swarm: the trusted root CA, and the
issuer's subject and public key.
## v1.29 API changes ## v1.29 API changes

View file

@ -32,6 +32,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInit(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(info.ControlAvailable, checker.True) c.Assert(info.ControlAvailable, checker.True)
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
c.Assert(info.Cluster.RootRotationInProgress, checker.False)
d2 := s.AddDaemon(c, true, false) d2 := s.AddDaemon(c, true, false)
info, err = d2.SwarmInfo() info, err = d2.SwarmInfo()