diff -up docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/container.go.secrets docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/container.go
--- docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/container.go.secrets 2014-07-22 20:29:56.000000000 -0400
+++ docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/container.go 2014-09-10 16:34:28.489624522 -0400
@@ -277,6 +277,9 @@ func (container *Container) Start() (err
if err := populateCommand(container, env); err != nil {
return err
}
+ if err := container.setupSecretFiles(); err != nil {
+ return err
+ }
if err := setupMountsForContainer(container); err != nil {
return err
}
@@ -284,7 +287,21 @@ func (container *Container) Start() (err
return err
}
- return container.waitForStart()
+ if err := container.waitForStart(); err != nil {
+ return err
+ }
+
+ // Now the container is running, unmount the secrets on the host
+ secretsPath, err := container.secretsPath()
+ if err != nil {
+ return err
+ }
+
+ if err := syscall.Unmount(secretsPath, syscall.MNT_DETACH); err != nil {
+ return err
+ }
+
+ return nil
}
func (container *Container) Run() error {
@@ -711,6 +728,10 @@ func (container *Container) jsonPath() (
return container.getRootResourcePath("config.json")
}
+func (container *Container) secretsPath() (string, error) {
+ return container.getRootResourcePath("secrets")
+}
+
// This method must be exported to be used from the lxc template
// This directory is only usable when the container is running
func (container *Container) RootfsPath() string {
@@ -962,6 +983,31 @@ func (container *Container) verifyDaemon
}
}
+func (container *Container) setupSecretFiles() error {
+ secretsPath, err := container.secretsPath()
+ if err != nil {
+ return err
+ }
+
+ if err := os.MkdirAll(secretsPath, 0700); err != nil {
+ return err
+ }
+
+ if err := syscall.Mount("tmpfs", secretsPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("", container.GetMountLabel())); err != nil {
+ return fmt.Errorf("mounting secret tmpfs: %s", err)
+ }
+
+ data, err := getHostSecretData()
+ if err != nil {
+ return err
+ }
+ for _, s := range data {
+ s.SaveTo(secretsPath)
+ }
+
+ return nil
+}
+
func (container *Container) setupLinkedContainers() ([]string, error) {
var (
env []string
diff -up docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/secrets.go.secrets docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/secrets.go
--- docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/secrets.go.secrets 2014-09-10 16:28:26.922130421 -0400
+++ docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/secrets.go 2014-09-10 16:28:26.922130421 -0400
@@ -0,0 +1,86 @@
+package daemon
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+type Secret struct {
+ Name string
+ IsDir bool
+ HostBased bool
+}
+
+type SecretData struct {
+ Name string
+ Data []byte
+}
+
+func (s SecretData) SaveTo(dir string) error {
+ path := filepath.Join(dir, s.Name)
+ if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil && !os.IsExist(err) {
+ return err
+ }
+ if err := ioutil.WriteFile(path, s.Data, 0755); err != nil {
+ return err
+ }
+ return nil
+}
+
+func readAll(root, prefix string) ([]SecretData, error) {
+ path := filepath.Join(root, prefix)
+
+ data := []SecretData{}
+
+ files, err := ioutil.ReadDir(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return data, nil
+ }
+
+ return nil, err
+ }
+
+ for _, f := range files {
+ fileData, err := readFile(root, filepath.Join(prefix, f.Name()))
+ if err != nil {
+ // If the file did not exist, might be a dangling symlink
+ // Ignore the error
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ data = append(data, fileData...)
+ }
+
+ return data, nil
+}
+
+func readFile(root, name string) ([]SecretData, error) {
+ path := filepath.Join(root, name)
+
+ s, err := os.Stat(path)
+ if err != nil {
+ return nil, err
+ }
+
+ if s.IsDir() {
+ dirData, err := readAll(root, name)
+ if err != nil {
+ return nil, err
+ }
+ return dirData, nil
+ } else {
+ bytes, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ return []SecretData{{Name: name, Data: bytes}}, nil
+ }
+}
+
+func getHostSecretData() ([]SecretData, error) {
+ return readAll("/usr/share/rhel/secrets", "")
+}
diff -up docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/volumes.go.secrets docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/volumes.go
--- docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/volumes.go.secrets 2014-09-10 16:28:26.922130421 -0400
+++ docker-d84a070e476ce923dd03e28232564a87704613ab/daemon/volumes.go 2014-09-10 16:40:34.683228046 -0400
@@ -48,6 +48,13 @@ func setupMountsForContainer(container *
mounts = append(mounts, execdriver.Mount{container.HostsPath, "/etc/hosts", false, true})
}
+ secretsPath, err := container.secretsPath()
+ if err != nil {
+ return err
+ }
+
+ mounts = append(mounts, execdriver.Mount{secretsPath, "/run/secrets", true, true})
+
// Mount user specified volumes
// Note, these are not private because you may want propagation of (un)mounts from host
// volumes. For instance if you use -v /usr:/usr and the host later mounts /usr/share you
diff -up docker-d84a070e476ce923dd03e28232564a87704613ab/graph/graph.go.secrets docker-d84a070e476ce923dd03e28232564a87704613ab/graph/graph.go
--- docker-d84a070e476ce923dd03e28232564a87704613ab/graph/graph.go.secrets 2014-07-22 20:29:56.000000000 -0400
+++ docker-d84a070e476ce923dd03e28232564a87704613ab/graph/graph.go 2014-09-10 16:28:26.923130420 -0400
@@ -266,6 +266,7 @@ func SetupInitLayer(initLayer string) er
"/etc/hostname": "file",
"/dev/console": "file",
"/etc/mtab": "/proc/mounts",
+ "/run/secrets": "dir",
} {
parts := strings.Split(pth, "/")
prev := "/"