hughesjr / rpms / docker

Forked from rpms/docker 4 years ago
Clone

Blame SOURCES/secrets.patch

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 := "/"