diff options
author | Nick Thomas <nick@gitlab.com> | 2019-03-13 13:12:58 +0000 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2019-03-13 13:12:58 +0000 |
commit | 049beb74303a03d9fa598d23b150e0ccea3cd60d (patch) | |
tree | 739325471ad815cdd14cdf1eea5c7b27e4f0c046 | |
parent | 6109b64ed81f80e90bf094ad1f1ded8f5e5f8324 (diff) | |
parent | f9d3d8b301c90d05012ac3a8ec53d0ff1dd3aa79 (diff) | |
download | gitlab-shell-049beb74303a03d9fa598d23b150e0ccea3cd60d.tar.gz |
Merge branch 'bvl-parse-secret' into 'master'
Get secret from config
See merge request gitlab-org/gitlab-shell!284
-rw-r--r-- | go/internal/config/config.go | 47 | ||||
-rw-r--r-- | go/internal/config/config_test.go | 94 | ||||
-rw-r--r-- | go/internal/handler/exec_test.go | 54 | ||||
-rw-r--r-- | go/internal/testhelper/testdata/testroot/.gitlab_shell_secret | 1 | ||||
-rw-r--r-- | go/internal/testhelper/testdata/testroot/config.yml | 0 | ||||
-rw-r--r-- | go/internal/testhelper/testdata/testroot/custom/my-contents-is-secret | 1 | ||||
-rw-r--r-- | go/internal/testhelper/testdata/testroot/gitlab-shell.log | 0 | ||||
-rw-r--r-- | go/internal/testhelper/testhelper.go | 72 | ||||
-rw-r--r-- | go/vendor/github.com/otiai10/copy/LICENSE | 21 | ||||
-rw-r--r-- | go/vendor/github.com/otiai10/copy/README.md | 14 | ||||
-rw-r--r-- | go/vendor/github.com/otiai10/copy/copy.go | 106 | ||||
-rw-r--r-- | go/vendor/github.com/otiai10/copy/go.mod | 6 | ||||
-rw-r--r-- | go/vendor/github.com/otiai10/copy/go.sum | 4 | ||||
-rw-r--r-- | go/vendor/vendor.json | 10 |
14 files changed, 343 insertions, 87 deletions
diff --git a/go/internal/config/config.go b/go/internal/config/config.go index f951fe6..d2afcdc 100644 --- a/go/internal/config/config.go +++ b/go/internal/config/config.go @@ -5,14 +5,16 @@ import ( "net/url" "os" "path" + "path/filepath" "strings" yaml "gopkg.in/yaml.v2" ) const ( - configFile = "config.yml" - logFile = "gitlab-shell.log" + configFile = "config.yml" + logFile = "gitlab-shell.log" + defaultSecretFileName = ".gitlab_shell_secret" ) type MigrationConfig struct { @@ -21,12 +23,14 @@ type MigrationConfig struct { } type Config struct { - RootDir string - LogFile string `yaml:"log_file"` - LogFormat string `yaml:"log_format"` - Migration MigrationConfig `yaml:"migration"` - GitlabUrl string `yaml:"gitlab_url"` - GitlabTracing string `yaml:"gitlab_tracing"` + RootDir string + LogFile string `yaml:"log_file"` + LogFormat string `yaml:"log_format"` + Migration MigrationConfig `yaml:"migration"` + GitlabUrl string `yaml:"gitlab_url"` + GitlabTracing string `yaml:"gitlab_tracing"` + SecretFilePath string `yaml:"secret_file"` + Secret string `yaml:"secret"` } func New() (*Config, error) { @@ -102,5 +106,32 @@ func parseConfig(configBytes []byte, cfg *Config) error { cfg.GitlabUrl = unescapedUrl } + if err := parseSecret(cfg); err != nil { + return err + } + + return nil +} + +func parseSecret(cfg *Config) error { + // The secret was parsed from yaml no need to read another file + if cfg.Secret != "" { + return nil + } + + if cfg.SecretFilePath == "" { + cfg.SecretFilePath = defaultSecretFileName + } + + if !filepath.IsAbs(cfg.SecretFilePath) { + cfg.SecretFilePath = path.Join(cfg.RootDir, cfg.SecretFilePath) + } + + secretFileContent, err := ioutil.ReadFile(cfg.SecretFilePath) + if err != nil { + return err + } + cfg.Secret = string(secretFileContent) + return nil } diff --git a/go/internal/config/config_test.go b/go/internal/config/config_test.go index 6640f42..e1e49d7 100644 --- a/go/internal/config/config_test.go +++ b/go/internal/config/config_test.go @@ -2,63 +2,105 @@ package config import ( "fmt" - "strings" + "path" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper" +) + +const ( + customSecret = "custom/my-contents-is-secret" +) + +var ( + testRoot = testhelper.TestRoot ) func TestParseConfig(t *testing.T) { - testRoot := "/foo/bar" + cleanup, err := testhelper.PrepareTestRootDir() + require.NoError(t, err) + defer cleanup() + testCases := []struct { yaml string path string format string gitlabUrl string migration MigrationConfig + secret string }{ - {path: "/foo/bar/gitlab-shell.log", format: "text"}, - {yaml: "log_file: my-log.log", path: "/foo/bar/my-log.log", format: "text"}, - {yaml: "log_file: /qux/my-log.log", path: "/qux/my-log.log", format: "text"}, - {yaml: "log_format: json", path: "/foo/bar/gitlab-shell.log", format: "json"}, + { + path: path.Join(testRoot, "gitlab-shell.log"), + format: "text", + secret: "default-secret-content", + }, + { + yaml: "log_file: my-log.log", + path: path.Join(testRoot, "my-log.log"), + format: "text", + secret: "default-secret-content", + }, + { + yaml: "log_file: /qux/my-log.log", + path: "/qux/my-log.log", + format: "text", + secret: "default-secret-content", + }, + { + yaml: "log_format: json", + path: path.Join(testRoot, "gitlab-shell.log"), + format: "json", + secret: "default-secret-content", + }, { yaml: "migration:\n enabled: true\n features:\n - foo\n - bar", - path: "/foo/bar/gitlab-shell.log", + path: path.Join(testRoot, "gitlab-shell.log"), format: "text", migration: MigrationConfig{Enabled: true, Features: []string{"foo", "bar"}}, + secret: "default-secret-content", }, { yaml: "gitlab_url: http+unix://%2Fpath%2Fto%2Fgitlab%2Fgitlab.socket", - path: "/foo/bar/gitlab-shell.log", + path: path.Join(testRoot, "gitlab-shell.log"), format: "text", gitlabUrl: "http+unix:///path/to/gitlab/gitlab.socket", + secret: "default-secret-content", + }, + { + yaml: fmt.Sprintf("secret_file: %s", customSecret), + path: path.Join(testRoot, "gitlab-shell.log"), + format: "text", + secret: "custom-secret-content", + }, + { + yaml: fmt.Sprintf("secret_file: %s", path.Join(testRoot, customSecret)), + path: path.Join(testRoot, "gitlab-shell.log"), + format: "text", + secret: "custom-secret-content", + }, + { + yaml: "secret: an inline secret", + path: path.Join(testRoot, "gitlab-shell.log"), + format: "text", + secret: "an inline secret", }, } for _, tc := range testCases { t.Run(fmt.Sprintf("yaml input: %q", tc.yaml), func(t *testing.T) { cfg := Config{RootDir: testRoot} - if err := parseConfig([]byte(tc.yaml), &cfg); err != nil { - t.Fatal(err) - } - - if cfg.Migration.Enabled != tc.migration.Enabled { - t.Fatalf("migration.enabled: expected %v, got %v", tc.migration.Enabled, cfg.Migration.Enabled) - } - - if strings.Join(cfg.Migration.Features, ":") != strings.Join(tc.migration.Features, ":") { - t.Fatalf("migration.features: expected %#v, got %#v", tc.migration.Features, cfg.Migration.Features) - } - - if cfg.LogFile != tc.path { - t.Fatalf("expected %q, got %q", tc.path, cfg.LogFile) - } - if cfg.LogFormat != tc.format { - t.Fatalf("expected %q, got %q", tc.format, cfg.LogFormat) - } + err := parseConfig([]byte(tc.yaml), &cfg) + require.NoError(t, err) + assert.Equal(t, tc.migration.Enabled, cfg.Migration.Enabled, "migration.enabled not equal") + assert.Equal(t, tc.migration.Features, cfg.Migration.Features, "migration.features not equal") + assert.Equal(t, tc.path, cfg.LogFile) + assert.Equal(t, tc.format, cfg.LogFormat) assert.Equal(t, tc.gitlabUrl, cfg.GitlabUrl) + assert.Equal(t, tc.secret, cfg.Secret) }) } } diff --git a/go/internal/handler/exec_test.go b/go/internal/handler/exec_test.go index e19ebc4..bf17826 100644 --- a/go/internal/handler/exec_test.go +++ b/go/internal/handler/exec_test.go @@ -3,12 +3,10 @@ package handler import ( "context" "fmt" - "io/ioutil" - "os" - "path/filepath" "testing" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper" "google.golang.org/grpc" ) @@ -88,7 +86,7 @@ func TestInteralRunHandler(t *testing.T) { currentTest = nil }() - done, err := createEnv() + done, err := testhelper.PrepareTestRootDir() defer done() require.NoError(t, err) @@ -103,51 +101,3 @@ func TestInteralRunHandler(t *testing.T) { }) } } - -// createEnv sets up an environment for `config.New()`. -func createEnv() (func(), error) { - var dir string - var oldWd string - closer := func() { - if oldWd != "" { - err := os.Chdir(oldWd) - if err != nil { - panic(err) - } - } - - if dir != "" { - err := os.RemoveAll(dir) - if err != nil { - panic(err) - } - } - } - - dir, err := ioutil.TempDir("", "test") - if err != nil { - return closer, err - } - - err = ioutil.WriteFile(filepath.Join(dir, "config.yml"), []byte{}, 0644) - if err != nil { - return closer, err - } - - err = ioutil.WriteFile(filepath.Join(dir, "gitlab-shell.log"), []byte{}, 0644) - if err != nil { - return closer, err - } - - oldWd, err = os.Getwd() - if err != nil { - return closer, err - } - - err = os.Chdir(dir) - if err != nil { - return closer, err - } - - return closer, err -} diff --git a/go/internal/testhelper/testdata/testroot/.gitlab_shell_secret b/go/internal/testhelper/testdata/testroot/.gitlab_shell_secret new file mode 100644 index 0000000..9bd459d --- /dev/null +++ b/go/internal/testhelper/testdata/testroot/.gitlab_shell_secret @@ -0,0 +1 @@ +default-secret-content
\ No newline at end of file diff --git a/go/internal/testhelper/testdata/testroot/config.yml b/go/internal/testhelper/testdata/testroot/config.yml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/go/internal/testhelper/testdata/testroot/config.yml diff --git a/go/internal/testhelper/testdata/testroot/custom/my-contents-is-secret b/go/internal/testhelper/testdata/testroot/custom/my-contents-is-secret new file mode 100644 index 0000000..645b575 --- /dev/null +++ b/go/internal/testhelper/testdata/testroot/custom/my-contents-is-secret @@ -0,0 +1 @@ +custom-secret-content
\ No newline at end of file diff --git a/go/internal/testhelper/testdata/testroot/gitlab-shell.log b/go/internal/testhelper/testdata/testroot/gitlab-shell.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/go/internal/testhelper/testdata/testroot/gitlab-shell.log diff --git a/go/internal/testhelper/testhelper.go b/go/internal/testhelper/testhelper.go index 5cdab89..5c900aa 100644 --- a/go/internal/testhelper/testhelper.go +++ b/go/internal/testhelper/testhelper.go @@ -1,6 +1,18 @@ package testhelper -import "os" +import ( + "fmt" + "io/ioutil" + "os" + "path" + "runtime" + + "github.com/otiai10/copy" +) + +var ( + TestRoot, _ = ioutil.TempDir("", "test-gitlab-shell") +) func TempEnv(env map[string]string) func() { var original = make(map[string]string) @@ -15,3 +27,61 @@ func TempEnv(env map[string]string) func() { } } } + +func PrepareTestRootDir() (func(), error) { + if err := os.MkdirAll(TestRoot, 0700); err != nil { + return nil, err + } + + var oldWd string + cleanup := func() { + if oldWd != "" { + err := os.Chdir(oldWd) + if err != nil { + panic(err) + } + } + + if err := os.RemoveAll(TestRoot); err != nil { + panic(err) + } + } + + if err := copyTestData(); err != nil { + cleanup() + return nil, err + } + + oldWd, err := os.Getwd() + if err != nil { + cleanup() + return nil, err + } + + if err := os.Chdir(TestRoot); err != nil { + cleanup() + return nil, err + } + + return cleanup, nil +} + +func copyTestData() error { + testDataDir, err := getTestDataDir() + if err != nil { + return err + } + + testdata := path.Join(testDataDir, "testroot") + + return copy.Copy(testdata, TestRoot) +} + +func getTestDataDir() (string, error) { + _, currentFile, _, ok := runtime.Caller(0) + if !ok { + return "", fmt.Errorf("Could not get caller info") + } + + return path.Join(path.Dir(currentFile), "testdata"), nil +} diff --git a/go/vendor/github.com/otiai10/copy/LICENSE b/go/vendor/github.com/otiai10/copy/LICENSE new file mode 100644 index 0000000..1f0cc5d --- /dev/null +++ b/go/vendor/github.com/otiai10/copy/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 otiai10 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/go/vendor/github.com/otiai10/copy/README.md b/go/vendor/github.com/otiai10/copy/README.md new file mode 100644 index 0000000..f5729fa --- /dev/null +++ b/go/vendor/github.com/otiai10/copy/README.md @@ -0,0 +1,14 @@ +# copy + +[![Build Status](https://travis-ci.org/otiai10/copy.svg?branch=master)](https://travis-ci.org/otiai10/copy) +[![codecov](https://codecov.io/gh/otiai10/copy/branch/master/graph/badge.svg)](https://codecov.io/gh/otiai10/copy) +[![GoDoc](https://godoc.org/github.com/otiai10/copy?status.svg)](https://godoc.org/github.com/otiai10/copy) +[![Go Report Card](https://goreportcard.com/badge/github.com/otiai10/copy)](https://goreportcard.com/report/github.com/otiai10/copy) + +`copy` copies directories recursively. + +Example: + +```go +err := Copy("your/directory", "your/directory.copy") +``` diff --git a/go/vendor/github.com/otiai10/copy/copy.go b/go/vendor/github.com/otiai10/copy/copy.go new file mode 100644 index 0000000..52afac4 --- /dev/null +++ b/go/vendor/github.com/otiai10/copy/copy.go @@ -0,0 +1,106 @@ +package copy + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" +) + +const ( + // tmpPermissionForDirectory makes the destination directory writable, + // so that stuff can be copied recursively even if any original directory is NOT writable. + // See https://github.com/otiai10/copy/pull/9 for more information. + tmpPermissionForDirectory = os.FileMode(0755) +) + +// Copy copies src to dest, doesn't matter if src is a directory or a file +func Copy(src, dest string) error { + info, err := os.Lstat(src) + if err != nil { + return err + } + return copy(src, dest, info) +} + +// copy dispatches copy-funcs according to the mode. +// Because this "copy" could be called recursively, +// "info" MUST be given here, NOT nil. +func copy(src, dest string, info os.FileInfo) error { + if info.Mode()&os.ModeSymlink != 0 { + return lcopy(src, dest, info) + } + if info.IsDir() { + return dcopy(src, dest, info) + } + return fcopy(src, dest, info) +} + +// fcopy is for just a file, +// with considering existence of parent directory +// and file permission. +func fcopy(src, dest string, info os.FileInfo) error { + + if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil { + return err + } + + f, err := os.Create(dest) + if err != nil { + return err + } + defer f.Close() + + if err = os.Chmod(f.Name(), info.Mode()); err != nil { + return err + } + + s, err := os.Open(src) + if err != nil { + return err + } + defer s.Close() + + _, err = io.Copy(f, s) + return err +} + +// dcopy is for a directory, +// with scanning contents inside the directory +// and pass everything to "copy" recursively. +func dcopy(srcdir, destdir string, info os.FileInfo) error { + + originalMode := info.Mode() + + // Make dest dir with 0755 so that everything writable. + if err := os.MkdirAll(destdir, tmpPermissionForDirectory); err != nil { + return err + } + // Recover dir mode with original one. + defer os.Chmod(destdir, originalMode) + + contents, err := ioutil.ReadDir(srcdir) + if err != nil { + return err + } + + for _, content := range contents { + cs, cd := filepath.Join(srcdir, content.Name()), filepath.Join(destdir, content.Name()) + if err := copy(cs, cd, content); err != nil { + // If any error, exit immediately + return err + } + } + + return nil +} + +// lcopy is for a symlink, +// with just creating a new symlink by replicating src symlink. +func lcopy(src, dest string, info os.FileInfo) error { + src, err := os.Readlink(src) + if err != nil { + return err + } + return os.Symlink(src, dest) +} diff --git a/go/vendor/github.com/otiai10/copy/go.mod b/go/vendor/github.com/otiai10/copy/go.mod new file mode 100644 index 0000000..a436c21 --- /dev/null +++ b/go/vendor/github.com/otiai10/copy/go.mod @@ -0,0 +1,6 @@ +module github.com/otiai10/copy + +require ( + bou.ke/monkey v1.0.1 // indirect + github.com/otiai10/mint v1.2.3 +) diff --git a/go/vendor/github.com/otiai10/copy/go.sum b/go/vendor/github.com/otiai10/copy/go.sum new file mode 100644 index 0000000..37b5672 --- /dev/null +++ b/go/vendor/github.com/otiai10/copy/go.sum @@ -0,0 +1,4 @@ +bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U= +bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= +github.com/otiai10/mint v1.2.3 h1:PsrRBmrxR68kyNu6YlqYHbNlItc5vOkuS6LBEsNttVA= +github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= diff --git a/go/vendor/vendor.json b/go/vendor/vendor.json index cf837f7..6e9a1a4 100644 --- a/go/vendor/vendor.json +++ b/go/vendor/vendor.json @@ -102,6 +102,12 @@ "revisionTime": "2019-02-18T02:30:34Z" }, { + "checksumSHA1": "ejq9Z6KUxfUyeL+IszhcxcGiw1s=", + "path": "github.com/otiai10/copy", + "revision": "a15b9cb96cf2f7930107fe0a9a6faf1b91e69df4", + "revisionTime": "2019-02-27T01:32:50Z" + }, + { "checksumSHA1": "8U5pEHFpXd1/Klgp+C/a6TqWoh8=", "path": "github.com/philhofer/fwd", "revision": "bb6d471dc95d4fe11e432687f8b70ff496cf3136", @@ -632,6 +638,10 @@ "path": "gopkg.in/yaml.v2", "revision": "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b", "revisionTime": "2017-04-07T17:21:22Z" + }, + { + "path": "https://github.com/otiai10/copy", + "revision": "" } ], "rootPath": "gitlab.com/gitlab-org/gitlab-shell/go" |