mirror of
				https://github.com/minio/minio.git
				synced 2025-11-04 02:01:05 +01:00 
			
		
		
		
	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)
		
			
				
	
	
		
			140 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
 * Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
package cmd
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/rand"
 | 
						|
	"encoding/base64"
 | 
						|
	"os"
 | 
						|
 | 
						|
	"github.com/minio/mc/pkg/console"
 | 
						|
 | 
						|
	"golang.org/x/crypto/bcrypt"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	accessKeyMinLen = 5
 | 
						|
	accessKeyMaxLen = 20
 | 
						|
	secretKeyMinLen = 8
 | 
						|
	secretKeyMaxLen = 40
 | 
						|
 | 
						|
	alphaNumericTable    = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
						|
	alphaNumericTableLen = byte(len(alphaNumericTable))
 | 
						|
)
 | 
						|
 | 
						|
func mustGetAccessKey() string {
 | 
						|
	keyBytes := make([]byte, accessKeyMaxLen)
 | 
						|
	if _, err := rand.Read(keyBytes); err != nil {
 | 
						|
		console.Fatalf("Unable to generate access key. Err: %s.\n", err)
 | 
						|
	}
 | 
						|
 | 
						|
	for i := 0; i < accessKeyMaxLen; i++ {
 | 
						|
		keyBytes[i] = alphaNumericTable[keyBytes[i]%alphaNumericTableLen]
 | 
						|
	}
 | 
						|
 | 
						|
	return string(keyBytes)
 | 
						|
}
 | 
						|
 | 
						|
func mustGetSecretKey() string {
 | 
						|
	keyBytes := make([]byte, secretKeyMaxLen)
 | 
						|
	if _, err := rand.Read(keyBytes); err != nil {
 | 
						|
		console.Fatalf("Unable to generate secret key. Err: %s.\n", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return string([]byte(base64.StdEncoding.EncodeToString(keyBytes))[:secretKeyMaxLen])
 | 
						|
}
 | 
						|
 | 
						|
// isAccessKeyValid - validate access key for right length.
 | 
						|
func isAccessKeyValid(accessKey string) bool {
 | 
						|
	return len(accessKey) >= accessKeyMinLen && len(accessKey) <= accessKeyMaxLen
 | 
						|
}
 | 
						|
 | 
						|
// isSecretKeyValid - validate secret key for right length.
 | 
						|
func isSecretKeyValid(secretKey string) bool {
 | 
						|
	return len(secretKey) >= secretKeyMinLen && len(secretKey) <= secretKeyMaxLen
 | 
						|
}
 | 
						|
 | 
						|
// credential container for access and secret keys.
 | 
						|
type credential struct {
 | 
						|
	AccessKey     string `json:"accessKey,omitempty"`
 | 
						|
	SecretKey     string `json:"secretKey,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 {
 | 
						|
		console.Fatalf("Unable to generate secret hash for secret key. Err: %s.\n", err)
 | 
						|
	}
 | 
						|
	return hashedSecretKey
 | 
						|
}
 | 
						|
 | 
						|
// Initialize a new credential object
 | 
						|
func newCredential() credential {
 | 
						|
	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 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
 | 
						|
	}
 | 
						|
 | 
						|
	return credential{}, nil
 | 
						|
}
 |