mirror of
https://github.com/minio/minio.git
synced 2025-11-09 13:39:46 -05:00
upgrade golang-lint to the latest (#15600)
This commit is contained in:
@@ -35,8 +35,8 @@ func shouldEscape(c byte) bool {
|
||||
|
||||
// s3URLEncode is based on Golang's url.QueryEscape() code,
|
||||
// while considering some S3 exceptions:
|
||||
// - Avoid encoding '/' and '*'
|
||||
// - Force encoding of '~'
|
||||
// - Avoid encoding '/' and '*'
|
||||
// - Force encoding of '~'
|
||||
func s3URLEncode(s string) string {
|
||||
spaceCount, hexCount := 0, 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
|
||||
@@ -288,9 +288,10 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in
|
||||
}
|
||||
|
||||
// Check request auth type verifies the incoming http request
|
||||
// - validates the request signature
|
||||
// - validates the policy action if anonymous tests bucket policies if any,
|
||||
// for authenticated requests validates IAM policies.
|
||||
// - validates the request signature
|
||||
// - validates the policy action if anonymous tests bucket policies if any,
|
||||
// for authenticated requests validates IAM policies.
|
||||
//
|
||||
// returns APIErrorCode if any to be replied to the client.
|
||||
func checkRequestAuthType(ctx context.Context, r *http.Request, action policy.Action, bucketName, objectName string) (s3Err APIErrorCode) {
|
||||
_, _, s3Err = checkRequestAuthTypeCredential(ctx, r, action, bucketName, objectName)
|
||||
@@ -298,9 +299,10 @@ func checkRequestAuthType(ctx context.Context, r *http.Request, action policy.Ac
|
||||
}
|
||||
|
||||
// Check request auth type verifies the incoming http request
|
||||
// - validates the request signature
|
||||
// - validates the policy action if anonymous tests bucket policies if any,
|
||||
// for authenticated requests validates IAM policies.
|
||||
// - validates the request signature
|
||||
// - validates the policy action if anonymous tests bucket policies if any,
|
||||
// for authenticated requests validates IAM policies.
|
||||
//
|
||||
// returns APIErrorCode if any to be replied to the client.
|
||||
// Additionally returns the accessKey used in the request, and if this request is by an admin.
|
||||
func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action policy.Action, bucketName, objectName string) (cred auth.Credentials, owner bool, s3Err APIErrorCode) {
|
||||
|
||||
@@ -26,9 +26,10 @@ import (
|
||||
)
|
||||
|
||||
// healTask represents what to heal along with options
|
||||
// path: '/' => Heal disk formats along with metadata
|
||||
// path: 'bucket/' or '/bucket/' => Heal bucket
|
||||
// path: 'bucket/object' => Heal object
|
||||
//
|
||||
// path: '/' => Heal disk formats along with metadata
|
||||
// path: 'bucket/' or '/bucket/' => Heal bucket
|
||||
// path: 'bucket/object' => Heal object
|
||||
type healTask struct {
|
||||
bucket string
|
||||
object string
|
||||
|
||||
@@ -67,11 +67,16 @@ const (
|
||||
// - Check if a bucket has an entry in etcd backend
|
||||
// -- If no, make an entry
|
||||
// -- If yes, check if the entry matches local IP check if we
|
||||
// need to update the entry then proceed to update
|
||||
//
|
||||
// need to update the entry then proceed to update
|
||||
//
|
||||
// -- If yes, check if the IP of entry matches local IP.
|
||||
// This means entry is for this instance.
|
||||
//
|
||||
// This means entry is for this instance.
|
||||
//
|
||||
// -- If IP of the entry doesn't match, this means entry is
|
||||
// for another instance. Log an error to console.
|
||||
//
|
||||
// for another instance. Log an error to console.
|
||||
func initFederatorBackend(buckets []BucketInfo, objLayer ObjectLayer) {
|
||||
if len(buckets) == 0 {
|
||||
return
|
||||
@@ -227,7 +232,6 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r *
|
||||
// using the Initiate Multipart Upload request, but has not yet been
|
||||
// completed or aborted. This operation returns at most 1,000 multipart
|
||||
// uploads in the response.
|
||||
//
|
||||
func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "ListMultipartUploads")
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ import (
|
||||
// Validate all the ListObjects query arguments, returns an APIErrorCode
|
||||
// if one of the args do not meet the required conditions.
|
||||
// Special conditions required by MinIO server are as below
|
||||
// - delimiter if set should be equal to '/', otherwise the request is rejected.
|
||||
// - marker if set should have a common prefix with 'prefix' param, otherwise
|
||||
// the request is rejected.
|
||||
// - delimiter if set should be equal to '/', otherwise the request is rejected.
|
||||
// - marker if set should have a common prefix with 'prefix' param, otherwise
|
||||
// the request is rejected.
|
||||
func validateListObjectsArgs(marker, delimiter, encodingType string, maxKeys int) APIErrorCode {
|
||||
// Max keys cannot be negative.
|
||||
if maxKeys < 0 {
|
||||
@@ -298,7 +298,6 @@ func proxyRequestByNodeIndex(ctx context.Context, w http.ResponseWriter, r *http
|
||||
// This implementation of the GET operation returns some or all (up to 1000)
|
||||
// of the objects in a bucket. You can use the request parameters as selection
|
||||
// criteria to return a subset of the objects in a bucket.
|
||||
//
|
||||
func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "ListObjectsV1")
|
||||
|
||||
|
||||
@@ -1377,7 +1377,6 @@ type ReplicationPool struct {
|
||||
mrfWorkerWg sync.WaitGroup
|
||||
once sync.Once
|
||||
mu sync.Mutex
|
||||
mrfMutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewReplicationPool creates a pool of replication workers of specified size
|
||||
|
||||
@@ -56,7 +56,8 @@ func storeDataUsageInBackend(ctx context.Context, objAPI ObjectLayer, dui <-chan
|
||||
}
|
||||
|
||||
// loadPrefixUsageFromBackend returns prefix usages found in passed buckets
|
||||
// e.g.: /testbucket/prefix => 355601334
|
||||
//
|
||||
// e.g.: /testbucket/prefix => 355601334
|
||||
func loadPrefixUsageFromBackend(ctx context.Context, objAPI ObjectLayer, bucket string) (map[string]uint64, error) {
|
||||
z, ok := objAPI.(*erasureServerPools)
|
||||
if !ok {
|
||||
|
||||
@@ -45,10 +45,10 @@ type DummyDataGen struct {
|
||||
//
|
||||
// Given the function:
|
||||
//
|
||||
// f := func(r io.Reader) string {
|
||||
// b, _ := ioutil.ReadAll(r)
|
||||
// return string(b)
|
||||
// }
|
||||
// f := func(r io.Reader) string {
|
||||
// b, _ := ioutil.ReadAll(r)
|
||||
// return string(b)
|
||||
// }
|
||||
//
|
||||
// for example, the following is true:
|
||||
//
|
||||
|
||||
@@ -231,8 +231,8 @@ func getLatestFileInfo(ctx context.Context, partsMetadata []FileInfo, defaultPar
|
||||
//
|
||||
// - disks which have all parts specified in the latest xl.meta.
|
||||
//
|
||||
// - slice of errors about the state of data files on disk - can have
|
||||
// a not-found error or a hash-mismatch error.
|
||||
// - slice of errors about the state of data files on disk - can have
|
||||
// a not-found error or a hash-mismatch error.
|
||||
func disksWithAllParts(ctx context.Context, onlineDisks []StorageAPI, partsMetadata []FileInfo,
|
||||
errs []error, latestMeta FileInfo, bucket, object string,
|
||||
scanMode madmin.HealScanMode) ([]StorageAPI, []error, time.Time,
|
||||
|
||||
@@ -652,6 +652,7 @@ func (z *erasureServerPools) decommissionObject(ctx context.Context, bucket stri
|
||||
}
|
||||
|
||||
// versionsSorter sorts FileInfo slices by version.
|
||||
//
|
||||
//msgp:ignore versionsSorter
|
||||
type versionsSorter []FileInfo
|
||||
|
||||
|
||||
@@ -371,9 +371,10 @@ func migrateCacheData(ctx context.Context, c *diskCache, bucket, object, oldfile
|
||||
|
||||
// migrate cache contents from old cacheFS format to new backend format
|
||||
// new format is flat
|
||||
// sha(bucket,object)/ <== dir name
|
||||
// - part.1 <== data
|
||||
// - cache.json <== metadata
|
||||
//
|
||||
// sha(bucket,object)/ <== dir name
|
||||
// - part.1 <== data
|
||||
// - cache.json <== metadata
|
||||
func migrateOldCache(ctx context.Context, c *diskCache) error {
|
||||
oldCacheBucketsPath := path.Join(c.dir, minioMetaBucket, "buckets")
|
||||
cacheFormatPath := pathJoin(c.dir, minioMetaBucket, formatConfigFile)
|
||||
|
||||
@@ -253,13 +253,13 @@ func genFormatCacheInvalidDisksOrder() []*formatCacheV2 {
|
||||
}
|
||||
|
||||
// Wrapper for calling FormatCache tests - validates
|
||||
// - valid format
|
||||
// - unrecognized version number
|
||||
// - unrecognized format tag
|
||||
// - unrecognized cache version
|
||||
// - wrong number of Disks entries
|
||||
// - invalid This uuid
|
||||
// - invalid Disks order
|
||||
// - valid format
|
||||
// - unrecognized version number
|
||||
// - unrecognized format tag
|
||||
// - unrecognized cache version
|
||||
// - wrong number of Disks entries
|
||||
// - invalid This uuid
|
||||
// - invalid Disks order
|
||||
func TestFormatCache(t *testing.T) {
|
||||
formatInputCases := [][]*formatCacheV1{
|
||||
genFormatCacheValid(),
|
||||
|
||||
@@ -100,12 +100,12 @@ func (t *TreeWalkPool) Release(params listParams) (resultCh chan TreeWalkResult,
|
||||
|
||||
// Set - adds a treeWalk to the treeWalkPool.
|
||||
// Also starts a timer go-routine that ends when:
|
||||
// 1) time.After() expires after t.timeOut seconds.
|
||||
// The expiration is needed so that the treeWalk go-routine resources are freed after a timeout
|
||||
// if the S3 client does only partial listing of objects.
|
||||
// 2) Release() signals the timer go-routine to end on endTimerCh.
|
||||
// During listing the timer should not timeout and end the treeWalk go-routine, hence the
|
||||
// timer go-routine should be ended.
|
||||
// 1. time.After() expires after t.timeOut seconds.
|
||||
// The expiration is needed so that the treeWalk go-routine resources are freed after a timeout
|
||||
// if the S3 client does only partial listing of objects.
|
||||
// 2. Release() signals the timer go-routine to end on endTimerCh.
|
||||
// During listing the timer should not timeout and end the treeWalk go-routine, hence the
|
||||
// timer go-routine should be ended.
|
||||
func (t *TreeWalkPool) Set(params listParams, resultCh chan TreeWalkResult, endWalkCh chan struct{}) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
@@ -139,10 +139,10 @@ func (fsi *fsIOPool) Open(path string) (*lock.RLockedFile, error) {
|
||||
}
|
||||
|
||||
// Write - Attempt to lock the file if it exists,
|
||||
// - if the file exists. Then we try to get a write lock this
|
||||
// will block if we can't get a lock perhaps another write
|
||||
// or read is in progress. Concurrent calls are protected
|
||||
// by the global namspace lock within the same process.
|
||||
// - if the file exists. Then we try to get a write lock this
|
||||
// will block if we can't get a lock perhaps another write
|
||||
// or read is in progress. Concurrent calls are protected
|
||||
// by the global namspace lock within the same process.
|
||||
func (fsi *fsIOPool) Write(path string) (wlk *lock.LockedFile, err error) {
|
||||
if err = checkPathLength(path); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -37,18 +37,17 @@ import (
|
||||
// will cache that Provider for all calls to IsExpired(), until Retrieve is
|
||||
// called again after IsExpired() is true.
|
||||
//
|
||||
// creds := credentials.NewChainCredentials(
|
||||
// []credentials.Provider{
|
||||
// &credentials.EnvAWSS3{},
|
||||
// &credentials.EnvMinio{},
|
||||
// })
|
||||
//
|
||||
// // Usage of ChainCredentials.
|
||||
// mc, err := minio.NewWithCredentials(endpoint, creds, secure, "us-east-1")
|
||||
// if err != nil {
|
||||
// log.Fatalln(err)
|
||||
// }
|
||||
// creds := credentials.NewChainCredentials(
|
||||
// []credentials.Provider{
|
||||
// &credentials.EnvAWSS3{},
|
||||
// &credentials.EnvMinio{},
|
||||
// })
|
||||
//
|
||||
// // Usage of ChainCredentials.
|
||||
// mc, err := minio.NewWithCredentials(endpoint, creds, secure, "us-east-1")
|
||||
// if err != nil {
|
||||
// log.Fatalln(err)
|
||||
// }
|
||||
type Chain struct {
|
||||
Providers []credentials.Provider
|
||||
curr credentials.Provider
|
||||
|
||||
@@ -140,21 +140,21 @@ func randString(n int, src rand.Source, prefix string) string {
|
||||
}
|
||||
|
||||
// Chains all credential types, in the following order:
|
||||
// - AWS env vars (i.e. AWS_ACCESS_KEY_ID)
|
||||
// - AWS creds file (i.e. AWS_SHARED_CREDENTIALS_FILE or ~/.aws/credentials)
|
||||
// - Static credentials provided by user (i.e. MINIO_ROOT_USER/MINIO_ACCESS_KEY)
|
||||
// - AWS env vars (i.e. AWS_ACCESS_KEY_ID)
|
||||
// - AWS creds file (i.e. AWS_SHARED_CREDENTIALS_FILE or ~/.aws/credentials)
|
||||
// - Static credentials provided by user (i.e. MINIO_ROOT_USER/MINIO_ACCESS_KEY)
|
||||
var defaultProviders = []credentials.Provider{
|
||||
&credentials.EnvAWS{},
|
||||
&credentials.FileAWSCredentials{},
|
||||
}
|
||||
|
||||
// Chains all credential types, in the following order:
|
||||
// - AWS env vars (i.e. AWS_ACCESS_KEY_ID)
|
||||
// - AWS creds file (i.e. AWS_SHARED_CREDENTIALS_FILE or ~/.aws/credentials)
|
||||
// - IAM profile based credentials. (performs an HTTP
|
||||
// call to a pre-defined endpoint, only valid inside
|
||||
// configured ec2 instances)
|
||||
// - Static credentials provided by user (i.e. MINIO_ROOT_USER/MINIO_ACCESS_KEY)
|
||||
// - AWS env vars (i.e. AWS_ACCESS_KEY_ID)
|
||||
// - AWS creds file (i.e. AWS_SHARED_CREDENTIALS_FILE or ~/.aws/credentials)
|
||||
// - IAM profile based credentials. (performs an HTTP
|
||||
// call to a pre-defined endpoint, only valid inside
|
||||
// configured ec2 instances)
|
||||
// - Static credentials provided by user (i.e. MINIO_ROOT_USER/MINIO_ACCESS_KEY)
|
||||
var defaultAWSCredProviders = []credentials.Provider{
|
||||
&credentials.EnvAWS{},
|
||||
&credentials.FileAWSCredentials{},
|
||||
|
||||
@@ -48,10 +48,11 @@ func etcdKvsToSet(prefix string, kvs []*mvccpb.KeyValue) set.StringSet {
|
||||
|
||||
// Extract path string by stripping off the `prefix` value and the suffix,
|
||||
// value, usually in the following form.
|
||||
// s := "config/iam/users/foo/config.json"
|
||||
// prefix := "config/iam/users/"
|
||||
// suffix := "config.json"
|
||||
// result is foo
|
||||
//
|
||||
// s := "config/iam/users/foo/config.json"
|
||||
// prefix := "config/iam/users/"
|
||||
// suffix := "config.json"
|
||||
// result is foo
|
||||
func extractPathPrefixAndSuffix(s string, prefix string, suffix string) string {
|
||||
return pathClean(strings.TrimSuffix(strings.TrimPrefix(s, prefix), suffix))
|
||||
}
|
||||
|
||||
@@ -322,7 +322,8 @@ func isLocalHost(host string, port string, localPort string) (bool, error) {
|
||||
|
||||
// sameLocalAddrs - returns true if two addresses, even with different
|
||||
// formats, point to the same machine, e.g:
|
||||
// ':9000' and 'http://localhost:9000/' will return true
|
||||
//
|
||||
// ':9000' and 'http://localhost:9000/' will return true
|
||||
func sameLocalAddrs(addr1, addr2 string) (bool, error) {
|
||||
// Extract host & port from given parameters
|
||||
host1, port1, err := extractHostPort(addr1)
|
||||
|
||||
@@ -1125,9 +1125,9 @@ func (sys *NotificationSys) GetClusterMetrics(ctx context.Context) <-chan Metric
|
||||
// 'freeze' is 'false' would resume all S3 API calls again.
|
||||
// NOTE: once a tenant is frozen either two things needs to
|
||||
// happen before resuming normal operations.
|
||||
// - Server needs to be restarted 'mc admin service restart'
|
||||
// - 'freeze' should be set to 'false' for this call
|
||||
// to resume normal operations.
|
||||
// - Server needs to be restarted 'mc admin service restart'
|
||||
// - 'freeze' should be set to 'false' for this call
|
||||
// to resume normal operations.
|
||||
func (sys *NotificationSys) ServiceFreeze(ctx context.Context, freeze bool) []NotificationPeerErr {
|
||||
serviceSig := serviceUnFreeze
|
||||
if freeze {
|
||||
|
||||
@@ -33,20 +33,22 @@ var etagRegex = regexp.MustCompile("\"*?([^\"]*?)\"*?$")
|
||||
|
||||
// Validates the preconditions for CopyObjectPart, returns true if CopyObjectPart
|
||||
// operation should not proceed. Preconditions supported are:
|
||||
// x-amz-copy-source-if-modified-since
|
||||
// x-amz-copy-source-if-unmodified-since
|
||||
// x-amz-copy-source-if-match
|
||||
// x-amz-copy-source-if-none-match
|
||||
//
|
||||
// x-amz-copy-source-if-modified-since
|
||||
// x-amz-copy-source-if-unmodified-since
|
||||
// x-amz-copy-source-if-match
|
||||
// x-amz-copy-source-if-none-match
|
||||
func checkCopyObjectPartPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo) bool {
|
||||
return checkCopyObjectPreconditions(ctx, w, r, objInfo)
|
||||
}
|
||||
|
||||
// Validates the preconditions for CopyObject, returns true if CopyObject operation should not proceed.
|
||||
// Preconditions supported are:
|
||||
// x-amz-copy-source-if-modified-since
|
||||
// x-amz-copy-source-if-unmodified-since
|
||||
// x-amz-copy-source-if-match
|
||||
// x-amz-copy-source-if-none-match
|
||||
//
|
||||
// x-amz-copy-source-if-modified-since
|
||||
// x-amz-copy-source-if-unmodified-since
|
||||
// x-amz-copy-source-if-match
|
||||
// x-amz-copy-source-if-none-match
|
||||
func checkCopyObjectPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo) bool {
|
||||
// Return false for methods other than GET and HEAD.
|
||||
if r.Method != http.MethodPut {
|
||||
@@ -128,10 +130,11 @@ func checkCopyObjectPreconditions(ctx context.Context, w http.ResponseWriter, r
|
||||
|
||||
// Validates the preconditions. Returns true if GET/HEAD operation should not proceed.
|
||||
// Preconditions supported are:
|
||||
// If-Modified-Since
|
||||
// If-Unmodified-Since
|
||||
// If-Match
|
||||
// If-None-Match
|
||||
//
|
||||
// If-Modified-Since
|
||||
// If-Unmodified-Since
|
||||
// If-Match
|
||||
// If-None-Match
|
||||
func checkPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo, opts ObjectOptions) bool {
|
||||
// Return false for methods other than GET and HEAD.
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
|
||||
@@ -3429,7 +3429,8 @@ func testAPIPutObjectPartHandlerStreaming(obj ObjectLayer, instanceType, bucketN
|
||||
}
|
||||
|
||||
// TestAPIPutObjectPartHandler - Tests validate the response of PutObjectPart HTTP handler
|
||||
// for variety of inputs.
|
||||
//
|
||||
// for variety of inputs.
|
||||
func TestAPIPutObjectPartHandler(t *testing.T) {
|
||||
defer DetectTestLeak(t)()
|
||||
ExecExtendedObjectLayerAPITest(t, testAPIPutObjectPartHandler, []string{"PutObjectPart"})
|
||||
@@ -3743,7 +3744,8 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin
|
||||
}
|
||||
|
||||
// TestAPIListObjectPartsHandlerPreSign - Tests validate the response of ListObjectParts HTTP handler
|
||||
// when signature type of the HTTP request is `Presigned`.
|
||||
//
|
||||
// when signature type of the HTTP request is `Presigned`.
|
||||
func TestAPIListObjectPartsHandlerPreSign(t *testing.T) {
|
||||
defer DetectTestLeak(t)()
|
||||
ExecObjectLayerAPITest(t, testAPIListObjectPartsHandlerPreSign,
|
||||
@@ -3832,7 +3834,8 @@ func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketN
|
||||
}
|
||||
|
||||
// TestAPIListObjectPartsHandler - Tests validate the response of ListObjectParts HTTP handler
|
||||
// for variety of success/failure cases.
|
||||
//
|
||||
// for variety of success/failure cases.
|
||||
func TestAPIListObjectPartsHandler(t *testing.T) {
|
||||
defer DetectTestLeak(t)()
|
||||
ExecExtendedObjectLayerAPITest(t, testAPIListObjectPartsHandler, []string{"ListObjectParts"})
|
||||
|
||||
@@ -50,7 +50,8 @@ const (
|
||||
)
|
||||
|
||||
// splitZipExtensionPath splits the S3 path to the zip file and the path inside the zip:
|
||||
// e.g /path/to/archive.zip/backup-2021/myimage.png => /path/to/archive.zip, backup/myimage.png
|
||||
//
|
||||
// e.g /path/to/archive.zip/backup-2021/myimage.png => /path/to/archive.zip, backup/myimage.png
|
||||
func splitZipExtensionPath(input string) (zipPath, object string, err error) {
|
||||
idx := strings.Index(input, archivePattern)
|
||||
if idx < 0 {
|
||||
|
||||
@@ -107,7 +107,8 @@ func unescapeQueries(encodedQuery string) (unescapedQueries []string, err error)
|
||||
}
|
||||
|
||||
// doesPresignV2SignatureMatch - Verify query headers with presigned signature
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
|
||||
//
|
||||
// returns ErrNone if matches. S3 errors otherwise.
|
||||
func doesPresignV2SignatureMatch(r *http.Request) APIErrorCode {
|
||||
// r.RequestURI will have raw encoded URI as sent by the client.
|
||||
|
||||
@@ -171,12 +171,12 @@ type preSignValues struct {
|
||||
|
||||
// Parses signature version '4' query string of the following form.
|
||||
//
|
||||
// querystring = X-Amz-Algorithm=algorithm
|
||||
// querystring += &X-Amz-Credential= urlencode(accessKey + '/' + credential_scope)
|
||||
// querystring += &X-Amz-Date=date
|
||||
// querystring += &X-Amz-Expires=timeout interval
|
||||
// querystring += &X-Amz-SignedHeaders=signed_headers
|
||||
// querystring += &X-Amz-Signature=signature
|
||||
// querystring = X-Amz-Algorithm=algorithm
|
||||
// querystring += &X-Amz-Credential= urlencode(accessKey + '/' + credential_scope)
|
||||
// querystring += &X-Amz-Date=date
|
||||
// querystring += &X-Amz-Expires=timeout interval
|
||||
// querystring += &X-Amz-SignedHeaders=signed_headers
|
||||
// querystring += &X-Amz-Signature=signature
|
||||
//
|
||||
// verifies if any of the necessary query params are missing in the presigned request.
|
||||
func doesV4PresignParamsExist(query url.Values) APIErrorCode {
|
||||
@@ -251,9 +251,8 @@ func parsePreSignV4(query url.Values, region string, stype serviceType) (psv pre
|
||||
|
||||
// Parses signature version '4' header of the following form.
|
||||
//
|
||||
// Authorization: algorithm Credential=accessKeyID/credScope, \
|
||||
// SignedHeaders=signedHeaders, Signature=signature
|
||||
//
|
||||
// Authorization: algorithm Credential=accessKeyID/credScope, \
|
||||
// SignedHeaders=signedHeaders, Signature=signature
|
||||
func parseSignV4(v4Auth string, region string, stype serviceType) (sv signValues, aec APIErrorCode) {
|
||||
// credElement is fetched first to skip replacing the space in access key.
|
||||
credElement := strings.TrimPrefix(strings.Split(strings.TrimSpace(v4Auth), ",")[0], signV4Algorithm)
|
||||
|
||||
@@ -82,10 +82,11 @@ func validateCredentialfields(t *testing.T, testNum int, expectedCredentials cre
|
||||
// A valid format of creadential should be of the following format.
|
||||
// Credential = accessKey + SlashSeparator+ scope
|
||||
// where scope = string.Join([]string{ currTime.Format(yyyymmdd),
|
||||
// globalMinioDefaultRegion,
|
||||
// "s3",
|
||||
// "aws4_request",
|
||||
// },SlashSeparator)
|
||||
//
|
||||
// globalMinioDefaultRegion,
|
||||
// "s3",
|
||||
// "aws4_request",
|
||||
// },SlashSeparator)
|
||||
func TestParseCredentialHeader(t *testing.T) {
|
||||
sampleTimeStr := UTCNow().Format(yyyymmdd)
|
||||
|
||||
|
||||
@@ -95,13 +95,13 @@ func getSignedHeaders(signedHeaders http.Header) string {
|
||||
// getCanonicalRequest generate a canonical request of style
|
||||
//
|
||||
// canonicalRequest =
|
||||
// <HTTPMethod>\n
|
||||
// <CanonicalURI>\n
|
||||
// <CanonicalQueryString>\n
|
||||
// <CanonicalHeaders>\n
|
||||
// <SignedHeaders>\n
|
||||
// <HashedPayload>
|
||||
//
|
||||
// <HTTPMethod>\n
|
||||
// <CanonicalURI>\n
|
||||
// <CanonicalQueryString>\n
|
||||
// <CanonicalHeaders>\n
|
||||
// <SignedHeaders>\n
|
||||
// <HashedPayload>
|
||||
func getCanonicalRequest(extractedSignedHeaders http.Header, payload, queryStr, urlPath, method string) string {
|
||||
rawQuery := strings.ReplaceAll(queryStr, "+", "%20")
|
||||
encodedPath := s3utils.EncodePath(urlPath)
|
||||
@@ -169,7 +169,8 @@ func compareSignatureV4(sig1, sig2 string) bool {
|
||||
}
|
||||
|
||||
// doesPolicySignatureMatch - Verify query headers with post policy
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
|
||||
//
|
||||
// returns ErrNone if the signature matches.
|
||||
func doesPolicySignatureV4Match(formValues http.Header) (auth.Credentials, APIErrorCode) {
|
||||
// Server region.
|
||||
@@ -203,7 +204,8 @@ func doesPolicySignatureV4Match(formValues http.Header) (auth.Credentials, APIEr
|
||||
}
|
||||
|
||||
// doesPresignedSignatureMatch - Verify query headers with presigned signature
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
|
||||
//
|
||||
// returns ErrNone if the signature matches.
|
||||
func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region string, stype serviceType) APIErrorCode {
|
||||
// Copy request
|
||||
@@ -329,7 +331,8 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
}
|
||||
|
||||
// doesSignatureMatch - Verify authorization header with calculated header in accordance with
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
|
||||
//
|
||||
// returns ErrNone if signature matches.
|
||||
func doesSignatureMatch(hashedPayload string, r *http.Request, region string, stype serviceType) APIErrorCode {
|
||||
// Copy request.
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
// DeleteOptions represents the disk level delete options available for the APIs
|
||||
//
|
||||
//msgp:ignore DeleteOptions
|
||||
type DeleteOptions struct {
|
||||
Recursive bool
|
||||
@@ -32,8 +33,11 @@ type DeleteOptions struct {
|
||||
|
||||
// DiskInfo is an extended type which returns current
|
||||
// disk usage per path.
|
||||
//msgp:tuple DiskInfo
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
//msgp:tuple DiskInfo
|
||||
type DiskInfo struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
@@ -65,8 +69,11 @@ type DiskMetrics struct {
|
||||
type VolsInfo []VolInfo
|
||||
|
||||
// VolInfo - represents volume stat information.
|
||||
//msgp:tuple VolInfo
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
//msgp:tuple VolInfo
|
||||
type VolInfo struct {
|
||||
// Name of the volume.
|
||||
Name string
|
||||
@@ -77,6 +84,8 @@ type VolInfo struct {
|
||||
|
||||
// FilesInfo represent a list of files, additionally
|
||||
// indicates if the list is last.
|
||||
//
|
||||
//msgp:tuple FileInfo
|
||||
type FilesInfo struct {
|
||||
Files []FileInfo
|
||||
IsTruncated bool
|
||||
@@ -91,8 +100,11 @@ func (f FileInfoVersions) Size() (size int64) {
|
||||
}
|
||||
|
||||
// FileInfoVersions represent a list of versions for a given file.
|
||||
//msgp:tuple FileInfoVersions
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
//
|
||||
//msgp:tuple FileInfoVersions
|
||||
type FileInfoVersions struct {
|
||||
// Name of the volume.
|
||||
Volume string `msg:"v,omitempty"`
|
||||
@@ -136,7 +148,6 @@ type RawFileInfo struct {
|
||||
}
|
||||
|
||||
// FileInfo - represents file stat information.
|
||||
//msgp:tuple FileInfo
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
// Make sure to bump the internode version at storage-rest-common.go
|
||||
type FileInfo struct {
|
||||
@@ -235,10 +246,10 @@ func (fi FileInfo) Equals(ofi FileInfo) (ok bool) {
|
||||
}
|
||||
|
||||
// GetDataDir returns an expected dataDir given FileInfo
|
||||
// - deleteMarker returns "delete-marker"
|
||||
// - returns "legacy" if FileInfo is XLV1 and DataDir is
|
||||
// empty, returns DataDir otherwise
|
||||
// - returns "dataDir"
|
||||
// - deleteMarker returns "delete-marker"
|
||||
// - returns "legacy" if FileInfo is XLV1 and DataDir is
|
||||
// empty, returns DataDir otherwise
|
||||
// - returns "dataDir"
|
||||
func (fi FileInfo) GetDataDir() string {
|
||||
if fi.Deleted {
|
||||
return "delete-marker"
|
||||
|
||||
@@ -63,7 +63,8 @@ func getChunkSignature(cred auth.Credentials, seedSignature string, region strin
|
||||
}
|
||||
|
||||
// calculateSeedSignature - Calculate seed signature in accordance with
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
|
||||
//
|
||||
// returns signature, error otherwise if the signature mismatches or any other
|
||||
// error while parsing and validating.
|
||||
func calculateSeedSignature(r *http.Request) (cred auth.Credentials, signature string, region string, date time.Time, errCode APIErrorCode) {
|
||||
@@ -195,7 +196,8 @@ func (cr *s3ChunkedReader) Close() (err error) {
|
||||
|
||||
// Now, we read one chunk from the underlying reader.
|
||||
// A chunk has the following format:
|
||||
// <chunk-size-as-hex> + ";chunk-signature=" + <signature-as-hex> + "\r\n" + <payload> + "\r\n"
|
||||
//
|
||||
// <chunk-size-as-hex> + ";chunk-signature=" + <signature-as-hex> + "\r\n" + <payload> + "\r\n"
|
||||
//
|
||||
// First, we read the chunk size but fail if it is larger
|
||||
// than 16 MiB. We must not accept arbitrary large chunks.
|
||||
@@ -414,7 +416,8 @@ const s3ChunkSignatureStr = ";chunk-signature="
|
||||
|
||||
// parses3ChunkExtension removes any s3 specific chunk-extension from buf.
|
||||
// For example,
|
||||
// "10000;chunk-signature=..." => "10000", "chunk-signature=..."
|
||||
//
|
||||
// "10000;chunk-signature=..." => "10000", "chunk-signature=..."
|
||||
func parseS3ChunkExtension(buf []byte) ([]byte, []byte) {
|
||||
buf = trimTrailingWhitespace(buf)
|
||||
semi := bytes.Index(buf, []byte(s3ChunkSignatureStr))
|
||||
|
||||
@@ -522,7 +522,8 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ
|
||||
// Connect-compatible identity provider.
|
||||
//
|
||||
// Eg:-
|
||||
// $ curl https://minio:9000/?Action=AssumeRoleWithWebIdentity&WebIdentityToken=<jwt>
|
||||
//
|
||||
// $ curl https://minio:9000/?Action=AssumeRoleWithWebIdentity&WebIdentityToken=<jwt>
|
||||
func (sts *stsAPIHandlers) AssumeRoleWithWebIdentity(w http.ResponseWriter, r *http.Request) {
|
||||
sts.AssumeRoleWithSSO(w, r)
|
||||
}
|
||||
@@ -531,7 +532,8 @@ func (sts *stsAPIHandlers) AssumeRoleWithWebIdentity(w http.ResponseWriter, r *h
|
||||
// OAuth2.0 client credential grants.
|
||||
//
|
||||
// Eg:-
|
||||
// $ curl https://minio:9000/?Action=AssumeRoleWithClientGrants&Token=<jwt>
|
||||
//
|
||||
// $ curl https://minio:9000/?Action=AssumeRoleWithClientGrants&Token=<jwt>
|
||||
func (sts *stsAPIHandlers) AssumeRoleWithClientGrants(w http.ResponseWriter, r *http.Request) {
|
||||
sts.AssumeRoleWithSSO(w, r)
|
||||
}
|
||||
|
||||
@@ -127,19 +127,17 @@ func TestMain(m *testing.M) {
|
||||
// concurrency level for certain parallel tests.
|
||||
const testConcurrencyLevel = 10
|
||||
|
||||
//
|
||||
// Excerpts from @lsegal - https://github.com/aws/aws-sdk-js/issues/659#issuecomment-120477258
|
||||
//
|
||||
// User-Agent:
|
||||
// User-Agent:
|
||||
//
|
||||
// This is ignored from signing because signing this causes problems with generating pre-signed URLs
|
||||
// (that are executed by other agents) or when customers pass requests through proxies, which may
|
||||
// modify the user-agent.
|
||||
// This is ignored from signing because signing this causes problems with generating pre-signed URLs
|
||||
// (that are executed by other agents) or when customers pass requests through proxies, which may
|
||||
// modify the user-agent.
|
||||
//
|
||||
// Authorization:
|
||||
//
|
||||
// Is skipped for obvious reasons
|
||||
// Authorization:
|
||||
//
|
||||
// Is skipped for obvious reasons
|
||||
var ignoredHeaders = map[string]bool{
|
||||
"Authorization": true,
|
||||
"User-Agent": true,
|
||||
@@ -302,8 +300,9 @@ func isSameType(obj1, obj2 interface{}) bool {
|
||||
|
||||
// TestServer encapsulates an instantiation of a MinIO instance with a temporary backend.
|
||||
// Example usage:
|
||||
// s := StartTestServer(t,"Erasure")
|
||||
// defer s.Stop()
|
||||
//
|
||||
// s := StartTestServer(t,"Erasure")
|
||||
// defer s.Stop()
|
||||
type TestServer struct {
|
||||
Root string
|
||||
Disks EndpointServerPools
|
||||
@@ -1563,11 +1562,14 @@ func prepareTestBackend(ctx context.Context, instanceType string) (ObjectLayer,
|
||||
// response for anonymous/unsigned and unknown signature type HTTP request.
|
||||
|
||||
// Here is the brief description of some of the arguments to the function below.
|
||||
// apiRouter - http.Handler with the relevant API endPoint (API endPoint under test) registered.
|
||||
// anonReq - unsigned *http.Request to invoke the handler's response for anonymous requests.
|
||||
// policyFunc - function to return bucketPolicy statement which would permit the anonymous request to be served.
|
||||
//
|
||||
// apiRouter - http.Handler with the relevant API endPoint (API endPoint under test) registered.
|
||||
// anonReq - unsigned *http.Request to invoke the handler's response for anonymous requests.
|
||||
// policyFunc - function to return bucketPolicy statement which would permit the anonymous request to be served.
|
||||
//
|
||||
// The test works in 2 steps, here is the description of the steps.
|
||||
// STEP 1: Call the handler with the unsigned HTTP request (anonReq), assert for the `ErrAccessDenied` error response.
|
||||
//
|
||||
// STEP 1: Call the handler with the unsigned HTTP request (anonReq), assert for the `ErrAccessDenied` error response.
|
||||
func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketName, objectName, instanceType string, apiRouter http.Handler,
|
||||
anonReq *http.Request, bucketPolicy *policy.Policy,
|
||||
) {
|
||||
|
||||
@@ -27,15 +27,17 @@ import (
|
||||
// // Perform a ObjectLayer.GetObjectInfo to fetch object version information
|
||||
// goiOpts := os.GetOpts()
|
||||
// gerr := objAPI.GetObjectInfo(ctx, bucket, object, goiOpts)
|
||||
// if gerr == nil {
|
||||
// os.SetTransitionState(goi)
|
||||
// }
|
||||
//
|
||||
// if gerr == nil {
|
||||
// os.SetTransitionState(goi)
|
||||
// }
|
||||
//
|
||||
// // After the overwriting object operation is complete.
|
||||
// if jentry, ok := os.ShouldRemoveRemoteObject(); ok {
|
||||
// err := globalTierJournal.AddEntry(jentry)
|
||||
// logger.LogIf(ctx, err)
|
||||
// }
|
||||
//
|
||||
// if jentry, ok := os.ShouldRemoveRemoteObject(); ok {
|
||||
// err := globalTierJournal.AddEntry(jentry)
|
||||
// logger.LogIf(ctx, err)
|
||||
// }
|
||||
type objSweeper struct {
|
||||
Object string
|
||||
Bucket string
|
||||
|
||||
@@ -51,8 +51,10 @@ func filterMatchingPrefix(entries []string, prefixEntry string) []string {
|
||||
// we need to remove this trailing "/" for objects and retain "/" for prefixes before
|
||||
// sorting because the trailing "/" can affect the sorting results for certain cases.
|
||||
// Ex. lets say entries = ["a-b/", "a/"] and both are objects.
|
||||
// sorting with out trailing "/" = ["a", "a-b"]
|
||||
// sorting with trailing "/" = ["a-b/", "a/"]
|
||||
//
|
||||
// sorting with out trailing "/" = ["a", "a-b"]
|
||||
// sorting with trailing "/" = ["a-b/", "a/"]
|
||||
//
|
||||
// Hence if entries[] does not have a case like the above example then isLeaf() check
|
||||
// can be delayed till the entry is pushed into the TreeWalkResult channel.
|
||||
// delayIsLeafCheck() returns true if isLeaf can be delayed or false if
|
||||
@@ -86,10 +88,10 @@ type ListDirFunc func(bucket, prefixDir, prefixEntry string) (emptyDir bool, ent
|
||||
// IsLeafFunc - A function isLeaf of type isLeafFunc is used to detect if an
|
||||
// entry is a leaf entry. There are 2 scenarios where isLeaf should behave
|
||||
// differently depending on the backend:
|
||||
// 1. FS backend object listing - isLeaf is true if the entry
|
||||
// has no trailing "/"
|
||||
// 2. Erasure backend object listing - isLeaf is true if the entry
|
||||
// is a directory and contains xl.meta
|
||||
// 1. FS backend object listing - isLeaf is true if the entry
|
||||
// has no trailing "/"
|
||||
// 2. Erasure backend object listing - isLeaf is true if the entry
|
||||
// is a directory and contains xl.meta
|
||||
type IsLeafFunc func(string, string) bool
|
||||
|
||||
// IsLeafDirFunc - A function isLeafDir of type isLeafDirFunc is used to detect
|
||||
|
||||
@@ -123,8 +123,7 @@ func GetCurrentReleaseTime() (releaseTime time.Time, err error) {
|
||||
//
|
||||
// https://github.com/moby/moby/blob/master/daemon/initlayer/setup_unix.go#L25
|
||||
//
|
||||
// "/.dockerenv": "file",
|
||||
//
|
||||
// "/.dockerenv": "file",
|
||||
func IsDocker() bool {
|
||||
if !globalIsCICD {
|
||||
_, err := os.Stat("/.dockerenv")
|
||||
@@ -220,7 +219,7 @@ func IsPCFTile() bool {
|
||||
// DO NOT CHANGE USER AGENT STYLE.
|
||||
// The style should be
|
||||
//
|
||||
// MinIO (<OS>; <ARCH>[; <MODE>][; dcos][; kubernetes][; docker][; source]) MinIO/<VERSION> MinIO/<RELEASE-TAG> MinIO/<COMMIT-ID> [MinIO/universe-<PACKAGE-NAME>] [MinIO/helm-<HELM-VERSION>]
|
||||
// MinIO (<OS>; <ARCH>[; <MODE>][; dcos][; kubernetes][; docker][; source]) MinIO/<VERSION> MinIO/<RELEASE-TAG> MinIO/<COMMIT-ID> [MinIO/universe-<PACKAGE-NAME>] [MinIO/helm-<HELM-VERSION>]
|
||||
//
|
||||
// Any change here should be discussed by opening an issue at
|
||||
// https://github.com/minio/minio/issues.
|
||||
|
||||
Reference in New Issue
Block a user