mirror of
https://github.com/project-zot/zot.git
synced 2025-01-13 22:50:38 -05:00
532 lines
15 KiB
Go
532 lines
15 KiB
Go
|
//go:build apikey
|
||
|
// +build apikey
|
||
|
|
||
|
package extensions_test
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/project-zot/mockoidc"
|
||
|
. "github.com/smartystreets/goconvey/convey"
|
||
|
"gopkg.in/resty.v1"
|
||
|
|
||
|
"zotregistry.io/zot/pkg/api"
|
||
|
"zotregistry.io/zot/pkg/api/config"
|
||
|
"zotregistry.io/zot/pkg/api/constants"
|
||
|
"zotregistry.io/zot/pkg/extensions"
|
||
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||
|
"zotregistry.io/zot/pkg/meta/repodb"
|
||
|
localCtx "zotregistry.io/zot/pkg/requestcontext"
|
||
|
"zotregistry.io/zot/pkg/test"
|
||
|
"zotregistry.io/zot/pkg/test/mocks"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
apiKeyResponse struct {
|
||
|
repodb.APIKeyDetails
|
||
|
APIKey string `json:"apiKey"`
|
||
|
}
|
||
|
)
|
||
|
|
||
|
var ErrUnexpectedError = errors.New("unexpected err")
|
||
|
|
||
|
func TestAPIKeys(t *testing.T) {
|
||
|
Convey("Make a new controller", t, func() {
|
||
|
port := test.GetFreePort()
|
||
|
baseURL := test.GetBaseURL(port)
|
||
|
|
||
|
conf := config.New()
|
||
|
conf.HTTP.Port = port
|
||
|
|
||
|
htpasswdPath := test.MakeHtpasswdFile()
|
||
|
defer os.Remove(htpasswdPath)
|
||
|
|
||
|
mockOIDCServer, err := test.MockOIDCRun()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
defer func() {
|
||
|
err := mockOIDCServer.Shutdown()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
mockOIDCConfig := mockOIDCServer.Config()
|
||
|
conf.HTTP.Auth = &config.AuthConfig{
|
||
|
HTPasswd: config.AuthHTPasswd{
|
||
|
Path: htpasswdPath,
|
||
|
},
|
||
|
OpenID: &config.OpenIDConfig{
|
||
|
Providers: map[string]config.OpenIDProviderConfig{
|
||
|
"dex": {
|
||
|
ClientID: mockOIDCConfig.ClientID,
|
||
|
ClientSecret: mockOIDCConfig.ClientSecret,
|
||
|
KeyPath: "",
|
||
|
Issuer: mockOIDCConfig.Issuer,
|
||
|
Scopes: []string{"openid", "email", "groups"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
conf.HTTP.AccessControl = &config.AccessControlConfig{}
|
||
|
|
||
|
defaultVal := true
|
||
|
apiKeyConfig := &extconf.APIKeyConfig{
|
||
|
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||
|
}
|
||
|
|
||
|
mgmtConfg := &extconf.MgmtConfig{
|
||
|
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||
|
}
|
||
|
|
||
|
conf.Extensions = &extconf.ExtensionConfig{
|
||
|
APIKey: apiKeyConfig,
|
||
|
Mgmt: mgmtConfg,
|
||
|
}
|
||
|
|
||
|
ctlr := api.NewController(conf)
|
||
|
dir := t.TempDir()
|
||
|
|
||
|
ctlr.Config.Storage.RootDirectory = dir
|
||
|
|
||
|
cm := test.NewControllerManager(ctlr)
|
||
|
|
||
|
cm.StartServer()
|
||
|
defer cm.StopServer()
|
||
|
test.WaitTillServerReady(baseURL)
|
||
|
|
||
|
payload := extensions.APIKeyPayload{
|
||
|
Label: "test",
|
||
|
Scopes: []string{"test"},
|
||
|
}
|
||
|
reqBody, err := json.Marshal(payload)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
Convey("API key retrieved with basic auth", func() {
|
||
|
// call endpoint with session ( added to client after previous request)
|
||
|
resp, err := resty.R().
|
||
|
SetBody(reqBody).
|
||
|
SetBasicAuth("test", "test").
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
user := mockoidc.DefaultUser()
|
||
|
|
||
|
// get API key and email from apikey route response
|
||
|
var apiKeyResponse apiKeyResponse
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
email := user.Email
|
||
|
So(email, ShouldNotBeEmpty)
|
||
|
|
||
|
resp, err = resty.R().
|
||
|
SetBasicAuth("test", apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// add another one
|
||
|
resp, err = resty.R().
|
||
|
SetBody(reqBody).
|
||
|
SetBasicAuth("test", "test").
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
resp, err = resty.R().
|
||
|
SetBasicAuth("test", apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
})
|
||
|
|
||
|
Convey("API key retrieved with openID", func() {
|
||
|
client := resty.New()
|
||
|
client.SetRedirectPolicy(test.CustomRedirectPolicy(20))
|
||
|
|
||
|
// first login user
|
||
|
resp, err := client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
SetQueryParam("provider", "dex").
|
||
|
Get(baseURL + constants.LoginPath)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
|
||
|
cookies := resp.Cookies()
|
||
|
|
||
|
// call endpoint without session
|
||
|
resp, err = client.R().
|
||
|
SetBody(reqBody).
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
|
||
|
client.SetCookies(cookies)
|
||
|
|
||
|
// call endpoint with session ( added to client after previous request)
|
||
|
resp, err = client.R().
|
||
|
SetBody(reqBody).
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
user := mockoidc.DefaultUser()
|
||
|
|
||
|
// get API key and email from apikey route response
|
||
|
var apiKeyResponse apiKeyResponse
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
email := user.Email
|
||
|
So(email, ShouldNotBeEmpty)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// trigger errors
|
||
|
ctlr.RepoDB = mocks.RepoDBMock{
|
||
|
GetUserAPIKeyInfoFn: func(hashedKey string) (string, error) {
|
||
|
return "", ErrUnexpectedError
|
||
|
},
|
||
|
}
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusInternalServerError)
|
||
|
|
||
|
ctlr.RepoDB = mocks.RepoDBMock{
|
||
|
GetUserAPIKeyInfoFn: func(hashedKey string) (string, error) {
|
||
|
return user.Email, nil
|
||
|
},
|
||
|
GetUserGroupsFn: func(ctx context.Context) ([]string, error) {
|
||
|
return []string{}, ErrUnexpectedError
|
||
|
},
|
||
|
}
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusInternalServerError)
|
||
|
|
||
|
ctlr.RepoDB = mocks.RepoDBMock{
|
||
|
GetUserAPIKeyInfoFn: func(hashedKey string) (string, error) {
|
||
|
return user.Email, nil
|
||
|
},
|
||
|
UpdateUserAPIKeyLastUsedFn: func(ctx context.Context, hashedKey string) error {
|
||
|
return ErrUnexpectedError
|
||
|
},
|
||
|
}
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusInternalServerError)
|
||
|
|
||
|
client = resty.New()
|
||
|
|
||
|
// call endpoint without session
|
||
|
resp, err = client.R().
|
||
|
SetBody(reqBody).
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
})
|
||
|
|
||
|
Convey("Login with openid and create API key", func() {
|
||
|
client := resty.New()
|
||
|
|
||
|
// mgmt should work both unauthenticated and authenticated
|
||
|
resp, err := client.R().
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
client.SetRedirectPolicy(test.CustomRedirectPolicy(20))
|
||
|
// first login user
|
||
|
resp, err = client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
SetQueryParam("provider", "dex").
|
||
|
Get(baseURL + constants.LoginPath)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
client.SetCookies(resp.Cookies())
|
||
|
|
||
|
// call endpoint with session ( added to client after previous request)
|
||
|
resp, err = client.R().
|
||
|
SetBody(reqBody).
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
var apiKeyResponse apiKeyResponse
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
user := mockoidc.DefaultUser()
|
||
|
email := user.Email
|
||
|
So(email, ShouldNotBeEmpty)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// auth with API key
|
||
|
// we need new client without session cookie set
|
||
|
client = resty.New()
|
||
|
client.SetRedirectPolicy(test.CustomRedirectPolicy(20))
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// invalid api keys
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth("invalidEmail", apiKeyResponse.APIKey).
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, "noprefixAPIKey").
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, "zak_notworkingAPIKey").
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
|
||
|
authzCtxKey := localCtx.GetContextKey()
|
||
|
|
||
|
acCtx := localCtx.AccessControlContext{
|
||
|
Username: email,
|
||
|
}
|
||
|
|
||
|
ctx := context.WithValue(context.Background(), authzCtxKey, acCtx)
|
||
|
|
||
|
err = ctlr.RepoDB.DeleteUserData(ctx)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusInternalServerError)
|
||
|
|
||
|
client = resty.New()
|
||
|
client.SetRedirectPolicy(test.CustomRedirectPolicy(20))
|
||
|
|
||
|
// without creds should work
|
||
|
resp, err = client.R().
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// login again
|
||
|
resp, err = client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
SetQueryParam("provider", "dex").
|
||
|
Get(baseURL + constants.LoginPath)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
client.SetCookies(resp.Cookies())
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBody(reqBody).
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Post(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||
|
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
// should work with session
|
||
|
resp, err = client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// should work with api key
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + constants.FullMgmtPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
err = json.Unmarshal(resp.Body(), &apiKeyResponse)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
// delete api key
|
||
|
resp, err = client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
SetQueryParam("id", apiKeyResponse.UUID).
|
||
|
Delete(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue).
|
||
|
Delete(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth(email, apiKeyResponse.APIKey).
|
||
|
Get(baseURL + "/v2/_catalog")
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||
|
|
||
|
resp, err = client.R().
|
||
|
SetBasicAuth("test", "test").
|
||
|
SetQueryParam("id", apiKeyResponse.UUID).
|
||
|
Delete(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||
|
|
||
|
// unsupported method
|
||
|
resp, err = client.R().
|
||
|
Put(baseURL + constants.FullAPIKeyPrefix)
|
||
|
So(err, ShouldBeNil)
|
||
|
So(resp, ShouldNotBeNil)
|
||
|
So(resp.StatusCode(), ShouldEqual, http.StatusMethodNotAllowed)
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestAPIKeysOpenDBError(t *testing.T) {
|
||
|
Convey("Test API keys - unable to create database", t, func() {
|
||
|
conf := config.New()
|
||
|
htpasswdPath := test.MakeHtpasswdFile()
|
||
|
defer os.Remove(htpasswdPath)
|
||
|
|
||
|
mockOIDCServer, err := test.MockOIDCRun()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
defer func() {
|
||
|
err := mockOIDCServer.Shutdown()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
mockOIDCConfig := mockOIDCServer.Config()
|
||
|
conf.HTTP.Auth = &config.AuthConfig{
|
||
|
HTPasswd: config.AuthHTPasswd{
|
||
|
Path: htpasswdPath,
|
||
|
},
|
||
|
|
||
|
OpenID: &config.OpenIDConfig{
|
||
|
Providers: map[string]config.OpenIDProviderConfig{
|
||
|
"dex": {
|
||
|
ClientID: mockOIDCConfig.ClientID,
|
||
|
ClientSecret: mockOIDCConfig.ClientSecret,
|
||
|
KeyPath: "",
|
||
|
Issuer: mockOIDCConfig.Issuer,
|
||
|
Scopes: []string{"openid", "email"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
defaultVal := true
|
||
|
apiKeyConfig := &extconf.APIKeyConfig{
|
||
|
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||
|
}
|
||
|
conf.Extensions = &extconf.ExtensionConfig{
|
||
|
APIKey: apiKeyConfig,
|
||
|
}
|
||
|
|
||
|
ctlr := api.NewController(conf)
|
||
|
dir := t.TempDir()
|
||
|
|
||
|
err = os.Chmod(dir, 0o000)
|
||
|
So(err, ShouldBeNil)
|
||
|
|
||
|
ctlr.Config.Storage.RootDirectory = dir
|
||
|
cm := test.NewControllerManager(ctlr)
|
||
|
|
||
|
So(func() {
|
||
|
cm.StartServer()
|
||
|
}, ShouldPanic)
|
||
|
})
|
||
|
}
|