Accepting request 480841 from Virtualization:containers
1 OBS-URL: https://build.opensuse.org/request/show/480841 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/docker?expand=0&rev=52
This commit is contained in:
commit
b61db04550
4
_service
4
_service
@ -3,8 +3,8 @@
|
|||||||
<param name="url">https://github.com/docker/docker.git</param>
|
<param name="url">https://github.com/docker/docker.git</param>
|
||||||
<param name="scm">git</param>
|
<param name="scm">git</param>
|
||||||
<param name="exclude">.git</param>
|
<param name="exclude">.git</param>
|
||||||
<param name="versionformat">1.12.6</param>
|
<param name="versionformat">1.13.0</param>
|
||||||
<param name="revision">v1.12.6</param>
|
<param name="revision">v1.13.0</param>
|
||||||
</service>
|
</service>
|
||||||
<service name="recompress" mode="disabled">
|
<service name="recompress" mode="disabled">
|
||||||
<param name="file">docker-*.tar</param>
|
<param name="file">docker-*.tar</param>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:ade8df08afa29834e772ae9061975801ff35bd2b4c7979df4ff4df8f22ffce8c
|
|
||||||
size 11190120
|
|
3
docker-1.13.0.tar.xz
Normal file
3
docker-1.13.0.tar.xz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1da90f2f637d55c7bef034761f0781a7cc4facdefc50b9d77f0c6a78185efe0a
|
||||||
|
size 5130016
|
@ -1,413 +0,0 @@
|
|||||||
From 17cd15ba4160f0e0830453529b9b01edc308d847 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Aleksa Sarai <asarai@suse.de>
|
|
||||||
Date: Mon, 11 Apr 2016 22:54:35 +1000
|
|
||||||
Subject: [PATCH] SUSE: implement SUSE container secrets
|
|
||||||
|
|
||||||
This allows for us to pass in host credentials to a container, allowing
|
|
||||||
for SUSEConnect to work with containers.
|
|
||||||
|
|
||||||
THIS PATCH IS NOT TO BE UPSTREAMED, DUE TO THE FACT THAT IT IS
|
|
||||||
SUSE-SPECIFIC, AND UPSTREAM DOES NOT APPROVE OF THIS CONCEPT BECAUSE IT
|
|
||||||
MAKES BUILDS NOT ENTIRELY REPRODUCIBLE.
|
|
||||||
|
|
||||||
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
|
||||||
---
|
|
||||||
container/container_unix.go | 63 ++++++++++++
|
|
||||||
daemon/container_operations_unix.go | 50 ++++++++++
|
|
||||||
daemon/daemon_unix.go | 6 +-
|
|
||||||
daemon/oci_linux.go | 6 ++
|
|
||||||
daemon/start.go | 6 ++
|
|
||||||
daemon/suse_secrets.go | 184 ++++++++++++++++++++++++++++++++++++
|
|
||||||
6 files changed, 313 insertions(+), 2 deletions(-)
|
|
||||||
create mode 100644 daemon/suse_secrets.go
|
|
||||||
|
|
||||||
diff --git a/container/container_unix.go b/container/container_unix.go
|
|
||||||
index 2727b81..07a0710 100644
|
|
||||||
--- a/container/container_unix.go
|
|
||||||
+++ b/container/container_unix.go
|
|
||||||
@@ -35,6 +35,8 @@ type Container struct {
|
|
||||||
HostsPath string
|
|
||||||
ShmPath string
|
|
||||||
ResolvConfPath string
|
|
||||||
+ // SUSE:secrets :: We need to add the container-specific secrets path here.
|
|
||||||
+ SuseSecretsPath string
|
|
||||||
SeccompProfile string
|
|
||||||
NoNewPrivileges bool
|
|
||||||
}
|
|
||||||
@@ -256,6 +258,67 @@ func (container *Container) IpcMounts() []Mount {
|
|
||||||
return mounts
|
|
||||||
}
|
|
||||||
|
|
||||||
+// SUSE:secrets :: SuseSecretsResourcePath returns the path to the container's
|
|
||||||
+// personal /run/secrets tmpfs.
|
|
||||||
+func (container *Container) SuseSecretsResourcePath() (string, error) {
|
|
||||||
+ return container.GetRootResourcePath("suse.secrets")
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SUSE:secrets :: SuseSecretMounts returns the list of mounts required for the
|
|
||||||
+// SUSE-specific /run/secrets patch. The container's personal /run/secrets tmpfs
|
|
||||||
+// has already been set up at this point.
|
|
||||||
+func (container *Container) SuseSecretMounts() []Mount {
|
|
||||||
+ var mounts []Mount
|
|
||||||
+
|
|
||||||
+ logrus.WithFields(logrus.Fields{
|
|
||||||
+ "container": container.ID,
|
|
||||||
+ "path": container.SuseSecretsPath,
|
|
||||||
+ "hasmount": container.HasMountFor("/run/secrets"),
|
|
||||||
+ }).Debug("SUSE:secrets :: adding container secrets to mountpoint")
|
|
||||||
+
|
|
||||||
+ // TODO(SUSE): How do we register for HasMountFor().
|
|
||||||
+ if !container.HasMountFor("/run/secrets") {
|
|
||||||
+ label.SetFileLabel(container.SuseSecretsPath, container.MountLabel)
|
|
||||||
+ mounts = append(mounts, Mount{
|
|
||||||
+ Source: container.SuseSecretsPath,
|
|
||||||
+ Destination: "/run/secrets",
|
|
||||||
+ Writable: true,
|
|
||||||
+ Propagation: volume.DefaultPropagationMode,
|
|
||||||
+ })
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return mounts
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SUSE:secrets :: Unmounts the container's personal /run/secrets tmpfs using the
|
|
||||||
+// provided function. This is done to clean up the mountpoints properly.
|
|
||||||
+func (container *Container) UnmountSuseSecretMounts(unmount func(string) error) {
|
|
||||||
+ logrus.WithFields(logrus.Fields{
|
|
||||||
+ "container": container.ID,
|
|
||||||
+ "hasmount": container.HasMountFor("/run/secrets"),
|
|
||||||
+ }).Debug("SUSE:secrets :: requested to clean up container secrets")
|
|
||||||
+
|
|
||||||
+ if !container.HasMountFor("/run/secrets") {
|
|
||||||
+ logrus.Debugf("SUSE:secrets :: cleaning up secrets mount for container")
|
|
||||||
+
|
|
||||||
+ suseSecretsPath, err := container.SuseSecretsResourcePath()
|
|
||||||
+ if err != nil {
|
|
||||||
+ logrus.Error("SUSE:secrets :: failed to clean up secrets mounts: no secrets resource path found for container %v: %v", container.ID, err)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if suseSecretsPath != "" {
|
|
||||||
+ logrus.WithFields(logrus.Fields{
|
|
||||||
+ "path": suseSecretsPath,
|
|
||||||
+ }).Debugf("SUSE:secrets :: actually unmounting conatiner secrets")
|
|
||||||
+
|
|
||||||
+ if err := unmount(suseSecretsPath); err != nil && !os.IsNotExist(err) {
|
|
||||||
+ // We can't error out here.
|
|
||||||
+ logrus.Warnf("SUSE:secrets :: failed to clean up secrets mounts: failed to umount %s: %v", suseSecretsPath, err)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
// UpdateContainer updates configuration of a container.
|
|
||||||
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
|
||||||
container.Lock()
|
|
||||||
diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go
|
|
||||||
index 55bd3fc..a3ab7fb 100644
|
|
||||||
--- a/daemon/container_operations_unix.go
|
|
||||||
+++ b/daemon/container_operations_unix.go
|
|
||||||
@@ -184,6 +184,56 @@ func (daemon *Daemon) getPidContainer(container *container.Container) (*containe
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
+// SUSE:secrets :: Create a container's personal /run/secrets tmpfs and fill it
|
|
||||||
+// with the host's credentials.
|
|
||||||
+func (daemon *Daemon) setupSuseSecrets(c *container.Container) (err error) {
|
|
||||||
+ c.SuseSecretsPath, err = c.SuseSecretsResourcePath()
|
|
||||||
+ if err != nil {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if !c.HasMountFor("/run/secrets") {
|
|
||||||
+ rootUID, rootGID := daemon.GetRemappedUIDGID()
|
|
||||||
+ if err = idtools.MkdirAllAs(c.SuseSecretsPath, 0700, rootUID, rootGID); err != nil {
|
|
||||||
+ return fmt.Errorf("SUSE:secrets :: failed to create container secret: %v", err)
|
|
||||||
+ }
|
|
||||||
+ if err = syscall.Mount("tmpfs", c.SuseSecretsPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("", c.GetMountLabel())); err != nil {
|
|
||||||
+ return fmt.Errorf("SUSE:secrets :: mounting secrets tmpfs: %v", err)
|
|
||||||
+ }
|
|
||||||
+ // We need to defer a cleanup, to make sure errors that occur before the container
|
|
||||||
+ // starts don't cause wasted memory due to tmpfs-es that aren't being used.
|
|
||||||
+ defer func() {
|
|
||||||
+ if err != nil {
|
|
||||||
+ logrus.Infof("SUSE::secrets :: cleaning up secrets mount due to failed setup")
|
|
||||||
+ c.UnmountSuseSecretMounts(detachMounted)
|
|
||||||
+ }
|
|
||||||
+ }()
|
|
||||||
+ if err = os.Chown(c.SuseSecretsPath, rootUID, rootGID); err != nil {
|
|
||||||
+ return fmt.Errorf("SUSE:secrets :: failed to chown container secret to (uid=%d,gid=%d): %v", rootUID, rootGID, err)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Now we need to inject the credentials. But in order to play properly with
|
|
||||||
+ // user namespaces, they must be owned by rootUID:rootGID.
|
|
||||||
+
|
|
||||||
+ data, err := getHostSuseSecretData()
|
|
||||||
+ if err != nil {
|
|
||||||
+ return fmt.Errorf("SUSE:secrets :: failed to get host secret data: %v", err)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ uidMap, gidMap := daemon.GetUIDGIDMaps()
|
|
||||||
+ for _, s := range data {
|
|
||||||
+ if err := s.SaveTo(c.SuseSecretsPath, uidMap, gidMap); err != nil {
|
|
||||||
+ logrus.WithFields(logrus.Fields{
|
|
||||||
+ "s.path": s.Path,
|
|
||||||
+ "path": c.SuseSecretsPath,
|
|
||||||
+ }).Errorf("SUSE:secrets :: failed to save secret data: %v", err)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
|
|
||||||
index f266912..2ced1b8 100644
|
|
||||||
--- a/daemon/daemon_unix.go
|
|
||||||
+++ b/daemon/daemon_unix.go
|
|
||||||
@@ -809,8 +809,10 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
|
|
||||||
// the container from unwanted side-effects on the rw layer.
|
|
||||||
func setupInitLayer(initLayer string, rootUID, rootGID int) error {
|
|
||||||
for pth, typ := range map[string]string{
|
|
||||||
- "/dev/pts": "dir",
|
|
||||||
- "/dev/shm": "dir",
|
|
||||||
+ "/dev/pts": "dir",
|
|
||||||
+ "/dev/shm": "dir",
|
|
||||||
+ // SUSE:secrets :: We need to add the mountpoint in the init layer.
|
|
||||||
+ "/run/secrets": "dir",
|
|
||||||
"/proc": "dir",
|
|
||||||
"/sys": "dir",
|
|
||||||
"/.dockerenv": "file",
|
|
||||||
diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go
|
|
||||||
index 4459d02..6af7d35 100644
|
|
||||||
--- a/daemon/oci_linux.go
|
|
||||||
+++ b/daemon/oci_linux.go
|
|
||||||
@@ -656,6 +656,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
|
|
||||||
if err := daemon.setupIpcDirs(c); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
+ // SUSE:secrets :: We need to set up the container-specific secrets tmpfs here.
|
|
||||||
+ if err := daemon.setupSuseSecrets(c); err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
|
|
||||||
ms, err := daemon.setupMounts(c)
|
|
||||||
if err != nil {
|
|
||||||
@@ -663,6 +667,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
|
|
||||||
}
|
|
||||||
ms = append(ms, c.IpcMounts()...)
|
|
||||||
ms = append(ms, c.TmpfsMounts()...)
|
|
||||||
+ // SUSE:secrets :: We add the mounts to the OCI config which containerd then uses.
|
|
||||||
+ ms = append(ms, c.SuseSecretMounts()...)
|
|
||||||
sort.Sort(mounts(ms))
|
|
||||||
if err := setMounts(daemon, &s, c, ms); err != nil {
|
|
||||||
return nil, fmt.Errorf("linux mounts: %v", err)
|
|
||||||
diff --git a/daemon/start.go b/daemon/start.go
|
|
||||||
index fcf24c5..57a8c33 100644
|
|
||||||
--- a/daemon/start.go
|
|
||||||
+++ b/daemon/start.go
|
|
||||||
@@ -173,6 +173,12 @@ func (daemon *Daemon) Cleanup(container *container.Container) {
|
|
||||||
|
|
||||||
container.UnmountIpcMounts(detachMounted)
|
|
||||||
|
|
||||||
+ // TODO(SUSE): Make sure this gets called by containerCleanup. Do we need to
|
|
||||||
+ // port this part of the patch there as well?
|
|
||||||
+
|
|
||||||
+ // SUSE:secrets :: We need to unmount stuff here so that we clean up properly.
|
|
||||||
+ container.UnmountSuseSecretMounts(detachMounted)
|
|
||||||
+
|
|
||||||
if err := daemon.conditionalUnmountOnCleanup(container); err != nil {
|
|
||||||
// FIXME: remove once reference counting for graphdrivers has been refactored
|
|
||||||
// Ensure that all the mounts are gone
|
|
||||||
diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..417a1a9
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/daemon/suse_secrets.go
|
|
||||||
@@ -0,0 +1,184 @@
|
|
||||||
+package daemon
|
|
||||||
+
|
|
||||||
+// SUSE:secrets :: This is a set of functions to copy host credentials into a
|
|
||||||
+// container's /run/secrets.
|
|
||||||
+
|
|
||||||
+import (
|
|
||||||
+ "io/ioutil"
|
|
||||||
+ "os"
|
|
||||||
+ "path/filepath"
|
|
||||||
+ "syscall"
|
|
||||||
+
|
|
||||||
+ "github.com/Sirupsen/logrus"
|
|
||||||
+ "github.com/docker/docker/pkg/idtools"
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+// TODO(SUSE): We need to reimplement this to use tar. Immediately.
|
|
||||||
+
|
|
||||||
+// Creating a fake file.
|
|
||||||
+type SuseFakeFile struct {
|
|
||||||
+ Path string
|
|
||||||
+ Uid int
|
|
||||||
+ Gid int
|
|
||||||
+ Mode os.FileMode
|
|
||||||
+ Data []byte
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (s *SuseFakeFile) SaveTo(dir string, uidMap, gidMap []idtools.IDMap) error {
|
|
||||||
+ // Create non-existant path components with an owner of root (other FakeFiles
|
|
||||||
+ // will clean this up if the owner is critical).
|
|
||||||
+ rootUid, rootGid, err := idtools.GetRootUIDGID(uidMap, gidMap)
|
|
||||||
+
|
|
||||||
+ path := filepath.Join(dir, s.Path)
|
|
||||||
+ if err := idtools.MkdirAllNewAs(filepath.Dir(path), 0755, rootUid, rootGid); err != nil && !os.IsExist(err) {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ uid, err := idtools.ToHost(s.Uid, uidMap)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ gid, err := idtools.ToHost(s.Gid, gidMap)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if s.Mode.IsDir() {
|
|
||||||
+ if err := idtools.MkdirAs(path, s.Mode, uid, gid); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if err := ioutil.WriteFile(path, s.Data, s.Mode); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return os.Chown(path, uid, gid)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// readDir will recurse into a directory prefix/dir, and return the set of secrets
|
|
||||||
+// in that directory. The Path attribute of each has the prefix stripped. Symlinks
|
|
||||||
+// are evaluated.
|
|
||||||
+func readDir(prefix, dir string) ([]*SuseFakeFile, error) {
|
|
||||||
+ var suseFiles []*SuseFakeFile
|
|
||||||
+
|
|
||||||
+ path := filepath.Join(prefix, dir)
|
|
||||||
+
|
|
||||||
+ fi, err := os.Stat(path)
|
|
||||||
+ if err != nil {
|
|
||||||
+ // Ignore dangling symlinks.
|
|
||||||
+ if os.IsNotExist(err) {
|
|
||||||
+ logrus.Warnf("SUSE:secrets :: dangling symlink: %s", path)
|
|
||||||
+ return suseFiles, nil
|
|
||||||
+ }
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ stat, ok := fi.Sys().(*syscall.Stat_t)
|
|
||||||
+ if !ok {
|
|
||||||
+ logrus.Warnf("SUSE:secrets :: failed to cast directory stat_t: defaulting to owned by root:root: %s", path)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ suseFiles = append(suseFiles, &SuseFakeFile{
|
|
||||||
+ Path: dir,
|
|
||||||
+ Uid: int(stat.Uid),
|
|
||||||
+ Gid: int(stat.Gid),
|
|
||||||
+ Mode: fi.Mode(),
|
|
||||||
+ })
|
|
||||||
+
|
|
||||||
+ files, err := ioutil.ReadDir(path)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for _, f := range files {
|
|
||||||
+ subpath := filepath.Join(dir, f.Name())
|
|
||||||
+
|
|
||||||
+ if f.IsDir() {
|
|
||||||
+ secrets, err := readDir(prefix, subpath)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ suseFiles = append(suseFiles, secrets...)
|
|
||||||
+ } else {
|
|
||||||
+ secrets, err := readFile(prefix, subpath)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ suseFiles = append(suseFiles, secrets...)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return suseFiles, nil
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func readFile(prefix, file string) ([]*SuseFakeFile, error) {
|
|
||||||
+ var suseFiles []*SuseFakeFile
|
|
||||||
+
|
|
||||||
+ path := filepath.Join(prefix, file)
|
|
||||||
+ fi, err := os.Stat(path)
|
|
||||||
+ if err != nil {
|
|
||||||
+ // Ignore dangling symlinks.
|
|
||||||
+ if os.IsNotExist(err) {
|
|
||||||
+ logrus.Warnf("SUSE:secrets :: dangling symlink: %s", path)
|
|
||||||
+ return suseFiles, nil
|
|
||||||
+ }
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ stat, ok := fi.Sys().(*syscall.Stat_t)
|
|
||||||
+ if !ok {
|
|
||||||
+ logrus.Warnf("SUSE:secrets :: failed to cast file stat_t: defaulting to owned by root:root: %s", path)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if fi.IsDir() {
|
|
||||||
+ secrets, err := readDir(prefix, file)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ suseFiles = append(suseFiles, secrets...)
|
|
||||||
+ } else {
|
|
||||||
+ bytes, err := ioutil.ReadFile(path)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ suseFiles = append(suseFiles, &SuseFakeFile{
|
|
||||||
+ Path: file,
|
|
||||||
+ Uid: int(stat.Uid),
|
|
||||||
+ Gid: int(stat.Gid),
|
|
||||||
+ Mode: fi.Mode(),
|
|
||||||
+ Data: bytes,
|
|
||||||
+ })
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return suseFiles, nil
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func getHostSuseSecretData() ([]*SuseFakeFile, error) {
|
|
||||||
+ secrets := []*SuseFakeFile{}
|
|
||||||
+
|
|
||||||
+ credentials, err := readDir("/etc/zypp", "credentials.d")
|
|
||||||
+ if err != nil {
|
|
||||||
+ if os.IsNotExist(err) {
|
|
||||||
+ credentials = []*SuseFakeFile{}
|
|
||||||
+ } else {
|
|
||||||
+ logrus.Errorf("SUSE:secrets :: error while reading zypp credentials: %s", err)
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ secrets = append(secrets, credentials...)
|
|
||||||
+
|
|
||||||
+ suseConnect, err := readFile("/etc", "SUSEConnect")
|
|
||||||
+ if err != nil {
|
|
||||||
+ if os.IsNotExist(err) {
|
|
||||||
+ suseConnect = []*SuseFakeFile{}
|
|
||||||
+ } else {
|
|
||||||
+ logrus.Errorf("SUSE:secrets :: error while reading /etc/SUSEConnect: %s", err)
|
|
||||||
+ return nil, err
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ secrets = append(secrets, suseConnect...)
|
|
||||||
+
|
|
||||||
+ return secrets, nil
|
|
||||||
+}
|
|
@ -1,3 +1,56 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Mar 17 11:08:03 UTC 2017 - asarai@suse.com
|
||||||
|
|
||||||
|
- Add a backport of fix to AppArmor lazy loading docker-exec case.
|
||||||
|
https://github.com/docker/docker/pull/31773
|
||||||
|
+ pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Mar 8 00:48:46 UTC 2017 - asarai@suse.com
|
||||||
|
|
||||||
|
- Clean up docker-mount-secrets.patch to use the new swarm secrets internals of
|
||||||
|
Docker 1.13.0, which removes the need to implement any secret handling
|
||||||
|
ourselves. This resulted in a split up of the patch.
|
||||||
|
- docker-mount-secrets.patch
|
||||||
|
+ secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch
|
||||||
|
+ secrets-0002-SUSE-implement-SUSE-container-secrets.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Mar 6 15:31:02 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
|
- Remove old plugins.json to prevent docker-1.13 to fail to start
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Mar 6 12:52:14 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
|
- Fix bsc#1026827: systemd TasksMax default throttles docker
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Mar 6 10:09:14 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
|
- Fix post section by adding shadow as a package requirement
|
||||||
|
Otherwise the groupadd instruction fails
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Sun Mar 5 04:54:52 UTC 2017 - asarai@suse.com
|
||||||
|
|
||||||
|
- Add patch to fix TestDaemonCommand failure in %check. This is an upstream
|
||||||
|
bug, and has an upstream PR to fix it https://github.com/docker/docker/pull/31549.
|
||||||
|
+ pr31549-cmd-docker-fix-TestDaemonCommand.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Feb 1 15:59:40 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
|
- update docker to 1.13.0
|
||||||
|
|
||||||
|
see details in https://github.com/docker/docker/releases/tag/v1.13.0
|
||||||
|
|
||||||
|
- use the same buildflags for building docker and for building the
|
||||||
|
tests.
|
||||||
|
|
||||||
|
- enable pkcs11:
|
||||||
|
https://github.com/docker/docker/commit/37fa75b3447007bb8ea311f02610bb383b0db77f
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Jan 27 12:30:18 UTC 2017 - bg@suse.com
|
Fri Jan 27 12:30:18 UTC 2017 - bg@suse.com
|
||||||
|
|
||||||
@ -8,20 +61,20 @@ Thu Jan 26 15:43:38 UTC 2017 - jmassaguerpla@suse.com
|
|||||||
|
|
||||||
- provide the oci runtime so that containers which were using an old
|
- provide the oci runtime so that containers which were using an old
|
||||||
runtime option, when started on the new docker version, the runtime
|
runtime option, when started on the new docker version, the runtime
|
||||||
is changed to the new one. fix bsc#1020806 bsc#1016992
|
is changed to the new one. fix bsc#1020806 bsc#1016992
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Jan 13 13:56:15 UTC 2017 - jmassaguerpla@suse.com
|
Fri Jan 13 13:56:15 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
- fix CVE-2016-9962 bsc#1012568 . Fix it by updating to 1.12.6
|
- fix CVE-2016-9962 bsc#1012568 . Fix it by updating to 1.12.6
|
||||||
plus an extra commit to fix liverestore:
|
plus an extra commit to fix liverestore:
|
||||||
https://github.com/docker/docker/commit/97cd32a6a9076306baa637a29bba84c3f1f3d218
|
https://github.com/docker/docker/commit/97cd32a6a9076306baa637a29bba84c3f1f3d218
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Jan 11 12:47:16 UTC 2017 - jmassaguerpla@suse.com
|
Wed Jan 11 12:47:16 UTC 2017 - jmassaguerpla@suse.com
|
||||||
|
|
||||||
- add "a wait" when starting docker service to fix
|
- add "a wait" when starting docker service to fix
|
||||||
bsc#1019251
|
bsc#1019251
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Dec 20 12:41:33 UTC 2016 - normand@linux.vnet.ibm.com
|
Tue Dec 20 12:41:33 UTC 2016 - normand@linux.vnet.ibm.com
|
||||||
|
@ -23,7 +23,7 @@ LimitCORE=infinity
|
|||||||
|
|
||||||
# Uncomment TasksMax if your systemd version supports it.
|
# Uncomment TasksMax if your systemd version supports it.
|
||||||
# Only systemd 226 and above support this property.
|
# Only systemd 226 and above support this property.
|
||||||
#TasksMax=infinity
|
TasksMax=infinity
|
||||||
|
|
||||||
# Set delegate yes so that systemd does not reset the cgroups of docker containers
|
# Set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||||
# Only systemd 218 and above support this property.
|
# Only systemd 218 and above support this property.
|
||||||
|
58
docker.spec
58
docker.spec
@ -36,7 +36,7 @@
|
|||||||
%global docker_migration_warnfile %{docker_store}/docker-update-message.txt
|
%global docker_migration_warnfile %{docker_store}/docker-update-message.txt
|
||||||
%define docker_graph %{docker_store}/graph
|
%define docker_graph %{docker_store}/graph
|
||||||
%define git_version 78d1802
|
%define git_version 78d1802
|
||||||
%define version_unconverted 1.12.6
|
%define version_unconverted 1.13.0
|
||||||
%define __arch_install_post export NO_BRP_STRIP_DEBUG=true
|
%define __arch_install_post export NO_BRP_STRIP_DEBUG=true
|
||||||
# When upgrading to a new version requires the service not to be restarted
|
# When upgrading to a new version requires the service not to be restarted
|
||||||
# Due to a long migration process update last_migration_version to the new version
|
# Due to a long migration process update last_migration_version to the new version
|
||||||
@ -44,7 +44,7 @@
|
|||||||
# 1.10.1
|
# 1.10.1
|
||||||
%global last_migration_version 1.10.1
|
%global last_migration_version 1.10.1
|
||||||
Name: docker
|
Name: docker
|
||||||
Version: 1.12.6
|
Version: 1.13.0
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: The Linux container runtime
|
Summary: The Linux container runtime
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
@ -59,7 +59,7 @@ Source7: README_SUSE.md
|
|||||||
Source8: docker-audit.rules
|
Source8: docker-audit.rules
|
||||||
Source9: docker-update-message.txt
|
Source9: docker-update-message.txt
|
||||||
Source10: tests.sh
|
Source10: tests.sh
|
||||||
Source11: docker_service_helper.sh
|
Source11: docker_service_helper.sh
|
||||||
# Fixes for architecture-specific issues (gcc-go).
|
# Fixes for architecture-specific issues (gcc-go).
|
||||||
Patch100: gcc-go-patches.patch
|
Patch100: gcc-go-patches.patch
|
||||||
Patch102: netlink_netns_powerpc.patch
|
Patch102: netlink_netns_powerpc.patch
|
||||||
@ -68,14 +68,21 @@ Patch103: boltdb_bolt_add_brokenUnaligned.patch
|
|||||||
# which is not snapshotted when images are committed. Note that if you modify
|
# which is not snapshotted when images are committed. Note that if you modify
|
||||||
# this patch, please also modify the patch in the suse-secrets-v<version>
|
# this patch, please also modify the patch in the suse-secrets-v<version>
|
||||||
# branch in http://github.com/suse/docker.mirror.
|
# branch in http://github.com/suse/docker.mirror.
|
||||||
Patch200: docker-mount-secrets.patch
|
Patch200: secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch
|
||||||
|
Patch201: secrets-0002-SUSE-implement-SUSE-container-secrets.patch
|
||||||
|
# PATCH-FIX-UPSTREAM: Backports.
|
||||||
Patch300: integration-cli-fix-TestInfoEnsureSucceeds.patch
|
Patch300: integration-cli-fix-TestInfoEnsureSucceeds.patch
|
||||||
|
Patch301: pr31549-cmd-docker-fix-TestDaemonCommand.patch
|
||||||
|
Patch302: pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch
|
||||||
BuildRequires: audit
|
BuildRequires: audit
|
||||||
BuildRequires: bash-completion
|
BuildRequires: bash-completion
|
||||||
|
BuildRequires: ca-certificates
|
||||||
BuildRequires: device-mapper-devel >= 1.2.68
|
BuildRequires: device-mapper-devel >= 1.2.68
|
||||||
BuildRequires: glibc-devel-static
|
BuildRequires: glibc-devel-static
|
||||||
BuildRequires: libapparmor-devel
|
BuildRequires: libapparmor-devel
|
||||||
BuildRequires: libbtrfs-devel >= 3.8
|
BuildRequires: libbtrfs-devel >= 3.8
|
||||||
|
BuildRequires: libseccomp-devel
|
||||||
|
BuildRequires: libtool
|
||||||
BuildRequires: procps
|
BuildRequires: procps
|
||||||
BuildRequires: sqlite3-devel
|
BuildRequires: sqlite3-devel
|
||||||
BuildRequires: systemd-devel
|
BuildRequires: systemd-devel
|
||||||
@ -83,12 +90,13 @@ BuildRequires: zsh
|
|||||||
Requires: apparmor-parser
|
Requires: apparmor-parser
|
||||||
Requires: bridge-utils
|
Requires: bridge-utils
|
||||||
Requires: ca-certificates-mozilla
|
Requires: ca-certificates-mozilla
|
||||||
|
Requires: docker-libnetwork = 0.0.0+git20161019.0f53435
|
||||||
# Containerd and runC are required as they are the only currently supported
|
# Containerd and runC are required as they are the only currently supported
|
||||||
# execdrivers of Docker. NOTE: The version pinning here matches upstream's
|
# execdrivers of Docker. NOTE: The version pinning here matches upstream's
|
||||||
# Dockerfile to ensure that we don't use a slightly incompatible version of
|
# Dockerfile to ensure that we don't use a slightly incompatible version of
|
||||||
# runC or containerd (which would be bad).
|
# runC or containerd (which would be bad).
|
||||||
Requires: containerd = 0.2.5+gitr569_2a5e70c
|
Requires: containerd = 0.2.5+gitr608_03e5862
|
||||||
Requires: runc = 0.1.1+gitr2819_50a19c6
|
Requires: runc = 0.1.1+gitr2942_2f7393a
|
||||||
# Provides mkfs.ext4 - used by Docker when devicemapper storage driver is used
|
# Provides mkfs.ext4 - used by Docker when devicemapper storage driver is used
|
||||||
Requires: e2fsprogs
|
Requires: e2fsprogs
|
||||||
Requires: git-core >= 1.7
|
Requires: git-core >= 1.7
|
||||||
@ -100,6 +108,7 @@ Requires: tar >= 1.26
|
|||||||
Requires: xz >= 4.9
|
Requires: xz >= 4.9
|
||||||
Requires(post): %fillup_prereq
|
Requires(post): %fillup_prereq
|
||||||
Requires(post): udev
|
Requires(post): udev
|
||||||
|
Requires(post): shadow
|
||||||
# Not necessary, but must be installed to have a smooth upgrade.
|
# Not necessary, but must be installed to have a smooth upgrade.
|
||||||
Recommends: docker-image-migrator
|
Recommends: docker-image-migrator
|
||||||
Conflicts: lxc < 1.0
|
Conflicts: lxc < 1.0
|
||||||
@ -169,6 +178,7 @@ Test package for docker. It contains the source code and the tests.
|
|||||||
# nothing
|
# nothing
|
||||||
%else
|
%else
|
||||||
%patch200 -p1
|
%patch200 -p1
|
||||||
|
%patch201 -p1
|
||||||
%endif
|
%endif
|
||||||
%ifnarch %{go_arches}
|
%ifnarch %{go_arches}
|
||||||
%patch100 -p1
|
%patch100 -p1
|
||||||
@ -176,6 +186,8 @@ Test package for docker. It contains the source code and the tests.
|
|||||||
%patch103 -p1
|
%patch103 -p1
|
||||||
%endif
|
%endif
|
||||||
%patch300 -p1
|
%patch300 -p1
|
||||||
|
%patch301 -p1
|
||||||
|
%patch302 -p1
|
||||||
cp %{SOURCE7} .
|
cp %{SOURCE7} .
|
||||||
cp %{SOURCE10} .
|
cp %{SOURCE10} .
|
||||||
|
|
||||||
@ -188,9 +200,18 @@ ln -s %{_bindir}/go-6 $tmphack/go
|
|||||||
export PATH=$tmphack:$PATH
|
export PATH=$tmphack:$PATH
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
# Note that these commands do not allow %%elseif.
|
||||||
|
# For versions equal to or below SLE12 && openSUSE_13.2 libdevmapper.h is not
|
||||||
|
# recent enough to define dm_task_deferred_remove(). (This is not true of
|
||||||
|
# SLE12_SP1 but we cannot distinguish it with this macro.)
|
||||||
|
BUILDTAGS="exclude_graphdriver_aufs apparmor seccomp selinux pkcs11"
|
||||||
|
%if 0%{?suse_version} <= 1320
|
||||||
|
BUILDTAGS="libdm_no_deferred_remove $BUILDTAGS"
|
||||||
|
%endif
|
||||||
|
|
||||||
(cat <<EOF
|
(cat <<EOF
|
||||||
export AUTO_GOPATH=1
|
export AUTO_GOPATH=1
|
||||||
export DOCKER_BUILDTAGS="exclude_graphdriver_aufs apparmor selinux"
|
export DOCKER_BUILDTAGS="$BUILDTAGS"
|
||||||
export DOCKER_GITCOMMIT=%{git_version}
|
export DOCKER_GITCOMMIT=%{git_version}
|
||||||
EOF
|
EOF
|
||||||
) > docker_build_env
|
) > docker_build_env
|
||||||
@ -233,22 +254,13 @@ cp -avr %{buildroot}/usr/src/%{name} $HOME/go/src/github.com/docker/docker
|
|||||||
|
|
||||||
cd $HOME/go/src/github.com/docker/docker
|
cd $HOME/go/src/github.com/docker/docker
|
||||||
|
|
||||||
# Note that these commands do not allow %%elseif.
|
|
||||||
# For versions equal to or below SLE12 && openSUSE_13.2 libdevmapper.h is not
|
|
||||||
# recent enough to define dm_task_deferred_remove(). (This is not true of
|
|
||||||
# SLE12_SP1 but we cannot distinguish it with this macro.)
|
|
||||||
EXCLUDE_TAGS=
|
|
||||||
%if 0%{?suse_version} <= 1320
|
|
||||||
EXCLUDE_TAGS="libdm_no_deferred_remove $EXCLUDE_TAGS"
|
|
||||||
%endif
|
|
||||||
|
|
||||||
# The command is taken from hack/make/test-unit and various test runs.
|
# The command is taken from hack/make/test-unit and various test runs.
|
||||||
# Everything that follows github.com/docker/pkg/integration-cli are packages
|
# Everything that follows github.com/docker/pkg/integration-cli are packages
|
||||||
# containing tests that cannot run in an obs build context.
|
# containing tests that cannot run in an obs build context.
|
||||||
PKG_LIST=$(go list -e \
|
PKG_LIST=$(go list -e \
|
||||||
-f '{{if ne .Name "github.com/docker/docker"}} {{.ImportPath}}
|
-f '{{if ne .Name "github.com/docker/docker"}} {{.ImportPath}}
|
||||||
{{end}}' \
|
{{end}}' \
|
||||||
-tags $EXCLUDE_TAGS \
|
-tags "$DOCKER_BUILDTAGS" \
|
||||||
-a "${BUILDFLAGS[@]}" ... \
|
-a "${BUILDFLAGS[@]}" ... \
|
||||||
| grep 'github.com/docker/docker' \
|
| grep 'github.com/docker/docker' \
|
||||||
| grep -v 'github.com/docker/docker/vendor' \
|
| grep -v 'github.com/docker/docker/vendor' \
|
||||||
@ -273,7 +285,7 @@ PKG_LIST=$(go list -e \
|
|||||||
| grep -v 'github.com/docker/docker/man$' \
|
| grep -v 'github.com/docker/docker/man$' \
|
||||||
| grep -v 'github.com/docker/docker/pkg/integration$')
|
| grep -v 'github.com/docker/docker/pkg/integration$')
|
||||||
|
|
||||||
go test -cover -ldflags -w -tags $EXCLUDE_TAGS -a -test.timeout=10m $PKG_LIST
|
go test -cover -ldflags -w -tags "$DOCKER_BUILDTAGS" -a -test.timeout=10m $PKG_LIST
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%install
|
%install
|
||||||
@ -282,11 +294,9 @@ install -d %{buildroot}%{_bindir}
|
|||||||
%ifarch %{go_arches}
|
%ifarch %{go_arches}
|
||||||
install -D -m755 bundles/latest/dynbinary-client/%{name} %{buildroot}/%{_bindir}/%{name}
|
install -D -m755 bundles/latest/dynbinary-client/%{name} %{buildroot}/%{_bindir}/%{name}
|
||||||
install -D -m755 bundles/latest/dynbinary-daemon/%{name}d %{buildroot}/%{_bindir}/%{name}d
|
install -D -m755 bundles/latest/dynbinary-daemon/%{name}d %{buildroot}/%{_bindir}/%{name}d
|
||||||
install -D -m755 bundles/latest/dynbinary-daemon/%{name}-proxy %{buildroot}/%{_bindir}/%{name}-proxy
|
|
||||||
%else
|
%else
|
||||||
install -D -m755 bundles/latest/dyngccgo/%{name} %{buildroot}/%{_bindir}/%{name}
|
install -D -m755 bundles/latest/dyngccgo/%{name} %{buildroot}/%{_bindir}/%{name}
|
||||||
install -D -m755 bundles/latest/dyngccgo/%{name}d %{buildroot}/%{_bindir}/%{name}d
|
install -D -m755 bundles/latest/dyngccgo/%{name}d %{buildroot}/%{_bindir}/%{name}d
|
||||||
install -D -m755 bundles/latest/dyngccgo/%{name}-proxy %{buildroot}/%{_bindir}/%{name}-proxy
|
|
||||||
%endif
|
%endif
|
||||||
install -d %{buildroot}/%{_prefix}/lib/docker
|
install -d %{buildroot}/%{_prefix}/lib/docker
|
||||||
install -Dd -m 0755 \
|
install -Dd -m 0755 \
|
||||||
@ -374,6 +384,13 @@ else
|
|||||||
rm %{docker_migration_warnfile}
|
rm %{docker_migration_warnfile}
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# If plugins.json is present, docker will fail to start
|
||||||
|
# https://github.com/docker/docker/releases/1.13.0
|
||||||
|
if [ -e /var/lib/docker/plugins/plugins.json ];then
|
||||||
|
echo "Warning: Disabling previous installed plugins"
|
||||||
|
echo "Otherwise docker will fail to boot"
|
||||||
|
mv /var/lib/docker/plugins/plugins.json /var/lib/docker/plugins/_plugins.json.old
|
||||||
|
fi
|
||||||
%service_add_post %{name}.service
|
%service_add_post %{name}.service
|
||||||
%{fillup_only -n docker}
|
%{fillup_only -n docker}
|
||||||
|
|
||||||
@ -392,7 +409,6 @@ fi
|
|||||||
%doc README.md LICENSE README_SUSE.md
|
%doc README.md LICENSE README_SUSE.md
|
||||||
%{_bindir}/docker
|
%{_bindir}/docker
|
||||||
%{_bindir}/dockerd
|
%{_bindir}/dockerd
|
||||||
%{_bindir}/docker-proxy
|
|
||||||
%{_sbindir}/rcdocker
|
%{_sbindir}/rcdocker
|
||||||
%{_libexecdir}/docker/
|
%{_libexecdir}/docker/
|
||||||
%{_unitdir}/%{name}.service
|
%{_unitdir}/%{name}.service
|
||||||
|
@ -1,18 +1,8 @@
|
|||||||
From 0f0c0fcb5b956782385e25c7c6c625e6c79ac78f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Thomas Hipp <thipp@suse.de>
|
|
||||||
Date: Wed, 7 Sep 2016 10:54:09 +0200
|
|
||||||
Subject: [PATCH] integration-cli: fix TestInfoEnsureSucceeds
|
|
||||||
|
|
||||||
Signed-off-by: Thomas Hipp <thipp@suse.de>
|
|
||||||
---
|
|
||||||
integration-cli/docker_cli_info_test.go | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/integration-cli/docker_cli_info_test.go b/integration-cli/docker_cli_info_test.go
|
diff --git a/integration-cli/docker_cli_info_test.go b/integration-cli/docker_cli_info_test.go
|
||||||
index a48e69a..c265a36 100644
|
index 62ce7e2..46516f9 100644
|
||||||
--- a/integration-cli/docker_cli_info_test.go
|
--- a/integration-cli/docker_cli_info_test.go
|
||||||
+++ b/integration-cli/docker_cli_info_test.go
|
+++ b/integration-cli/docker_cli_info_test.go
|
||||||
@@ -36,7 +36,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
|
@@ -40,7 +40,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if DaemonIsLinux.Condition() {
|
if DaemonIsLinux.Condition() {
|
||||||
@ -20,7 +10,4 @@ index a48e69a..c265a36 100644
|
|||||||
+ stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: oci")
|
+ stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: oci")
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.ExperimentalBuild() {
|
if experimentalDaemon {
|
||||||
--
|
|
||||||
2.9.3
|
|
||||||
|
|
||||||
|
49
pr31549-cmd-docker-fix-TestDaemonCommand.patch
Normal file
49
pr31549-cmd-docker-fix-TestDaemonCommand.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
From dd7159060f60ea04007c069df189a29fda2c655f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleksa Sarai <asarai@suse.de>
|
||||||
|
Date: Sun, 5 Mar 2017 15:25:11 +1100
|
||||||
|
Subject: [PATCH] cmd: docker: fix TestDaemonCommand
|
||||||
|
|
||||||
|
In more recent versions of Cobra, `--help` parsing is done before
|
||||||
|
anything else resulting in TestDaemonCommand not actually passing. I'm
|
||||||
|
actually unsure if this test ever passed since it appears that !daemon
|
||||||
|
is not being run as part of the test suite.
|
||||||
|
|
||||||
|
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
||||||
|
---
|
||||||
|
cmd/docker/daemon_none.go | 6 ++++--
|
||||||
|
cmd/docker/daemon_none_test.go | 2 +-
|
||||||
|
2 files changed, 5 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cmd/docker/daemon_none.go b/cmd/docker/daemon_none.go
|
||||||
|
index 65f9f37be22f..6fbd00012526 100644
|
||||||
|
--- a/cmd/docker/daemon_none.go
|
||||||
|
+++ b/cmd/docker/daemon_none.go
|
||||||
|
@@ -12,8 +12,10 @@ import (
|
||||||
|
|
||||||
|
func newDaemonCommand() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
- Use: "daemon",
|
||||||
|
- Hidden: true,
|
||||||
|
+ Use: "daemon",
|
||||||
|
+ Hidden: true,
|
||||||
|
+ Args: cobra.ArbitraryArgs,
|
||||||
|
+ DisableFlagParsing: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runDaemon()
|
||||||
|
},
|
||||||
|
diff --git a/cmd/docker/daemon_none_test.go b/cmd/docker/daemon_none_test.go
|
||||||
|
index 32032fe1b344..bd42add98696 100644
|
||||||
|
--- a/cmd/docker/daemon_none_test.go
|
||||||
|
+++ b/cmd/docker/daemon_none_test.go
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
|
func TestDaemonCommand(t *testing.T) {
|
||||||
|
cmd := newDaemonCommand()
|
||||||
|
- cmd.SetArgs([]string{"--help"})
|
||||||
|
+ cmd.SetArgs([]string{"--version"})
|
||||||
|
err := cmd.Execute()
|
||||||
|
|
||||||
|
assert.Error(t, err, "Please run `dockerd`")
|
||||||
|
--
|
||||||
|
2.12.0
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
From 790a81ea9acce318d0e037771c253951b874140b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleksa Sarai <asarai@suse.de>
|
||||||
|
Date: Mon, 13 Mar 2017 14:57:35 +1100
|
||||||
|
Subject: [PATCH] daemon: also ensureDefaultApparmorProfile in exec path
|
||||||
|
|
||||||
|
When 567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor
|
||||||
|
profiles") was merged, it didn't correctly handle the exec path if
|
||||||
|
AppArmor profiles were deleted. Fix this by duplicating the
|
||||||
|
ensureDefaultApparmorProfile code in the exec code.
|
||||||
|
|
||||||
|
Fixes: 567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor profiles")
|
||||||
|
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
||||||
|
---
|
||||||
|
daemon/exec_linux.go | 23 +++++++++++++++++++++++
|
||||||
|
1 file changed, 23 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemon/exec_linux.go b/daemon/exec_linux.go
|
||||||
|
index 5aeedc347027..bb11c11e447c 100644
|
||||||
|
--- a/daemon/exec_linux.go
|
||||||
|
+++ b/daemon/exec_linux.go
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
||||||
|
"github.com/docker/docker/daemon/caps"
|
||||||
|
"github.com/docker/docker/daemon/exec"
|
||||||
|
"github.com/docker/docker/libcontainerd"
|
||||||
|
+ "github.com/opencontainers/runc/libcontainer/apparmor"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -23,5 +24,27 @@ func execSetPlatformOpt(c *container.Container, ec *exec.Config, p *libcontainer
|
||||||
|
if ec.Privileged {
|
||||||
|
p.Capabilities = caps.GetAllCapabilities()
|
||||||
|
}
|
||||||
|
+ if apparmor.IsEnabled() {
|
||||||
|
+ var appArmorProfile string
|
||||||
|
+ if c.AppArmorProfile != "" {
|
||||||
|
+ appArmorProfile = c.AppArmorProfile
|
||||||
|
+ } else if c.HostConfig.Privileged {
|
||||||
|
+ appArmorProfile = "unconfined"
|
||||||
|
+ } else {
|
||||||
|
+ appArmorProfile = "docker-default"
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if appArmorProfile == "docker-default" {
|
||||||
|
+ // Unattended upgrades and other fun services can unload AppArmor
|
||||||
|
+ // profiles inadvertently. Since we cannot store our profile in
|
||||||
|
+ // /etc/apparmor.d, nor can we practically add other ways of
|
||||||
|
+ // telling the system to keep our profile loaded, in order to make
|
||||||
|
+ // sure that we keep the default profile enabled we dynamically
|
||||||
|
+ // reload it if necessary.
|
||||||
|
+ if err := ensureDefaultAppArmorProfile(); err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.12.0
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 0c4cf4fac76f2a5272a808665985a2e0df6af0db Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleksa Sarai <asarai@suse.de>
|
||||||
|
Date: Wed, 8 Mar 2017 12:41:54 +1100
|
||||||
|
Subject: [PATCH 1/2] daemon: allow directory creation in /run/secrets
|
||||||
|
|
||||||
|
Since FileMode can have the directory bit set, allow a SecretStore
|
||||||
|
implementation to return secrets that are actually directories. This is
|
||||||
|
useful for creating directories and subdirectories of secrets.
|
||||||
|
|
||||||
|
Backport: https://github.com/docker/docker/pull/31632
|
||||||
|
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
||||||
|
---
|
||||||
|
daemon/container_operations_unix.go | 10 ++++++++--
|
||||||
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go
|
||||||
|
index 2296045765d4..8527a7907373 100644
|
||||||
|
--- a/daemon/container_operations_unix.go
|
||||||
|
+++ b/daemon/container_operations_unix.go
|
||||||
|
@@ -195,8 +195,14 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
||||||
|
if secret == nil {
|
||||||
|
return fmt.Errorf("unable to get secret from secret store")
|
||||||
|
}
|
||||||
|
- if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil {
|
||||||
|
- return errors.Wrap(err, "error injecting secret")
|
||||||
|
+ if s.File.Mode.IsDir() {
|
||||||
|
+ if err := os.Mkdir(fPath, s.File.Mode); err != nil {
|
||||||
|
+ return errors.Wrap(err, "error injecting secret dir")
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil {
|
||||||
|
+ return errors.Wrap(err, "error injecting secret")
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, err := strconv.Atoi(s.File.UID)
|
||||||
|
--
|
||||||
|
2.12.0
|
||||||
|
|
290
secrets-0002-SUSE-implement-SUSE-container-secrets.patch
Normal file
290
secrets-0002-SUSE-implement-SUSE-container-secrets.patch
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
From a3106907d4786ed7d624201debdd43dc41fb4b97 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleksa Sarai <asarai@suse.de>
|
||||||
|
Date: Wed, 8 Mar 2017 11:43:29 +1100
|
||||||
|
Subject: [PATCH 2/2] SUSE: implement SUSE container secrets
|
||||||
|
|
||||||
|
This allows for us to pass in host credentials to a container, allowing
|
||||||
|
for SUSEConnect to work with containers.
|
||||||
|
|
||||||
|
THIS PATCH IS NOT TO BE UPSTREAMED, DUE TO THE FACT THAT IT IS
|
||||||
|
SUSE-SPECIFIC, AND UPSTREAM DOES NOT APPROVE OF THIS CONCEPT BECAUSE IT
|
||||||
|
MAKES BUILDS NOT ENTIRELY REPRODUCIBLE.
|
||||||
|
|
||||||
|
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
||||||
|
---
|
||||||
|
daemon/start.go | 5 +
|
||||||
|
daemon/suse_secrets.go | 246 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 251 insertions(+)
|
||||||
|
create mode 100644 daemon/suse_secrets.go
|
||||||
|
|
||||||
|
diff --git a/daemon/start.go b/daemon/start.go
|
||||||
|
index 6c94fd5482d0..3c06eed778d7 100644
|
||||||
|
--- a/daemon/start.go
|
||||||
|
+++ b/daemon/start.go
|
||||||
|
@@ -146,6 +146,11 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // SUSE:secrets -- inject the SUSE secret store
|
||||||
|
+ if err := daemon.injectSuseSecretStore(container); err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
spec, err := daemon.createSpec(container)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000000..591abc998e67
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/daemon/suse_secrets.go
|
||||||
|
@@ -0,0 +1,246 @@
|
||||||
|
+/*
|
||||||
|
+ * suse-secrets: patch for Docker to implement SUSE secrets
|
||||||
|
+ * Copyright (C) 2017 SUSE LLC.
|
||||||
|
+ *
|
||||||
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
+ * you may not use this file except in compliance with the License.
|
||||||
|
+ * You may obtain a copy of the License at
|
||||||
|
+ *
|
||||||
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
+ *
|
||||||
|
+ * Unless required by applicable law or agreed to in writing, software
|
||||||
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
+ * See the License for the specific language governing permissions and
|
||||||
|
+ * limitations under the License.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+package daemon
|
||||||
|
+
|
||||||
|
+import (
|
||||||
|
+ "fmt"
|
||||||
|
+ "io/ioutil"
|
||||||
|
+ "os"
|
||||||
|
+ "path/filepath"
|
||||||
|
+ "syscall"
|
||||||
|
+
|
||||||
|
+ "github.com/Sirupsen/logrus"
|
||||||
|
+ "github.com/docker/distribution/digest"
|
||||||
|
+ "github.com/docker/docker/container"
|
||||||
|
+
|
||||||
|
+ swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||||
|
+ swarmexec "github.com/docker/swarmkit/agent/exec"
|
||||||
|
+ swarmapi "github.com/docker/swarmkit/api"
|
||||||
|
+)
|
||||||
|
+
|
||||||
|
+func init() {
|
||||||
|
+ // Output to tell us in logs that SUSE:secrets is enabled.
|
||||||
|
+ logrus.Infof("SUSE:secrets :: enabled")
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// Creating a fake file.
|
||||||
|
+type SuseFakeFile struct {
|
||||||
|
+ Path string
|
||||||
|
+ Uid int
|
||||||
|
+ Gid int
|
||||||
|
+ Mode os.FileMode
|
||||||
|
+ Data []byte
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func (s SuseFakeFile) id() string {
|
||||||
|
+ return fmt.Sprintf("suse::%s:%s", digest.FromBytes(s.Data), s.Path)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func (s SuseFakeFile) toSecret() *swarmapi.Secret {
|
||||||
|
+ return &swarmapi.Secret{
|
||||||
|
+ ID: s.id(),
|
||||||
|
+ Internal: true,
|
||||||
|
+ Spec: swarmapi.SecretSpec{
|
||||||
|
+ Data: s.Data,
|
||||||
|
+ },
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func (s SuseFakeFile) toSecretReference() *swarmtypes.SecretReference {
|
||||||
|
+ return &swarmtypes.SecretReference{
|
||||||
|
+ SecretID: s.id(),
|
||||||
|
+ SecretName: s.id(),
|
||||||
|
+ File: &swarmtypes.SecretReferenceFileTarget{
|
||||||
|
+ Name: s.Path,
|
||||||
|
+ UID: fmt.Sprintf("%d", s.Uid),
|
||||||
|
+ GID: fmt.Sprintf("%d", s.Gid),
|
||||||
|
+ Mode: s.Mode,
|
||||||
|
+ },
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// readDir will recurse into a directory prefix/dir, and return the set of secrets
|
||||||
|
+// in that directory. The Path attribute of each has the prefix stripped. Symlinks
|
||||||
|
+// are evaluated.
|
||||||
|
+func readDir(prefix, dir string) ([]*SuseFakeFile, error) {
|
||||||
|
+ var suseFiles []*SuseFakeFile
|
||||||
|
+
|
||||||
|
+ path := filepath.Join(prefix, dir)
|
||||||
|
+
|
||||||
|
+ fi, err := os.Stat(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ // Ignore dangling symlinks.
|
||||||
|
+ if os.IsNotExist(err) {
|
||||||
|
+ logrus.Warnf("SUSE:secrets :: dangling symlink: %s", path)
|
||||||
|
+ return suseFiles, nil
|
||||||
|
+ }
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ stat, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
|
+ if !ok {
|
||||||
|
+ logrus.Warnf("SUSE:secrets :: failed to cast directory stat_t: defaulting to owned by root:root: %s", path)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ suseFiles = append(suseFiles, &SuseFakeFile{
|
||||||
|
+ Path: dir,
|
||||||
|
+ Uid: int(stat.Uid),
|
||||||
|
+ Gid: int(stat.Gid),
|
||||||
|
+ Mode: fi.Mode(),
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+ files, err := ioutil.ReadDir(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for _, f := range files {
|
||||||
|
+ subpath := filepath.Join(dir, f.Name())
|
||||||
|
+
|
||||||
|
+ if f.IsDir() {
|
||||||
|
+ secrets, err := readDir(prefix, subpath)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ suseFiles = append(suseFiles, secrets...)
|
||||||
|
+ } else {
|
||||||
|
+ secrets, err := readFile(prefix, subpath)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ suseFiles = append(suseFiles, secrets...)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return suseFiles, nil
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// readFile returns a secret given a file under a given prefix.
|
||||||
|
+func readFile(prefix, file string) ([]*SuseFakeFile, error) {
|
||||||
|
+ var suseFiles []*SuseFakeFile
|
||||||
|
+
|
||||||
|
+ path := filepath.Join(prefix, file)
|
||||||
|
+ fi, err := os.Stat(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ // Ignore dangling symlinks.
|
||||||
|
+ if os.IsNotExist(err) {
|
||||||
|
+ logrus.Warnf("SUSE:secrets :: dangling symlink: %s", path)
|
||||||
|
+ return suseFiles, nil
|
||||||
|
+ }
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ stat, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
|
+ if !ok {
|
||||||
|
+ logrus.Warnf("SUSE:secrets :: failed to cast file stat_t: defaulting to owned by root:root: %s", path)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if fi.IsDir() {
|
||||||
|
+ secrets, err := readDir(prefix, file)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ suseFiles = append(suseFiles, secrets...)
|
||||||
|
+ } else {
|
||||||
|
+ bytes, err := ioutil.ReadFile(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ suseFiles = append(suseFiles, &SuseFakeFile{
|
||||||
|
+ Path: file,
|
||||||
|
+ Uid: int(stat.Uid),
|
||||||
|
+ Gid: int(stat.Gid),
|
||||||
|
+ Mode: fi.Mode(),
|
||||||
|
+ Data: bytes,
|
||||||
|
+ })
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return suseFiles, nil
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// getHostSuseSecretData returns the list of SuseFakeFiles the need to be added
|
||||||
|
+// as SUSE secrets.
|
||||||
|
+func getHostSuseSecretData() ([]*SuseFakeFile, error) {
|
||||||
|
+ secrets := []*SuseFakeFile{}
|
||||||
|
+
|
||||||
|
+ credentials, err := readDir("/etc/zypp", "credentials.d")
|
||||||
|
+ if err != nil {
|
||||||
|
+ if os.IsNotExist(err) {
|
||||||
|
+ credentials = []*SuseFakeFile{}
|
||||||
|
+ } else {
|
||||||
|
+ logrus.Errorf("SUSE:secrets :: error while reading zypp credentials: %s", err)
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ secrets = append(secrets, credentials...)
|
||||||
|
+
|
||||||
|
+ suseConnect, err := readFile("/etc", "SUSEConnect")
|
||||||
|
+ if err != nil {
|
||||||
|
+ if os.IsNotExist(err) {
|
||||||
|
+ suseConnect = []*SuseFakeFile{}
|
||||||
|
+ } else {
|
||||||
|
+ logrus.Errorf("SUSE:secrets :: error while reading /etc/SUSEConnect: %s", err)
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ secrets = append(secrets, suseConnect...)
|
||||||
|
+
|
||||||
|
+ return secrets, nil
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// In order to reduce the amount of code touched outside of this file, we
|
||||||
|
+// implement the swarm API for SecretGetter. This asserts that this requirement
|
||||||
|
+// will always be matched.
|
||||||
|
+var _ swarmexec.SecretGetter = &suseSecretGetter{}
|
||||||
|
+
|
||||||
|
+type suseSecretGetter struct {
|
||||||
|
+ dfl swarmexec.SecretGetter
|
||||||
|
+ secrets map[string]*swarmapi.Secret
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func (s *suseSecretGetter) Get(id string) *swarmapi.Secret {
|
||||||
|
+ logrus.Debugf("SUSE:secrets :: id=%s requested from suseSecretGetter", id)
|
||||||
|
+
|
||||||
|
+ secret, ok := s.secrets[id]
|
||||||
|
+ if !ok {
|
||||||
|
+ // fallthrough
|
||||||
|
+ return s.dfl.Get(id)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return secret
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func (daemon *Daemon) injectSuseSecretStore(c *container.Container) error {
|
||||||
|
+ newSecretStore := &suseSecretGetter{
|
||||||
|
+ dfl: c.SecretStore,
|
||||||
|
+ secrets: make(map[string]*swarmapi.Secret),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ secrets, err := getHostSuseSecretData()
|
||||||
|
+ if err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for _, secret := range secrets {
|
||||||
|
+ newSecretStore.secrets[secret.id()] = secret.toSecret()
|
||||||
|
+ c.SecretReferences = append(c.SecretReferences, secret.toSecretReference())
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ c.SecretStore = newSecretStore
|
||||||
|
+ return nil
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.12.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user