Further fixes for ACL support, currently code is disabled in all the handlers

Disabled because due to lack of testing support. Once we get that in we can
uncomment them back.
master
Harshavardhana 10 years ago
parent 1c0ff2c758
commit 848c4ee31c
  1. 33
      pkg/api/acl.go
  2. 18
      pkg/api/api_bucket_handlers.go
  3. 25
      pkg/api/api_generic_handlers.go
  4. 53
      pkg/api/api_object_handlers.go
  5. 2
      pkg/api/api_router.go
  6. 2
      pkg/api/api_test.go
  7. 21
      pkg/api/contenttype.go
  8. 5
      pkg/api/errors.go

@ -16,10 +16,7 @@
package api package api
import ( import "net/http"
"net/http"
"strings"
)
// Please read for more information - http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl // Please read for more information - http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl
// //
@ -41,16 +38,20 @@ const (
// Get acl type requested from 'x-amz-acl' header // Get acl type requested from 'x-amz-acl' header
func getACLType(req *http.Request) ACLType { func getACLType(req *http.Request) ACLType {
aclHeader := req.Header.Get("x-amz-acl") aclHeader := req.Header.Get("x-amz-acl")
switch { if aclHeader != "" {
case strings.HasPrefix(aclHeader, "private"): switch {
return privateACLType case aclHeader == "private":
case strings.HasPrefix(aclHeader, "public-read"): return privateACLType
return publicReadACLType case aclHeader == "public-read":
case strings.HasPrefix(aclHeader, "public-read-write"): return publicReadACLType
return publicReadWriteACLType case aclHeader == "public-read-write":
default: return publicReadWriteACLType
return unsupportedACLType default:
return unsupportedACLType
}
} }
// make it default private
return privateACLType
} }
// ACL type to human readable string // ACL type to human readable string
@ -68,7 +69,11 @@ func getACLTypeString(acl ACLType) string {
{ {
return "public-read-write" return "public-read-write"
} }
case unsupportedACLType:
{
return ""
}
default: default:
return "" return "private"
} }
} }

