2018-09-02 21:20:47 +00:00
|
|
|
package s3api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// AWS Signature Version '4' constants.
|
|
|
|
const (
|
2018-09-03 23:47:00 +00:00
|
|
|
signV4Algorithm = "AWS4-HMAC-SHA256"
|
|
|
|
signV2Algorithm = "AWS"
|
2020-02-09 22:30:02 +00:00
|
|
|
iso8601Format = "20060102T150405Z"
|
|
|
|
yyyymmdd = "20060102"
|
2018-09-02 21:20:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Verify if request has JWT.
|
|
|
|
func isRequestJWT(r *http.Request) bool {
|
|
|
|
return strings.HasPrefix(r.Header.Get("Authorization"), "Bearer")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify if request has AWS Signature Version '4'.
|
|
|
|
func isRequestSignatureV4(r *http.Request) bool {
|
|
|
|
return strings.HasPrefix(r.Header.Get("Authorization"), signV4Algorithm)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify if request has AWS Signature Version '2'.
|
|
|
|
func isRequestSignatureV2(r *http.Request) bool {
|
2020-02-09 22:30:02 +00:00
|
|
|
return !strings.HasPrefix(r.Header.Get("Authorization"), signV4Algorithm) &&
|
|
|
|
strings.HasPrefix(r.Header.Get("Authorization"), signV2Algorithm)
|
2018-09-02 21:20:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Verify if request has AWS PreSign Version '4'.
|
|
|
|
func isRequestPresignedSignatureV4(r *http.Request) bool {
|
|
|
|
_, ok := r.URL.Query()["X-Amz-Credential"]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify request has AWS PreSign Version '2'.
|
|
|
|
func isRequestPresignedSignatureV2(r *http.Request) bool {
|
|
|
|
_, ok := r.URL.Query()["AWSAccessKeyId"]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify if request has AWS Post policy Signature Version '4'.
|
|
|
|
func isRequestPostPolicySignatureV4(r *http.Request) bool {
|
|
|
|
return strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") &&
|
|
|
|
r.Method == http.MethodPost
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify if the request has AWS Streaming Signature Version '4'. This is only valid for 'PUT' operation.
|
|
|
|
func isRequestSignStreamingV4(r *http.Request) bool {
|
|
|
|
return r.Header.Get("x-amz-content-sha256") == streamingContentSHA256 &&
|
|
|
|
r.Method == http.MethodPut
|
|
|
|
}
|
|
|
|
|
|
|
|
// Authorization type.
|
|
|
|
type authType int
|
|
|
|
|
|
|
|
// List of all supported auth types.
|
|
|
|
const (
|
|
|
|
authTypeUnknown authType = iota
|
|
|
|
authTypeAnonymous
|
|
|
|
authTypePresigned
|
|
|
|
authTypePresignedV2
|
|
|
|
authTypePostPolicy
|
|
|
|
authTypeStreamingSigned
|
|
|
|
authTypeSigned
|
|
|
|
authTypeSignedV2
|
|
|
|
authTypeJWT
|
|
|
|
)
|
|
|
|
|
|
|
|
// Get request authentication type.
|
|
|
|
func getRequestAuthType(r *http.Request) authType {
|
|
|
|
if isRequestSignatureV2(r) {
|
|
|
|
return authTypeSignedV2
|
|
|
|
} else if isRequestPresignedSignatureV2(r) {
|
|
|
|
return authTypePresignedV2
|
|
|
|
} else if isRequestSignStreamingV4(r) {
|
|
|
|
return authTypeStreamingSigned
|
|
|
|
} else if isRequestSignatureV4(r) {
|
|
|
|
return authTypeSigned
|
|
|
|
} else if isRequestPresignedSignatureV4(r) {
|
|
|
|
return authTypePresigned
|
|
|
|
} else if isRequestJWT(r) {
|
|
|
|
return authTypeJWT
|
|
|
|
} else if isRequestPostPolicySignatureV4(r) {
|
|
|
|
return authTypePostPolicy
|
|
|
|
} else if _, ok := r.Header["Authorization"]; !ok {
|
|
|
|
return authTypeAnonymous
|
|
|
|
}
|
|
|
|
return authTypeUnknown
|
|
|
|
}
|