Merge pull request #883 from harshavardhana/simplify-signature

Simplify signature handling
master
Harshavardhana 9 years ago
commit bdd8e5873a
  1. 1
      pkg/donut/disk/disk_linux.go
  2. 5
      pkg/donut/donut-v1.go
  3. 20
      pkg/donut/donut-v1_test.go
  4. 70
      pkg/donut/donut-v2.go
  5. 20
      pkg/donut/donut-v2_test.go
  6. 18
      pkg/donut/interfaces.go
  7. 46
      pkg/donut/multipart.go
  8. 87
      server-api-bucket-handlers.go
  9. 42
      server-api-generic-handlers.go
  10. 96
      server-api-object-handlers.go
  11. 99
      server-api-signature-handler.go
  12. 3
      server-api-signature.go
  13. 2
      server-router.go

@ -31,6 +31,7 @@ var fsType2StringMap = map[string]string{
"6969": "NFS",
"ef51": "EXT2OLD",
"ef53": "EXT4",
"f15f": "ecryptfs",
}
// getFSType - get filesystem type

@ -619,10 +619,11 @@ func (donut API) makeDonutBucket(bucketName, acl string) *probe.Error {
}
nodeNumber = nodeNumber + 1
}
metadata, err := donut.getDonutBucketMetadata()
var metadata *AllBuckets
metadata, err = donut.getDonutBucketMetadata()
if err != nil {
if os.IsNotExist(err.ToGoError()) {
metadata := new(AllBuckets)
metadata = new(AllBuckets)
metadata.Buckets = make(map[string]BucketMetadata)
metadata.Buckets[bucketName] = bucketMetadata
err = donut.setDonutBucketMetadata(metadata)

@ -74,7 +74,7 @@ func (s *MyDonutSuite) SetUpSuite(c *C) {
c.Assert(perr, IsNil)
// testing empty donut
buckets, perr := dd.ListBuckets(nil)
buckets, perr := dd.ListBuckets()
c.Assert(perr, IsNil)
c.Assert(len(buckets), Equals, 0)
}
@ -99,7 +99,7 @@ func (s *MyDonutSuite) TestEmptyBucket(c *C) {
// check if bucket is empty
var resources BucketResourcesMetadata
resources.Maxkeys = 1
objectsMetadata, resources, err := dd.ListObjects("foo1", resources, nil)
objectsMetadata, resources, err := dd.ListObjects("foo1", resources)
c.Assert(err, IsNil)
c.Assert(len(objectsMetadata), Equals, 0)
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
@ -113,7 +113,7 @@ func (s *MyDonutSuite) TestMakeBucketAndList(c *C) {
c.Assert(err, IsNil)
// check bucket exists
buckets, err := dd.ListBuckets(nil)
buckets, err := dd.ListBuckets()
c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 5)
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)
c.Assert(err, IsNil)
buckets, err := dd.ListBuckets(nil)
buckets, err := dd.ListBuckets()
c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 2)
@ -147,7 +147,7 @@ func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) {
err = dd.MakeBucket("foobar1", "private", nil, nil)
c.Assert(err, IsNil)
buckets, err = dd.ListBuckets(nil)
buckets, err = dd.ListBuckets()
c.Assert(err, IsNil)
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(buffer.Bytes(), DeepEquals, []byte(data))
actualMetadata, err = dd.GetObjectMetadata("foo", "obj", nil)
actualMetadata, err = dd.GetObjectMetadata("foo", "obj")
c.Assert(err, IsNil)
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
@ -244,7 +244,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = "1"
resources.Maxkeys = 10
objectsMetadata, resources, err := dd.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err := dd.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false)
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
@ -253,7 +253,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = ""
resources.Delimiter = "1"
resources.Maxkeys = 10
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
c.Assert(resources.IsTruncated, Equals, false)
@ -263,7 +263,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = ""
resources.Maxkeys = 10
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false)
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
@ -283,7 +283,7 @@ func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = ""
resources.Maxkeys = 2
objectsMetadata, resources, err = dd.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, true)
c.Assert(len(objectsMetadata), Equals, 2)

@ -205,20 +205,10 @@ func (donut API) GetObject(w io.Writer, bucket string, object string, start, len
}
// 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()
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) {
return BucketMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
}
@ -238,20 +228,10 @@ func (donut API) GetBucketMetadata(bucket string, signature *signv4.Signature) (
}
// 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()
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) {
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
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()
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) {
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 }
// 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()
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
if len(donut.config.NodeDiskMap) > 0 {
buckets, err := donut.listBuckets()
@ -624,30 +584,10 @@ func (donut API) ListBuckets(signature *signv4.Signature) ([]BucketMetadata, *pr
}
// 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()
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
if !IsValidBucket(bucket) {
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})

