Update dependencies

Among others, this updates minio-go, so that the new "eu-west-3" zone
for AWS is supported.
This commit is contained in:
Alexander Neumann
2018-01-23 19:40:42 +01:00
parent b63de7c798
commit 2b39f9f4b2
3435 changed files with 1317989 additions and 315639 deletions
+16 -16
View File
@@ -17,8 +17,6 @@
package credentials
import "fmt"
// A Chain will search for a provider which returns credentials
// and cache that provider until Retrieve is called again.
//
@@ -27,11 +25,11 @@ import "fmt"
// Providers in the list.
//
// If none of the Providers retrieve valid credentials Value, ChainProvider's
// Retrieve() will return the error, collecting all errors from all providers.
// Retrieve() will return the no credentials value.
//
// If a Provider is found which returns valid credentials Value ChainProvider
// will cache that Provider for all calls to IsExpired(), until Retrieve is
// called again.
// called again after IsExpired() is true.
//
// creds := credentials.NewChainCredentials(
// []credentials.Provider{
@@ -58,28 +56,30 @@ func NewChainCredentials(providers []Provider) *Credentials {
})
}
// Retrieve returns the credentials value or error if no provider returned
// without error.
// Retrieve returns the credentials value, returns no credentials(anonymous)
// if no credentials provider returned any value.
//
// If a provider is found it will be cached and any calls to IsExpired()
// will return the expired state of the cached provider.
// If a provider is found with credentials, it will be cached and any calls
// to IsExpired() will return the expired state of the cached provider.
func (c *Chain) Retrieve() (Value, error) {
var errs []error
for _, p := range c.Providers {
creds, err := p.Retrieve()
if err != nil {
errs = append(errs, err)
creds, _ := p.Retrieve()
// Always prioritize non-anonymous providers, if any.
if creds.AccessKeyID == "" && creds.SecretAccessKey == "" {
continue
} // Success.
}
c.curr = p
return creds, nil
}
c.curr = nil
return Value{}, fmt.Errorf("No valid providers found %v", errs)
// At this point we have exhausted all the providers and
// are left without any credentials return anonymous.
return Value{
SignerType: SignatureAnonymous,
}, nil
}
// IsExpired will returned the expired state of the currently cached provider
// if there is one. If there is no current provider, true will be returned.
// if there is one. If there is no current provider, true will be returned.
func (c *Chain) IsExpired() bool {
if c.curr != nil {
return c.curr.IsExpired()
+8 -1
View File
@@ -76,7 +76,14 @@ func TestChainGet(t *testing.T) {
}
func TestChainIsExpired(t *testing.T) {
credProvider := &credProvider{expired: true}
credProvider := &credProvider{
creds: Value{
AccessKeyID: "UXHW",
SecretAccessKey: "MYSECRET",
SessionToken: "",
},
expired: true,
}
p := &Chain{
Providers: []Provider{
credProvider,
+1 -1
View File
@@ -22,7 +22,7 @@ import (
"path/filepath"
"github.com/go-ini/ini"
homedir "github.com/minio/go-homedir"
homedir "github.com/mitchellh/go-homedir"
)
// A FileAWSCredentials retrieves credentials from the current user's home
+1 -1
View File
@@ -24,7 +24,7 @@ import (
"path/filepath"
"runtime"
homedir "github.com/minio/go-homedir"
homedir "github.com/mitchellh/go-homedir"
)
// A FileMinioClient retrieves credentials from the current user's home
@@ -33,7 +33,7 @@ func TestGetSeedSignature(t *testing.T) {
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", body)
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
req.URL.Host = "s3.amazonaws.com"
req.Host = "s3.amazonaws.com"
reqTime, err := time.Parse("20060102T150405Z", "20130524T000000Z")
if err != nil {
@@ -69,6 +69,7 @@ func TestSetStreamingAuthorization(t *testing.T) {
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", nil)
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
req.Host = ""
req.URL.Host = "s3.amazonaws.com"
dataLen := int64(65 * 1024)
@@ -93,6 +94,7 @@ func TestStreamingReader(t *testing.T) {
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", nil)
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
req.ContentLength = 65 * 1024
req.Host = ""
req.URL.Host = "s3.amazonaws.com"
baseReader := ioutil.NopCloser(bytes.NewReader(bytes.Repeat([]byte("a"), 65*1024)))
+11 -10
View File
@@ -40,22 +40,23 @@ const (
)
// Encode input URL path to URL encoded path.
func encodeURL2Path(u *url.URL) (path string) {
func encodeURL2Path(req *http.Request) (path string) {
reqHost := getHostAddr(req)
// Encode URL path.
if isS3, _ := filepath.Match("*.s3*.amazonaws.com", u.Host); isS3 {
bucketName := u.Host[:strings.LastIndex(u.Host, ".s3")]
if isS3, _ := filepath.Match("*.s3*.amazonaws.com", reqHost); isS3 {
bucketName := reqHost[:strings.LastIndex(reqHost, ".s3")]
path = "/" + bucketName
path += u.Path
path += req.URL.Path
path = s3utils.EncodePath(path)
return
}
if strings.HasSuffix(u.Host, ".storage.googleapis.com") {
path = "/" + strings.TrimSuffix(u.Host, ".storage.googleapis.com")
path += u.Path
if strings.HasSuffix(reqHost, ".storage.googleapis.com") {
path = "/" + strings.TrimSuffix(reqHost, ".storage.googleapis.com")
path += req.URL.Path
path = s3utils.EncodePath(path)
return
}
path = s3utils.EncodePath(u.Path)
path = s3utils.EncodePath(req.URL.Path)
return
}
@@ -86,7 +87,7 @@ func PreSignV2(req http.Request, accessKeyID, secretAccessKey string, expires in
query := req.URL.Query()
// Handle specially for Google Cloud Storage.
if strings.Contains(req.URL.Host, ".storage.googleapis.com") {
if strings.Contains(getHostAddr(&req), ".storage.googleapis.com") {
query.Set("GoogleAccessId", accessKeyID)
} else {
query.Set("AWSAccessKeyId", accessKeyID)
@@ -291,7 +292,7 @@ func writeCanonicalizedResource(buf *bytes.Buffer, req http.Request) {
// Save request URL.
requestURL := req.URL
// Get encoded URL path.
buf.WriteString(encodeURL2Path(requestURL))
buf.WriteString(encodeURL2Path(&req))
if requestURL.RawQuery != "" {
var n int
vals, _ := url.ParseQuery(requestURL.RawQuery)
+1 -1
View File
@@ -144,7 +144,7 @@ func getCanonicalHeaders(req http.Request, ignoredHeaders map[string]bool) strin
buf.WriteByte(':')
switch {
case k == "host":
buf.WriteString(req.URL.Host)
buf.WriteString(getHostAddr(&req))
fallthrough
default:
for idx, v := range vals[k] {
@@ -0,0 +1,50 @@
/*
* Minio Go Library for Amazon S3 Compatible Cloud Storage
* Copyright 2015-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 s3signer
import (
"io"
"net/http"
"strings"
"testing"
)
func TestRequestHost(t *testing.T) {
req, _ := buildRequest("dynamodb", "us-east-1", "{}")
req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a"
req.Host = "myhost"
canonicalHeaders := getCanonicalHeaders(*req, v4IgnoredHeaders)
if !strings.Contains(canonicalHeaders, "host:"+req.Host) {
t.Errorf("canonical host header invalid")
}
}
func buildRequest(serviceName, region, body string) (*http.Request, io.ReadSeeker) {
endpoint := "https://" + serviceName + "." + region + ".amazonaws.com"
reader := strings.NewReader(body)
req, _ := http.NewRequest("POST", endpoint, reader)
req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()"
req.Header.Add("X-Amz-Target", "prefix.Operation")
req.Header.Add("Content-Type", "application/x-amz-json-1.0")
req.Header.Add("Content-Length", string(len(body)))
req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)")
req.Header.Add("X-Amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
req.Header.Add("X-amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
return req, reader
}
+9
View File
@@ -20,6 +20,7 @@ package s3signer
import (
"crypto/hmac"
"crypto/sha256"
"net/http"
)
// unsignedPayload - value to be set to X-Amz-Content-Sha256 header when
@@ -38,3 +39,11 @@ func sumHMAC(key []byte, data []byte) []byte {
hash.Write(data)
return hash.Sum(nil)
}
// getHostAddr returns host header if available, otherwise returns host from URL
func getHostAddr(req *http.Request) string {
if req.Host != "" {
return req.Host
}
return req.URL.Host
}
+2 -1
View File
@@ -19,6 +19,7 @@ package s3signer
import (
"fmt"
"net/http"
"net/url"
"testing"
)
@@ -66,7 +67,7 @@ func TestEncodeURL2Path(t *testing.T) {
t.Fatal("Error:", err)
}
urlPath := "/" + bucketName + "/" + o.encodedObjName
if urlPath != encodeURL2Path(u) {
if urlPath != encodeURL2Path(&http.Request{URL: u}) {
t.Fatal("Error")
}
}
+45 -20
View File
@@ -81,18 +81,56 @@ func IsVirtualHostSupported(endpointURL url.URL, bucketName string) bool {
return IsAmazonEndpoint(endpointURL) || IsGoogleEndpoint(endpointURL)
}
// AmazonS3Host - regular expression used to determine if an arg is s3 host.
var AmazonS3Host = regexp.MustCompile("^s3[.-]?(.*?)\\.amazonaws\\.com$")
// Refer for region styles - https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
// amazonS3HostHyphen - regular expression used to determine if an arg is s3 host in hyphenated style.
var amazonS3HostHyphen = regexp.MustCompile(`^s3-(.*?)\.amazonaws\.com$`)
// amazonS3HostDualStack - regular expression used to determine if an arg is s3 host dualstack.
var amazonS3HostDualStack = regexp.MustCompile(`^s3\.dualstack\.(.*?)\.amazonaws\.com$`)
// amazonS3HostDot - regular expression used to determine if an arg is s3 host in . style.
var amazonS3HostDot = regexp.MustCompile(`^s3\.(.*?)\.amazonaws\.com$`)
// amazonS3ChinaHost - regular expression used to determine if the arg is s3 china host.
var amazonS3ChinaHost = regexp.MustCompile(`^s3\.(cn.*?)\.amazonaws\.com\.cn$`)
// GetRegionFromURL - returns a region from url host.
func GetRegionFromURL(endpointURL url.URL) string {
if endpointURL == sentinelURL {
return ""
}
if endpointURL.Host == "s3-external-1.amazonaws.com" {
return ""
}
if IsAmazonGovCloudEndpoint(endpointURL) {
return "us-gov-west-1"
}
parts := amazonS3HostDualStack.FindStringSubmatch(endpointURL.Host)
if len(parts) > 1 {
return parts[1]
}
parts = amazonS3HostHyphen.FindStringSubmatch(endpointURL.Host)
if len(parts) > 1 {
return parts[1]
}
parts = amazonS3ChinaHost.FindStringSubmatch(endpointURL.Host)
if len(parts) > 1 {
return parts[1]
}
parts = amazonS3HostDot.FindStringSubmatch(endpointURL.Host)
if len(parts) > 1 {
return parts[1]
}
return ""
}
// IsAmazonEndpoint - Match if it is exactly Amazon S3 endpoint.
func IsAmazonEndpoint(endpointURL url.URL) bool {
if IsAmazonChinaEndpoint(endpointURL) {
if endpointURL.Host == "s3-external-1.amazonaws.com" || endpointURL.Host == "s3.amazonaws.com" {
return true
}
if IsAmazonGovCloudEndpoint(endpointURL) {
return true
}
return AmazonS3Host.MatchString(endpointURL.Host)
return GetRegionFromURL(endpointURL) != ""
}
// IsAmazonGovCloudEndpoint - Match if it is exactly Amazon S3 GovCloud endpoint.
@@ -112,19 +150,6 @@ func IsAmazonFIPSGovCloudEndpoint(endpointURL url.URL) bool {
return endpointURL.Host == "s3-fips-us-gov-west-1.amazonaws.com"
}
// IsAmazonChinaEndpoint - Match if it is exactly Amazon S3 China endpoint.
// Customers who wish to use the new Beijing Region are required
// to sign up for a separate set of account credentials unique to
// the China (Beijing) Region. Customers with existing AWS credentials
// will not be able to access resources in the new Region, and vice versa.
// For more info https://aws.amazon.com/about-aws/whats-new/2013/12/18/announcing-the-aws-china-beijing-region/
func IsAmazonChinaEndpoint(endpointURL url.URL) bool {
if endpointURL == sentinelURL {
return false
}
return endpointURL.Host == "s3.cn-north-1.amazonaws.com.cn"
}
// IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint.
func IsGoogleEndpoint(endpointURL url.URL) bool {
if endpointURL == sentinelURL {
+69 -35
View File
@@ -23,6 +23,66 @@ import (
"testing"
)
// Tests get region from host URL.
func TestGetRegionFromURL(t *testing.T) {
testCases := []struct {
u url.URL
expectedRegion string
}{
{
u: url.URL{Host: "storage.googleapis.com"},
expectedRegion: "",
},
{
u: url.URL{Host: "s3.cn-north-1.amazonaws.com.cn"},
expectedRegion: "cn-north-1",
},
{
u: url.URL{Host: "s3.cn-northwest-1.amazonaws.com.cn"},
expectedRegion: "cn-northwest-1",
},
{
u: url.URL{Host: "s3-fips-us-gov-west-1.amazonaws.com"},
expectedRegion: "us-gov-west-1",
},
{
u: url.URL{Host: "s3-us-gov-west-1.amazonaws.com"},
expectedRegion: "us-gov-west-1",
},
{
u: url.URL{Host: "192.168.1.1"},
expectedRegion: "",
},
{
u: url.URL{Host: "s3-eu-west-1.amazonaws.com"},
expectedRegion: "eu-west-1",
},
{
u: url.URL{Host: "s3.eu-west-1.amazonaws.com"},
expectedRegion: "eu-west-1",
},
{
u: url.URL{Host: "s3.dualstack.eu-west-1.amazonaws.com"},
expectedRegion: "eu-west-1",
},
{
u: url.URL{Host: "s3.amazonaws.com"},
expectedRegion: "",
},
{
u: url.URL{Host: "s3-external-1.amazonaws.com"},
expectedRegion: "",
},
}
for i, testCase := range testCases {
region := GetRegionFromURL(testCase.u)
if testCase.expectedRegion != region {
t.Errorf("Test %d: Expected region %s, got %s", i+1, testCase.expectedRegion, region)
}
}
}
// Tests for 'isValidDomain(host string) bool'.
func TestIsValidDomain(t *testing.T) {
testCases := []struct {
@@ -33,6 +93,7 @@ func TestIsValidDomain(t *testing.T) {
}{
{"s3.amazonaws.com", true},
{"s3.cn-north-1.amazonaws.com.cn", true},
{"s3.cn-northwest-1.amazonaws.com.cn", true},
{"s3.amazonaws.com_", false},
{"%$$$", false},
{"s3.amz.test.com", true},
@@ -120,9 +181,17 @@ func TestIsAmazonEndpoint(t *testing.T) {
{"https://amazons3.amazonaws.com", false},
{"-192.168.1.1", false},
{"260.192.1.1", false},
{"https://s3-.amazonaws.com", false},
{"https://s3..amazonaws.com", false},
{"https://s3.dualstack.us-west-1.amazonaws.com.cn", false},
{"https://s3..us-west-1.amazonaws.com.cn", false},
// valid inputs.
{"https://s3.amazonaws.com", true},
{"https://s3-external-1.amazonaws.com", true},
{"https://s3.cn-north-1.amazonaws.com.cn", true},
{"https://s3-us-west-1.amazonaws.com", true},
{"https://s3.us-west-1.amazonaws.com", true},
{"https://s3.dualstack.us-west-1.amazonaws.com", true},
}
for i, testCase := range testCases {
@@ -138,41 +207,6 @@ func TestIsAmazonEndpoint(t *testing.T) {
}
// Tests validate Amazon S3 China endpoint validator.
func TestIsAmazonChinaEndpoint(t *testing.T) {
testCases := []struct {
url string
// Expected result.
result bool
}{
{"https://192.168.1.1", false},
{"192.168.1.1", false},
{"http://storage.googleapis.com", false},
{"https://storage.googleapis.com", false},
{"storage.googleapis.com", false},
{"s3.amazonaws.com", false},
{"https://amazons3.amazonaws.com", false},
{"-192.168.1.1", false},
{"260.192.1.1", false},
// s3.amazonaws.com is not a valid Amazon S3 China end point.
{"https://s3.amazonaws.com", false},
// valid input.
{"https://s3.cn-north-1.amazonaws.com.cn", true},
}
for i, testCase := range testCases {
u, err := url.Parse(testCase.url)
if err != nil {
t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err)
}
result := IsAmazonChinaEndpoint(*u)
if testCase.result != result {
t.Errorf("Test %d: Expected isAmazonEndpoint to be '%v' for input \"%s\", but found it to be '%v' instead", i+1, testCase.result, testCase.url, result)
}
}
}
// Tests validate Google Cloud end point validator.
func TestIsGoogleEndpoint(t *testing.T) {
testCases := []struct {