Honor envs properly for access and secret key. (#3703)

Also changes the behavior of `secretKeyHash` which is
not necessary to be sent over the network, each node
has its own secretKeyHash to validate.

Fixes #3696
Partial(fix) #3700 (More changes needed with some code cleanup)
This commit is contained in:
Harshavardhana 2017-02-07 12:51:43 -08:00 committed by GitHub
parent fd72c21e0e
commit 31dff87903
19 changed files with 237 additions and 314 deletions

View file

@ -14,7 +14,7 @@ env:
script:
- make
- make test GOFLAGS="-timeout 15m -race -v"
- make test GOFLAGS="-timeout 20m -race -v"
- make coverage
after_success:

View file

@ -35,9 +35,9 @@ test_script:
# Unit tests
- ps: Add-AppveyorTest "Unit Tests" -Outcome Running
- mkdir build\coverage
- go test -timeout 15m -v -race github.com/minio/minio/cmd...
- go test -timeout 20m -v -race github.com/minio/minio/cmd...
- go test -v -race github.com/minio/minio/pkg...
- go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
- go test -timeout 15m -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
- ps: Update-AppveyorTest "Unit Tests" -Outcome Passed
after_test:

View file

@ -154,24 +154,25 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter
}
// Check passed credentials
cred, err := getCredential(req.Username, req.Password)
switch err {
case errInvalidAccessKeyLength:
writeErrorResponse(w, ErrAdminInvalidAccessKey, r.URL)
return
case errInvalidSecretKeyLength:
writeErrorResponse(w, ErrAdminInvalidSecretKey, r.URL)
err = validateAuthKeys(req.Username, req.Password)
if err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return
}
creds := credential{
AccessKey: req.Username,
SecretKey: req.Password,
}
// Notify all other Minio peers to update credentials
updateErrs := updateCredsOnPeers(cred)
updateErrs := updateCredsOnPeers(creds)
for peer, err := range updateErrs {
errorIf(err, "Unable to update credentials on peer %s.", peer)
}
// Update local credentials
serverConfig.SetCredential(cred)
// Update local credentials in memory.
serverConfig.SetCredential(creds)
if err = serverConfig.Save(); err != nil {
writeErrorResponse(w, ErrInternalError, r.URL)
return

View file

@ -43,6 +43,7 @@ type adminXLTestBed struct {
func prepareAdminXLTestBed() (*adminXLTestBed, error) {
// reset global variables to start afresh.
resetTestGlobals()
// Initialize minio server config.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {

View file

@ -610,7 +610,10 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) {
apiErr = ErrEntityTooLarge
case errDataTooSmall:
apiErr = ErrEntityTooSmall
case errInvalidAccessKeyLength:
apiErr = ErrAdminInvalidAccessKey
case errInvalidSecretKeyLength:
apiErr = ErrAdminInvalidSecretKey
}
if apiErr != ErrNone {

View file

@ -315,11 +315,7 @@ func TestIsReqAuthenticated(t *testing.T) {
}
defer removeAll(path)
creds, err := getCredential("myuser", "mypassword")
if err != nil {
t.Fatal(err)
}
creds := newCredentialWithKeys("myuser", "mypassword")
serverConfig.SetCredential(creds)
// List of test cases for validating http request authentication.

View file

@ -63,13 +63,12 @@ func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *AuthR
return err
}
creds, err := getCredential(args.Creds.AccessKey, args.Creds.SecretKey)
if err != nil {
if err := validateAuthKeys(args.Creds.AccessKey, args.Creds.SecretKey); err != nil {
return err
}
// Update credentials in memory
serverConfig.SetCredential(creds)
serverConfig.SetCredential(args.Creds)
// Save credentials to config file
if err := serverConfig.Save(); err != nil {

View file

@ -50,7 +50,7 @@ func TestServerConfigMigrateV1(t *testing.T) {
}
// Initialize server config and check again if everything is fine
if _, err := initConfig(); err != nil {
if err := loadConfig(credential{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
}
@ -143,7 +143,7 @@ func TestServerConfigMigrateV2toV12(t *testing.T) {
}
// Initialize server config and check again if everything is fine
if _, err := initConfig(); err != nil {
if err := loadConfig(credential{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
@ -160,11 +160,6 @@ func TestServerConfigMigrateV2toV12(t *testing.T) {
if serverConfig.Credential.SecretKey != secretKey {
t.Fatalf("Secret key lost during migration, expected: %v, found: %v", secretKey, serverConfig.Credential.SecretKey)
}
// Initialize server config and check again if everything is fine
if _, err := initConfig(); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
}
// Test if all migrate code returns error with corrupted config files

View file

@ -42,77 +42,88 @@ type serverConfigV13 struct {
Notify notifier `json:"notify"`
}
// initConfig - initialize server config and indicate if we are
// creating a new file or we are just loading
func initConfig() (bool, error) {
if !isConfigFileExists() {
// Initialize server config.
srvCfg := &serverConfigV13{}
srvCfg.Version = globalMinioConfigVersion
srvCfg.Region = globalMinioDefaultRegion
srvCfg.Credential = newCredential()
// newConfig - initialize a new server config, saves creds from env
// if globalIsEnvCreds is set otherwise generates a new set of keys
// and those are saved.
func newConfig(envCreds credential) error {
// Initialize server config.
srvCfg := &serverConfigV13{}
srvCfg.Version = globalMinioConfigVersion
srvCfg.Region = globalMinioDefaultRegion
// Enable console logger by default on a fresh run.
srvCfg.Logger.Console = consoleLogger{
Enable: true,
Level: "error",
}
// Make sure to initialize notification configs.
srvCfg.Notify.AMQP = make(map[string]amqpNotify)
srvCfg.Notify.AMQP["1"] = amqpNotify{}
srvCfg.Notify.ElasticSearch = make(map[string]elasticSearchNotify)
srvCfg.Notify.ElasticSearch["1"] = elasticSearchNotify{}
srvCfg.Notify.Redis = make(map[string]redisNotify)
srvCfg.Notify.Redis["1"] = redisNotify{}
srvCfg.Notify.NATS = make(map[string]natsNotify)
srvCfg.Notify.NATS["1"] = natsNotify{}
srvCfg.Notify.PostgreSQL = make(map[string]postgreSQLNotify)
srvCfg.Notify.PostgreSQL["1"] = postgreSQLNotify{}
srvCfg.Notify.Kafka = make(map[string]kafkaNotify)
srvCfg.Notify.Kafka["1"] = kafkaNotify{}
srvCfg.Notify.Webhook = make(map[string]webhookNotify)
srvCfg.Notify.Webhook["1"] = webhookNotify{}
// Create config path.
err := createConfigPath()
if err != nil {
return false, err
}
// hold the mutex lock before a new config is assigned.
// Save the new config globally.
// unlock the mutex.
serverConfigMu.Lock()
serverConfig = srvCfg
serverConfigMu.Unlock()
// Save config into file.
return true, serverConfig.Save()
// If env is set for a fresh start, save them to config file.
if globalIsEnvCreds {
srvCfg.SetCredential(envCreds)
} else {
srvCfg.SetCredential(newCredential())
}
// Enable console logger by default on a fresh run.
srvCfg.Logger.Console = consoleLogger{
Enable: true,
Level: "error",
}
// Make sure to initialize notification configs.
srvCfg.Notify.AMQP = make(map[string]amqpNotify)
srvCfg.Notify.AMQP["1"] = amqpNotify{}
srvCfg.Notify.ElasticSearch = make(map[string]elasticSearchNotify)
srvCfg.Notify.ElasticSearch["1"] = elasticSearchNotify{}
srvCfg.Notify.Redis = make(map[string]redisNotify)
srvCfg.Notify.Redis["1"] = redisNotify{}
srvCfg.Notify.NATS = make(map[string]natsNotify)
srvCfg.Notify.NATS["1"] = natsNotify{}
srvCfg.Notify.PostgreSQL = make(map[string]postgreSQLNotify)
srvCfg.Notify.PostgreSQL["1"] = postgreSQLNotify{}
srvCfg.Notify.Kafka = make(map[string]kafkaNotify)
srvCfg.Notify.Kafka["1"] = kafkaNotify{}
srvCfg.Notify.Webhook = make(map[string]webhookNotify)
srvCfg.Notify.Webhook["1"] = webhookNotify{}
// Create config path.
if err := createConfigPath(); err != nil {
return err
}
// hold the mutex lock before a new config is assigned.
// Save the new config globally.
// unlock the mutex.
serverConfigMu.Lock()
serverConfig = srvCfg
serverConfigMu.Unlock()
// Save config into file.
return serverConfig.Save()
}
// loadConfig - loads a new config from disk, overrides creds from env
// if globalIsEnvCreds is set otherwise serves the creds from loaded
// from the disk.
func loadConfig(envCreds credential) error {
configFile, err := getConfigFile()
if err != nil {
return false, err
return err
}
if _, err = os.Stat(configFile); err != nil {
return false, err
return err
}
srvCfg := &serverConfigV13{}
srvCfg.Version = globalMinioConfigVersion
qc, err := quick.New(srvCfg)
if err != nil {
return false, err
return err
}
if err = qc.Load(configFile); err != nil {
return false, err
return err
}
srvCfg.Credential, err = getCredential(srvCfg.Credential.AccessKey, srvCfg.Credential.SecretKey)
if err != nil {
return false, err
// If env is set override the credentials from config file.
if globalIsEnvCreds {
srvCfg.SetCredential(envCreds)
} else {
srvCfg.SetCredential(srvCfg.Credential)
}
// hold the mutex lock before a new config is assigned.
@ -123,8 +134,7 @@ func initConfig() (bool, error) {
// Set the version properly after the unmarshalled json is loaded.
serverConfig.Version = globalMinioConfigVersion
return false, nil
return nil
}
// serverConfig server config.
@ -347,7 +357,7 @@ func (s *serverConfigV13) SetCredential(creds credential) {
defer serverConfigMu.Unlock()
// Set updated credential.
s.Credential = creds
s.Credential = newCredentialWithKeys(creds.AccessKey, creds.SecretKey)
}
// GetCredentials get current credentials.

View file

@ -106,7 +106,7 @@ func TestServerConfig(t *testing.T) {
setGlobalConfigPath(rootPath)
// Initialize server config.
if _, err := initConfig(); err != nil {
if err := loadConfig(credential{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
}

View file

@ -19,6 +19,9 @@ package cmd
import (
"crypto/rand"
"encoding/base64"
"os"
"github.com/minio/mc/pkg/console"
"golang.org/x/crypto/bcrypt"
)
@ -36,7 +39,7 @@ const (
func mustGetAccessKey() string {
keyBytes := make([]byte, accessKeyMaxLen)
if _, err := rand.Read(keyBytes); err != nil {
panic(err)
console.Fatalf("Unable to generate access key. Err: %s.\n", err)
}
for i := 0; i < accessKeyMaxLen; i++ {
@ -49,7 +52,7 @@ func mustGetAccessKey() string {
func mustGetSecretKey() string {
keyBytes := make([]byte, secretKeyMaxLen)
if _, err := rand.Read(keyBytes); err != nil {
panic(err)
console.Fatalf("Unable to generate secret key. Err: %s.\n", err)
}
return string([]byte(base64.StdEncoding.EncodeToString(keyBytes))[:secretKeyMaxLen])
@ -69,38 +72,68 @@ func isSecretKeyValid(secretKey string) bool {
type credential struct {
AccessKey string `json:"accessKey,omitempty"`
SecretKey string `json:"secretKey,omitempty"`
SecretKeyHash []byte `json:"secretKeyHash,omitempty"`
secretKeyHash []byte
}
// Generate a bcrypt hashed key for input secret key.
func mustGetHashedSecretKey(secretKey string) []byte {
hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.DefaultCost)
if err != nil {
panic(err)
console.Fatalf("Unable to generate secret hash for secret key. Err: %s.\n", err)
}
return hashedSecretKey
}
// Initialize a new credential object.
// Initialize a new credential object
func newCredential() credential {
secretKey := mustGetSecretKey()
accessKey := mustGetAccessKey()
return newCredentialWithKeys(mustGetAccessKey(), mustGetSecretKey())
}
func newCredentialWithKeys(accessKey, secretKey string) credential {
secretHash := mustGetHashedSecretKey(secretKey)
return credential{accessKey, secretKey, secretHash}
}
// Validate incoming auth keys.
func validateAuthKeys(accessKey, secretKey string) error {
// Validate the env values before proceeding.
if !isAccessKeyValid(accessKey) {
return errInvalidAccessKeyLength
}
if !isSecretKeyValid(secretKey) {
return errInvalidSecretKeyLength
}
return nil
}
// Variant of getCredentialFromEnv but upon error fails right here.
func mustGetCredentialFromEnv() credential {
creds, err := getCredentialFromEnv()
if err != nil {
console.Fatalf("Unable to load credentials from environment. Err: %s.\n", err)
}
return creds
}
// Converts accessKey and secretKeys into credential object which
// contains bcrypt secret key hash for future validation.
func getCredential(accessKey, secretKey string) (credential, error) {
if !isAccessKeyValid(accessKey) {
return credential{}, errInvalidAccessKeyLength
func getCredentialFromEnv() (credential, error) {
// Fetch access keys from environment variables and update the config.
accessKey := os.Getenv("MINIO_ACCESS_KEY")
secretKey := os.Getenv("MINIO_SECRET_KEY")
// Envs are set globally.
globalIsEnvCreds = accessKey != "" && secretKey != ""
if globalIsEnvCreds {
// Validate the env values before proceeding.
if err := validateAuthKeys(accessKey, secretKey); err != nil {
return credential{}, err
}
// Return credential object.
return newCredentialWithKeys(accessKey, secretKey), nil
}
if !isSecretKeyValid(secretKey) {
return credential{}, errInvalidSecretKeyLength
}
secretHash := mustGetHashedSecretKey(secretKey)
return credential{accessKey, secretKey, secretHash}, nil
return credential{}, nil
}

View file

@ -38,12 +38,15 @@ const (
defaultInterNodeJWTExpiry = 100 * 365 * 24 * time.Hour
)
var errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length")
var errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length")
var (
errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length")
errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length")
var errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records")
var errAuthentication = errors.New("Authentication failed, check your access credentials")
var errNoAuthToken = errors.New("JWT token missing")
errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records")
errChangeCredNotAllowed = errors.New("Changing access key and secret key not allowed")
errAuthentication = errors.New("Authentication failed, check your access credentials")
errNoAuthToken = errors.New("JWT token missing")
)
func authenticateJWT(accessKey, secretKey string, expiry time.Duration) (string, error) {
// Trim spaces.
@ -65,8 +68,15 @@ func authenticateJWT(accessKey, secretKey string, expiry time.Duration) (string,
// Validate secret key.
// Using bcrypt to avoid timing attacks.
if bcrypt.CompareHashAndPassword(serverCred.SecretKeyHash, []byte(secretKey)) != nil {
return "", errAuthentication
if serverCred.secretKeyHash != nil {
if bcrypt.CompareHashAndPassword(serverCred.secretKeyHash, []byte(secretKey)) != nil {
return "", errAuthentication
}
} else {
// Secret key hash not set then generate and validate.
if bcrypt.CompareHashAndPassword(mustGetHashedSecretKey(serverCred.SecretKey), []byte(secretKey)) != nil {
return "", errAuthentication
}
}
utcNow := time.Now().UTC()

View file

@ -163,6 +163,29 @@ func checkUpdate() {
}
}
// Initializes a new config if it doesn't exist, else migrates any old config
// to newer config and finally loads the config to memory.
func initConfig() {
envCreds := mustGetCredentialFromEnv()
// Config file does not exist, we create it fresh and return upon success.
if !isConfigFileExists() {
if err := newConfig(envCreds); err != nil {
console.Fatalf("Unable to initialize minio config for the first time. Err: %s.\n", err)
}
console.Println("Created minio configuration file successfully at " + mustGetConfigPath())
return
}
// Migrate any old version of config / state files to newer format.
migrate()
// Once we have migrated all the old config, now load them.
if err := loadConfig(envCreds); err != nil {
console.Fatalf("Unable to initialize minio config. Err: %s.\n", err)
}
}
// Generic Minio initialization to create/load config, prepare loggers, etc..
func minioInit(ctx *cli.Context) {
// Set global variables after parsing passed arguments
@ -174,32 +197,12 @@ func minioInit(ctx *cli.Context) {
// Is TLS configured?.
globalIsSSL = isSSL()
// Migrate any old version of config / state files to newer format.
migrate()
// Initialize config.
configCreated, err := initConfig()
if err != nil {
console.Fatalf("Unable to initialize minio config. Err: %s.\n", err)
}
if configCreated {
console.Println("Created minio configuration file at " + mustGetConfigPath())
}
// Initialize minio server config.
initConfig()
// Enable all loggers by now so we can use errorIf() and fatalIf()
enableLoggers()
// Fetch access keys from environment variables and update the config.
accessKey := os.Getenv("MINIO_ACCESS_KEY")
secretKey := os.Getenv("MINIO_SECRET_KEY")
if accessKey != "" && secretKey != "" {
creds, err := getCredential(accessKey, secretKey)
fatalIf(err, "Credentials are invalid, please set proper credentials `minio server --help`")
// Set new credentials.
serverConfig.SetCredential(creds)
}
// Init the error tracing module.
initError()

View file

@ -21,7 +21,6 @@ import (
"fmt"
"net"
"net/url"
"os"
"path"
"sort"
"strconv"
@ -128,22 +127,17 @@ func parseStorageEndpoints(eps []string) (endpoints []*url.URL, err error) {
return endpoints, nil
}
// initServerConfig initialize server config.
// initServer initialize server config.
func initServerConfig(c *cli.Context) {
// Initialization such as config generating/loading config, enable logging, ..
minioInit(c)
// Create certs path.
err := createCertsPath()
fatalIf(err, "Unable to create \"certs\" directory.")
fatalIf(createCertsPath(), "Unable to create \"certs\" directory.")
// Load user supplied root CAs
loadRootCAs()
// When credentials inherited from the env, server cmd has to save them in the disk
if os.Getenv("MINIO_ACCESS_KEY") != "" && os.Getenv("MINIO_SECRET_KEY") != "" {
// Env credentials are already loaded in serverConfig, just save in the disk
err = serverConfig.Save()
fatalIf(err, "Unable to save credentials in the disk.")
}
// Set maxOpenFiles, This is necessary since default operating
// system limits of 1024, 2048 are not enough for Minio server.
setMaxOpenFiles()
@ -372,8 +366,8 @@ func serverMain(c *cli.Context) {
cli.ShowCommandHelpAndExit(c, "server", 1)
}
// Initialization routine, such as config loading, enable logging, ..
minioInit(c)
// Initializes server config, certs, logging and system settings.
initServerConfig(c)
// Check for new updates from dl.minio.io.
checkUpdate()
@ -390,9 +384,6 @@ func serverMain(c *cli.Context) {
// as parseStorageEndpoints() depends on it.
checkServerSyntax(c)
// Initialize server config.
initServerConfig(c)
// Disks to be used in server init.
endpoints, err := parseStorageEndpoints(c.Args())
fatalIf(err, "Unable to parse storage endpoints %s", c.Args())

View file

@ -452,8 +452,14 @@ func TestIsDistributedSetup(t *testing.T) {
globalMinioHost = ""
}
func TestInitServerConfig(t *testing.T) {
ctx := &cli.Context{}
// Tests init server.
func TestInitServer(t *testing.T) {
app := cli.NewApp()
app.Commands = []cli.Command{serverCmd}
serverFlagSet := flag.NewFlagSet("server", 0)
serverFlagSet.String("address", ":9000", "")
ctx := cli.NewContext(app, serverFlagSet, serverFlagSet)
root, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatal("Failed to set up test config")
@ -473,6 +479,7 @@ func TestInitServerConfig(t *testing.T) {
t.Fatalf("Test %d failed with %v", i+1, tErr)
}
initServerConfig(ctx)
os.Unsetenv(test.envVar)
}
}

View file

@ -119,17 +119,13 @@ func TestDoesPresignedV2SignatureMatch(t *testing.T) {
// TestValidateV2AuthHeader - Tests validate the logic of V2 Authorization header validator.
func TestValidateV2AuthHeader(t *testing.T) {
// Initialize server config.
if _, err := initConfig(); err != nil {
t.Fatal(err)
root, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatal("Unable to initialize test config.")
}
defer removeAll(root)
// Save config.
if err := serverConfig.Save(); err != nil {
t.Fatal(err)
}
accessID := serverConfig.GetCredential().AccessKey
testCases := []struct {
authString string
expectedError APIErrorCode
@ -194,13 +190,11 @@ func TestValidateV2AuthHeader(t *testing.T) {
}
func TestDoesPolicySignatureV2Match(t *testing.T) {
if _, err := initConfig(); err != nil {
t.Fatal(err)
}
if err := serverConfig.Save(); err != nil {
t.Fatal(err)
root, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatal("Unable to initialize test config.")
}
defer removeAll(root)
creds := serverConfig.GetCredential()
policy := "policy"
testCases := []struct {

View file

@ -496,6 +496,10 @@ func resetGlobalIsXL() {
globalIsXL = false
}
func resetGlobalIsEnvs() {
globalIsEnvCreds = false
}
// Resets all the globals used modified in tests.
// Resetting ensures that the changes made to globals by one test doesn't affect others.
func resetTestGlobals() {
@ -513,6 +517,8 @@ func resetTestGlobals() {
resetGlobalEndpoints()
// Reset global isXL flag.
resetGlobalIsXL()
// Reset global isEnvCreds flag.
resetGlobalIsEnvs()
}
// Configure the server for the test run.
@ -527,7 +533,7 @@ func newTestConfig(bucketLocation string) (rootPath string, err error) {
setGlobalConfigPath(rootPath)
// Initialize server config.
if _, err = initConfig(); err != nil {
if err = newConfig(credential{}); err != nil {
return "", err
}
@ -1790,6 +1796,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName,
failTestStr := func(testType, failMsg string) string {
return fmt.Sprintf("Minio %s: %s fail for \"%s\": \n<Error> %s", instanceType, testType, testName, failMsg)
}
// httptest Recorder to capture all the response by the http handler.
rec := httptest.NewRecorder()
// reading the body to preserve it so that it can be used again for second attempt of sending unsigned HTTP request.
@ -1941,8 +1948,10 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [
// reset globals.
// this is to make sure that the tests are not affected by modified value.
resetTestGlobals()
// initialize NSLock.
initNSLock(false)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
@ -2025,6 +2034,7 @@ func ExecObjectLayerDiskAlteredTest(t *testing.T, objTest objTestDiskNotFoundTyp
if err != nil {
t.Fatalf("Initialization of object layer failed for XL setup: %s", err)
}
// Executing the object layer tests for XL.
objTest(objLayer, XLTestStr, fsDirs, t)
defer removeRoots(fsDirs)

View file

@ -362,12 +362,21 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
return toJSONError(errAuthentication)
}
// If creds are set through ENV disallow changing credentials.
if globalIsEnvCreds {
return toJSONError(errChangeCredNotAllowed)
}
// As we already validated the authentication, we save given access/secret keys.
creds, err := getCredential(args.AccessKey, args.SecretKey)
if err != nil {
if err := validateAuthKeys(args.AccessKey, args.SecretKey); err != nil {
return toJSONError(err)
}
creds := credential{
AccessKey: args.AccessKey,
SecretKey: args.SecretKey,
}
// Notify all other Minio peers to update credentials
errsMap := updateCredsOnPeers(creds)
@ -375,7 +384,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
serverConfig.SetCredential(creds)
// Persist updated credentials.
if err = serverConfig.Save(); err != nil {
if err := serverConfig.Save(); err != nil {
errsMap[globalMinioAddr] = err
}
@ -397,7 +406,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se
}
// As we have updated access/secret key, generate new auth token.
token, err := authenticateWeb(args.AccessKey, args.SecretKey)
token, err := authenticateWeb(creds.AccessKey, creds.SecretKey)
if err != nil {
// Did we have peer errors?
if len(errsMap) > 0 {
@ -829,8 +838,13 @@ func toWebAPIError(err error) APIError {
HTTPStatusCode: http.StatusBadRequest,
Description: err.Error(),
}
} else if err == errChangeCredNotAllowed {
return APIError{
Code: "MethodNotAllowed",
HTTPStatusCode: http.StatusMethodNotAllowed,
Description: err.Error(),
}
}
// Convert error type to api error code.
var apiErrCode APIErrorCode
switch err.(type) {

View file

@ -128,15 +128,6 @@ func TestWebHandlerLogin(t *testing.T) {
func testLoginWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
// test cases with sample input and expected output.
@ -177,15 +168,6 @@ func testStorageInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHa
// get random bucket name.
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -223,15 +205,6 @@ func TestWebHandlerServerInfo(t *testing.T) {
func testServerInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -269,15 +242,6 @@ func TestWebHandlerMakeBucket(t *testing.T) {
func testMakeBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -329,15 +293,6 @@ func TestWebHandlerListBuckets(t *testing.T) {
func testListBucketsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -386,15 +341,6 @@ func TestWebHandlerListObjects(t *testing.T) {
func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
rec := httptest.NewRecorder()
@ -490,15 +436,6 @@ func TestWebHandlerRemoveObject(t *testing.T) {
func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
rec := httptest.NewRecorder()
@ -566,15 +503,6 @@ func TestWebHandlerGenerateAuth(t *testing.T) {
func testGenerateAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
rec := httptest.NewRecorder()
@ -612,15 +540,6 @@ func TestWebHandlerSetAuth(t *testing.T) {
func testSetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
rec := httptest.NewRecorder()
@ -673,15 +592,6 @@ func TestWebHandlerGetAuth(t *testing.T) {
func testGetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
rec := httptest.NewRecorder()
@ -718,18 +628,9 @@ func TestWebHandlerUpload(t *testing.T) {
func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
content := []byte("temporary file's content")
content := []byte("temporary file's content")
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
if err != nil {
t.Fatal("Cannot authenticate")
@ -820,15 +721,6 @@ func TestWebHandlerDownload(t *testing.T) {
func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -912,15 +804,6 @@ func TestWebHandlerPresignedGetHandler(t *testing.T) {
func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -1025,15 +908,6 @@ func TestWebHandlerGetBucketPolicyHandler(t *testing.T) {
func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -1108,15 +982,6 @@ func TestWebHandlerListAllBucketPoliciesHandler(t *testing.T) {
func testWebListAllBucketPoliciesHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
@ -1214,15 +1079,6 @@ func TestWebHandlerSetBucketPolicyHandler(t *testing.T) {
func testWebSetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint(obj)
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
}
// remove the root directory after the test ends.
defer removeAll(rootPath)
credentials := serverConfig.GetCredential()
authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)