diff --git a/cmd/proxy/actions/app.go b/cmd/proxy/actions/app.go index 7a1404ad..295e055a 100644 --- a/cmd/proxy/actions/app.go +++ b/cmd/proxy/actions/app.go @@ -33,28 +33,28 @@ func App(conf *config.Config) (*buffalo.App, error) { // ENV is used to help switch settings based on where the // application is being run. Default is "development". ENV := conf.GoEnv - store, err := GetStorage(conf.Proxy.StorageType, conf.Storage) + store, err := GetStorage(conf.StorageType, conf.Storage) if err != nil { err = fmt.Errorf("error getting storage configuration (%s)", err) return nil, err } - if conf.Proxy.GithubToken != "" { - if conf.Proxy.NETRCPath != "" { + if conf.GithubToken != "" { + if conf.NETRCPath != "" { fmt.Println("Cannot provide both GithubToken and NETRCPath. Only provide one.") os.Exit(1) } - netrcFromToken(conf.Proxy.GithubToken) + netrcFromToken(conf.GithubToken) } // mount .netrc to home dir // to have access to private repos. - initializeAuthFile(conf.Proxy.NETRCPath) + initializeAuthFile(conf.NETRCPath) // mount .hgrc to home dir // to have access to private repos. - initializeAuthFile(conf.Proxy.HGRCPath) + initializeAuthFile(conf.HGRCPath) logLvl, err := logrus.ParseLevel(conf.LogLevel) if err != nil { @@ -75,11 +75,11 @@ func App(conf *config.Config) (*buffalo.App, error) { }, SessionName: "_athens_session", Logger: blggr, - Addr: conf.Proxy.Port, + Addr: conf.Port, WorkerOff: true, - Host: "http://127.0.0.1" + conf.Proxy.Port, + Host: "http://127.0.0.1" + conf.Port, }) - if prefix := conf.Proxy.PathPrefix; prefix != "" { + if prefix := conf.PathPrefix; prefix != "" { // certain Ingress Controllers (such as GCP Load Balancer) // can not send custom headers and therefore if the proxy // is running behind a prefix as well as some authentication @@ -109,7 +109,7 @@ func App(conf *config.Config) (*buffalo.App, error) { // Automatically redirect to SSL app.Use(forcessl.Middleware(secure.Options{ - SSLRedirect: conf.Proxy.ForceSSL, + SSLRedirect: conf.ForceSSL, SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, })) @@ -124,15 +124,15 @@ func App(conf *config.Config) (*buffalo.App, error) { if err != nil { lggr.Fatal(err) } - app.Use(mw.NewFilterMiddleware(mf, conf.Proxy.GlobalEndpoint)) + app.Use(mw.NewFilterMiddleware(mf, conf.GlobalEndpoint)) } // Having the hook set means we want to use it - if vHook := conf.Proxy.ValidatorHook; vHook != "" { + if vHook := conf.ValidatorHook; vHook != "" { app.Use(mw.LogEntryMiddleware(mw.NewValidationMiddleware, lggr, vHook)) } - user, pass, ok := conf.Proxy.BasicAuth() + user, pass, ok := conf.BasicAuth() if ok { app.Use(basicAuth(user, pass)) } diff --git a/config.dev.toml b/config.dev.toml index f54ab2e8..7028527c 100644 --- a/config.dev.toml +++ b/config.dev.toml @@ -54,81 +54,80 @@ FilterFile = "" # Env override: ATHENS_TIMEOUT Timeout = 300 -[Proxy] - # StorageType sets the type of storage backend the proxy will use. - # Possible values are memory, disk, mongo, gcp, minio, s3 - # Defaults to memory - # Env override: ATHENS_STORAGE_TYPE - StorageType = "memory" +# StorageType sets the type of storage backend the proxy will use. +# Possible values are memory, disk, mongo, gcp, minio, s3 +# Defaults to memory +# Env override: ATHENS_STORAGE_TYPE +StorageType = "memory" - # Port sets the port the proxy listens on - # Env override: PORT - Port = ":3000" +# Port sets the port the proxy listens on +# Env override: PORT +Port = ":3000" - # The endpoint for a package registry in case of a proxy cache miss - # NOTE: Currently no registries have been implemented - # Env override: ATHENS_GLOBAL_ENDPOINT - GlobalEndpoint = "http://localhost:3001" +# The endpoint for a package registry in case of a proxy cache miss +# NOTE: Currently no registries have been implemented +# Env override: ATHENS_GLOBAL_ENDPOINT +GlobalEndpoint = "http://localhost:3001" - # Username for basic auth - # Env override: BASIC_AUTH_USER - BasicAuthUser = "" +# Username for basic auth +# Env override: BASIC_AUTH_USER +BasicAuthUser = "" - # Password for basic auth - # Env override: BASIC_AUTH_PASS - BasicAuthPass = "" +# Password for basic auth +# Env override: BASIC_AUTH_PASS +BasicAuthPass = "" - # Set to true to force an SSL redirect - # Env override: PROXY_FORCE_SSL - ForceSSL = false +# Set to true to force an SSL redirect +# Env override: PROXY_FORCE_SSL +ForceSSL = false - # ValidatorHook specifies the endpoint to validate modules against - # Not used if left blank or not specified - # Env override: ATHENS_PROXY_VALIDATOR - ValidatorHook = "" +# ValidatorHook specifies the endpoint to validate modules against +# Not used if left blank or not specified +# Env override: ATHENS_PROXY_VALIDATOR +ValidatorHook = "" - # PathPrefix specifies whether the Proxy - # should have a basepath. Certain proxies and services - # are distinguished based on subdomain, while others are based - # on path prefixes. - # Env override: ATHENS_PATH_PREFIX - PathPrefix = "" +# PathPrefix specifies whether the Proxy +# should have a basepath. Certain proxies and services +# are distinguished based on subdomain, while others are based +# on path prefixes. +# Env override: ATHENS_PATH_PREFIX +PathPrefix = "" - # NETRCPath tells you where the .netrc path initially resides. - # This is so that you can mount the .netrc file to a secret location - # in the fs system and then move it ~/.netrc. In certain deployments - # like Kubernetes, we can't mount directly to ~ because it would then - # clean out whatever is already there as part of the image (such as - # .cache directory in the Go image). - # Env override: ATHENS_NETRC_PATH - NETRCPath = "" +# NETRCPath tells you where the .netrc path initially resides. +# This is so that you can mount the .netrc file to a secret location +# in the fs system and then move it ~/.netrc. In certain deployments +# like Kubernetes, we can't mount directly to ~ because it would then +# clean out whatever is already there as part of the image (such as +# .cache directory in the Go image). +# Env override: ATHENS_NETRC_PATH +NETRCPath = "" - # GithubToken can be used instead of a NETRCPath to authenticate - # the proxy to your own private repos on github. This makes it - # easier for users and for platforms like GAE to only be provided - # a Github token instead of a .netrc file. Internally, the proxy - # just create a .netrc file for you. - # Env override: ATHENS_GITHUB_TOKEN - GithubToken = "" +# GithubToken can be used instead of a NETRCPath to authenticate +# the proxy to your own private repos on github. This makes it +# easier for users and for platforms like GAE to only be provided +# a Github token instead of a .netrc file. Internally, the proxy +# just create a .netrc file for you. +# Env override: ATHENS_GITHUB_TOKEN +GithubToken = "" - # HGRCPath tells you where the .hgrc path initially resides. - # This is so that you can mount the .hgrc file to a secret location - # in the fs system and then move it ~/.hgrc. In certain deployments - # like Kubernetes, we can't mount directly to ~ because it would then - # clean out whatever is already there as part of the image (such as - # .cache directory in the Go image). - # Env override: ATHENS_HGRC_PATH - HGRCPath = "" +# HGRCPath tells you where the .hgrc path initially resides. +# This is so that you can mount the .hgrc file to a secret location +# in the fs system and then move it ~/.hgrc. In certain deployments +# like Kubernetes, we can't mount directly to ~ because it would then +# clean out whatever is already there as part of the image (such as +# .cache directory in the Go image). +# Env override: ATHENS_HGRC_PATH +HGRCPath = "" - # TraceExporterURL is the URL to which Athens populates distributed tracing - # information such as Jaeger. In Stackdriver, use this as the GCP ProjectID. - # Env override: ATHENS_TRACE_EXPORTER_URL - TraceExporterURL = "" +# TraceExporterURL is the URL to which Athens populates distributed tracing +# information such as Jaeger. In Stackdriver, use this as the GCP ProjectID. +# Env override: ATHENS_TRACE_EXPORTER_URL +TraceExporterURL = "" - # TraceExporter is the service to which the data collected by OpenCensus can be exported to. - # Possible values are: jaeger, datadog, and stackdriver. - # Env overide: ATHENS_TRACE_EXPORTER - TraceExporter = "" +# TraceExporter is the service to which the data collected by OpenCensus can be exported to. +# Possible values are: jaeger, datadog, and stackdriver. +# Env overide: ATHENS_TRACE_EXPORTER +TraceExporter = "" [Storage] # Only storage backends that are specified in Proxy.StorageType are required here diff --git a/pkg/config/config.go b/pkg/config/config.go index 80f68d9f..79b432e9 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -24,10 +24,29 @@ type Config struct { FilterFile string `envconfig:"ATHENS_FILTER_FILE"` TraceExporterURL string `envconfig:"ATHENS_TRACE_EXPORTER_URL"` TraceExporter string `envconfig:"ATHENS_TRACE_EXPORTER"` - Proxy *ProxyConfig + StorageType string `validate:"required" envconfig:"ATHENS_STORAGE_TYPE"` + GlobalEndpoint string `envconfig:"ATHENS_GLOBAL_ENDPOINT"` // This feature is not yet implemented + Port string `envconfig:"ATHENS_PORT" default:":3000"` + BasicAuthUser string `envconfig:"BASIC_AUTH_USER"` + BasicAuthPass string `envconfig:"BASIC_AUTH_PASS"` + ForceSSL bool `envconfig:"PROXY_FORCE_SSL"` + ValidatorHook string `envconfig:"ATHENS_PROXY_VALIDATOR"` + PathPrefix string `envconfig:"ATHENS_PATH_PREFIX"` + NETRCPath string `envconfig:"ATHENS_NETRC_PATH"` + GithubToken string `envconfig:"ATHENS_GITHUB_TOKEN"` + HGRCPath string `envconfig:"ATHENS_HGRC_PATH"` Storage *StorageConfig } +// BasicAuth returns BasicAuthUser and BasicAuthPassword +// and ok if neither of them are empty +func (c *Config) BasicAuth() (user, pass string, ok bool) { + user = c.BasicAuthUser + pass = c.BasicAuthPass + ok = user != "" && pass != "" + return user, pass, ok +} + // FilterOff returns true if the FilterFile is empty func (c *Config) FilterOff() bool { return c.FilterFile == "" diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index d1faf2a3..8a5e4666 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -14,15 +14,11 @@ import ( const exampleConfigPath = "../../config.dev.toml" func compareConfigs(parsedConf *Config, expConf *Config, t *testing.T) { - opts := cmpopts.IgnoreTypes(StorageConfig{}, ProxyConfig{}) + opts := cmpopts.IgnoreTypes(StorageConfig{}) eq := cmp.Equal(parsedConf, expConf, opts) if !eq { t.Errorf("Parsed Example configuration did not match expected values. Expected: %+v. Actual: %+v", expConf, parsedConf) } - eq = cmp.Equal(parsedConf.Proxy, expConf.Proxy) - if !eq { - t.Errorf("Parsed Example Proxy configuration did not match expected values. Expected: %+v. Actual: %+v", expConf.Proxy, parsedConf.Proxy) - } compareStorageConfigs(parsedConf.Storage, expConf.Storage, t) } @@ -60,26 +56,12 @@ func TestPortDefaultsCorrectly(t *testing.T) { t.Fatalf("Env override failed: %v", err) } expPort := ":3000" - if conf.Proxy.Port != expPort { - t.Errorf("Port was incorrect. Got: %s, want: %s", conf.Proxy.Port, expPort) + if conf.Port != expPort { + t.Errorf("Port was incorrect. Got: %s, want: %s", conf.Port, expPort) } } func TestEnvOverrides(t *testing.T) { - - expProxy := ProxyConfig{ - StorageType: "minio", - GlobalEndpoint: "mytikas.gomods.io", - Port: ":7000", - BasicAuthUser: "testuser", - BasicAuthPass: "testpass", - ForceSSL: true, - ValidatorHook: "testhook.io", - PathPrefix: "prefix", - NETRCPath: "/test/path/.netrc", - HGRCPath: "/test/path/.hgrc", - } - expConf := &Config{ GoEnv: "production", GoGetWorkers: 10, @@ -91,8 +73,17 @@ func TestEnvOverrides(t *testing.T) { TimeoutConf: TimeoutConf{ Timeout: 30, }, - Proxy: &expProxy, - Storage: &StorageConfig{}, + StorageType: "minio", + GlobalEndpoint: "mytikas.gomods.io", + Port: ":7000", + BasicAuthUser: "testuser", + BasicAuthPass: "testpass", + ForceSSL: true, + ValidatorHook: "testhook.io", + PathPrefix: "prefix", + NETRCPath: "/test/path/.netrc", + HGRCPath: "/test/path/.hgrc", + Storage: &StorageConfig{}, } envVars := getEnvMap(expConf) @@ -186,7 +177,6 @@ func TestParseExampleConfig(t *testing.T) { // initialize all struct pointers so we get all applicable env variables emptyConf := &Config{ - Proxy: &ProxyConfig{}, Storage: &StorageConfig{ CDN: &CDNConfig{}, Disk: &DiskConfig{}, @@ -209,14 +199,6 @@ func TestParseExampleConfig(t *testing.T) { globalTimeout := 300 - expProxy := &ProxyConfig{ - StorageType: "memory", - GlobalEndpoint: "http://localhost:3001", - Port: ":3000", - BasicAuthUser: "", - BasicAuthPass: "", - } - expStorage := &StorageConfig{ CDN: &CDNConfig{ Endpoint: "cdn.example.com", @@ -275,8 +257,12 @@ func TestParseExampleConfig(t *testing.T) { TimeoutConf: TimeoutConf{ Timeout: 300, }, - Proxy: expProxy, - Storage: expStorage, + StorageType: "memory", + GlobalEndpoint: "http://localhost:3001", + Port: ":3000", + BasicAuthUser: "", + BasicAuthPass: "", + Storage: expStorage, } absPath, err := filepath.Abs(exampleConfigPath) @@ -306,19 +292,16 @@ func getEnvMap(config *Config) map[string]string { "ATHENS_TRACE_EXPORTER": config.TraceExporterURL, } - proxy := config.Proxy - if proxy != nil { - envVars["ATHENS_STORAGE_TYPE"] = proxy.StorageType - envVars["ATHENS_GLOBAL_ENDPOINT"] = proxy.GlobalEndpoint - envVars["ATHENS_PORT"] = proxy.Port - envVars["BASIC_AUTH_USER"] = proxy.BasicAuthUser - envVars["BASIC_AUTH_PASS"] = proxy.BasicAuthPass - envVars["PROXY_FORCE_SSL"] = strconv.FormatBool(proxy.ForceSSL) - envVars["ATHENS_PROXY_VALIDATOR"] = proxy.ValidatorHook - envVars["ATHENS_PATH_PREFIX"] = proxy.PathPrefix - envVars["ATHENS_NETRC_PATH"] = proxy.NETRCPath - envVars["ATHENS_HGRC_PATH"] = proxy.HGRCPath - } + envVars["ATHENS_STORAGE_TYPE"] = config.StorageType + envVars["ATHENS_GLOBAL_ENDPOINT"] = config.GlobalEndpoint + envVars["ATHENS_PORT"] = config.Port + envVars["BASIC_AUTH_USER"] = config.BasicAuthUser + envVars["BASIC_AUTH_PASS"] = config.BasicAuthPass + envVars["PROXY_FORCE_SSL"] = strconv.FormatBool(config.ForceSSL) + envVars["ATHENS_PROXY_VALIDATOR"] = config.ValidatorHook + envVars["ATHENS_PATH_PREFIX"] = config.PathPrefix + envVars["ATHENS_NETRC_PATH"] = config.NETRCPath + envVars["ATHENS_HGRC_PATH"] = config.HGRCPath storage := config.Storage if storage != nil { diff --git a/pkg/config/proxy.go b/pkg/config/proxy.go deleted file mode 100644 index d6398a5e..00000000 --- a/pkg/config/proxy.go +++ /dev/null @@ -1,25 +0,0 @@ -package config - -// ProxyConfig specifies the properties required to run the proxy -type ProxyConfig struct { - StorageType string `validate:"required" envconfig:"ATHENS_STORAGE_TYPE"` - GlobalEndpoint string `envconfig:"ATHENS_GLOBAL_ENDPOINT"` // This feature is not yet implemented - Port string `envconfig:"ATHENS_PORT" default:":3000"` - BasicAuthUser string `envconfig:"BASIC_AUTH_USER"` - BasicAuthPass string `envconfig:"BASIC_AUTH_PASS"` - ForceSSL bool `envconfig:"PROXY_FORCE_SSL"` - ValidatorHook string `envconfig:"ATHENS_PROXY_VALIDATOR"` - PathPrefix string `envconfig:"ATHENS_PATH_PREFIX"` - NETRCPath string `envconfig:"ATHENS_NETRC_PATH"` - GithubToken string `envconfig:"ATHENS_GITHUB_TOKEN"` - HGRCPath string `envconfig:"ATHENS_HGRC_PATH"` -} - -// BasicAuth returns BasicAuthUser and BasicAuthPassword -// and ok if neither of them are empty -func (p *ProxyConfig) BasicAuth() (user, pass string, ok bool) { - user = p.BasicAuthUser - pass = p.BasicAuthPass - ok = user != "" && pass != "" - return user, pass, ok -} diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 3512b258..78c6343c 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -70,16 +70,13 @@ func Test_FilterMiddleware(t *testing.T) { if err != nil { t.Fatalf("Unable to parse config file: %s", err.Error()) } - if conf.Proxy == nil { - t.Fatalf("No Proxy configuration in test config") - } // Test with a filter file not existing - app, err := middlewareFilterApp("nofsfile", conf.Proxy.GlobalEndpoint) + app, err := middlewareFilterApp("nofsfile", conf.GlobalEndpoint) r.Nil(app, "app should be nil when a file not exisiting") r.Error(err, "Expected error when a file not existing on the filesystem is given") - app, err = middlewareFilterApp(filter.Name(), conf.Proxy.GlobalEndpoint) + app, err = middlewareFilterApp(filter.Name(), conf.GlobalEndpoint) r.NoError(err, "app should be succesfully created in the test") w := willie.New(app) @@ -88,7 +85,7 @@ func Test_FilterMiddleware(t *testing.T) { for _, path := range paths { res := w.Request(path).Get() r.Equal(303, res.Code) - r.Equal(conf.Proxy.GlobalEndpoint+"/github.com/gomods/athens/@v/list/", res.HeaderMap.Get("Location")) + r.Equal(conf.GlobalEndpoint+"/github.com/gomods/athens/@v/list/", res.HeaderMap.Get("Location")) } // Excluded, expects a 403