зеркало из https://github.com/microsoft/docker.git
support custom paths for secrets
This adds support to specify custom container paths for secrets. Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
Родитель
f4349a77fd
Коммит
67d282a5c9
|
@ -948,3 +948,20 @@ func (container *Container) InitializeStdio(iop libcontainerd.IOPipe) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SecretMountPath returns the path of the secret mount for the container
|
||||
func (container *Container) SecretMountPath() string {
|
||||
return filepath.Join(container.Root, "secrets")
|
||||
}
|
||||
|
||||
func (container *Container) getLocalSecretPath(r *swarmtypes.SecretReference) string {
|
||||
return filepath.Join(container.SecretMountPath(), filepath.Base(r.File.Name))
|
||||
}
|
||||
|
||||
func getSecretTargetPath(r *swarmtypes.SecretReference) string {
|
||||
if filepath.IsAbs(r.File.Name) {
|
||||
return r.File.Name
|
||||
}
|
||||
|
||||
return filepath.Join(containerSecretMountPath, r.File.Name)
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ func detachMounted(path string) error {
|
|||
return unix.Unmount(path, 0)
|
||||
}
|
||||
|
||||
// SecretMount returns the mount for the secret path
|
||||
func (container *Container) SecretMount() *Mount {
|
||||
// SecretMounts returns the mounts for the secret path
|
||||
func (container *Container) SecretMounts() []Mount {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
)
|
||||
|
||||
|
@ -58,3 +60,17 @@ func TestContainerStopTimeout(t *testing.T) {
|
|||
t.Fatalf("Expected 15, got %v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerSecretReferenceDestTarget(t *testing.T) {
|
||||
ref := &swarmtypes.SecretReference{
|
||||
File: &swarmtypes.SecretReferenceFileTarget{
|
||||
Name: "app",
|
||||
},
|
||||
}
|
||||
|
||||
d := getSecretTargetPath(ref)
|
||||
expected := filepath.Join(containerSecretMountPath, "app")
|
||||
if d != expected {
|
||||
t.Fatalf("expected secret dest %q; received %q", expected, d)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,11 +163,6 @@ func (container *Container) NetworkMounts() []Mount {
|
|||
return mounts
|
||||
}
|
||||
|
||||
// SecretMountPath returns the path of the secret mount for the container
|
||||
func (container *Container) SecretMountPath() string {
|
||||
return filepath.Join(container.Root, "secrets")
|
||||
}
|
||||
|
||||
// CopyImagePathContent copies files in destination to the volume.
|
||||
func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error {
|
||||
rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, destination), container.BaseFS)
|
||||
|
@ -253,17 +248,21 @@ func (container *Container) IpcMounts() []Mount {
|
|||
return mounts
|
||||
}
|
||||
|
||||
// SecretMount returns the mount for the secret path
|
||||
func (container *Container) SecretMount() *Mount {
|
||||
if len(container.SecretReferences) > 0 {
|
||||
return &Mount{
|
||||
Source: container.SecretMountPath(),
|
||||
Destination: containerSecretMountPath,
|
||||
// SecretMounts returns the mount for the secret path
|
||||
func (container *Container) SecretMounts() []Mount {
|
||||
var mounts []Mount
|
||||
for _, r := range container.SecretReferences {
|
||||
// secrets are created in the SecretMountPath at a single level
|
||||
// i.e. /var/run/secrets/foo
|
||||
srcPath := container.getLocalSecretPath(r)
|
||||
mounts = append(mounts, Mount{
|
||||
Source: srcPath,
|
||||
Destination: getSecretTargetPath(r),
|
||||
Writable: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
return mounts
|
||||
}
|
||||
|
||||
// UnmountSecrets unmounts the local tmpfs for secrets
|
||||
|
|
|
@ -10,6 +10,10 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
)
|
||||
|
||||
const (
|
||||
containerSecretMountPath = `C:\ProgramData\Docker\secrets`
|
||||
)
|
||||
|
||||
// Container holds fields specific to the Windows implementation. See
|
||||
// CommonContainer for standard fields common to all containers.
|
||||
type Container struct {
|
||||
|
@ -43,8 +47,8 @@ func (container *Container) IpcMounts() []Mount {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SecretMount returns the mount for the secret path
|
||||
func (container *Container) SecretMount() *Mount {
|
||||
// SecretMounts returns the mount for the secret path
|
||||
func (container *Container) SecretMounts() []Mount {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -177,13 +177,9 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
|||
return fmt.Errorf("secret target type is not a file target")
|
||||
}
|
||||
|
||||
targetPath := filepath.Clean(s.File.Name)
|
||||
// ensure that the target is a filename only; no paths allowed
|
||||
if targetPath != filepath.Base(targetPath) {
|
||||
return fmt.Errorf("error creating secret: secret must not be a path")
|
||||
}
|
||||
|
||||
fPath := filepath.Join(localMountPath, targetPath)
|
||||
// secrets are created in the SecretMountPath at a single level
|
||||
// i.e. /var/run/secrets/foo
|
||||
fPath := filepath.Join(localMountPath, filepath.Base(s.File.Name))
|
||||
if err := idtools.MkdirAllAs(filepath.Dir(fPath), 0700, rootUID, rootGID); err != nil {
|
||||
return errors.Wrap(err, "error creating secret mount path")
|
||||
}
|
||||
|
|
|
@ -750,8 +750,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
|||
}
|
||||
ms = append(ms, tmpfsMounts...)
|
||||
|
||||
if m := c.SecretMount(); m != nil {
|
||||
ms = append(ms, *m)
|
||||
if m := c.SecretMounts(); m != nil {
|
||||
ms = append(ms, m...)
|
||||
}
|
||||
|
||||
sort.Sort(mounts(ms))
|
||||
|
|
|
@ -90,35 +90,48 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSimple(c *check.C) {
|
|||
c.Assert(refs[0].File.Name, checker.Equals, testName)
|
||||
c.Assert(refs[0].File.UID, checker.Equals, "0")
|
||||
c.Assert(refs[0].File.GID, checker.Equals, "0")
|
||||
|
||||
out, err = d.Cmd("service", "rm", serviceName)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
d.DeleteSecret(c, testName)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTarget(c *check.C) {
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
serviceName := "test-service-secret"
|
||||
testName := "test_secret"
|
||||
id := d.CreateSecret(c, swarm.SecretSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: testName,
|
||||
},
|
||||
Data: []byte("TESTINGDATA"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
||||
testTarget := "testing"
|
||||
testPaths := map[string]string{
|
||||
"app": "/etc/secret",
|
||||
"test_secret": "test_secret",
|
||||
}
|
||||
for testName, testTarget := range testPaths {
|
||||
serviceName := "svc-" + testName
|
||||
id := d.CreateSecret(c, swarm.SecretSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: testName,
|
||||
},
|
||||
Data: []byte("TESTINGDATA"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
||||
|
||||
out, err := d.Cmd("service", "create", "--name", serviceName, "--secret", fmt.Sprintf("source=%s,target=%s", testName, testTarget), "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
out, err := d.Cmd("service", "create", "--name", serviceName, "--secret", fmt.Sprintf("source=%s,target=%s", testName, testTarget), "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var refs []swarm.SecretReference
|
||||
c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
|
||||
c.Assert(refs, checker.HasLen, 1)
|
||||
var refs []swarm.SecretReference
|
||||
c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
|
||||
c.Assert(refs, checker.HasLen, 1)
|
||||
|
||||
c.Assert(refs[0].SecretName, checker.Equals, testName)
|
||||
c.Assert(refs[0].File, checker.Not(checker.IsNil))
|
||||
c.Assert(refs[0].File.Name, checker.Equals, testTarget)
|
||||
c.Assert(refs[0].SecretName, checker.Equals, testName)
|
||||
c.Assert(refs[0].File, checker.Not(checker.IsNil))
|
||||
c.Assert(refs[0].File.Name, checker.Equals, testTarget)
|
||||
|
||||
out, err = d.Cmd("service", "rm", serviceName)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
d.DeleteSecret(c, testName)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/csv"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -53,10 +52,6 @@ func (o *SecretOpt) Set(value string) error {
|
|||
case "source", "src":
|
||||
options.SecretName = value
|
||||
case "target":
|
||||
tDir, _ := filepath.Split(value)
|
||||
if tDir != "" {
|
||||
return fmt.Errorf("target must not be a path")
|
||||
}
|
||||
options.File.Name = value
|
||||
case "uid":
|
||||
options.File.UID = value
|
||||
|
|
Загрузка…
Ссылка в новой задаче