From a28c9109167084526254595682b4f83017d137c6 Mon Sep 17 00:00:00 2001 From: Evan Hazlett Date: Thu, 27 Oct 2016 15:51:02 -0700 Subject: [PATCH] add secret support for service update - add nosuid and noexec to tmpfs Signed-off-by: Evan Hazlett Upstream-commit: 00237a96249739dbf426d81672a904e9f4c5e702 Component: engine --- components/engine/cli/command/service/opts.go | 2 ++ .../engine/cli/command/service/update.go | 34 +++++++++++++++++++ components/engine/container/container_unix.go | 2 +- .../daemon/container_operations_unix.go | 8 ++--- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/components/engine/cli/command/service/opts.go b/components/engine/cli/command/service/opts.go index 3ef24ee33c..37da5d1145 100644 --- a/components/engine/cli/command/service/opts.go +++ b/components/engine/cli/command/service/opts.go @@ -557,4 +557,6 @@ const ( flagHealthTimeout = "health-timeout" flagNoHealthcheck = "no-healthcheck" flagSecret = "secret" + flagSecretAdd = "secret-add" + flagSecretRemove = "secret-rm" ) diff --git a/components/engine/cli/command/service/update.go b/components/engine/cli/command/service/update.go index 4a77229497..a9f5ac9be6 100644 --- a/components/engine/cli/command/service/update.go +++ b/components/engine/cli/command/service/update.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/client" "github.com/docker/docker/opts" runconfigopts "github.com/docker/docker/runconfig/opts" "github.com/docker/go-connections/nat" @@ -54,6 +55,8 @@ func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command { flags.Var(&opts.labels, flagLabelAdd, "Add or update a service label") flags.Var(&opts.containerLabels, flagContainerLabelAdd, "Add or update a container label") flags.Var(&opts.env, flagEnvAdd, "Add or update an environment variable") + flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret") + flags.StringSliceVar(&opts.secrets, flagSecretAdd, []string{}, "Add a secret") flags.Var(&opts.mounts, flagMountAdd, "Add or update a mount on a service") flags.Var(&opts.constraints, flagConstraintAdd, "Add or update a placement constraint") flags.Var(&opts.endpoint.ports, flagPublishAdd, "Add or update a published port") @@ -97,6 +100,13 @@ func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, serviceID str return err } + updatedSecrets, err := getUpdatedSecrets(apiClient, flags, spec.TaskTemplate.ContainerSpec.Secrets) + if err != nil { + return err + } + + spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets + // only send auth if flag was set sendAuth, err := flags.GetBool(flagRegistryAuth) if err != nil { @@ -401,6 +411,30 @@ func updateEnvironment(flags *pflag.FlagSet, field *[]string) { *field = removeItems(*field, toRemove, envKey) } +func getUpdatedSecrets(apiClient client.APIClient, flags *pflag.FlagSet, secrets []*swarm.SecretReference) ([]*swarm.SecretReference, error) { + if flags.Changed(flagSecretAdd) { + values, err := flags.GetStringSlice(flagSecretAdd) + if err != nil { + return nil, err + } + + addSecrets, err := parseSecrets(apiClient, values) + if err != nil { + return nil, err + } + secrets = append(secrets, addSecrets...) + } + toRemove := buildToRemoveSet(flags, flagSecretRemove) + newSecrets := []*swarm.SecretReference{} + for _, secret := range secrets { + if _, exists := toRemove[secret.SecretName]; !exists { + newSecrets = append(newSecrets, secret) + } + } + + return newSecrets, nil +} + func envKey(value string) string { kv := strings.SplitN(value, "=", 2) return kv[0] diff --git a/components/engine/container/container_unix.go b/components/engine/container/container_unix.go index 3cd0d4c17a..8d825c7698 100644 --- a/components/engine/container/container_unix.go +++ b/components/engine/container/container_unix.go @@ -268,7 +268,7 @@ func (container *Container) IpcMounts() []Mount { return mounts } -// SecretMount returns the list of Secret mounts +// SecretMount returns the mount for the secret path func (container *Container) SecretMount() *Mount { if len(container.Secrets) > 0 { return &Mount{ diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go index abbe180eb8..bdadaa7d7f 100644 --- a/components/engine/daemon/container_operations_unix.go +++ b/components/engine/daemon/container_operations_unix.go @@ -148,8 +148,8 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { localMountPath := c.SecretMountPath() logrus.Debugf("secrets: setting up secret dir: %s", localMountPath) - defer func(err error) { - if err != nil { + defer func() { + if setupErr != nil { // cleanup _ = detachMounted(localMountPath) @@ -157,13 +157,13 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { log.Errorf("error cleaning up secret mount: %s", err) } } - }(setupErr) + }() // create tmpfs if err := os.MkdirAll(localMountPath, 0700); err != nil { return errors.Wrap(err, "error creating secret local mount path") } - if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev"); err != nil { + if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev,nosuid,noexec"); err != nil { return errors.Wrap(err, "unable to setup secret mount") }