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,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"net/url" "net/url"
"os" "os"
"path" "path"
"path/filepath"
"strings" "strings"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
...@@ -13,6 +14,7 @@ import ( ...@@ -13,6 +14,7 @@ import (
const ( const (
configFile = "config.yml" configFile = "config.yml"
logFile = "gitlab-shell.log" logFile = "gitlab-shell.log"
defaultSecretFileName = ".gitlab_shell_secret"
) )
type MigrationConfig struct { type MigrationConfig struct {
...@@ -27,6 +29,8 @@ type Config struct { ...@@ -27,6 +29,8 @@ type Config struct {
Migration MigrationConfig `yaml:"migration"` Migration MigrationConfig `yaml:"migration"`
GitlabUrl string `yaml:"gitlab_url"` GitlabUrl string `yaml:"gitlab_url"`
GitlabTracing string `yaml:"gitlab_tracing"` GitlabTracing string `yaml:"gitlab_tracing"`
SecretFilePath string `yaml:"secret_file"`
Secret string `yaml:"secret"`
} }
func New() (*Config, error) { func New() (*Config, error) {
...@@ -102,5 +106,32 @@ func parseConfig(configBytes []byte, cfg *Config) error { ...@@ -102,5 +106,32 @@ func parseConfig(configBytes []byte, cfg *Config) error {
cfg.GitlabUrl = unescapedUrl 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 return nil
} }
...@@ -2,63 +2,105 @@ package config ...@@ -2,63 +2,105 @@ package config
import ( import (
"fmt" "fmt"
"strings" "path"
"testing" "testing"
"github.com/stretchr/testify/assert" "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) { func TestParseConfig(t *testing.T) {
testRoot := "/foo/bar" cleanup, err := testhelper.PrepareTestRootDir()
require.NoError(t, err)
defer cleanup()
testCases := []struct { testCases := []struct {
yaml string yaml string
path string path string
format string format string
gitlabUrl string gitlabUrl string
migration MigrationConfig 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"}, path: path.Join(testRoot, "gitlab-shell.log"),
{yaml: "log_file: /qux/my-log.log", path: "/qux/my-log.log", format: "text"}, format: "text",
{yaml: "log_format: json", path: "/foo/bar/gitlab-shell.log", format: "json"}, 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", 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", format: "text",
migration: MigrationConfig{Enabled: true, Features: []string{"foo", "bar"}}, migration: MigrationConfig{Enabled: true, Features: []string{"foo", "bar"}},
secret: "default-secret-content",
}, },
{ {
yaml: "gitlab_url: http+unix://%2Fpath%2Fto%2Fgitlab%2Fgitlab.socket", 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", format: "text",
gitlabUrl: "http+unix:///path/to/gitlab/gitlab.socket", 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 { for _, tc := range testCases {
t.Run(fmt.Sprintf("yaml input: %q", tc.yaml), func(t *testing.T) { t.Run(fmt.Sprintf("yaml input: %q", tc.yaml), func(t *testing.T) {
cfg := Config{RootDir: testRoot} 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 { err := parseConfig([]byte(tc.yaml), &cfg)
t.Fatalf("expected %q, got %q", tc.format, cfg.LogFormat) 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.gitlabUrl, cfg.GitlabUrl)
assert.Equal(t, tc.secret, cfg.Secret)
}) })
} }
} }
......
...@@ -3,12 +3,10 @@ package handler ...@@ -3,12 +3,10 @@ package handler
import ( import (
"context" "context"
"fmt" "fmt"
"io/ioutil"
"os"
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
...@@ -88,7 +86,7 @@ func TestInteralRunHandler(t *testing.T) { ...@@ -88,7 +86,7 @@ func TestInteralRunHandler(t *testing.T) {
currentTest = nil currentTest = nil
}() }()
done, err := createEnv() done, err := testhelper.PrepareTestRootDir()
defer done() defer done()
require.NoError(t, err) require.NoError(t, err)
...@@ -103,51 +101,3 @@ func TestInteralRunHandler(t *testing.T) { ...@@ -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 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() { func TempEnv(env map[string]string) func() {
var original = make(map[string]string) var original = make(map[string]string)
...@@ -15,3 +27,61 @@ func TempEnv(env map[string]string) func() { ...@@ -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