s3cmd: Handle support for s3cmd.

This commit is contained in:
Harshavardhana 2015-12-09 15:38:40 -08:00
parent 7187668828
commit 3c71c5c80c
6 changed files with 63 additions and 12 deletions

View file

@ -126,11 +126,28 @@ Listening on http://172.30.2.17:9000
Please follow the documentation here - [Using aws-sdk-go with Minio server](./AWS-SDK-GO.md)
#### How to use s3cmd with Minio?
<blockquote>
Even with Signature version '4' enabled, 's3cmd' falls back to Signature version '2' for listing your buckets. Since minio server is only Signature version '4' listing your buckets with Signature version '2' fails. We have no immediate plans on supporting Signature version '2'. Please follow https://github.com/minio/minio/issues/987 to know more on this issue.
</blockquote>
`s3cmd` is currently not supported.
Edit the following fields in your s3cmd configuration file. ~/.s3cfg
```
host_base = localhost:9000
host_bucket = localhost:9000
access_key = YOUR_ACCESS_KEY_HERE
secret_key = YOUR_SECRET_KEY_HERE
```
To list your buckets.
```
$ s3cmd --region us-east-1 ls s3://
2015-12-09 16:12 s3://testbbucket
```
To list contents inside buckets.
```
$ s3cmd --region us-east-1 ls s3://testbucket/
DIR s3://testbucket/test/
2015-12-09 16:05 138504 s3://testbucket/newfile
```
## Contribute to Minio Project
Please follow Minio [Contributor's Guide](./CONTRIBUTING.md)

View file

@ -30,12 +30,14 @@ type APIError struct {
// APIErrorResponse - error response format
type APIErrorResponse struct {
XMLName xml.Name `xml:"Error" json:"-"`
Code string
Message string
Resource string
RequestID string `xml:"RequestId"`
HostID string `xml:"HostId"`
XMLName xml.Name `xml:"Error" json:"-"`
Code string
Message string
Key string
BucketName string
Resource string
RequestID string `xml:"RequestId"`
HostID string `xml:"HostId"`
}
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
@ -70,6 +72,7 @@ const (
InvalidPartOrder
AuthorizationHeaderMalformed
MalformedPOSTRequest
SignatureVersionNotSupported
BucketNotEmpty
RootPathFull
)
@ -221,6 +224,11 @@ var errorCodeResponse = map[int]APIError{
Description: "The body of your POST request is not well-formed multipart/form-data.",
HTTPStatusCode: http.StatusBadRequest,
},
SignatureVersionNotSupported: {
Code: "InvalidRequest",
Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.",
HTTPStatusCode: http.StatusBadRequest,
},
BucketNotEmpty: {
Code: "BucketNotEmpty",
Description: "The bucket you tried to delete is not empty.",

View file

@ -57,6 +57,7 @@ func setCommonHeaders(w http.ResponseWriter, contentLength int) {
func encodeErrorResponse(response interface{}) []byte {
var bytesBuffer bytes.Buffer
// write common headers
bytesBuffer.WriteString(xml.Header)
e := xml.NewEncoder(&bytesBuffer)
e.Encode(response)
return bytesBuffer.Bytes()
@ -92,6 +93,7 @@ func setObjectHeaders(w http.ResponseWriter, metadata fs.ObjectMetadata, content
func encodeSuccessResponse(response interface{}) []byte {
var bytesBuffer bytes.Buffer
bytesBuffer.WriteString(xml.Header)
e := xml.NewEncoder(&bytesBuffer)
e.Encode(response)
return bytesBuffer.Bytes()

View file

@ -46,6 +46,10 @@ type resourceHandler struct {
handler http.Handler
}
type ignoreSignatureV2RequestHandler struct {
handler http.Handler
}
func parseDate(req *http.Request) (time.Time, error) {
amzDate := req.Header.Get(http.CanonicalHeaderKey("x-amz-date"))
switch {
@ -128,6 +132,23 @@ func CorsHandler(h http.Handler) http.Handler {
return c.Handler(h)
}
// IgnoreSignatureV2RequestHandler -
// Verify if authorization header has signature version '2', reject it cleanly.
func IgnoreSignatureV2RequestHandler(h http.Handler) http.Handler {
return ignoreSignatureV2RequestHandler{h}
}
// Ignore signature version '2' ServerHTTP() wrapper.
func (h ignoreSignatureV2RequestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if _, ok := r.Header["Authorization"]; ok {
if !strings.HasPrefix(r.Header.Get("Authorization"), authHeaderPrefix) {
writeErrorResponse(w, r, SignatureVersionNotSupported, r.URL.Path)
return
}
}
h.handler.ServeHTTP(w, r)
}
// IgnoreResourcesHandler -
// Ignore resources handler is wrapper handler used for API request resource validation
// Since we do not support all the S3 queries, it is necessary for us to throw back a

View file

@ -80,9 +80,10 @@ func getNewCloudStorageAPI(conf cloudServerConfig) CloudStorageAPI {
func getCloudStorageAPIHandler(api CloudStorageAPI) http.Handler {
var mwHandlers = []MiddlewareHandler{
CorsHandler,
TimeValidityHandler,
IgnoreResourcesHandler,
CorsHandler,
IgnoreSignatureV2RequestHandler,
}
if !api.Anonymous {
mwHandlers = append(mwHandlers, SignatureHandler)

View file

@ -37,7 +37,9 @@ func SignatureHandler(h http.Handler) http.Handler {
func isRequestSignatureV4(req *http.Request) bool {
if _, ok := req.Header["Authorization"]; ok {
return ok
if strings.HasPrefix(req.Header.Get("Authorization"), authHeaderPrefix) {
return ok
}
}
return false
}