@ -45,6 +45,15 @@ func (server *minioAPI) listObjectsHandler(w http.ResponseWriter, req *http.Requ
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
// Enable this after tests supports them
// verify for if bucket is private or public
// bucketMetadata, err := server.driver.GetBucketMetadata(bucket)
// if err != nil || (stripAccessKey(req) == "" && bucketMetadata.ACL.IsPrivate()) {
// writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
// return
// }
objects, resources, err := server.driver.ListObjects(bucket, resources) objects, resources, err := server.driver.ListObjects(bucket, resources)
switch err.(type) { switch err.(type) {
case nil: // success case nil: // success
@ -167,6 +176,15 @@ func (server *minioAPI) headBucketHandler(w http.ResponseWriter, req *http.Reque
vars := mux.Vars(req) vars := mux.Vars(req)
bucket := vars["bucket"] bucket := vars["bucket"]
// Enable this after tests supports them
// verify for if bucket is private or public
// bucketMetadata, err := server.driver.GetBucketMetadata(bucket)
// if err != nil || (stripAccessKey(req) == "" && bucketMetadata.ACL.IsPrivate()) {
// writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
// return
// }
_, err := server.driver.GetBucketMetadata(bucket) _, err := server.driver.GetBucketMetadata(bucket)
switch err.(type) { switch err.(type) {
case nil: case nil:

@ -20,14 +20,11 @@ import (
"net/http" "net/http"
"strings" "strings"
"github.com/gorilla/mux"
"github.com/minio-io/minio/pkg/api/config" "github.com/minio-io/minio/pkg/api/config"
"github.com/minio-io/minio/pkg/storage/drivers"
) )
type vHandler struct { type vHandler struct {
conf config.Config conf config.Config
driver drivers.Driver
handler http.Handler handler http.Handler
} }
@ -50,10 +47,9 @@ func stripAccessKey(r *http.Request) string {
// Validate handler is wrapper handler used for API request validation with authorization header. // Validate handler is wrapper handler used for API request validation with authorization header.
// Current authorization layer supports S3's standard HMAC based signature request. // Current authorization layer supports S3's standard HMAC based signature request.
func validateHandler(conf config.Config, driver drivers.Driver, h http.Handler) http.Handler { func validateHandler(conf config.Config, h http.Handler) http.Handler {
return vHandler{ return vHandler{
conf: conf, conf: conf,
driver: driver,
handler: h, handler: h,
} }
} }
@ -66,25 +62,6 @@ func (h vHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
writeErrorResponse(w, r, NotAcceptable, acceptsContentType, r.URL.Path) writeErrorResponse(w, r, NotAcceptable, acceptsContentType, r.URL.Path)
return return
} }
// verify for if bucket is private or public
vars := mux.Vars(r)
bucket, ok := vars["bucket"]
if ok {
bucketMetadata, err := h.driver.GetBucketMetadata(bucket)
if err != nil {
writeErrorResponse(w, r, AccessDenied, acceptsContentType, r.URL.Path)
return
}
if accessKey == "" && bucketMetadata.ACL.IsPrivate() {
writeErrorResponse(w, r, AccessDenied, acceptsContentType, r.URL.Path)
return
}
if r.Method == "PUT" && bucketMetadata.ACL.IsPublicRead() {
writeErrorResponse(w, r, AccessDenied, acceptsContentType, r.URL.Path)
return
}
}
switch true { switch true {
case accessKey != "": case accessKey != "":
if err := h.conf.ReadConfig(); err != nil { if err := h.conf.ReadConfig(); err != nil {

@ -40,6 +40,16 @@ func (server *minioAPI) getObjectHandler(w http.ResponseWriter, req *http.Reques
vars := mux.Vars(req) vars := mux.Vars(req)
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
// Enable this after tests supports them
// verify for if bucket is private or public
// bucketMetadata, err := server.driver.GetBucketMetadata(bucket)
// if err != nil || (stripAccessKey(req) == "" && bucketMetadata.ACL.IsPrivate()) {
// writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
// return
// }
metadata, err := server.driver.GetObjectMetadata(bucket, object, "") metadata, err := server.driver.GetObjectMetadata(bucket, object, "")
switch err := err.(type) { switch err := err.(type) {
case nil: // success case nil: // success
@ -51,23 +61,18 @@ func (server *minioAPI) getObjectHandler(w http.ResponseWriter, req *http.Reques
} }
switch httpRange.start == 0 && httpRange.length == 0 { switch httpRange.start == 0 && httpRange.length == 0 {
case true: case true:
{ setObjectHeaders(w, metadata)
setObjectHeaders(w, metadata) if _, err := server.driver.GetObject(w, bucket, object); err != nil {
if _, err := server.driver.GetObject(w, bucket, object); err != nil { // unable to write headers, we've already printed data. Just close the connection.
// unable to write headers, we've already printed data. Just close the connection. log.Error.Println(err)
log.Error.Println(err)
}
} }
case false: case false:
{ metadata.Size = httpRange.length
metadata.Size = httpRange.length setRangeObjectHeaders(w, metadata, httpRange)
setRangeObjectHeaders(w, metadata, httpRange) w.WriteHeader(http.StatusPartialContent)
w.WriteHeader(http.StatusPartialContent) if _, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length); err != nil {
_, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length) // unable to write headers, we've already printed data. Just close the connection.
if err != nil { log.Error.Println(iodine.New(err, nil))
// unable to write headers, we've already printed data. Just close the connection.
log.Error.Println(iodine.New(err, nil))
}
} }
} }
} }
@ -109,6 +114,15 @@ func (server *minioAPI) headObjectHandler(w http.ResponseWriter, req *http.Reque
vars := mux.Vars(req) vars := mux.Vars(req)
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
// verify for if bucket is private or public
// verify for if bucket is private or public
// bucketMetadata, err := server.driver.GetBucketMetadata(bucket)
// if err != nil || (stripAccessKey(req) == "" && bucketMetadata.ACL.IsPrivate()) {
// writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
// return
// }
metadata, err := server.driver.GetObjectMetadata(bucket, object, "") metadata, err := server.driver.GetObjectMetadata(bucket, object, "")
switch err := err.(type) { switch err := err.(type) {
case nil: case nil:
@ -146,6 +160,15 @@ func (server *minioAPI) putObjectHandler(w http.ResponseWriter, req *http.Reques
vars := mux.Vars(req) vars := mux.Vars(req)
bucket = vars["bucket"] bucket = vars["bucket"]
object = vars["object"] object = vars["object"]
// verify for if bucket is private or public
// verify for if bucket is private or public
// bucketMetadata, err := server.driver.GetBucketMetadata(bucket)
// if err != nil || (stripAccessKey(req) == "" && bucketMetadata.ACL.IsPrivate()) || bucketMetadtata.ACL.IsPublicRead() {
// writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
// return
// }
// get Content-MD5 sent by client and verify if valid // get Content-MD5 sent by client and verify if valid
md5 := req.Header.Get("Content-MD5") md5 := req.Header.Get("Content-MD5")
if !isValidMD5(md5) { if !isValidMD5(md5) {

@ -89,5 +89,5 @@ func HTTPHandler(domain string, driver drivers.Driver) http.Handler {
log.Fatal(iodine.New(err, map[string]string{"domain": domain})) log.Fatal(iodine.New(err, map[string]string{"domain": domain}))
} }
return validateHandler(conf, api.driver, ignoreResourcesHandler(mux)) return validateHandler(conf, ignoreResourcesHandler(mux))
} }

@ -115,11 +115,11 @@ func (s *MySuite) TestNonExistantObject(c *C) {
} }
} }
driver := s.Driver driver := s.Driver
s.MockDriver.On("GetObjectMetadata", "bucket", "object", "").Return(drivers.ObjectMetadata{}, drivers.BucketNotFound{Bucket: "bucket"}).Once()
httpHandler := api.HTTPHandler("", driver) httpHandler := api.HTTPHandler("", driver)
testServer := httptest.NewServer(httpHandler) testServer := httptest.NewServer(httpHandler)
defer testServer.Close() defer testServer.Close()
s.MockDriver.On("GetObjectMetadata", "bucket", "object", "").Return(drivers.ObjectMetadata{}, drivers.BucketNotFound{Bucket: "bucket"}).Once()
response, err := http.Get(testServer.URL + "/bucket/object") response, err := http.Get(testServer.URL + "/bucket/object")
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusNotFound) c.Assert(response.StatusCode, Equals, http.StatusNotFound)

@ -29,17 +29,18 @@ const (
// Get content type requested from 'Accept' header // Get content type requested from 'Accept' header
func getContentType(req *http.Request) contentType { func getContentType(req *http.Request) contentType {
acceptHeader := req.Header.Get("Accept") acceptHeader := req.Header.Get("Accept")
if acceptHeader != "" { switch {
switch { case acceptHeader == "application/json":
case acceptHeader == "application/json": return jsonContentType
return jsonContentType case acceptHeader == "application/xml":
case acceptHeader == "application/xml": return xmlContentType
return xmlContentType case acceptHeader == "*/*":
default: return xmlContentType
return unknownContentType case acceptHeader != "":
} return unknownContentType
default:
return xmlContentType
} }
return xmlContentType
} }
// Content type to human readable string // Content type to human readable string

@ -176,9 +176,8 @@ var errorCodeResponse = map[int]Error{
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
NotAcceptable: { NotAcceptable: {
Code: "NotAcceptable", Code: "NotAcceptable",
Description: `The requested resource is only capable of generating content Description: "The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.",
not acceptable according to the Accept headers sent in the request.`,
HTTPStatusCode: http.StatusNotAcceptable, HTTPStatusCode: http.StatusNotAcceptable,
}, },
} }

Loading…
Cancel
Save