mirror of
https://github.com/minio/minio.git
synced 2025-04-01 02:03:42 -04:00
Simplify signature handling
This change brings a new SignatureHandler where Presigned. Requests without Payload are handled very early before even going through the call. This change simplifies Donut codebase to not have signature related logic for all API's. Simplification is still needed for Payload based signature eg. PUT/POST calls , which are still part of the donut codebase, which will be done subsequently after donut re-write.
This commit is contained in:
parent
3de10f9472
commit
cfdb29cac0
@ -31,6 +31,7 @@ var fsType2StringMap = map[string]string{
|
|||||||
"6969": "NFS",
|
"6969": "NFS",
|
||||||
"ef51": "EXT2OLD",
|
"ef51": "EXT2OLD",
|
||||||
"ef53": "EXT4",
|
"ef53": "EXT4",
|
||||||
|
"f15f": "ecryptfs",
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFSType - get filesystem type
|
// getFSType - get filesystem type
|
||||||
|
@ -619,10 +619,11 @@ func (donut API) makeDonutBucket(bucketName, acl string) *probe.Error {
|
|||||||
}
|
}
|
||||||
nodeNumber = nodeNumber + 1
|
nodeNumber = nodeNumber + 1
|
||||||
}
|
}
|
||||||
metadata, err := donut.getDonutBucketMetadata()
|
var metadata *AllBuckets
|
||||||
|
metadata, err = donut.getDonutBucketMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err.ToGoError()) {
|
if os.IsNotExist(err.ToGoError()) {
|
||||||
metadata := new(AllBuckets)
|
metadata = new(AllBuckets)
|
||||||
metadata.Buckets = make(map[string]BucketMetadata)
|
metadata.Buckets = make(map[string]BucketMetadata)
|
||||||
metadata.Buckets[bucketName] = bucketMetadata
|
metadata.Buckets[bucketName] = bucketMetadata
|
||||||
err = donut.setDonutBucketMetadata(metadata)
|
err = donut.setDonutBucketMetadata(metadata)
|
||||||
|
@ -74,7 +74,7 @@ func (s *MyDonutSuite) SetUpSuite(c *C) {
|
|||||||
c.Assert(perr, IsNil)
|
c.Assert(perr, IsNil)
|
||||||
|
|
||||||
// testing empty donut
|
// testing empty donut
|
||||||
buckets, perr := dd.ListBuckets(nil)
|
buckets, perr := dd.ListBuckets()
|
||||||
c.Assert(perr, IsNil)
|
c.Assert(perr, IsNil)
|
||||||
c.Assert(len(buckets), Equals, 0)
|
c.Assert(len(buckets), Equals, 0)
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ func (s *MyDonutSuite) TestEmptyBucket(c *C) {
|
|||||||
// check if bucket is empty
|
// check if bucket is empty
|
||||||
var resources BucketResourcesMetadata
|
var resources BucketResourcesMetadata
|
||||||
resources.Maxkeys = 1
|
resources.Maxkeys = 1
|
||||||
objectsMetadata, resources, err := dd.ListObjects("foo1", resources, nil)
|
objectsMetadata, resources, err := dd.ListObjects("foo1", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(len(objectsMetadata), Equals, 0)
|
c.Assert(len(objectsMetadata), Equals, 0)
|
||||||
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
||||||
@ -113,7 +113,7 @@ func (s *MyDonutSuite) TestMakeBucketAndList(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
// check bucket exists
|
// check bucket exists
|
||||||
buckets, err := dd.ListBuckets(nil)
|
buckets, err := dd.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(len(buckets), Equals, 5)
|
c.Assert(len(buckets), Equals, 5)
|
||||||
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
||||||
@ -137,7 +137,7 @@ func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) {
|
|||||||
err = dd.MakeBucket("bar1", "private", nil, nil)
|
err = dd.MakeBucket("bar1", "private", nil, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
buckets, err := dd.ListBuckets(nil)
|
buckets, err := dd.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(len(buckets), Equals, 2)
|
c.Assert(len(buckets), Equals, 2)
|
||||||
@ -147,7 +147,7 @@ func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) {
|
|||||||
err = dd.MakeBucket("foobar1", "private", nil, nil)
|
err = dd.MakeBucket("foobar1", "private", nil, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
buckets, err = dd.ListBuckets(nil)
|
buckets, err = dd.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(len(buckets), Equals, 3)
|
c.Assert(len(buckets), Equals, 3)
|
||||||
@ -205,7 +205,7 @@ func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) {
|
|||||||
c.Assert(size, Equals, int64(len(data)))
|
c.Assert(size, Equals, int64(len(data)))
|
||||||
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
||||||
|
|
||||||
actualMetadata, err = dd.GetObjectMetadata("foo", "obj", nil)
|
actualMetadata, err = dd.GetObjectMetadata("foo", "obj")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
||||||
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
||||||
@ -244,7 +244,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = "1"
|
resources.Delimiter = "1"
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err := dd.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err := dd.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||||
@ -253,7 +253,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = ""
|
resources.Prefix = ""
|
||||||
resources.Delimiter = "1"
|
resources.Delimiter = "1"
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
@ -263,7 +263,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = ""
|
resources.Delimiter = ""
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
||||||
@ -283,7 +283,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = ""
|
resources.Delimiter = ""
|
||||||
resources.Maxkeys = 2
|
resources.Maxkeys = 2
|
||||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, true)
|
c.Assert(resources.IsTruncated, Equals, true)
|
||||||
c.Assert(len(objectsMetadata), Equals, 2)
|
c.Assert(len(objectsMetadata), Equals, 2)
|
||||||
|
@ -205,20 +205,10 @@ func (donut API) GetObject(w io.Writer, bucket string, object string, start, len
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetBucketMetadata -
|
// GetBucketMetadata -
|
||||||
func (donut API) GetBucketMetadata(bucket string, signature *signv4.Signature) (BucketMetadata, *probe.Error) {
|
func (donut API) GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error) {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return BucketMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return BucketMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return BucketMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return BucketMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
}
|
}
|
||||||
@ -238,20 +228,10 @@ func (donut API) GetBucketMetadata(bucket string, signature *signv4.Signature) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetBucketMetadata -
|
// SetBucketMetadata -
|
||||||
func (donut API) SetBucketMetadata(bucket string, metadata map[string]string, signature *signv4.Signature) *probe.Error {
|
func (donut API) SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
}
|
}
|
||||||
@ -487,20 +467,10 @@ func (donut API) MakeBucket(bucketName, acl string, location io.Reader, signatur
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListObjects - list objects from cache
|
// ListObjects - list objects from cache
|
||||||
func (donut API) ListObjects(bucket string, resources BucketResourcesMetadata, signature *signv4.Signature) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error) {
|
func (donut API) ListObjects(bucket string, resources BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error) {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return nil, BucketResourcesMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return nil, BucketResourcesMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return nil, BucketResourcesMetadata{IsTruncated: false}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return nil, BucketResourcesMetadata{IsTruncated: false}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
}
|
}
|
||||||
@ -590,20 +560,10 @@ func (b byBucketName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
|||||||
func (b byBucketName) Less(i, j int) bool { return b[i].Name < b[j].Name }
|
func (b byBucketName) Less(i, j int) bool { return b[i].Name < b[j].Name }
|
||||||
|
|
||||||
// ListBuckets - List buckets from cache
|
// ListBuckets - List buckets from cache
|
||||||
func (donut API) ListBuckets(signature *signv4.Signature) ([]BucketMetadata, *probe.Error) {
|
func (donut API) ListBuckets() ([]BucketMetadata, *probe.Error) {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return nil, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var results []BucketMetadata
|
var results []BucketMetadata
|
||||||
if len(donut.config.NodeDiskMap) > 0 {
|
if len(donut.config.NodeDiskMap) > 0 {
|
||||||
buckets, err := donut.listBuckets()
|
buckets, err := donut.listBuckets()
|
||||||
@ -624,30 +584,10 @@ func (donut API) ListBuckets(signature *signv4.Signature) ([]BucketMetadata, *pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectMetadata - get object metadata from cache
|
// GetObjectMetadata - get object metadata from cache
|
||||||
func (donut API) GetObjectMetadata(bucket, key string, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
func (donut API) GetObjectMetadata(bucket, key string) (ObjectMetadata, *probe.Error) {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
if signature.Presigned {
|
|
||||||
ok, err := signature.DoesPresignedSignatureMatch()
|
|
||||||
if err != nil {
|
|
||||||
return ObjectMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return ObjectMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return ObjectMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return ObjectMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if bucket exists
|
// check if bucket exists
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
|
@ -49,7 +49,7 @@ func (s *MyCacheSuite) SetUpSuite(c *C) {
|
|||||||
|
|
||||||
// testing empty cache
|
// testing empty cache
|
||||||
var buckets []BucketMetadata
|
var buckets []BucketMetadata
|
||||||
buckets, perr := dc.ListBuckets(nil)
|
buckets, perr := dc.ListBuckets()
|
||||||
c.Assert(perr, IsNil)
|
c.Assert(perr, IsNil)
|
||||||
c.Assert(len(buckets), Equals, 0)
|
c.Assert(len(buckets), Equals, 0)
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ func (s *MyCacheSuite) TestEmptyBucket(c *C) {
|
|||||||
// check if bucket is empty
|
// check if bucket is empty
|
||||||
var resources BucketResourcesMetadata
|
var resources BucketResourcesMetadata
|
||||||
resources.Maxkeys = 1
|
resources.Maxkeys = 1
|
||||||
objectsMetadata, resources, err := dc.ListObjects("foo1", resources, nil)
|
objectsMetadata, resources, err := dc.ListObjects("foo1", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(len(objectsMetadata), Equals, 0)
|
c.Assert(len(objectsMetadata), Equals, 0)
|
||||||
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
||||||
@ -88,7 +88,7 @@ func (s *MyCacheSuite) TestMakeBucketAndList(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
// check bucket exists
|
// check bucket exists
|
||||||
buckets, err := dc.ListBuckets(nil)
|
buckets, err := dc.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(len(buckets), Equals, 5)
|
c.Assert(len(buckets), Equals, 5)
|
||||||
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
||||||
@ -112,7 +112,7 @@ func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) {
|
|||||||
err = dc.MakeBucket("bar1", "private", nil, nil)
|
err = dc.MakeBucket("bar1", "private", nil, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
buckets, err := dc.ListBuckets(nil)
|
buckets, err := dc.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(len(buckets), Equals, 2)
|
c.Assert(len(buckets), Equals, 2)
|
||||||
@ -122,7 +122,7 @@ func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) {
|
|||||||
err = dc.MakeBucket("foobar1", "private", nil, nil)
|
err = dc.MakeBucket("foobar1", "private", nil, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
buckets, err = dc.ListBuckets(nil)
|
buckets, err = dc.ListBuckets()
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(len(buckets), Equals, 3)
|
c.Assert(len(buckets), Equals, 3)
|
||||||
@ -180,7 +180,7 @@ func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) {
|
|||||||
c.Assert(size, Equals, int64(len(data)))
|
c.Assert(size, Equals, int64(len(data)))
|
||||||
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
||||||
|
|
||||||
actualMetadata, err = dc.GetObjectMetadata("foo", "obj", nil)
|
actualMetadata, err = dc.GetObjectMetadata("foo", "obj")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
||||||
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
||||||
@ -219,7 +219,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = "1"
|
resources.Delimiter = "1"
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err := dc.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err := dc.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||||
@ -228,7 +228,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = ""
|
resources.Prefix = ""
|
||||||
resources.Delimiter = "1"
|
resources.Delimiter = "1"
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
@ -238,7 +238,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = ""
|
resources.Delimiter = ""
|
||||||
resources.Maxkeys = 10
|
resources.Maxkeys = 10
|
||||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, false)
|
c.Assert(resources.IsTruncated, Equals, false)
|
||||||
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
||||||
@ -258,7 +258,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
|
|||||||
resources.Prefix = "o"
|
resources.Prefix = "o"
|
||||||
resources.Delimiter = ""
|
resources.Delimiter = ""
|
||||||
resources.Maxkeys = 2
|
resources.Maxkeys = 2
|
||||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
|
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(resources.IsTruncated, Equals, true)
|
c.Assert(resources.IsTruncated, Equals, true)
|
||||||
c.Assert(len(objectsMetadata), Equals, 2)
|
c.Assert(len(objectsMetadata), Equals, 2)
|
||||||
|
@ -34,17 +34,17 @@ type Interface interface {
|
|||||||
// CloudStorage is a donut cloud storage interface
|
// CloudStorage is a donut cloud storage interface
|
||||||
type CloudStorage interface {
|
type CloudStorage interface {
|
||||||
// Storage service operations
|
// Storage service operations
|
||||||
GetBucketMetadata(bucket string, signature *signv4.Signature) (BucketMetadata, *probe.Error)
|
GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error)
|
||||||
SetBucketMetadata(bucket string, metadata map[string]string, signature *signv4.Signature) *probe.Error
|
SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error
|
||||||
ListBuckets(signature *signv4.Signature) ([]BucketMetadata, *probe.Error)
|
ListBuckets() ([]BucketMetadata, *probe.Error)
|
||||||
MakeBucket(bucket string, ACL string, location io.Reader, signature *signv4.Signature) *probe.Error
|
MakeBucket(bucket string, ACL string, location io.Reader, signature *signv4.Signature) *probe.Error
|
||||||
|
|
||||||
// Bucket operations
|
// Bucket operations
|
||||||
ListObjects(string, BucketResourcesMetadata, *signv4.Signature) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
|
ListObjects(string, BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
|
||||||
|
|
||||||
// Object operations
|
// Object operations
|
||||||
GetObject(w io.Writer, bucket, object string, start, length int64) (int64, *probe.Error)
|
GetObject(w io.Writer, bucket, object string, start, length int64) (int64, *probe.Error)
|
||||||
GetObjectMetadata(bucket, object string, signature *signv4.Signature) (ObjectMetadata, *probe.Error)
|
GetObjectMetadata(bucket, object string) (ObjectMetadata, *probe.Error)
|
||||||
// bucket, object, expectedMD5Sum, size, reader, metadata, signature
|
// bucket, object, expectedMD5Sum, size, reader, metadata, signature
|
||||||
CreateObject(string, string, string, int64, io.Reader, map[string]string, *signv4.Signature) (ObjectMetadata, *probe.Error)
|
CreateObject(string, string, string, int64, io.Reader, map[string]string, *signv4.Signature) (ObjectMetadata, *probe.Error)
|
||||||
|
|
||||||
@ -53,12 +53,12 @@ type CloudStorage interface {
|
|||||||
|
|
||||||
// Multipart API
|
// Multipart API
|
||||||
type Multipart interface {
|
type Multipart interface {
|
||||||
NewMultipartUpload(bucket, key, contentType string, signature *signv4.Signature) (string, *probe.Error)
|
NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error)
|
||||||
AbortMultipartUpload(bucket, key, uploadID string, signature *signv4.Signature) *probe.Error
|
AbortMultipartUpload(bucket, key, uploadID string) *probe.Error
|
||||||
CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *signv4.Signature) (string, *probe.Error)
|
CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *signv4.Signature) (string, *probe.Error)
|
||||||
CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error)
|
CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error)
|
||||||
ListMultipartUploads(string, BucketMultipartResourcesMetadata, *signv4.Signature) (BucketMultipartResourcesMetadata, *probe.Error)
|
ListMultipartUploads(string, BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error)
|
||||||
ListObjectParts(string, string, ObjectResourcesMetadata, *signv4.Signature) (ObjectResourcesMetadata, *probe.Error)
|
ListObjectParts(string, string, ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Management is a donut management system interface
|
// Management is a donut management system interface
|
||||||
|
@ -41,7 +41,7 @@ import (
|
|||||||
/// V2 API functions
|
/// V2 API functions
|
||||||
|
|
||||||
// NewMultipartUpload - initiate a new multipart session
|
// NewMultipartUpload - initiate a new multipart session
|
||||||
func (donut API) NewMultipartUpload(bucket, key, contentType string, signature *signv4.Signature) (string, *probe.Error) {
|
func (donut API) NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error) {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
@ -51,15 +51,6 @@ func (donut API) NewMultipartUpload(bucket, key, contentType string, signature *
|
|||||||
if !IsValidObjectName(key) {
|
if !IsValidObjectName(key) {
|
||||||
return "", probe.NewError(ObjectNameInvalid{Object: key})
|
return "", probe.NewError(ObjectNameInvalid{Object: key})
|
||||||
}
|
}
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return "", err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return "", probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if len(donut.config.NodeDiskMap) > 0 {
|
// if len(donut.config.NodeDiskMap) > 0 {
|
||||||
// return donut.newMultipartUpload(bucket, key, contentType)
|
// return donut.newMultipartUpload(bucket, key, contentType)
|
||||||
// }
|
// }
|
||||||
@ -89,7 +80,7 @@ func (donut API) NewMultipartUpload(bucket, key, contentType string, signature *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AbortMultipartUpload - abort an incomplete multipart session
|
// AbortMultipartUpload - abort an incomplete multipart session
|
||||||
func (donut API) AbortMultipartUpload(bucket, key, uploadID string, signature *signv4.Signature) *probe.Error {
|
func (donut API) AbortMultipartUpload(bucket, key, uploadID string) *probe.Error {
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
@ -99,15 +90,6 @@ func (donut API) AbortMultipartUpload(bucket, key, uploadID string, signature *s
|
|||||||
if !IsValidObjectName(key) {
|
if !IsValidObjectName(key) {
|
||||||
return probe.NewError(ObjectNameInvalid{Object: key})
|
return probe.NewError(ObjectNameInvalid{Object: key})
|
||||||
}
|
}
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||||
//
|
//
|
||||||
@ -381,21 +363,11 @@ func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|||||||
func (a byKey) Less(i, j int) bool { return a[i].Key < a[j].Key }
|
func (a byKey) Less(i, j int) bool { return a[i].Key < a[j].Key }
|
||||||
|
|
||||||
// ListMultipartUploads - list incomplete multipart sessions for a given bucket
|
// ListMultipartUploads - list incomplete multipart sessions for a given bucket
|
||||||
func (donut API) ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata, signature *signv4.Signature) (BucketMultipartResourcesMetadata, *probe.Error) {
|
func (donut API) ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error) {
|
||||||
// TODO handle delimiter, low priority
|
// TODO handle delimiter, low priority
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return BucketMultipartResourcesMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return BucketMultipartResourcesMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return BucketMultipartResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return BucketMultipartResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
}
|
}
|
||||||
@ -466,21 +438,11 @@ func (a partNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|||||||
func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
|
func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
|
||||||
|
|
||||||
// ListObjectParts - list parts from incomplete multipart session for a given object
|
// ListObjectParts - list parts from incomplete multipart session for a given object
|
||||||
func (donut API) ListObjectParts(bucket, key string, resources ObjectResourcesMetadata, signature *signv4.Signature) (ObjectResourcesMetadata, *probe.Error) {
|
func (donut API) ListObjectParts(bucket, key string, resources ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error) {
|
||||||
// Verify upload id
|
// Verify upload id
|
||||||
donut.lock.Lock()
|
donut.lock.Lock()
|
||||||
defer donut.lock.Unlock()
|
defer donut.lock.Unlock()
|
||||||
|
|
||||||
if signature != nil {
|
|
||||||
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
|
||||||
if err != nil {
|
|
||||||
return ObjectResourcesMetadata{}, err.Trace()
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return ObjectResourcesMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !IsValidBucket(bucket) {
|
if !IsValidBucket(bucket) {
|
||||||
return ObjectResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
return ObjectResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func (api API) isValidOp(w http.ResponseWriter, req *http.Request) bool {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
bucketMetadata, err := api.Donut.GetBucketMetadata(bucket, nil)
|
bucketMetadata, err := api.Donut.GetBucketMetadata(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
@ -94,24 +94,10 @@ func (api API) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Requ
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
resources, err := api.Donut.ListMultipartUploads(bucket, resources)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resources, err := api.Donut.ListMultipartUploads(bucket, resources, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "ListMultipartUploads failed.", nil)
|
errorIf(err.Trace(), "ListMultipartUploads failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.BucketNotFound:
|
case donut.BucketNotFound:
|
||||||
writeErrorResponse(w, req, NoSuchBucket, req.URL.Path)
|
writeErrorResponse(w, req, NoSuchBucket, req.URL.Path)
|
||||||
default:
|
default:
|
||||||
@ -165,19 +151,7 @@ func (api API) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
objects, resources, err := api.Donut.ListObjects(bucket, resources)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objects, resources, err := api.Donut.ListObjects(bucket, resources, signature)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// generate response
|
// generate response
|
||||||
response := generateListObjectsResponse(bucket, objects, resources)
|
response := generateListObjectsResponse(bucket, objects, resources)
|
||||||
@ -189,8 +163,6 @@ func (api API) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.BucketNameInvalid:
|
case donut.BucketNameInvalid:
|
||||||
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
||||||
case donut.BucketNotFound:
|
case donut.BucketNotFound:
|
||||||
@ -226,19 +198,7 @@ func (api API) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
var signature *signv4.Signature
|
buckets, err := api.Donut.ListBuckets()
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buckets, err := api.Donut.ListBuckets(signature)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// generate response
|
// generate response
|
||||||
response := generateListBucketsResponse(buckets)
|
response := generateListBucketsResponse(buckets)
|
||||||
@ -249,13 +209,8 @@ func (api API) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
w.Write(encodedSuccessResponse)
|
w.Write(encodedSuccessResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch err.ToGoError().(type) {
|
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
||||||
case signv4.DoesNotMatch:
|
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
default:
|
|
||||||
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutBucketHandler - PUT Bucket
|
// PutBucketHandler - PUT Bucket
|
||||||
@ -402,8 +357,6 @@ func (api API) PostPolicyBucketHandler(w http.ResponseWriter, req *http.Request)
|
|||||||
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
|
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
|
||||||
case donut.BadDigest:
|
case donut.BadDigest:
|
||||||
writeErrorResponse(w, req, BadDigest, req.URL.Path)
|
writeErrorResponse(w, req, BadDigest, req.URL.Path)
|
||||||
case signv4.MissingDateHeader:
|
|
||||||
writeErrorResponse(w, req, RequestTimeTooSkewed, req.URL.Path)
|
|
||||||
case signv4.DoesNotMatch:
|
case signv4.DoesNotMatch:
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
||||||
case donut.IncompleteBody:
|
case donut.IncompleteBody:
|
||||||
@ -444,19 +397,7 @@ func (api API) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)})
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)}, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "PutBucketACL failed.", nil)
|
errorIf(err.Trace(), "PutBucketACL failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
@ -493,19 +434,7 @@ func (api API) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
_, err := api.Donut.GetBucketMetadata(bucket)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := api.Donut.GetBucketMetadata(bucket, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/pkg/auth"
|
|
||||||
"github.com/rs/cors"
|
"github.com/rs/cors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,47 +98,6 @@ func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
h.handler.ServeHTTP(w, r)
|
h.handler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateAuthHeaderHandler - validate auth header handler is wrapper handler used
|
|
||||||
// for request validation with authorization header. Current authorization layer
|
|
||||||
// supports S3's standard HMAC based signature request.
|
|
||||||
func ValidateAuthHeaderHandler(h http.Handler) http.Handler {
|
|
||||||
return validateAuthHandler{h}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate auth header handler ServeHTTP() wrapper
|
|
||||||
func (h validateAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
accessKeyID, err := stripAccessKeyID(r.Header.Get("Authorization"))
|
|
||||||
switch err.ToGoError() {
|
|
||||||
case errInvalidRegion:
|
|
||||||
writeErrorResponse(w, r, AuthorizationHeaderMalformed, r.URL.Path)
|
|
||||||
return
|
|
||||||
case errAccessKeyIDInvalid:
|
|
||||||
writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
|
|
||||||
return
|
|
||||||
case nil:
|
|
||||||
// load auth config
|
|
||||||
authConfig, err := auth.LoadConfig()
|
|
||||||
if err != nil {
|
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Access key not found
|
|
||||||
for _, user := range authConfig.Users {
|
|
||||||
if user.AccessKeyID == accessKeyID {
|
|
||||||
h.handler.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
|
|
||||||
return
|
|
||||||
// All other errors for now, serve them
|
|
||||||
default:
|
|
||||||
// control reaches here, we should just send the request up the stack - internally
|
|
||||||
// individual calls will validate themselves against un-authenticated requests
|
|
||||||
h.handler.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CorsHandler handler for CORS (Cross Origin Resource Sharing)
|
// CorsHandler handler for CORS (Cross Origin Resource Sharing)
|
||||||
func CorsHandler(h http.Handler) http.Handler {
|
func CorsHandler(h http.Handler) http.Handler {
|
||||||
return cors.Default().Handler(h)
|
return cors.Default().Handler(h)
|
||||||
|
@ -53,40 +53,10 @@ func (api API) GetObjectHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
bucket = vars["bucket"]
|
bucket = vars["bucket"]
|
||||||
object = vars["object"]
|
object = vars["object"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
metadata, err := api.Donut.GetObjectMetadata(bucket, object)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if _, ok := req.URL.Query()["X-Amz-Credential"]; ok {
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initPresignedSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
switch err.ToGoError() {
|
|
||||||
case errAccessKeyIDInvalid:
|
|
||||||
errorIf(err.Trace(), "Invalid access key id requested.", nil)
|
|
||||||
writeErrorResponse(w, req, InvalidAccessKeyID, req.URL.Path)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
metadata, err := api.Donut.GetObjectMetadata(bucket, object, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "GetObject failed.", nil)
|
errorIf(err.Trace(), "GetObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.BucketNameInvalid:
|
case donut.BucketNameInvalid:
|
||||||
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
||||||
case donut.BucketNotFound:
|
case donut.BucketNotFound:
|
||||||
@ -135,24 +105,10 @@ func (api API) HeadObjectHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
bucket = vars["bucket"]
|
bucket = vars["bucket"]
|
||||||
object = vars["object"]
|
object = vars["object"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
metadata, err := api.Donut.GetObjectMetadata(bucket, object)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata, err := api.Donut.GetObjectMetadata(bucket, object, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "GetObjectMetadata failed.", nil)
|
errorIf(err.Trace(), "GetObjectMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.BucketNameInvalid:
|
case donut.BucketNameInvalid:
|
||||||
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
|
||||||
case donut.BucketNotFound:
|
case donut.BucketNotFound:
|
||||||
@ -299,24 +255,10 @@ func (api API) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Reques
|
|||||||
bucket = vars["bucket"]
|
bucket = vars["bucket"]
|
||||||
object = vars["object"]
|
object = vars["object"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
uploadID, err := api.Donut.NewMultipartUpload(bucket, object, req.Header.Get("Content-Type"))
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadID, err := api.Donut.NewMultipartUpload(bucket, object, req.Header.Get("Content-Type"), signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "NewMultipartUpload failed.", nil)
|
errorIf(err.Trace(), "NewMultipartUpload failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.ObjectExists:
|
case donut.ObjectExists:
|
||||||
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
|
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
|
||||||
default:
|
default:
|
||||||
@ -455,24 +397,10 @@ func (api API) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Requ
|
|||||||
|
|
||||||
objectResourcesMetadata := getObjectResources(req.URL.Query())
|
objectResourcesMetadata := getObjectResources(req.URL.Query())
|
||||||
|
|
||||||
var signature *signv4.Signature
|
err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "AbortMutlipartUpload failed.", nil)
|
errorIf(err.Trace(), "AbortMutlipartUpload failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.InvalidUploadID:
|
case donut.InvalidUploadID:
|
||||||
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
|
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
|
||||||
default:
|
default:
|
||||||
@ -516,24 +444,10 @@ func (api API) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request)
|
|||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
object := vars["object"]
|
object := vars["object"]
|
||||||
|
|
||||||
var signature *signv4.Signature
|
objectResourcesMetadata, err := api.Donut.ListObjectParts(bucket, object, objectResourcesMetadata)
|
||||||
if _, ok := req.Header["Authorization"]; ok {
|
|
||||||
// Init signature V4 verification
|
|
||||||
var err *probe.Error
|
|
||||||
signature, err = initSignatureV4(req)
|
|
||||||
if err != nil {
|
|
||||||
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objectResourcesMetadata, err := api.Donut.ListObjectParts(bucket, object, objectResourcesMetadata, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "ListObjectParts failed.", nil)
|
errorIf(err.Trace(), "ListObjectParts failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
case donut.InvalidUploadID:
|
case donut.InvalidUploadID:
|
||||||
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
|
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
|
||||||
default:
|
default:
|
||||||
|
99
server-api-signature-handler.go
Normal file
99
server-api-signature-handler.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/minio/minio/pkg/probe"
|
||||||
|
signv4 "github.com/minio/minio/pkg/signature"
|
||||||
|
)
|
||||||
|
|
||||||
|
type signatureHandler struct {
|
||||||
|
handler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureHandler to validate authorization header for the incoming request.
|
||||||
|
func SignatureHandler(h http.Handler) http.Handler {
|
||||||
|
return signatureHandler{h}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRequestSignatureV4(req *http.Request) bool {
|
||||||
|
if _, ok := req.Header["Authorization"]; ok {
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRequestPresignedSignatureV4(req *http.Request) bool {
|
||||||
|
if _, ok := req.URL.Query()["X-Amz-Credential"]; ok {
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s signatureHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var signature *signv4.Signature
|
||||||
|
if isRequestSignatureV4(r) {
|
||||||
|
// If the request is not a PUT method handle the verification here.
|
||||||
|
// For PUT and POST requests with payload, send the call upwards for verification
|
||||||
|
if r.Method != "PUT" && r.Method != "POST" {
|
||||||
|
// Init signature V4 verification
|
||||||
|
var err *probe.Error
|
||||||
|
signature, err = initSignatureV4(r)
|
||||||
|
if err != nil {
|
||||||
|
switch err.ToGoError() {
|
||||||
|
case errInvalidRegion:
|
||||||
|
errorIf(err.Trace(), "Unknown region in authorization header.", nil)
|
||||||
|
writeErrorResponse(w, r, AuthorizationHeaderMalformed, r.URL.Path)
|
||||||
|
return
|
||||||
|
case errAccessKeyIDInvalid:
|
||||||
|
errorIf(err.Trace(), "Invalid access key id.", nil)
|
||||||
|
writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
||||||
|
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok, err := signature.DoesSignatureMatch("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||||
|
if err != nil {
|
||||||
|
errorIf(err.Trace(), "Unable to verify signature.", nil)
|
||||||
|
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isRequestPresignedSignatureV4(r) {
|
||||||
|
var err *probe.Error
|
||||||
|
signature, err = initPresignedSignatureV4(r)
|
||||||
|
if err != nil {
|
||||||
|
switch err.ToGoError() {
|
||||||
|
case errAccessKeyIDInvalid:
|
||||||
|
errorIf(err.Trace(), "Invalid access key id requested.", nil)
|
||||||
|
writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
|
||||||
|
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok, err := signature.DoesPresignedSignatureMatch()
|
||||||
|
if err != nil {
|
||||||
|
errorIf(err.Trace(), "Unable to verify signature.", nil)
|
||||||
|
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.handler.ServeHTTP(w, r)
|
||||||
|
}
|
@ -19,7 +19,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
@ -127,7 +126,7 @@ func initSignatureV4(req *http.Request) (*signv4.Signature, *probe.Error) {
|
|||||||
return signature, nil
|
return signature, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, probe.NewError(errors.New("AccessKeyID not found"))
|
return nil, probe.NewError(errAccessKeyIDInvalid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, map[string]string, *probe.Error) {
|
func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, map[string]string, *probe.Error) {
|
||||||
|
@ -85,7 +85,7 @@ func getAPIHandler(api API) http.Handler {
|
|||||||
var mwHandlers = []MiddlewareHandler{
|
var mwHandlers = []MiddlewareHandler{
|
||||||
TimeValidityHandler,
|
TimeValidityHandler,
|
||||||
IgnoreResourcesHandler,
|
IgnoreResourcesHandler,
|
||||||
ValidateAuthHeaderHandler,
|
SignatureHandler,
|
||||||
// api.LoggingHandler, // Disabled logging until we bring in external logging support
|
// api.LoggingHandler, // Disabled logging until we bring in external logging support
|
||||||
CorsHandler,
|
CorsHandler,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user