@ -49,7 +49,7 @@ func (s *MyCacheSuite) SetUpSuite(c *C) {
// testing empty cache
var buckets []BucketMetadata
buckets, perr := dc.ListBuckets(nil)
buckets, perr := dc.ListBuckets()
c.Assert(perr, IsNil)
c.Assert(len(buckets), Equals, 0)
}
@ -74,7 +74,7 @@ func (s *MyCacheSuite) TestEmptyBucket(c *C) {
// check if bucket is empty
var resources BucketResourcesMetadata
resources.Maxkeys = 1
objectsMetadata, resources, err := dc.ListObjects("foo1", resources, nil)
objectsMetadata, resources, err := dc.ListObjects("foo1", resources)
c.Assert(err, IsNil)
c.Assert(len(objectsMetadata), Equals, 0)
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
@ -88,7 +88,7 @@ func (s *MyCacheSuite) TestMakeBucketAndList(c *C) {
c.Assert(err, IsNil)
// check bucket exists
buckets, err := dc.ListBuckets(nil)
buckets, err := dc.ListBuckets()
c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 5)
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)
c.Assert(err, IsNil)
buckets, err := dc.ListBuckets(nil)
buckets, err := dc.ListBuckets()
c.Assert(err, IsNil)
c.Assert(len(buckets), Equals, 2)
@ -122,7 +122,7 @@ func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) {
err = dc.MakeBucket("foobar1", "private", nil, nil)
c.Assert(err, IsNil)
buckets, err = dc.ListBuckets(nil)
buckets, err = dc.ListBuckets()
c.Assert(err, IsNil)
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(buffer.Bytes(), DeepEquals, []byte(data))
actualMetadata, err = dc.GetObjectMetadata("foo", "obj", nil)
actualMetadata, err = dc.GetObjectMetadata("foo", "obj")
c.Assert(err, IsNil)
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
@ -219,7 +219,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = "1"
resources.Maxkeys = 10
objectsMetadata, resources, err := dc.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err := dc.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false)
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
@ -228,7 +228,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = ""
resources.Delimiter = "1"
resources.Maxkeys = 10
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
c.Assert(resources.IsTruncated, Equals, false)
@ -238,7 +238,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = ""
resources.Maxkeys = 10
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, false)
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
@ -258,7 +258,7 @@ func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
resources.Prefix = "o"
resources.Delimiter = ""
resources.Maxkeys = 2
objectsMetadata, resources, err = dc.ListObjects("foo5", resources, nil)
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
c.Assert(err, IsNil)
c.Assert(resources.IsTruncated, Equals, true)
c.Assert(len(objectsMetadata), Equals, 2)

