From 1847bb899a07d3dd324e75a3ed9b3489fcfc302f Mon Sep 17 00:00:00 2001 From: Ying Li Date: Tue, 2 May 2017 14:58:57 -0700 Subject: [PATCH] Propagate the desired CA certificate and CAConfig ForceRotate parameter in the Docker REST APIs when viewing or updating the swarm spec info, and also propagate the desired CA key in the Docker REST APIs when updating swarm spec info only (it is not available for viewing). Signed-off-by: Ying Li --- api/swagger.yaml | 8 ++++++++ api/types/swarm/swarm.go | 10 ++++++++++ daemon/cluster/convert/swarm.go | 13 +++++++++++++ docs/api/version-history.md | 5 ++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/api/swagger.yaml b/api/swagger.yaml index 18971c4b07..9e33a6c6fd 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -1886,6 +1886,14 @@ definitions: CACert: description: "The root CA certificate (in PEM format) this external CA uses to issue TLS certificates (assumed to be to the current swarm root CA certificate if not provided)." type: "string" + SigningCACert: + description: "The desired signing CA certificate for all swarm node TLS leaf certificates, in PEM format." + type: "string" + SigningCAKey: + description: "The desired signing CA key for all swarm node TLS leaf certificates, in PEM format." + type: "string" + ForceRotate: + description: "An integer whose purpose is to force swarm to generate a new signing CA certificate and key, if none have been specified in `SigningCACert` and `SigningCAKey`" EncryptionConfig: description: "Parameters related to encryption-at-rest." type: "object" diff --git a/api/types/swarm/swarm.go b/api/types/swarm/swarm.go index bdb3042337..5b74f14b11 100644 --- a/api/types/swarm/swarm.go +++ b/api/types/swarm/swarm.go @@ -109,6 +109,16 @@ type CAConfig struct { // ExternalCAs is a list of CAs to which a manager node will make // certificate signing requests for node certificates. ExternalCAs []*ExternalCA `json:",omitempty"` + + // SigningCACert and SigningCAKey specify the desired signing root CA and + // root CA key for the swarm. When inspecting the cluster, the key will + // be redacted. + SigningCACert string `json:",omitempty"` + SigningCAKey string `json:",omitempty"` + + // If this value changes, and there is no specified signing cert and key, + // then the swarm is forced to generate a new root certificate ane key. + ForceRotate uint64 `json:",omitempty"` } // ExternalCAProtocol represents type of external CA. diff --git a/daemon/cluster/convert/swarm.go b/daemon/cluster/convert/swarm.go index 64fc7f72d9..c6e1f3652b 100644 --- a/daemon/cluster/convert/swarm.go +++ b/daemon/cluster/convert/swarm.go @@ -30,6 +30,11 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm { EncryptionConfig: types.EncryptionConfig{ AutoLockManagers: c.Spec.EncryptionConfig.AutoLockManagers, }, + CAConfig: types.CAConfig{ + // do not include the signing CA key (it should already be redacted via the swarm APIs) + SigningCACert: string(c.Spec.CAConfig.SigningCACert), + ForceRotate: c.Spec.CAConfig.ForceRotate, + }, }, TLSInfo: types.TLSInfo{ TrustRoot: string(c.RootCA.CACert), @@ -114,6 +119,14 @@ func MergeSwarmSpecToGRPC(s types.Spec, spec swarmapi.ClusterSpec) (swarmapi.Clu if s.CAConfig.NodeCertExpiry != 0 { spec.CAConfig.NodeCertExpiry = gogotypes.DurationProto(s.CAConfig.NodeCertExpiry) } + if s.CAConfig.SigningCACert != "" { + spec.CAConfig.SigningCACert = []byte(s.CAConfig.SigningCACert) + } + if s.CAConfig.SigningCAKey != "" { + // do prpagate the signing CA key here because we want to provide it TO the swarm APIs + spec.CAConfig.SigningCAKey = []byte(s.CAConfig.SigningCAKey) + } + spec.CAConfig.ForceRotate = s.CAConfig.ForceRotate for _, ca := range s.CAConfig.ExternalCAs { protocol, ok := swarmapi.ExternalCA_CAProtocol_value[strings.ToUpper(string(ca.Protocol))] diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 359813d87e..4e02e7193a 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -19,11 +19,14 @@ keywords: "API, Docker, rcli, REST, documentation" * `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. + leaf certificate issuer's subject and public key. It also displays the desired CA signing certificate, if any was provided as part of the spec. * `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. * `GET /distribution/(name)/json` is a new endpoint that returns a JSON output stream with payload `types.DistributionInspect` for an image name. It includes a descriptor with the digest, and supported platforms retrieved from directly contacting the registry. +* `POST /swarm/update` now accepts 3 additional parameters as part of the swarm spec's CA configuration; the desired CA certificate for + the swarm, the desired CA key for the swarm (if not using an external certificate), and an optional parameter to force swarm to + generate and rotate to a new CA certificate/key pair. ## v1.29 API changes