mirror of
https://github.com/minio/minio.git
synced 2025-02-04 02:15:59 -05:00
log: Fix printing of signature error request headers. (#4444)
The following commit f44f2e341c931222a8f1e3f1e9911dda80bb2dc0 fix was incomplete and we still had presigned URLs printing in query strings in wrong fashion. This PR fixes this properly. Avoid double encoding percent encoded strings such as `s3%!!(MISSING)A(MISSING)` Print properly as json encoded. `s3%3AObjectCreated%3A%2A`
This commit is contained in:
parent
0bba3cc8e3
commit
458f22f37c
@ -113,13 +113,13 @@ func checkRequestAuthType(r *http.Request, bucket, policyAction, region string)
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
}
|
}
|
||||||
return s3Error
|
return s3Error
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
s3Error := isReqAuthenticated(r, region)
|
s3Error := isReqAuthenticated(r, region)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
}
|
}
|
||||||
return s3Error
|
return s3Error
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,14 @@ func (api gatewayAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
// Initialize stream signature verifier.
|
// Initialize stream signature verifier.
|
||||||
reader, s3Error := newSignV4ChunkedReader(r)
|
reader, s3Error := newSignV4ChunkedReader(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -260,14 +260,14 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
case authTypeSignedV2, authTypePresignedV2:
|
case authTypeSignedV2, authTypePresignedV2:
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -313,14 +313,14 @@ func (api gatewayAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.R
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -727,14 +727,14 @@ func (api gatewayAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *htt
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -797,14 +797,14 @@ func (api gatewayAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.R
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
s3Error := isReqAuthenticated(r, serverConfig.GetRegion())
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -849,7 +849,7 @@ func (api gatewayAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r
|
|||||||
// Signature V2 validation.
|
// Signature V2 validation.
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -860,7 +860,7 @@ func (api gatewayAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r
|
|||||||
s3Error = isReqAuthenticated(r, serverConfig.GetRegion())
|
s3Error = isReqAuthenticated(r, serverConfig.GetRegion())
|
||||||
}
|
}
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
// Initialize stream signature verifier.
|
// Initialize stream signature verifier.
|
||||||
reader, s3Error := newSignV4ChunkedReader(r)
|
reader, s3Error := newSignV4ChunkedReader(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -515,14 +515,14 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
case authTypeSignedV2, authTypePresignedV2:
|
case authTypeSignedV2, authTypePresignedV2:
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -788,7 +788,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
// Initialize stream signature verifier.
|
// Initialize stream signature verifier.
|
||||||
reader, s3Error := newSignV4ChunkedReader(r)
|
reader, s3Error := newSignV4ChunkedReader(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -796,14 +796,14 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
case authTypeSignedV2, authTypePresignedV2:
|
case authTypeSignedV2, authTypePresignedV2:
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum)
|
partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum)
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
22
cmd/utils.go
22
cmd/utils.go
@ -17,6 +17,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
@ -163,20 +164,25 @@ var globalProfiler interface {
|
|||||||
func dumpRequest(r *http.Request) string {
|
func dumpRequest(r *http.Request) string {
|
||||||
header := cloneHeader(r.Header)
|
header := cloneHeader(r.Header)
|
||||||
header.Set("Host", r.Host)
|
header.Set("Host", r.Host)
|
||||||
|
// Replace all '%' to '%%' so that printer format parser
|
||||||
|
// to ignore URL encoded values.
|
||||||
|
rawURI := strings.Replace(r.RequestURI, "%", "%%", -1)
|
||||||
req := struct {
|
req := struct {
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Path string `json:"path"`
|
RequestURI string `json:"reqURI"`
|
||||||
Query string `json:"query"`
|
|
||||||
Header http.Header `json:"header"`
|
Header http.Header `json:"header"`
|
||||||
}{r.Method, getURLEncodedName(r.URL.Path), r.URL.RawQuery, header}
|
}{r.Method, rawURI, header}
|
||||||
jsonBytes, err := json.Marshal(&req)
|
|
||||||
if err != nil {
|
var buffer bytes.Buffer
|
||||||
|
enc := json.NewEncoder(&buffer)
|
||||||
|
enc.SetEscapeHTML(false)
|
||||||
|
if err := enc.Encode(&req); err != nil {
|
||||||
// Upon error just return Go-syntax representation of the value
|
// Upon error just return Go-syntax representation of the value
|
||||||
return fmt.Sprintf("%#v", req)
|
return fmt.Sprintf("%#v", req)
|
||||||
}
|
}
|
||||||
// Replace all '%' to '%%' so that printer format parser
|
|
||||||
// to ignore URL encoded values.
|
// Formatted string.
|
||||||
return strings.Replace(string(jsonBytes), "%", "%%", -1)
|
return strings.TrimSpace(string(buffer.Bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// isFile - returns whether given path is a file or not.
|
// isFile - returns whether given path is a file or not.
|
||||||
|
@ -248,16 +248,16 @@ func TestCheckURL(t *testing.T) {
|
|||||||
|
|
||||||
// Testing dumping request function.
|
// Testing dumping request function.
|
||||||
func TestDumpRequest(t *testing.T) {
|
func TestDumpRequest(t *testing.T) {
|
||||||
req, err := http.NewRequest("GET", "http://localhost:9000?prefix=Hello%2AWorld%2A", nil)
|
req, err := http.NewRequest("GET", "http://localhost:9000?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=USWUXHGYZQYFYFFIT3RE%2F20170529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170529T190139Z&X-Amz-Expires=600&X-Amz-Signature=19b58080999df54b446fc97304eb8dda60d3df1812ae97f3e8783351bfd9781d&X-Amz-SignedHeaders=host&prefix=Hello%2AWorld%2A", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
req.RequestURI = "/?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=USWUXHGYZQYFYFFIT3RE%2F20170529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170529T190139Z&X-Amz-Expires=600&X-Amz-Signature=19b58080999df54b446fc97304eb8dda60d3df1812ae97f3e8783351bfd9781d&X-Amz-SignedHeaders=host&prefix=Hello%2AWorld%2A"
|
||||||
req.Header.Set("content-md5", "====test")
|
req.Header.Set("content-md5", "====test")
|
||||||
jsonReq := dumpRequest(req)
|
jsonReq := dumpRequest(req)
|
||||||
type jsonResult struct {
|
type jsonResult struct {
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Path string `json:"path"`
|
RequestURI string `json:"reqURI"`
|
||||||
Query string `json:"query"`
|
|
||||||
Header http.Header `json:"header"`
|
Header http.Header `json:"header"`
|
||||||
}
|
}
|
||||||
jsonReq = strings.Replace(jsonReq, "%%", "%", -1)
|
jsonReq = strings.Replace(jsonReq, "%%", "%", -1)
|
||||||
@ -274,8 +274,15 @@ func TestDumpRequest(t *testing.T) {
|
|||||||
// Look for expected query values
|
// Look for expected query values
|
||||||
expectedQuery := url.Values{}
|
expectedQuery := url.Values{}
|
||||||
expectedQuery.Set("prefix", "Hello*World*")
|
expectedQuery.Set("prefix", "Hello*World*")
|
||||||
if !reflect.DeepEqual(res.Query, expectedQuery.Encode()) {
|
expectedQuery.Set("X-Amz-Algorithm", "AWS4-HMAC-SHA256")
|
||||||
t.Fatalf("Expected %#v, got %#v", expectedQuery, res.Query)
|
expectedQuery.Set("X-Amz-Credential", "USWUXHGYZQYFYFFIT3RE/20170529/us-east-1/s3/aws4_request")
|
||||||
|
expectedQuery.Set("X-Amz-Date", "20170529T190139Z")
|
||||||
|
expectedQuery.Set("X-Amz-Expires", "600")
|
||||||
|
expectedQuery.Set("X-Amz-SignedHeaders", "host")
|
||||||
|
expectedQuery.Set("X-Amz-Signature", "19b58080999df54b446fc97304eb8dda60d3df1812ae97f3e8783351bfd9781d")
|
||||||
|
expectedRequestURI := "/?" + expectedQuery.Encode()
|
||||||
|
if !reflect.DeepEqual(res.RequestURI, expectedRequestURI) {
|
||||||
|
t.Fatalf("Expected %#v, got %#v", expectedRequestURI, res.RequestURI)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for expected header.
|
// Look for expected header.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user