minio/server-api-signature-handler.go
Harshavardhana cfdb29cac0 Simplify signature handling
This change brings a new SignatureHandler where Presigned.
Requests without Payload are handled very early before even
going through the call.

This change simplifies Donut codebase to not have signature related
logic for all API's.

Simplification is still needed for Payload based signature eg. PUT/POST calls
, which are still part of the donut codebase, which will be done subsequently
after donut re-write.
2015-10-04 13:15:33 -07:00

100 lines
2.8 KiB
Go

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)
}