mirror of
https://github.com/pgsty/minio.git
synced 2026-10-04 16:55:57 +03:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b472dae78 | |||
| eb50175ad9 | |||
| e85349381e | |||
| 06bc68a4b3 | |||
| fb506c7fca | |||
| 8a7cffe7b8 | |||
| 5c85ce1afd | |||
| 710db6bdad | |||
| 058ea84605 | |||
| 6e7d33df20 | |||
| 5311eb22fd | |||
| 83abb310b4 | |||
| 3d98311d9f | |||
| d44e38b462 | |||
| 8948c972ee | |||
| 29b49f9343 | |||
| f8e4700a11 | |||
| 4c5c00c640 | |||
| 0be44133d4 | |||
| 817e763416 | |||
| 0abab5305f | |||
| e6e855a7cf | |||
| 6fca1d164c | |||
| 9b76eba37e | |||
| 03714d4809 | |||
| 3a73ea3f54 | |||
| 9625629fc7 | |||
| 8507ce2a87 |
+1
-1
@@ -11,7 +11,7 @@ RUN \
|
|||||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||||
go get -v -d github.com/minio/minio && \
|
go get -v -d github.com/minio/minio && \
|
||||||
cd /go/src/github.com/minio/minio && \
|
cd /go/src/github.com/minio/minio && \
|
||||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
go install -v -ldflags "-X github.com/minio/minio/cmd.Version=2017-04-29T00:40:27Z -X github.com/minio/minio/cmd.ReleaseTag=RELEASE.2017-04-29T00-40-27Z -X github.com/minio/minio/cmd.CommitID=eb50175ad911d496bf583a599de89547f0c9be89" && \
|
||||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ RUN \
|
|||||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||||
go get -v -d github.com/minio/minio && \
|
go get -v -d github.com/minio/minio && \
|
||||||
cd /go/src/github.com/minio/minio && \
|
cd /go/src/github.com/minio/minio && \
|
||||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
go install -v -ldflags "-X github.com/minio/minio/cmd.Version=2017-03-16T21:50:32Z -X github.com/minio/minio/cmd.ReleaseTag=RELEASE.2017-03-16T21-50-32Z -X github.com/minio/minio/cmd.CommitID=5311eb22fd681a8cd4a46e2a872d46c2352c64e8" && \
|
||||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ RUN \
|
|||||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||||
go get -v -d github.com/minio/minio && \
|
go get -v -d github.com/minio/minio && \
|
||||||
cd /go/src/github.com/minio/minio && \
|
cd /go/src/github.com/minio/minio && \
|
||||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
go install -v -ldflags "-X github.com/minio/minio/cmd.Version=2017-03-16T21:50:32Z -X github.com/minio/minio/cmd.ReleaseTag=RELEASE.2017-03-16T21-50-32Z -X github.com/minio/minio/cmd.CommitID=5311eb22fd681a8cd4a46e2a872d46c2352c64e8" && \
|
||||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
LDFLAGS := $(shell go run buildscripts/gen-ldflags.go)
|
LDFLAGS := $(shell go run buildscripts/gen-ldflags.go)
|
||||||
PWD := $(shell pwd)
|
PWD := $(shell pwd)
|
||||||
GOPATH := $(shell go env GOPATH)
|
GOPATH := $(shell go env GOPATH)
|
||||||
BUILD_LDFLAGS := '$(LDFLAGS)'
|
BUILD_LDFLAGS := '$(LDFLAGS) -s -w'
|
||||||
TAG := latest
|
TAG := latest
|
||||||
|
|
||||||
HOST ?= $(shell uname)
|
HOST ?= $(shell uname)
|
||||||
|
|||||||
@@ -18,19 +18,19 @@ docker run -p 9000:9000 minio/minio:edge server /export
|
|||||||
```
|
```
|
||||||
Please visit Minio Docker quickstart guide for more [here](https://docs.minio.io/docs/minio-docker-quickstart-guide)
|
Please visit Minio Docker quickstart guide for more [here](https://docs.minio.io/docs/minio-docker-quickstart-guide)
|
||||||
|
|
||||||
## OS X
|
## macOS
|
||||||
### Homebrew
|
### Homebrew
|
||||||
Install minio packages using [Homebrew](http://brew.sh/)
|
Install minio packages using [Homebrew](http://brew.sh/)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew install minio
|
brew install minio/stable/minio
|
||||||
minio server ~/Photos
|
minio server ~/Photos
|
||||||
```
|
```
|
||||||
|
|
||||||
### Binary Download
|
### Binary Download
|
||||||
| Platform| Architecture | URL|
|
| Platform| Architecture | URL|
|
||||||
| ----------| -------- | ------|
|
| ----------| -------- | ------|
|
||||||
|Apple OS X|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio|
|
|Apple macOS|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio |
|
||||||
```sh
|
```sh
|
||||||
chmod 755 minio
|
chmod 755 minio
|
||||||
./minio server ~/Photos
|
./minio server ~/Photos
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ go_build() {
|
|||||||
|
|
||||||
release_bin_6="$release_str/$os-${arch}6vl/$(basename $package).$release_tag"
|
release_bin_6="$release_str/$os-${arch}6vl/$(basename $package).$release_tag"
|
||||||
## Support building for ARM6vl
|
## Support building for ARM6vl
|
||||||
GOARM=6 GOOS=$os GOARCH=$arch go build --ldflags "${LDFLAGS}" -o $release_bin_6
|
GOARM=6 GOOS=$os GOARCH=$arch go build --ldflags "-s -w ${LDFLAGS}" -o $release_bin_6
|
||||||
|
|
||||||
## Copy
|
## Copy
|
||||||
$CP -p $release_bin_6 $release_real_bin_6
|
$CP -p $release_bin_6 $release_real_bin_6
|
||||||
@@ -70,7 +70,7 @@ go_build() {
|
|||||||
|
|
||||||
release_bin_7="$release_str/$os-$arch/$(basename $package).$release_tag"
|
release_bin_7="$release_str/$os-$arch/$(basename $package).$release_tag"
|
||||||
## Support building for ARM7vl
|
## Support building for ARM7vl
|
||||||
GOARM=7 GOOS=$os GOARCH=$arch go build --ldflags "${LDFLAGS}" -o $release_bin_7
|
GOARM=7 GOOS=$os GOARCH=$arch go build --ldflags "-s -w ${LDFLAGS}" -o $release_bin_7
|
||||||
|
|
||||||
## Copy
|
## Copy
|
||||||
$CP -p $release_bin_7 $release_real_bin_7
|
$CP -p $release_bin_7 $release_real_bin_7
|
||||||
@@ -82,7 +82,7 @@ go_build() {
|
|||||||
shasum_str=$(${SHASUM} ${release_bin_7})
|
shasum_str=$(${SHASUM} ${release_bin_7})
|
||||||
echo ${shasum_str} | $SED "s/$release_str\/$os-$arch\///g" > $release_shasum_7
|
echo ${shasum_str} | $SED "s/$release_str\/$os-$arch\///g" > $release_shasum_7
|
||||||
else
|
else
|
||||||
GOOS=$os GOARCH=$arch go build --ldflags "${LDFLAGS}" -o $release_bin
|
GOOS=$os GOARCH=$arch go build --ldflags "-s -w ${LDFLAGS}" -o $release_bin
|
||||||
|
|
||||||
# Create copy
|
# Create copy
|
||||||
if [ $os == "windows" ]; then
|
if [ $os == "windows" ]; then
|
||||||
|
|||||||
+7
-1
@@ -139,6 +139,7 @@ const (
|
|||||||
ErrObjectExistsAsDirectory
|
ErrObjectExistsAsDirectory
|
||||||
ErrPolicyNesting
|
ErrPolicyNesting
|
||||||
ErrInvalidObjectName
|
ErrInvalidObjectName
|
||||||
|
ErrInvalidResourceName
|
||||||
ErrServerNotInitialized
|
ErrServerNotInitialized
|
||||||
// Add new extended error codes here.
|
// Add new extended error codes here.
|
||||||
// Please open a https://github.com/minio/minio/issues before adding
|
// Please open a https://github.com/minio/minio/issues before adding
|
||||||
@@ -588,7 +589,12 @@ var errorCodeResponse = map[APIErrorCode]APIError{
|
|||||||
},
|
},
|
||||||
ErrInvalidObjectName: {
|
ErrInvalidObjectName: {
|
||||||
Code: "XMinioInvalidObjectName",
|
Code: "XMinioInvalidObjectName",
|
||||||
Description: "Object name contains unsupported characters. Unsupported characters are `^*|\\\"",
|
Description: "Object name contains unsupported characters.",
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
ErrInvalidResourceName: {
|
||||||
|
Code: "XMinioInvalidResourceName",
|
||||||
|
Description: "Resource name contains bad components such as \"..\" or \".\".",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
ErrServerNotInitialized: {
|
ErrServerNotInitialized: {
|
||||||
|
|||||||
+5
-3
@@ -123,9 +123,11 @@ func azureToObjectError(err error, params ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inits azure blob storage client and returns AzureObjects.
|
// Inits azure blob storage client and returns AzureObjects.
|
||||||
func newAzureLayer(account, key string) (GatewayLayer, error) {
|
func newAzureLayer(endPoint string, account, key string, secure bool) (GatewayLayer, error) {
|
||||||
useHTTPS := true
|
if endPoint == "" {
|
||||||
c, err := storage.NewClient(account, key, storage.DefaultBaseURL, globalAzureAPIVersion, useHTTPS)
|
endPoint = storage.DefaultBaseURL
|
||||||
|
}
|
||||||
|
c, err := storage.NewClient(account, key, endPoint, globalAzureAPIVersion, secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return AzureObjects{}, err
|
return AzureObjects{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-12
@@ -18,7 +18,9 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/minio/cli"
|
"github.com/minio/cli"
|
||||||
@@ -29,11 +31,14 @@ var gatewayTemplate = `NAME:
|
|||||||
{{.HelpName}} - {{.Usage}}
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
{{.HelpName}} {{if .VisibleFlags}}[FLAGS]{{end}} BACKEND
|
{{.HelpName}} {{if .VisibleFlags}}[FLAGS]{{end}} BACKEND [ENDPOINT]
|
||||||
{{if .VisibleFlags}}
|
{{if .VisibleFlags}}
|
||||||
FLAGS:
|
FLAGS:
|
||||||
{{range .VisibleFlags}}{{.}}
|
{{range .VisibleFlags}}{{.}}
|
||||||
{{end}}{{end}}
|
{{end}}{{end}}
|
||||||
|
BACKEND:
|
||||||
|
azure: Microsoft Azure Blob Storage. Default ENDPOINT is https://core.windows.net
|
||||||
|
|
||||||
ENVIRONMENT VARIABLES:
|
ENVIRONMENT VARIABLES:
|
||||||
ACCESS:
|
ACCESS:
|
||||||
MINIO_ACCESS_KEY: Username or access key of your storage backend.
|
MINIO_ACCESS_KEY: Username or access key of your storage backend.
|
||||||
@@ -41,21 +46,22 @@ ENVIRONMENT VARIABLES:
|
|||||||
|
|
||||||
EXAMPLES:
|
EXAMPLES:
|
||||||
1. Start minio gateway server for Azure Blob Storage backend.
|
1. Start minio gateway server for Azure Blob Storage backend.
|
||||||
|
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||||
|
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||||
$ {{.HelpName}} azure
|
$ {{.HelpName}} azure
|
||||||
|
|
||||||
2. Start minio gateway server bound to a specific ADDRESS:PORT.
|
|
||||||
$ {{.HelpName}} --address 192.168.1.101:9000 azure
|
|
||||||
`
|
`
|
||||||
|
|
||||||
var gatewayCmd = cli.Command{
|
var gatewayCmd = cli.Command{
|
||||||
Name: "gateway",
|
Name: "gateway",
|
||||||
Usage: "Start object storage gateway server.",
|
Usage: "Start object storage gateway.",
|
||||||
Action: gatewayMain,
|
Action: gatewayMain,
|
||||||
CustomHelpTemplate: gatewayTemplate,
|
CustomHelpTemplate: gatewayTemplate,
|
||||||
Flags: append(serverFlags, cli.BoolFlag{
|
Flags: append(serverFlags,
|
||||||
Name: "quiet",
|
cli.BoolFlag{
|
||||||
Usage: "Disable startup banner.",
|
Name: "quiet",
|
||||||
}),
|
Usage: "Disable startup banner.",
|
||||||
|
},
|
||||||
|
),
|
||||||
HideHelpCommand: true,
|
HideHelpCommand: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,11 +89,11 @@ func mustGetGatewayCredsFromEnv() (accessKey, secretKey string) {
|
|||||||
//
|
//
|
||||||
// - Azure Blob Storage.
|
// - Azure Blob Storage.
|
||||||
// - Add your favorite backend here.
|
// - Add your favorite backend here.
|
||||||
func newGatewayLayer(backendType, accessKey, secretKey string) (GatewayLayer, error) {
|
func newGatewayLayer(backendType, endPoint, accessKey, secretKey string, secure bool) (GatewayLayer, error) {
|
||||||
if gatewayBackend(backendType) != azureBackend {
|
if gatewayBackend(backendType) != azureBackend {
|
||||||
return nil, fmt.Errorf("Unrecognized backend type %s", backendType)
|
return nil, fmt.Errorf("Unrecognized backend type %s", backendType)
|
||||||
}
|
}
|
||||||
return newAzureLayer(accessKey, secretKey)
|
return newAzureLayer(endPoint, accessKey, secretKey, secure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a new gateway config.
|
// Initialize a new gateway config.
|
||||||
@@ -125,6 +131,28 @@ func newGatewayConfig(accessKey, secretKey, region string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return endpoint.
|
||||||
|
func parseGatewayEndpoint(arg string) (endPoint string, secure bool, err error) {
|
||||||
|
schemeSpecified := len(strings.Split(arg, "://")) > 1
|
||||||
|
if !schemeSpecified {
|
||||||
|
// Default connection will be "secure".
|
||||||
|
arg = "https://" + arg
|
||||||
|
}
|
||||||
|
u, err := url.Parse(arg)
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "http":
|
||||||
|
return u.Host, false, nil
|
||||||
|
case "https":
|
||||||
|
return u.Host, true, nil
|
||||||
|
default:
|
||||||
|
return "", false, fmt.Errorf("Unrecognized scheme %s", u.Scheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handler for 'minio gateway'.
|
// Handler for 'minio gateway'.
|
||||||
func gatewayMain(ctx *cli.Context) {
|
func gatewayMain(ctx *cli.Context) {
|
||||||
if !ctx.Args().Present() || ctx.Args().First() == "help" {
|
if !ctx.Args().Present() || ctx.Args().First() == "help" {
|
||||||
@@ -153,7 +181,20 @@ func gatewayMain(ctx *cli.Context) {
|
|||||||
// First argument is selected backend type.
|
// First argument is selected backend type.
|
||||||
backendType := ctx.Args().First()
|
backendType := ctx.Args().First()
|
||||||
|
|
||||||
newObject, err := newGatewayLayer(backendType, accessKey, secretKey)
|
// Second argument is endpoint. If no endpoint is specified then the
|
||||||
|
// gateway implementation should use a default setting.
|
||||||
|
endPoint, secure, err := parseGatewayEndpoint(ctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
console.Fatalf("Unable to parse endpoint. Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create certs path for SSL configuration.
|
||||||
|
err = createConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
console.Fatalf("Unable to create configuration directory. Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newObject, err := newGatewayLayer(backendType, endPoint, accessKey, secretKey, secure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
console.Fatalf("Unable to initialize gateway layer. Error: %s", err)
|
console.Fatalf("Unable to initialize gateway layer. Error: %s", err)
|
||||||
}
|
}
|
||||||
@@ -164,6 +205,8 @@ func gatewayMain(ctx *cli.Context) {
|
|||||||
registerGatewayAPIRouter(router, newObject)
|
registerGatewayAPIRouter(router, newObject)
|
||||||
|
|
||||||
var handlerFns = []HandlerFunc{
|
var handlerFns = []HandlerFunc{
|
||||||
|
// Validate all the incoming paths.
|
||||||
|
setPathValidityHandler,
|
||||||
// Limits all requests size to a maximum fixed limit
|
// Limits all requests size to a maximum fixed limit
|
||||||
setRequestSizeLimitHandler,
|
setRequestSizeLimitHandler,
|
||||||
// Adds 'crossdomain.xml' policy handler to serve legacy flash clients.
|
// Adds 'crossdomain.xml' policy handler to serve legacy flash clients.
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Minio Cloud Storage, (C) 2017 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
// Test parseGatewayEndpoint
|
||||||
|
func TestParseGatewayEndpoint(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
arg string
|
||||||
|
endPoint string
|
||||||
|
secure bool
|
||||||
|
errReturned bool
|
||||||
|
}{
|
||||||
|
{"http://127.0.0.1:9000", "127.0.0.1:9000", false, false},
|
||||||
|
{"https://127.0.0.1:9000", "127.0.0.1:9000", true, false},
|
||||||
|
{"http://play.minio.io:9000", "play.minio.io:9000", false, false},
|
||||||
|
{"https://play.minio.io:9000", "play.minio.io:9000", true, false},
|
||||||
|
{"ftp://127.0.0.1:9000", "", false, true},
|
||||||
|
{"ftp://play.minio.io:9000", "", false, true},
|
||||||
|
{"play.minio.io:9000", "play.minio.io:9000", true, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range testCases {
|
||||||
|
endPoint, secure, err := parseGatewayEndpoint(test.arg)
|
||||||
|
errReturned := err != nil
|
||||||
|
|
||||||
|
if endPoint != test.endPoint ||
|
||||||
|
secure != test.secure ||
|
||||||
|
errReturned != test.errReturned {
|
||||||
|
t.Errorf("Test %d: expected %s,%t,%t got %s,%t,%t",
|
||||||
|
i+1, test.endPoint, test.secure, test.errReturned,
|
||||||
|
endPoint, secure, errReturned)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -407,3 +407,52 @@ func (h httpStatsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Update http statistics
|
// Update http statistics
|
||||||
globalHTTPStats.updateStats(r, ww)
|
globalHTTPStats.updateStats(r, ww)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pathValidityHandler validates all the incoming paths for
|
||||||
|
// any bad components and rejects them.
|
||||||
|
type pathValidityHandler struct {
|
||||||
|
handler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPathValidityHandler(h http.Handler) http.Handler {
|
||||||
|
return pathValidityHandler{handler: h}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad path components to be rejected by the path validity handler.
|
||||||
|
const (
|
||||||
|
dotdotComponent = ".."
|
||||||
|
dotComponent = "."
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the incoming path has bad path components,
|
||||||
|
// such as ".." and "."
|
||||||
|
func hasBadPathComponent(path string) bool {
|
||||||
|
path = strings.TrimSpace(path)
|
||||||
|
for _, p := range strings.Split(path, slashSeparator) {
|
||||||
|
switch strings.TrimSpace(p) {
|
||||||
|
case dotdotComponent:
|
||||||
|
return true
|
||||||
|
case dotComponent:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h pathValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Check for bad components in URL path.
|
||||||
|
if hasBadPathComponent(r.URL.Path) {
|
||||||
|
writeErrorResponse(w, ErrInvalidResourceName, r.URL)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Check for bad components in URL query values.
|
||||||
|
for _, vv := range r.URL.Query() {
|
||||||
|
for _, v := range vv {
|
||||||
|
if hasBadPathComponent(v) {
|
||||||
|
writeErrorResponse(w, ErrInvalidResourceName, r.URL)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.handler.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
|||||||
{"test-bucket-list-object", "", "", "*", 0, ListObjectsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "*"), false},
|
{"test-bucket-list-object", "", "", "*", 0, ListObjectsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "*"), false},
|
||||||
{"test-bucket-list-object", "", "", "-", 0, ListObjectsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "-"), false},
|
{"test-bucket-list-object", "", "", "-", 0, ListObjectsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "-"), false},
|
||||||
// Testing for failure cases with both perfix and marker (11).
|
// Testing for failure cases with both perfix and marker (11).
|
||||||
// The prefix and marker combination to be valid it should satisy strings.HasPrefix(marker, prefix).
|
// The prefix and marker combination to be valid it should satisfy strings.HasPrefix(marker, prefix).
|
||||||
{"test-bucket-list-object", "asia", "europe-object", "", 0, ListObjectsInfo{}, fmt.Errorf("Invalid combination of marker '%s' and prefix '%s'", "europe-object", "asia"), false},
|
{"test-bucket-list-object", "asia", "europe-object", "", 0, ListObjectsInfo{}, fmt.Errorf("Invalid combination of marker '%s' and prefix '%s'", "europe-object", "asia"), false},
|
||||||
// Setting a non-existing directory to be prefix (12-13).
|
// Setting a non-existing directory to be prefix (12-13).
|
||||||
{"empty-bucket", "europe/france/", "", "", 1, ListObjectsInfo{}, nil, true},
|
{"empty-bucket", "europe/france/", "", "", 1, ListObjectsInfo{}, nil, true},
|
||||||
|
|||||||
@@ -1110,7 +1110,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
{bucketNames[0], "", "", "", "*", 0, ListMultipartsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "*"), false},
|
{bucketNames[0], "", "", "", "*", 0, ListMultipartsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "*"), false},
|
||||||
{bucketNames[0], "", "", "", "-", 0, ListMultipartsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "-"), false},
|
{bucketNames[0], "", "", "", "-", 0, ListMultipartsInfo{}, fmt.Errorf("delimiter '%s' is not supported", "-"), false},
|
||||||
// Testing for failure cases with both perfix and marker (Test number 10).
|
// Testing for failure cases with both perfix and marker (Test number 10).
|
||||||
// The prefix and marker combination to be valid it should satisy strings.HasPrefix(marker, prefix).
|
// The prefix and marker combination to be valid it should satisfy strings.HasPrefix(marker, prefix).
|
||||||
{bucketNames[0], "asia", "europe-object", "", "", 0, ListMultipartsInfo{},
|
{bucketNames[0], "asia", "europe-object", "", "", 0, ListMultipartsInfo{},
|
||||||
fmt.Errorf("Invalid combination of marker '%s' and prefix '%s'", "europe-object", "asia"), false},
|
fmt.Errorf("Invalid combination of marker '%s' and prefix '%s'", "europe-object", "asia"), false},
|
||||||
// Setting an invalid combination of uploadIDMarker and Marker (Test number 11-12).
|
// Setting an invalid combination of uploadIDMarker and Marker (Test number 11-12).
|
||||||
|
|||||||
@@ -131,6 +131,9 @@ func IsValidObjectName(object string) bool {
|
|||||||
// IsValidObjectPrefix verifies whether the prefix is a valid object name.
|
// IsValidObjectPrefix verifies whether the prefix is a valid object name.
|
||||||
// Its valid to have a empty prefix.
|
// Its valid to have a empty prefix.
|
||||||
func IsValidObjectPrefix(object string) bool {
|
func IsValidObjectPrefix(object string) bool {
|
||||||
|
if hasBadPathComponent(object) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if len(object) > 1024 {
|
if len(object) > 1024 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,12 +100,22 @@ func TestIsValidObjectName(t *testing.T) {
|
|||||||
{"contains-|-pipe", true},
|
{"contains-|-pipe", true},
|
||||||
{"contains-\"-quote", true},
|
{"contains-\"-quote", true},
|
||||||
{"contains-`-tick", true},
|
{"contains-`-tick", true},
|
||||||
|
{"..test", true},
|
||||||
|
{".. test", true},
|
||||||
|
{". test", true},
|
||||||
|
{".test", true},
|
||||||
{"There are far too many object names, and far too few bucket names!", true},
|
{"There are far too many object names, and far too few bucket names!", true},
|
||||||
// cases for which test should fail.
|
// cases for which test should fail.
|
||||||
// passing invalid object names.
|
// passing invalid object names.
|
||||||
{"", false},
|
{"", false},
|
||||||
{"a/b/c/", false},
|
{"a/b/c/", false},
|
||||||
{"/a/b/c", false},
|
{"/a/b/c", false},
|
||||||
|
{"../../etc", false},
|
||||||
|
{"../../", false},
|
||||||
|
{"/../../etc", false},
|
||||||
|
{" ../etc", false},
|
||||||
|
{"./././", false},
|
||||||
|
{"./etc", false},
|
||||||
{"contains-\\-backslash", false},
|
{"contains-\\-backslash", false},
|
||||||
{string([]byte{0xff, 0xfe, 0xfd}), false},
|
{string([]byte{0xff, 0xfe, 0xfd}), false},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,6 +316,58 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrInvalidAccessKeyID), getGetObjectURL("", bucketName, objectName))),
|
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrInvalidAccessKeyID), getGetObjectURL("", bucketName, objectName))),
|
||||||
expectedRespStatus: http.StatusForbidden,
|
expectedRespStatus: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
|
// Test case - 7.
|
||||||
|
// Case with bad components in object name.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: "../../etc",
|
||||||
|
byteRange: "",
|
||||||
|
accessKey: credentials.AccessKey,
|
||||||
|
secretKey: credentials.SecretKey,
|
||||||
|
|
||||||
|
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrInvalidObjectName),
|
||||||
|
getGetObjectURL("", bucketName, "../../etc"))),
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
// Test case - 8.
|
||||||
|
// Case with strange components but returning error as not found.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: ". ./. ./etc",
|
||||||
|
byteRange: "",
|
||||||
|
accessKey: credentials.AccessKey,
|
||||||
|
secretKey: credentials.SecretKey,
|
||||||
|
|
||||||
|
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrNoSuchKey),
|
||||||
|
"/"+bucketName+"/"+". ./. ./etc")),
|
||||||
|
expectedRespStatus: http.StatusNotFound,
|
||||||
|
},
|
||||||
|
// Test case - 9.
|
||||||
|
// Case with bad components in object name.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: ". ./../etc",
|
||||||
|
byteRange: "",
|
||||||
|
accessKey: credentials.AccessKey,
|
||||||
|
secretKey: credentials.SecretKey,
|
||||||
|
|
||||||
|
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrInvalidObjectName),
|
||||||
|
"/"+bucketName+"/"+". ./../etc")),
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
// Test case - 10.
|
||||||
|
// Case with proper components
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: "etc/path/proper/.../etc",
|
||||||
|
byteRange: "",
|
||||||
|
accessKey: credentials.AccessKey,
|
||||||
|
secretKey: credentials.SecretKey,
|
||||||
|
|
||||||
|
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(ErrNoSuchKey),
|
||||||
|
getGetObjectURL("", bucketName, "etc/path/proper/.../etc"))),
|
||||||
|
expectedRespStatus: http.StatusNotFound,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterating over the cases, fetching the object validating the response.
|
// Iterating over the cases, fetching the object validating the response.
|
||||||
@@ -346,7 +398,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
}
|
}
|
||||||
// Verify whether the bucket obtained object is same as the one created.
|
// Verify whether the bucket obtained object is same as the one created.
|
||||||
if !bytes.Equal(testCase.expectedContent, actualContent) {
|
if !bytes.Equal(testCase.expectedContent, actualContent) {
|
||||||
t.Errorf("Test %d: %s: Object content differs from expected value.: %s", i+1, instanceType, string(actualContent))
|
t.Errorf("Test %d: %s: Object content differs from expected value %s, got %s", i+1, instanceType, testCase.expectedContent, string(actualContent))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify response of the V2 signed HTTP request.
|
// Verify response of the V2 signed HTTP request.
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ func configureServerHandler(srvCmdConfig serverCmdConfig) (http.Handler, error)
|
|||||||
|
|
||||||
// List of some generic handlers which are applied for all incoming requests.
|
// List of some generic handlers which are applied for all incoming requests.
|
||||||
var handlerFns = []HandlerFunc{
|
var handlerFns = []HandlerFunc{
|
||||||
|
// Validate all the incoming paths.
|
||||||
|
setPathValidityHandler,
|
||||||
// Network statistics
|
// Network statistics
|
||||||
setHTTPStatsHandler,
|
setHTTPStatsHandler,
|
||||||
// Limits all requests size to a maximum fixed limit
|
// Limits all requests size to a maximum fixed limit
|
||||||
|
|||||||
+2
-2
@@ -170,7 +170,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *C) {
|
|||||||
response, err = client.Do(request)
|
response, err = client.Do(request)
|
||||||
|
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters. Unsupported characters are `^*|\\\"", http.StatusBadRequest)
|
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *C) {
|
func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *C) {
|
||||||
@@ -1226,7 +1226,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *C) {
|
|||||||
|
|
||||||
response, err = client.Do(request)
|
response, err = client.Do(request)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters. Unsupported characters are `^*|\\\"", http.StatusBadRequest)
|
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestNotBeAbleToCreateObjectInNonexistentBucket - Validates the error response
|
// TestNotBeAbleToCreateObjectInNonexistentBucket - Validates the error response
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ var errFileNotFound = errors.New("file not found")
|
|||||||
// errFileNameTooLong - given file name is too long than supported length.
|
// errFileNameTooLong - given file name is too long than supported length.
|
||||||
var errFileNameTooLong = errors.New("file name too long")
|
var errFileNameTooLong = errors.New("file name too long")
|
||||||
|
|
||||||
|
// errFileComponentInvalid - given file name has invalid components.
|
||||||
|
var errFileComponentInvalid = errors.New("file name has invalid components")
|
||||||
|
|
||||||
// errVolumeExists - cannot create same volume again.
|
// errVolumeExists - cannot create same volume again.
|
||||||
var errVolumeExists = errors.New("volume already exists")
|
var errVolumeExists = errors.New("volume already exists")
|
||||||
|
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ func StartTestServer(t TestErrHandler, instanceType string) TestServer {
|
|||||||
// The object Layer will be a temp back used for testing purpose.
|
// The object Layer will be a temp back used for testing purpose.
|
||||||
func initTestStorageRPCEndPoint(srvCmdConfig serverCmdConfig) http.Handler {
|
func initTestStorageRPCEndPoint(srvCmdConfig serverCmdConfig) http.Handler {
|
||||||
// Initialize router.
|
// Initialize router.
|
||||||
muxRouter := router.NewRouter()
|
muxRouter := router.NewRouter().SkipClean(true)
|
||||||
registerStorageRPCRouters(muxRouter, srvCmdConfig)
|
registerStorageRPCRouters(muxRouter, srvCmdConfig)
|
||||||
return muxRouter
|
return muxRouter
|
||||||
}
|
}
|
||||||
@@ -421,7 +421,8 @@ func StartTestPeersRPCServer(t TestErrHandler, instanceType string) TestServer {
|
|||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := router.NewRouter()
|
mux := router.NewRouter().SkipClean(true)
|
||||||
|
|
||||||
// need storage layer for bucket config storage.
|
// need storage layer for bucket config storage.
|
||||||
registerStorageRPCRouters(mux, srvCfg)
|
registerStorageRPCRouters(mux, srvCfg)
|
||||||
// need API layer to send requests, etc.
|
// need API layer to send requests, etc.
|
||||||
@@ -2182,7 +2183,7 @@ func registerAPIFunctions(muxRouter *router.Router, objLayer ObjectLayer, apiFun
|
|||||||
func initTestAPIEndPoints(objLayer ObjectLayer, apiFunctions []string) http.Handler {
|
func initTestAPIEndPoints(objLayer ObjectLayer, apiFunctions []string) http.Handler {
|
||||||
// initialize a new mux router.
|
// initialize a new mux router.
|
||||||
// goriilla/mux is the library used to register all the routes and handle them.
|
// goriilla/mux is the library used to register all the routes and handle them.
|
||||||
muxRouter := router.NewRouter()
|
muxRouter := router.NewRouter().SkipClean(true)
|
||||||
if len(apiFunctions) > 0 {
|
if len(apiFunctions) > 0 {
|
||||||
// Iterate the list of API functions requested for and register them in mux HTTP handler.
|
// Iterate the list of API functions requested for and register them in mux HTTP handler.
|
||||||
registerAPIFunctions(muxRouter, objLayer, apiFunctions...)
|
registerAPIFunctions(muxRouter, objLayer, apiFunctions...)
|
||||||
@@ -2199,7 +2200,7 @@ func initTestWebRPCEndPoint(objLayer ObjectLayer) http.Handler {
|
|||||||
globalObjLayerMutex.Unlock()
|
globalObjLayerMutex.Unlock()
|
||||||
|
|
||||||
// Initialize router.
|
// Initialize router.
|
||||||
muxRouter := router.NewRouter()
|
muxRouter := router.NewRouter().SkipClean(true)
|
||||||
registerWebRouter(muxRouter)
|
registerWebRouter(muxRouter)
|
||||||
return muxRouter
|
return muxRouter
|
||||||
}
|
}
|
||||||
@@ -2207,7 +2208,7 @@ func initTestWebRPCEndPoint(objLayer ObjectLayer) http.Handler {
|
|||||||
// Initialize browser RPC endpoint.
|
// Initialize browser RPC endpoint.
|
||||||
func initTestBrowserPeerRPCEndPoint() http.Handler {
|
func initTestBrowserPeerRPCEndPoint() http.Handler {
|
||||||
// Initialize router.
|
// Initialize router.
|
||||||
muxRouter := router.NewRouter()
|
muxRouter := router.NewRouter().SkipClean(true)
|
||||||
registerBrowserPeerRPCRouter(muxRouter)
|
registerBrowserPeerRPCRouter(muxRouter)
|
||||||
return muxRouter
|
return muxRouter
|
||||||
}
|
}
|
||||||
@@ -2261,7 +2262,7 @@ func StartTestS3PeerRPCServer(t TestErrHandler) (TestServer, []string) {
|
|||||||
globalObjLayerMutex.Unlock()
|
globalObjLayerMutex.Unlock()
|
||||||
|
|
||||||
// Register router on a new mux
|
// Register router on a new mux
|
||||||
muxRouter := router.NewRouter()
|
muxRouter := router.NewRouter().SkipClean(true)
|
||||||
err = registerS3PeerRPCRouter(muxRouter)
|
err = registerS3PeerRPCRouter(muxRouter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
%define tag RELEASE.2017-02-16T01-47-30Z
|
%define tag RELEASE.2017-04-29T00-40-27Z
|
||||||
%define subver %(echo %{tag} | sed -e 's/[^0-9]//g')
|
%define subver %(echo %{tag} | sed -e 's/[^0-9]//g')
|
||||||
# git fetch https://github.com/minio/minio.git refs/tags/RELEASE.2017-02-16T01-47-30Z
|
# git fetch https://github.com/minio/minio.git refs/tags/RELEASE.2017-04-25T01-27-49Z
|
||||||
# git rev-list -n 1 FETCH_HEAD
|
# git rev-list -n 1 FETCH_HEAD
|
||||||
%define commitid 3d98311d9f4ceb78dba996dcdc0751253241e697
|
%define commitid 0e6a222c4e0647880ed6a9f1900eb8ce69a5b33b
|
||||||
Summary: Cloud Storage Server.
|
Summary: Cloud Storage Server.
|
||||||
Name: minio
|
Name: minio
|
||||||
Version: 0.0.%{subver}
|
Version: 0.0.%{subver}
|
||||||
@@ -19,7 +19,7 @@ BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
|
|||||||
%define debug_package %{nil}
|
%define debug_package %{nil}
|
||||||
|
|
||||||
## Go related tags.
|
## Go related tags.
|
||||||
%define gobuild(o:) go build -ldflags "${LDFLAGS:-}" %{?**};
|
%define gobuild(o:) go build -ldflags "-s -w ${LDFLAGS:-}" %{?**};
|
||||||
%define gopath %{_libdir}/golang
|
%define gopath %{_libdir}/golang
|
||||||
%define import_path github.com/minio/minio
|
%define import_path github.com/minio/minio
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user