mirror of
https://github.com/minio/minio.git
synced 2025-04-09 06:00:12 -04:00
Merge pull request #883 from harshavardhana/simplify-signature
Simplify signature handling
This commit is contained in:
commit
bdd8e5873a
@ -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,14 +209,9 @@ func (api API) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
w.Write(encodedSuccessResponse)
|
w.Write(encodedSuccessResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch err.ToGoError().(type) {
|
|
||||||
case signv4.DoesNotMatch:
|
|
||||||
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
|
|
||||||
default:
|
|
||||||
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
||||||
writeErrorResponse(w, req, InternalError, req.URL.Path)
|
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