Commit f9d3d8b3 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Get secret from config

This adds parsing if the `secret_file` from YAML. And reads the
contents of the configured file.

If no file is configured, we fall back to the `.gitlab_shell_secret`
in the root dir of the configuration.

If the configured path does not start with a `/` we start looking for
the file relative to the root dir of the configuration.
parent 2a51ab39
......@@ -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
}
......@@ -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)
})
}
}
......
......@@ -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
}
default-secret-content
\ No newline at end of file
custom-secret-content
\ No newline at end of file
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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment