|
|
a2b5ed |
From ed97ccf535888a5e1fa2cadf42d01089e1192e06 Mon Sep 17 00:00:00 2001
|
|
|
a2b5ed |
From: Dan Walsh <dwalsh@redhat.com>
|
|
|
a2b5ed |
Date: Thu, 13 Nov 2014 15:28:39 -0500
|
|
|
a2b5ed |
Subject: [PATCH] Super Secrets Patch
|
|
|
a2b5ed |
|
|
|
a2b5ed |
Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
|
|
|
a2b5ed |
---
|
|
|
a2b5ed |
daemon/container.go | 48 +++++++++++++++++++++++++++++-
|
|
|
a2b5ed |
daemon/secrets.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
a2b5ed |
daemon/volumes.go | 11 +++++++
|
|
|
a2b5ed |
graph/graph.go | 1 +
|
|
|
a2b5ed |
4 files changed, 145 insertions(+), 1 deletion(-)
|
|
|
a2b5ed |
create mode 100644 daemon/secrets.go
|
|
|
a2b5ed |
|
|
|
a2b5ed |
diff --git a/daemon/container.go b/daemon/container.go
|
|
|
a2b5ed |
index 2ac8316..b754105 100644
|
|
|
a2b5ed |
--- a/daemon/container.go
|
|
|
a2b5ed |
+++ b/daemon/container.go
|
|
|
a2b5ed |
@@ -338,11 +338,28 @@ func (container *Container) Start() (err error) {
|
|
|
a2b5ed |
if err := populateCommand(container, env); err != nil {
|
|
|
a2b5ed |
return err
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
+ if err := container.setupSecretFiles(); err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
if err := container.setupMounts(); err != nil {
|
|
|
a2b5ed |
return err
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
|
|
|
a2b5ed |
- return container.waitForStart()
|
|
|
a2b5ed |
+ if err := container.waitForStart(); err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ // Now the container is running, unmount the secrets on the host
|
|
|
a2b5ed |
+ secretsPath, err := container.secretsPath()
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ if err := syscall.Unmount(secretsPath, syscall.MNT_DETACH); err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ return nil
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
|
|
|
a2b5ed |
func (container *Container) Run() error {
|
|
|
a2b5ed |
@@ -793,6 +810,10 @@ func (container *Container) jsonPath() (string, error) {
|
|
|
a2b5ed |
return container.getRootResourcePath("config.json")
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
|
|
|
a2b5ed |
+func (container *Container) secretsPath() (string, error) {
|
|
|
a2b5ed |
+ return container.getRootResourcePath("secrets")
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
// This method must be exported to be used from the lxc template
|
|
|
a2b5ed |
// This directory is only usable when the container is running
|
|
|
a2b5ed |
func (container *Container) RootfsPath() string {
|
|
|
a2b5ed |
@@ -1064,6 +1085,31 @@ func (container *Container) verifyDaemonSettings() {
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
|
|
|
a2b5ed |
+func (container *Container) setupSecretFiles() error {
|
|
|
a2b5ed |
+ secretsPath, err := container.secretsPath()
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ if err := os.MkdirAll(secretsPath, 0700); err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ if err := syscall.Mount("tmpfs", secretsPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("", container.GetMountLabel())); err != nil {
|
|
|
a2b5ed |
+ return fmt.Errorf("mounting secret tmpfs: %s", err)
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ data, err := getHostSecretData()
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ for _, s := range data {
|
|
|
a2b5ed |
+ s.SaveTo(secretsPath)
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ return nil
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
func (container *Container) setupLinkedContainers() ([]string, error) {
|
|
|
a2b5ed |
var (
|
|
|
a2b5ed |
env []string
|
|
|
a2b5ed |
diff --git a/daemon/secrets.go b/daemon/secrets.go
|
|
|
a2b5ed |
new file mode 100644
|
|
|
a2b5ed |
index 0000000..8bd97a5
|
|
|
a2b5ed |
--- /dev/null
|
|
|
a2b5ed |
+++ b/daemon/secrets.go
|
|
|
a2b5ed |
@@ -0,0 +1,86 @@
|
|
|
a2b5ed |
+package daemon
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+import (
|
|
|
a2b5ed |
+ "io/ioutil"
|
|
|
a2b5ed |
+ "os"
|
|
|
a2b5ed |
+ "path/filepath"
|
|
|
a2b5ed |
+)
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+type Secret struct {
|
|
|
a2b5ed |
+ Name string
|
|
|
a2b5ed |
+ IsDir bool
|
|
|
a2b5ed |
+ HostBased bool
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+type SecretData struct {
|
|
|
a2b5ed |
+ Name string
|
|
|
a2b5ed |
+ Data []byte
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+func (s SecretData) SaveTo(dir string) error {
|
|
|
a2b5ed |
+ path := filepath.Join(dir, s.Name)
|
|
|
a2b5ed |
+ if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil && !os.IsExist(err) {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ if err := ioutil.WriteFile(path, s.Data, 0755); err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ return nil
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+func readAll(root, prefix string) ([]SecretData, error) {
|
|
|
a2b5ed |
+ path := filepath.Join(root, prefix)
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ data := []SecretData{}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ files, err := ioutil.ReadDir(path)
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ if os.IsNotExist(err) {
|
|
|
a2b5ed |
+ return data, nil
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ return nil, err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ for _, f := range files {
|
|
|
a2b5ed |
+ fileData, err := readFile(root, filepath.Join(prefix, f.Name()))
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ // If the file did not exist, might be a dangling symlink
|
|
|
a2b5ed |
+ // Ignore the error
|
|
|
a2b5ed |
+ if os.IsNotExist(err) {
|
|
|
a2b5ed |
+ continue
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ return nil, err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ data = append(data, fileData...)
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ return data, nil
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+func readFile(root, name string) ([]SecretData, error) {
|
|
|
a2b5ed |
+ path := filepath.Join(root, name)
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ s, err := os.Stat(path)
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return nil, err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ if s.IsDir() {
|
|
|
a2b5ed |
+ dirData, err := readAll(root, name)
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return nil, err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ return dirData, nil
|
|
|
a2b5ed |
+ } else {
|
|
|
a2b5ed |
+ bytes, err := ioutil.ReadFile(path)
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return nil, err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+ return []SecretData{{Name: name, Data: bytes}}, nil
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+func getHostSecretData() ([]SecretData, error) {
|
|
|
a2b5ed |
+ return readAll("/usr/share/rhel/secrets", "")
|
|
|
a2b5ed |
+}
|
|
|
a2b5ed |
diff --git a/daemon/volumes.go b/daemon/volumes.go
|
|
|
a2b5ed |
index 6523dae..322d3f4 100644
|
|
|
a2b5ed |
--- a/daemon/volumes.go
|
|
|
a2b5ed |
+++ b/daemon/volumes.go
|
|
|
a2b5ed |
@@ -260,6 +260,17 @@ func (container *Container) setupMounts() error {
|
|
|
a2b5ed |
})
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
|
|
|
a2b5ed |
+ secretsPath, err := container.secretsPath()
|
|
|
a2b5ed |
+ if err != nil {
|
|
|
a2b5ed |
+ return err
|
|
|
a2b5ed |
+ }
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
+ mounts = append(mounts, execdriver.Mount{
|
|
|
a2b5ed |
+ Source: secretsPath,
|
|
|
a2b5ed |
+ Destination: "/run/secrets",
|
|
|
a2b5ed |
+ Writable: true,
|
|
|
a2b5ed |
+ })
|
|
|
a2b5ed |
+
|
|
|
a2b5ed |
container.command.Mounts = mounts
|
|
|
a2b5ed |
return nil
|
|
|
a2b5ed |
}
|
|
|
a2b5ed |
diff --git a/graph/graph.go b/graph/graph.go
|
|
|
a2b5ed |
index 720f6e6..647b64d 100644
|
|
|
a2b5ed |
--- a/graph/graph.go
|
|
|
a2b5ed |
+++ b/graph/graph.go
|
|
|
a2b5ed |
@@ -242,6 +242,7 @@ func SetupInitLayer(initLayer string) error {
|
|
|
a2b5ed |
"/etc/hostname": "file",
|
|
|
a2b5ed |
"/dev/console": "file",
|
|
|
a2b5ed |
"/etc/mtab": "/proc/mounts",
|
|
|
a2b5ed |
+ "/run/secrets": "dir",
|
|
|
a2b5ed |
} {
|
|
|
a2b5ed |
parts := strings.Split(pth, "/")
|
|
|
a2b5ed |
prev := "/"
|