diff --git a/api/server/router/swarm/cluster_routes.go b/api/server/router/swarm/cluster_routes.go index 930e13132c..2c380b4b56 100644 --- a/api/server/router/swarm/cluster_routes.go +++ b/api/server/router/swarm/cluster_routes.go @@ -87,6 +87,15 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, flags.RotateManagerToken = rot } + if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" { + rot, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value) + } + + flags.RotateManagerUnlockKey = rot + } + if err := sr.backend.Update(version, swarm, flags); err != nil { logrus.Errorf("Error configuring swarm: %v", err) return err diff --git a/cli/command/swarm/unlock_key.go b/cli/command/swarm/unlock_key.go index 19caa0cc2b..96450f55b8 100644 --- a/cli/command/swarm/unlock_key.go +++ b/cli/command/swarm/unlock_key.go @@ -5,6 +5,7 @@ import ( "github.com/spf13/cobra" + "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/pkg/errors" @@ -23,7 +24,24 @@ func newUnlockKeyCommand(dockerCli *command.DockerCli) *cobra.Command { ctx := context.Background() if rotate { - // FIXME(aaronl) + flags := swarm.UpdateFlags{RotateManagerUnlockKey: true} + + swarm, err := client.SwarmInspect(ctx) + if err != nil { + return err + } + + if !swarm.Spec.EncryptionConfig.AutoLockManagers { + return errors.New("cannot rotate because autolock is not turned on") + } + + err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, flags) + if err != nil { + return err + } + if !quiet { + fmt.Fprintf(dockerCli.Out(), "Successfully rotated manager unlock key.\n\n") + } } unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) @@ -31,6 +49,10 @@ func newUnlockKeyCommand(dockerCli *command.DockerCli) *cobra.Command { return errors.Wrap(err, "could not fetch unlock key") } + if unlockKeyResp.UnlockKey == "" { + return errors.New("no unlock key is set") + } + if quiet { fmt.Fprintln(dockerCli.Out(), unlockKeyResp.UnlockKey) } else { diff --git a/client/swarm_update.go b/client/swarm_update.go index f0be145ba2..cc8eeb6554 100644 --- a/client/swarm_update.go +++ b/client/swarm_update.go @@ -15,6 +15,7 @@ func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm query.Set("version", strconv.FormatUint(version.Index, 10)) query.Set("rotateWorkerToken", fmt.Sprintf("%v", flags.RotateWorkerToken)) query.Set("rotateManagerToken", fmt.Sprintf("%v", flags.RotateManagerToken)) + query.Set("rotateManagerUnlockKey", fmt.Sprintf("%v", flags.RotateManagerUnlockKey)) resp, err := cli.post(ctx, "/swarm/update", query, swarm, nil) ensureReaderClosed(resp) return err diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go index 5eea652a77..c3f9d96a39 100644 --- a/daemon/cluster/cluster.go +++ b/daemon/cluster/cluster.go @@ -558,6 +558,11 @@ func (c *Cluster) GetUnlockKey() (string, error) { return "", err } + if len(r.UnlockKey) == 0 { + // no key + return "", nil + } + return encryption.HumanReadableKey(r.UnlockKey), nil }