Merge pull request #1960 from hashicorp/fix-perm-issues

Fixed permission issues on client
This commit is contained in:
Diptanu Choudhury
2016-11-08 12:57:18 -08:00
committed by GitHub
2 changed files with 134 additions and 5 deletions

View File

@@ -313,13 +313,12 @@ func (d *AllocDir) Embed(task string, entries map[string]string) error {
// Embedding a single file
if !s.IsDir() {
destDir := filepath.Join(taskdir, filepath.Dir(dest))
if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
if err := d.createDir(taskdir, filepath.Dir(dest)); err != nil {
return fmt.Errorf("Couldn't create destination directory %v: %v", dest, err)
}
// Copy the file.
taskEntry := filepath.Join(destDir, filepath.Base(dest))
taskEntry := filepath.Join(taskdir, dest)
if err := d.linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil {
return err
}
@@ -329,7 +328,8 @@ func (d *AllocDir) Embed(task string, entries map[string]string) error {
// Create destination directory.
destDir := filepath.Join(taskdir, dest)
if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
if err := d.createDir(taskdir, dest); err != nil {
return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
}
@@ -565,3 +565,67 @@ func (d *AllocDir) GetSecretDir(task string) (string, error) {
return filepath.Join(t, TaskSecrets), nil
}
}
// createDir creates a directory structure inside the basepath. This functions
// preserves the permissions of each of the subdirectories in the relative path
// by looking up the permissions in the host.
func (d *AllocDir) createDir(basePath, relPath string) error {
filePerms, err := d.splitPath(relPath)
if err != nil {
return err
}
// We are going backwards since we create the root of the directory first
// and then create the entire nested structure.
for i := len(filePerms) - 1; i >= 0; i-- {
fi := filePerms[i]
destDir := filepath.Join(basePath, fi.Name)
if err := os.MkdirAll(destDir, fi.Perm); err != nil {
return err
}
}
return nil
}
// fileInfo holds the path and the permissions of a file
type fileInfo struct {
Name string
Perm os.FileMode
}
// splitPath stats each subdirectory of a path. The first element of the array
// is the file passed to this method, and the last element is the root of the
// path.
func (d *AllocDir) splitPath(path string) ([]fileInfo, error) {
var mode os.FileMode
i, err := os.Stat(path)
// If the path is not present in the host then we respond with the most
// flexible permission.
if err != nil {
mode = os.ModePerm
} else {
mode = i.Mode()
}
var dirs []fileInfo
dirs = append(dirs, fileInfo{Name: path, Perm: mode})
currentDir := path
for {
dir := filepath.Dir(filepath.Clean(currentDir))
if dir == currentDir {
break
}
// We try to find the permission of the file in the host. If the path is not
// present in the host then we respond with the most flexible permission.
i, err = os.Stat(dir)
if err != nil {
mode = os.ModePerm
} else {
mode = i.Mode()
}
dirs = append(dirs, fileInfo{Name: dir, Perm: mode})
currentDir = dir
}
return dirs, nil
}

View File

@@ -5,6 +5,7 @@ import (
"bytes"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"reflect"
@@ -417,3 +418,67 @@ func TestAllocDir_ReadAt_SecretDir(t *testing.T) {
t.Fatalf("ReadAt of secret file didn't error: %v", err)
}
}
func TestAllocDir_SplitPath(t *testing.T) {
dir, err := ioutil.TempDir("/tmp", "tmpdirtest")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
dest := filepath.Join(dir, "/foo/bar/baz")
if err := os.MkdirAll(dest, os.ModePerm); err != nil {
t.Fatalf("err: %v", err)
}
d := NewAllocDir(dir)
defer d.Destroy()
info, err := d.splitPath(dest)
if err != nil {
t.Fatalf("err: %v", err)
}
if len(info) != 6 {
t.Fatalf("expected: %v, actual: %v", 6, len(info))
}
}
func TestAllocDir_CreateDir(t *testing.T) {
dir, err := ioutil.TempDir("/tmp", "tmpdirtest")
if err != nil {
t.Fatalf("err: %v", err)
}
defer os.RemoveAll(dir)
// create a subdir and a file
subdir := filepath.Join(dir, "subdir")
if err := os.MkdirAll(subdir, 0760); err != nil {
t.Fatalf("err: %v", err)
}
subdirMode, err := os.Stat(subdir)
if err != nil {
t.Fatalf("err: %v", err)
}
// Create the above hierarchy under another destination
dir1, err := ioutil.TempDir("/tmp", "tempdirdest")
if err != nil {
t.Fatalf("err: %v", err)
}
d := NewAllocDir(dir)
defer d.Destroy()
if err := d.createDir(dir1, subdir); err != nil {
t.Fatalf("err: %v", err)
}
// Ensure that the subdir had the right perm
fi, err := os.Stat(filepath.Join(dir1, dir, "subdir"))
if err != nil {
t.Fatalf("err: %v", err)
}
if fi.Mode() != subdirMode.Mode() {
t.Fatalf("wrong file mode: %v, expected: %v", fi.Mode(), subdirMode.Mode())
}
}