@ -34,17 +34,17 @@ type Interface interface {
// CloudStorage is a donut cloud storage interface
type CloudStorage interface {
// Storage service operations
GetBucketMetadata(bucket string, signature *signv4.Signature) (BucketMetadata, *probe.Error)
SetBucketMetadata(bucket string, metadata map[string]string, signature *signv4.Signature) *probe.Error
ListBuckets(signature *signv4.Signature) ([]BucketMetadata, *probe.Error)
GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error)
SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error
ListBuckets() ([]BucketMetadata, *probe.Error)
MakeBucket(bucket string, ACL string, location io.Reader, signature *signv4.Signature) *probe.Error
// Bucket operations
ListObjects(string, BucketResourcesMetadata, *signv4.Signature) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
ListObjects(string, BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
// Object operations
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
CreateObject(string, string, string, int64, io.Reader, map[string]string, *signv4.Signature) (ObjectMetadata, *probe.Error)
@ -53,12 +53,12 @@ type CloudStorage interface {
// Multipart API
type Multipart interface {
NewMultipartUpload(bucket, key, contentType string, signature *signv4.Signature) (string, *probe.Error)
AbortMultipartUpload(bucket, key, uploadID string, signature *signv4.Signature) *probe.Error
NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error)
AbortMultipartUpload(bucket, key, uploadID 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)
ListMultipartUploads(string, BucketMultipartResourcesMetadata, *signv4.Signature) (BucketMultipartResourcesMetadata, *probe.Error)
ListObjectParts(string, string, ObjectResourcesMetadata, *signv4.Signature) (ObjectResourcesMetadata, *probe.Error)
ListMultipartUploads(string, BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error)
ListObjectParts(string, string, ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error)
}
// Management is a donut management system interface

@ -41,7 +41,7 @@ import (
/// V2 API functions
// 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()
defer donut.lock.Unlock()
@ -51,15 +51,6 @@ func (donut API) NewMultipartUpload(bucket, key, contentType string, signature *
if !IsValidObjectName(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 {
// 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
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()
defer donut.lock.Unlock()
@ -99,15 +90,6 @@ func (donut API) AbortMultipartUpload(bucket, key, uploadID string, signature *s
if !IsValidObjectName(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
// 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 }
// 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
donut.lock.Lock()
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) {
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 }
// 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
donut.lock.Lock()
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) {
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)
bucket := vars["bucket"]
bucketMetadata, err := api.Donut.GetBucketMetadata(bucket, nil)
bucketMetadata, err := api.Donut.GetBucketMetadata(bucket)
if err != nil {
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
switch err.ToGoError().(type) {
@ -94,24 +94,10 @@ func (api API) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Requ
vars := mux.Vars(req)
bucket := vars["bucket"]
var signature *signv4.Signature
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)
resources, err := api.Donut.ListMultipartUploads(bucket, resources)
if err != nil {
errorIf(err.Trace(), "ListMultipartUploads failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.BucketNotFound:
writeErrorResponse(w, req, NoSuchBucket, req.URL.Path)
default:
@ -165,19 +151,7 @@ func (api API) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
bucket := vars["bucket"]
var signature *signv4.Signature
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)
objects, resources, err := api.Donut.ListObjects(bucket, resources)
if err == nil {
// generate response
response := generateListObjectsResponse(bucket, objects, resources)
@ -189,8 +163,6 @@ func (api API) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
return
}
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
case donut.BucketNotFound:
@ -226,19 +198,7 @@ func (api API) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
// return
// }
var signature *signv4.Signature
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)
buckets, err := api.Donut.ListBuckets()
if err == nil {
// generate response
response := generateListBucketsResponse(buckets)
@ -249,13 +209,8 @@ func (api API) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
w.Write(encodedSuccessResponse)
return
}
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
default:
errorIf(err.Trace(), "ListBuckets failed.", nil)
writeErrorResponse(w, req, InternalError, req.URL.Path)
}
errorIf(err.Trace(), "ListBuckets failed.", nil)
writeErrorResponse(w, req, InternalError, req.URL.Path)
}
// PutBucketHandler - PUT Bucket
@ -402,8 +357,6 @@ func (api API) PostPolicyBucketHandler(w http.ResponseWriter, req *http.Request)
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
case donut.BadDigest:
writeErrorResponse(w, req, BadDigest, req.URL.Path)
case signv4.MissingDateHeader:
writeErrorResponse(w, req, RequestTimeTooSkewed, req.URL.Path)
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.IncompleteBody:
@ -444,19 +397,7 @@ func (api API) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
bucket := vars["bucket"]
var signature *signv4.Signature
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)
err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)})
if err != nil {
errorIf(err.Trace(), "PutBucketACL failed.", nil)
switch err.ToGoError().(type) {
@ -493,19 +434,7 @@ func (api API) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
bucket := vars["bucket"]
var signature *signv4.Signature
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)
_, err := api.Donut.GetBucketMetadata(bucket)
if err != nil {
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
switch err.ToGoError().(type) {

@ -21,7 +21,6 @@ import (
"net/http"
"time"
"github.com/minio/minio/pkg/auth"
"github.com/rs/cors"
)
@ -99,47 +98,6 @@ func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
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)
func CorsHandler(h http.Handler) http.Handler {
return cors.Default().Handler(h)

@ -53,40 +53,10 @@ func (api API) GetObjectHandler(w http.ResponseWriter, req *http.Request) {
bucket = vars["bucket"]
object = vars["object"]
var signature *signv4.Signature
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)
metadata, err := api.Donut.GetObjectMetadata(bucket, object)
if err != nil {
errorIf(err.Trace(), "GetObject failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
case donut.BucketNotFound:
@ -135,24 +105,10 @@ func (api API) HeadObjectHandler(w http.ResponseWriter, req *http.Request) {
bucket = vars["bucket"]
object = vars["object"]
var signature *signv4.Signature
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)
metadata, err := api.Donut.GetObjectMetadata(bucket, object)
if err != nil {
errorIf(err.Trace(), "GetObjectMetadata failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
case donut.BucketNotFound:
@ -299,24 +255,10 @@ func (api API) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Reques
bucket = vars["bucket"]
object = vars["object"]
var signature *signv4.Signature
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)
uploadID, err := api.Donut.NewMultipartUpload(bucket, object, req.Header.Get("Content-Type"))
if err != nil {
errorIf(err.Trace(), "NewMultipartUpload failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.ObjectExists:
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path)
default:
@ -455,24 +397,10 @@ func (api API) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Requ
objectResourcesMetadata := getObjectResources(req.URL.Query())
var signature *signv4.Signature
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)
err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID)
if err != nil {
errorIf(err.Trace(), "AbortMutlipartUpload failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.InvalidUploadID:
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
default:
@ -516,24 +444,10 @@ func (api API) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request)
bucket := vars["bucket"]
object := vars["object"]
var signature *signv4.Signature
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)
objectResourcesMetadata, err := api.Donut.ListObjectParts(bucket, object, objectResourcesMetadata)
if err != nil {
errorIf(err.Trace(), "ListObjectParts failed.", nil)
switch err.ToGoError().(type) {
case signv4.DoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
case donut.InvalidUploadID:
writeErrorResponse(w, req, NoSuchUpload, req.URL.Path)
default:

@ -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 (
"bytes"
"encoding/base64"
"errors"
"io"
"io/ioutil"
"mime/multipart"
@ -127,7 +126,7 @@ func initSignatureV4(req *http.Request) (*signv4.Signature, *probe.Error) {
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) {

@ -85,7 +85,7 @@ func getAPIHandler(api API) http.Handler {
var mwHandlers = []MiddlewareHandler{
TimeValidityHandler,
IgnoreResourcesHandler,
ValidateAuthHeaderHandler,
SignatureHandler,
// api.LoggingHandler, // Disabled logging until we bring in external logging support
CorsHandler,
}

Loading…
Cancel
Save