summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/pkg/credentials
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/minio-go/pkg/credentials')
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/chain.go89
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go137
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/config.json.sample17
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/credentials.go175
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/credentials.sample12
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/credentials_test.go73
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/doc.go45
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/env_aws.go71
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/env_minio.go62
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/env_test.go105
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go120
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go129
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/file_test.go189
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/iam_aws.go196
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/iam_aws_test.go180
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/signature-type.go76
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/static.go67
-rw-r--r--vendor/github.com/minio/minio-go/pkg/credentials/static_test.go68
18 files changed, 1811 insertions, 0 deletions
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/chain.go b/vendor/github.com/minio/minio-go/pkg/credentials/chain.go
new file mode 100644
index 000000000..6b0e57440
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/chain.go
@@ -0,0 +1,89 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import "fmt"
+
+// A Chain will search for a provider which returns credentials
+// and cache that provider until Retrieve is called again.
+//
+// The Chain provides a way of chaining multiple providers together
+// which will pick the first available using priority order of the
+// 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.
+//
+// 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.
+//
+// creds := credentials.NewChainCredentials(
+// []credentials.Provider{
+// &credentials.EnvAWSS3{},
+// &credentials.EnvMinio{},
+// })
+//
+// // Usage of ChainCredentials.
+// mc, err := minio.NewWithCredentials(endpoint, creds, secure, "us-east-1")
+// if err != nil {
+// log.Fatalln(err)
+// }
+//
+type Chain struct {
+ Providers []Provider
+ curr Provider
+}
+
+// NewChainCredentials returns a pointer to a new Credentials object
+// wrapping a chain of providers.
+func NewChainCredentials(providers []Provider) *Credentials {
+ return New(&Chain{
+ Providers: append([]Provider{}, providers...),
+ })
+}
+
+// Retrieve returns the credentials value or error if no provider returned
+// without error.
+//
+// If a provider is found 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)
+ continue
+ } // Success.
+ c.curr = p
+ return creds, nil
+ }
+ c.curr = nil
+ return Value{}, fmt.Errorf("No valid providers found %v", errs)
+}
+
+// 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.
+func (c *Chain) IsExpired() bool {
+ if c.curr != nil {
+ return c.curr.IsExpired()
+ }
+
+ return true
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go
new file mode 100644
index 000000000..cb5a6dda5
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go
@@ -0,0 +1,137 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "errors"
+ "testing"
+)
+
+type testCredProvider struct {
+ creds Value
+ expired bool
+ err error
+}
+
+func (s *testCredProvider) Retrieve() (Value, error) {
+ s.expired = false
+ return s.creds, s.err
+}
+func (s *testCredProvider) IsExpired() bool {
+ return s.expired
+}
+
+func TestChainGet(t *testing.T) {
+ p := &Chain{
+ Providers: []Provider{
+ &credProvider{err: errors.New("FirstError")},
+ &credProvider{err: errors.New("SecondError")},
+ &testCredProvider{
+ creds: Value{
+ AccessKeyID: "AKIF",
+ SecretAccessKey: "NOSECRET",
+ SessionToken: "",
+ },
+ },
+ &credProvider{
+ creds: Value{
+ AccessKeyID: "AKID",
+ SecretAccessKey: "SECRET",
+ SessionToken: "",
+ },
+ },
+ },
+ }
+
+ creds, err := p.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Also check credentials
+ if creds.AccessKeyID != "AKIF" {
+ t.Fatalf("Expected 'AKIF', got %s", creds.AccessKeyID)
+ }
+ if creds.SecretAccessKey != "NOSECRET" {
+ t.Fatalf("Expected 'NOSECRET', got %s", creds.SecretAccessKey)
+ }
+ if creds.SessionToken != "" {
+ t.Fatalf("Expected empty token, got %s", creds.SessionToken)
+ }
+}
+
+func TestChainIsExpired(t *testing.T) {
+ credProvider := &credProvider{expired: true}
+ p := &Chain{
+ Providers: []Provider{
+ credProvider,
+ },
+ }
+
+ if !p.IsExpired() {
+ t.Fatal("Expected expired to be true before any Retrieve")
+ }
+
+ _, err := p.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if p.IsExpired() {
+ t.Fatal("Expected to be not expired after Retrieve")
+ }
+}
+
+func TestChainWithNoProvider(t *testing.T) {
+ p := &Chain{
+ Providers: []Provider{},
+ }
+ if !p.IsExpired() {
+ t.Fatal("Expected to be expired with no providers")
+ }
+ _, err := p.Retrieve()
+ if err != nil {
+ if err.Error() != "No valid providers found []" {
+ t.Error(err)
+ }
+ }
+}
+
+func TestChainProviderWithNoValidProvider(t *testing.T) {
+ errs := []error{
+ errors.New("FirstError"),
+ errors.New("SecondError"),
+ }
+ p := &Chain{
+ Providers: []Provider{
+ &credProvider{err: errs[0]},
+ &credProvider{err: errs[1]},
+ },
+ }
+
+ if !p.IsExpired() {
+ t.Fatal("Expected to be expired with no providers")
+ }
+
+ _, err := p.Retrieve()
+ if err != nil {
+ if err.Error() != "No valid providers found [FirstError SecondError]" {
+ t.Error(err)
+ }
+ }
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/config.json.sample b/vendor/github.com/minio/minio-go/pkg/credentials/config.json.sample
new file mode 100644
index 000000000..130746f4b
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/config.json.sample
@@ -0,0 +1,17 @@
+{
+ "version": "8",
+ "hosts": {
+ "play": {
+ "url": "https://play.minio.io:9000",
+ "accessKey": "Q3AM3UQ867SPQQA43P2F",
+ "secretKey": "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
+ "api": "S3v2"
+ },
+ "s3": {
+ "url": "https://s3.amazonaws.com",
+ "accessKey": "accessKey",
+ "secretKey": "secret",
+ "api": "S3v4"
+ }
+ }
+} \ No newline at end of file
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/credentials.go b/vendor/github.com/minio/minio-go/pkg/credentials/credentials.go
new file mode 100644
index 000000000..cc3000532
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/credentials.go
@@ -0,0 +1,175 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "sync"
+ "time"
+)
+
+// A Value is the AWS credentials value for individual credential fields.
+type Value struct {
+ // AWS Access key ID
+ AccessKeyID string
+
+ // AWS Secret Access Key
+ SecretAccessKey string
+
+ // AWS Session Token
+ SessionToken string
+
+ // Signature Type.
+ SignerType SignatureType
+}
+
+// A Provider is the interface for any component which will provide credentials
+// Value. A provider is required to manage its own Expired state, and what to
+// be expired means.
+type Provider interface {
+ // Retrieve returns nil if it successfully retrieved the value.
+ // Error is returned if the value were not obtainable, or empty.
+ Retrieve() (Value, error)
+
+ // IsExpired returns if the credentials are no longer valid, and need
+ // to be retrieved.
+ IsExpired() bool
+}
+
+// A Expiry provides shared expiration logic to be used by credentials
+// providers to implement expiry functionality.
+//
+// The best method to use this struct is as an anonymous field within the
+// provider's struct.
+//
+// Example:
+// type IAMCredentialProvider struct {
+// Expiry
+// ...
+// }
+type Expiry struct {
+ // The date/time when to expire on
+ expiration time.Time
+
+ // If set will be used by IsExpired to determine the current time.
+ // Defaults to time.Now if CurrentTime is not set.
+ CurrentTime func() time.Time
+}
+
+// SetExpiration sets the expiration IsExpired will check when called.
+//
+// If window is greater than 0 the expiration time will be reduced by the
+// window value.
+//
+// Using a window is helpful to trigger credentials to expire sooner than
+// the expiration time given to ensure no requests are made with expired
+// tokens.
+func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
+ e.expiration = expiration
+ if window > 0 {
+ e.expiration = e.expiration.Add(-window)
+ }
+}
+
+// IsExpired returns if the credentials are expired.
+func (e *Expiry) IsExpired() bool {
+ if e.CurrentTime == nil {
+ e.CurrentTime = time.Now
+ }
+ return e.expiration.Before(e.CurrentTime())
+}
+
+// Credentials - A container for synchronous safe retrieval of credentials Value.
+// Credentials will cache the credentials value until they expire. Once the value
+// expires the next Get will attempt to retrieve valid credentials.
+//
+// Credentials is safe to use across multiple goroutines and will manage the
+// synchronous state so the Providers do not need to implement their own
+// synchronization.
+//
+// The first Credentials.Get() will always call Provider.Retrieve() to get the
+// first instance of the credentials Value. All calls to Get() after that
+// will return the cached credentials Value until IsExpired() returns true.
+type Credentials struct {
+ sync.Mutex
+
+ creds Value
+ forceRefresh bool
+ provider Provider
+}
+
+// New returns a pointer to a new Credentials with the provider set.
+func New(provider Provider) *Credentials {
+ return &Credentials{
+ provider: provider,
+ forceRefresh: true,
+ }
+}
+
+// Get returns the credentials value, or error if the credentials Value failed
+// to be retrieved.
+//
+// Will return the cached credentials Value if it has not expired. If the
+// credentials Value has expired the Provider's Retrieve() will be called
+// to refresh the credentials.
+//
+// If Credentials.Expire() was called the credentials Value will be force
+// expired, and the next call to Get() will cause them to be refreshed.
+func (c *Credentials) Get() (Value, error) {
+ c.Lock()
+ defer c.Unlock()
+
+ if c.isExpired() {
+ creds, err := c.provider.Retrieve()
+ if err != nil {
+ return Value{}, err
+ }
+ c.creds = creds
+ c.forceRefresh = false
+ }
+
+ return c.creds, nil
+}
+
+// Expire expires the credentials and forces them to be retrieved on the
+// next call to Get().
+//
+// This will override the Provider's expired state, and force Credentials
+// to call the Provider's Retrieve().
+func (c *Credentials) Expire() {
+ c.Lock()
+ defer c.Unlock()
+
+ c.forceRefresh = true
+}
+
+// IsExpired returns if the credentials are no longer valid, and need
+// to be refreshed.
+//
+// If the Credentials were forced to be expired with Expire() this will
+// reflect that override.
+func (c *Credentials) IsExpired() bool {
+ c.Lock()
+ defer c.Unlock()
+
+ return c.isExpired()
+}
+
+// isExpired helper method wrapping the definition of expired credentials.
+func (c *Credentials) isExpired() bool {
+ return c.forceRefresh || c.provider.IsExpired()
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/credentials.sample b/vendor/github.com/minio/minio-go/pkg/credentials/credentials.sample
new file mode 100644
index 000000000..7fc91d9d2
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/credentials.sample
@@ -0,0 +1,12 @@
+[default]
+aws_access_key_id = accessKey
+aws_secret_access_key = secret
+aws_session_token = token
+
+[no_token]
+aws_access_key_id = accessKey
+aws_secret_access_key = secret
+
+[with_colon]
+aws_access_key_id: accessKey
+aws_secret_access_key: secret
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/credentials_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/credentials_test.go
new file mode 100644
index 000000000..cbfb673b7
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/credentials_test.go
@@ -0,0 +1,73 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "errors"
+ "testing"
+)
+
+type credProvider struct {
+ creds Value
+ expired bool
+ err error
+}
+
+func (s *credProvider) Retrieve() (Value, error) {
+ s.expired = false
+ return s.creds, s.err
+}
+func (s *credProvider) IsExpired() bool {
+ return s.expired
+}
+
+func TestCredentialsGet(t *testing.T) {
+ c := New(&credProvider{
+ creds: Value{
+ AccessKeyID: "UXHW",
+ SecretAccessKey: "MYSECRET",
+ SessionToken: "",
+ },
+ expired: true,
+ })
+
+ creds, err := c.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if "UXHW" != creds.AccessKeyID {
+ t.Errorf("Expected \"UXHW\", got %s", creds.AccessKeyID)
+ }
+ if "MYSECRET" != creds.SecretAccessKey {
+ t.Errorf("Expected \"MYSECRET\", got %s", creds.SecretAccessKey)
+ }
+ if creds.SessionToken != "" {
+ t.Errorf("Expected session token to be empty, got %s", creds.SessionToken)
+ }
+}
+
+func TestCredentialsGetWithError(t *testing.T) {
+ c := New(&credProvider{err: errors.New("Custom error")})
+
+ _, err := c.Get()
+ if err != nil {
+ if err.Error() != "Custom error" {
+ t.Errorf("Expected \"Custom error\", got %s", err.Error())
+ }
+ }
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/doc.go b/vendor/github.com/minio/minio-go/pkg/credentials/doc.go
new file mode 100644
index 000000000..fa1908aeb
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/doc.go
@@ -0,0 +1,45 @@
+// Package credentials provides credential retrieval and management
+// for S3 compatible object storage.
+//
+// By default the Credentials.Get() will cache the successful result of a
+// Provider's Retrieve() until Provider.IsExpired() returns true. At which
+// point Credentials will call Provider's Retrieve() to get new credential Value.
+//
+// The Provider is responsible for determining when credentials have expired.
+// It is also important to note that Credentials will always call Retrieve the
+// first time Credentials.Get() is called.
+//
+// Example of using the environment variable credentials.
+//
+// creds := NewFromEnv()
+// // Retrieve the credentials value
+// credValue, err := creds.Get()
+// if err != nil {
+// // handle error
+// }
+//
+// Example of forcing credentials to expire and be refreshed on the next Get().
+// This may be helpful to proactively expire credentials and refresh them sooner
+// than they would naturally expire on their own.
+//
+// creds := NewFromIAM("")
+// creds.Expire()
+// credsValue, err := creds.Get()
+// // New credentials will be retrieved instead of from cache.
+//
+//
+// Custom Provider
+//
+// Each Provider built into this package also provides a helper method to generate
+// a Credentials pointer setup with the provider. To use a custom Provider just
+// create a type which satisfies the Provider interface and pass it to the
+// NewCredentials method.
+//
+// type MyProvider struct{}
+// func (m *MyProvider) Retrieve() (Value, error) {...}
+// func (m *MyProvider) IsExpired() bool {...}
+//
+// creds := NewCredentials(&MyProvider{})
+// credValue, err := creds.Get()
+//
+package credentials
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/env_aws.go b/vendor/github.com/minio/minio-go/pkg/credentials/env_aws.go
new file mode 100644
index 000000000..11934433c
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/env_aws.go
@@ -0,0 +1,71 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import "os"
+
+// A EnvAWS retrieves credentials from the environment variables of the
+// running process. EnvAWSironment credentials never expire.
+//
+// EnvAWSironment variables used:
+//
+// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY.
+// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY.
+// * Secret Token: AWS_SESSION_TOKEN.
+type EnvAWS struct {
+ retrieved bool
+}
+
+// NewEnvAWS returns a pointer to a new Credentials object
+// wrapping the environment variable provider.
+func NewEnvAWS() *Credentials {
+ return New(&EnvAWS{})
+}
+
+// Retrieve retrieves the keys from the environment.
+func (e *EnvAWS) Retrieve() (Value, error) {
+ e.retrieved = false
+
+ id := os.Getenv("AWS_ACCESS_KEY_ID")
+ if id == "" {
+ id = os.Getenv("AWS_ACCESS_KEY")
+ }
+
+ secret := os.Getenv("AWS_SECRET_ACCESS_KEY")
+ if secret == "" {
+ secret = os.Getenv("AWS_SECRET_KEY")
+ }
+
+ signerType := SignatureV4
+ if id == "" || secret == "" {
+ signerType = SignatureAnonymous
+ }
+
+ e.retrieved = true
+ return Value{
+ AccessKeyID: id,
+ SecretAccessKey: secret,
+ SessionToken: os.Getenv("AWS_SESSION_TOKEN"),
+ SignerType: signerType,
+ }, nil
+}
+
+// IsExpired returns if the credentials have been retrieved.
+func (e *EnvAWS) IsExpired() bool {
+ return !e.retrieved
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/env_minio.go b/vendor/github.com/minio/minio-go/pkg/credentials/env_minio.go
new file mode 100644
index 000000000..791087ef5
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/env_minio.go
@@ -0,0 +1,62 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import "os"
+
+// A EnvMinio retrieves credentials from the environment variables of the
+// running process. EnvMinioironment credentials never expire.
+//
+// EnvMinioironment variables used:
+//
+// * Access Key ID: MINIO_ACCESS_KEY.
+// * Secret Access Key: MINIO_SECRET_KEY.
+type EnvMinio struct {
+ retrieved bool
+}
+
+// NewEnvMinio returns a pointer to a new Credentials object
+// wrapping the environment variable provider.
+func NewEnvMinio() *Credentials {
+ return New(&EnvMinio{})
+}
+
+// Retrieve retrieves the keys from the environment.
+func (e *EnvMinio) Retrieve() (Value, error) {
+ e.retrieved = false
+
+ id := os.Getenv("MINIO_ACCESS_KEY")
+ secret := os.Getenv("MINIO_SECRET_KEY")
+
+ signerType := SignatureV4
+ if id == "" || secret == "" {
+ signerType = SignatureAnonymous
+ }
+
+ e.retrieved = true
+ return Value{
+ AccessKeyID: id,
+ SecretAccessKey: secret,
+ SignerType: signerType,
+ }, nil
+}
+
+// IsExpired returns if the credentials have been retrieved.
+func (e *EnvMinio) IsExpired() bool {
+ return !e.retrieved
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/env_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/env_test.go
new file mode 100644
index 000000000..2f72bea40
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/env_test.go
@@ -0,0 +1,105 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "os"
+ "reflect"
+ "testing"
+)
+
+func TestEnvAWSRetrieve(t *testing.T) {
+ os.Clearenv()
+ os.Setenv("AWS_ACCESS_KEY_ID", "access")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
+ os.Setenv("AWS_SESSION_TOKEN", "token")
+
+ e := EnvAWS{}
+ if !e.IsExpired() {
+ t.Error("Expect creds to be expired before retrieve.")
+ }
+
+ creds, err := e.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expectedCreds := Value{
+ AccessKeyID: "access",
+ SecretAccessKey: "secret",
+ SessionToken: "token",
+ SignerType: SignatureV4,
+ }
+ if !reflect.DeepEqual(creds, expectedCreds) {
+ t.Errorf("Expected %v, got %v", expectedCreds, creds)
+ }
+
+ if e.IsExpired() {
+ t.Error("Expect creds to not be expired after retrieve.")
+ }
+
+ os.Clearenv()
+ os.Setenv("AWS_ACCESS_KEY", "access")
+ os.Setenv("AWS_SECRET_KEY", "secret")
+
+ expectedCreds = Value{
+ AccessKeyID: "access",
+ SecretAccessKey: "secret",
+ SignerType: SignatureV4,
+ }
+
+ creds, err = e.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !reflect.DeepEqual(creds, expectedCreds) {
+ t.Errorf("Expected %v, got %v", expectedCreds, creds)
+ }
+
+}
+
+func TestEnvMinioRetrieve(t *testing.T) {
+ os.Clearenv()
+
+ os.Setenv("MINIO_ACCESS_KEY", "access")
+ os.Setenv("MINIO_SECRET_KEY", "secret")
+
+ e := EnvMinio{}
+ if !e.IsExpired() {
+ t.Error("Expect creds to be expired before retrieve.")
+ }
+
+ creds, err := e.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expectedCreds := Value{
+ AccessKeyID: "access",
+ SecretAccessKey: "secret",
+ SignerType: SignatureV4,
+ }
+ if !reflect.DeepEqual(creds, expectedCreds) {
+ t.Errorf("Expected %v, got %v", expectedCreds, creds)
+ }
+
+ if e.IsExpired() {
+ t.Error("Expect creds to not be expired after retrieve.")
+ }
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go b/vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go
new file mode 100644
index 000000000..1be621385
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go
@@ -0,0 +1,120 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/go-ini/ini"
+ homedir "github.com/minio/go-homedir"
+)
+
+// A FileAWSCredentials retrieves credentials from the current user's home
+// directory, and keeps track if those credentials are expired.
+//
+// Profile ini file example: $HOME/.aws/credentials
+type FileAWSCredentials struct {
+ // Path to the shared credentials file.
+ //
+ // If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the
+ // env value is empty will default to current user's home directory.
+ // Linux/OSX: "$HOME/.aws/credentials"
+ // Windows: "%USERPROFILE%\.aws\credentials"
+ filename string
+
+ // AWS Profile to extract credentials from the shared credentials file. If empty
+ // will default to environment variable "AWS_PROFILE" or "default" if
+ // environment variable is also not set.
+ profile string
+
+ // retrieved states if the credentials have been successfully retrieved.
+ retrieved bool
+}
+
+// NewFileAWSCredentials returns a pointer to a new Credentials object
+// wrapping the Profile file provider.
+func NewFileAWSCredentials(filename string, profile string) *Credentials {
+ return New(&FileAWSCredentials{
+ filename: filename,
+ profile: profile,
+ })
+}
+
+// Retrieve reads and extracts the shared credentials from the current
+// users home directory.
+func (p *FileAWSCredentials) Retrieve() (Value, error) {
+ if p.filename == "" {
+ p.filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE")
+ if p.filename == "" {
+ homeDir, err := homedir.Dir()
+ if err != nil {
+ return Value{}, err
+ }
+ p.filename = filepath.Join(homeDir, ".aws", "credentials")
+ }
+ }
+ if p.profile == "" {
+ p.profile = os.Getenv("AWS_PROFILE")
+ if p.profile == "" {
+ p.profile = "default"
+ }
+ }
+
+ p.retrieved = false
+
+ iniProfile, err := loadProfile(p.filename, p.profile)
+ if err != nil {
+ return Value{}, err
+ }
+
+ // Default to empty string if not found.
+ id := iniProfile.Key("aws_access_key_id")
+ // Default to empty string if not found.
+ secret := iniProfile.Key("aws_secret_access_key")
+ // Default to empty string if not found.
+ token := iniProfile.Key("aws_session_token")
+
+ p.retrieved = true
+ return Value{
+ AccessKeyID: id.String(),
+ SecretAccessKey: secret.String(),
+ SessionToken: token.String(),
+ SignerType: SignatureV4,
+ }, nil
+}
+
+// IsExpired returns if the shared credentials have expired.
+func (p *FileAWSCredentials) IsExpired() bool {
+ return !p.retrieved
+}
+
+// loadProfiles loads from the file pointed to by shared credentials filename for profile.
+// The credentials retrieved from the profile will be returned or error. Error will be
+// returned if it fails to read from the file, or the data is invalid.
+func loadProfile(filename, profile string) (*ini.Section, error) {
+ config, err := ini.Load(filename)
+ if err != nil {
+ return nil, err
+ }
+ iniProfile, err := config.GetSection(profile)
+ if err != nil {
+ return nil, err
+ }
+ return iniProfile, nil
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go b/vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go
new file mode 100644
index 000000000..9e26dd302
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go
@@ -0,0 +1,129 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ homedir "github.com/minio/go-homedir"
+)
+
+// A FileMinioClient retrieves credentials from the current user's home
+// directory, and keeps track if those credentials are expired.
+//
+// Configuration file example: $HOME/.mc/config.json
+type FileMinioClient struct {
+ // Path to the shared credentials file.
+ //
+ // If empty will look for "MINIO_SHARED_CREDENTIALS_FILE" env variable. If the
+ // env value is empty will default to current user's home directory.
+ // Linux/OSX: "$HOME/.mc/config.json"
+ // Windows: "%USERALIAS%\mc\config.json"
+ filename string
+
+ // Minio Alias to extract credentials from the shared credentials file. If empty
+ // will default to environment variable "MINIO_ALIAS" or "default" if
+ // environment variable is also not set.
+ alias string
+
+ // retrieved states if the credentials have been successfully retrieved.
+ retrieved bool
+}
+
+// NewFileMinioClient returns a pointer to a new Credentials object
+// wrapping the Alias file provider.
+func NewFileMinioClient(filename string, alias string) *Credentials {
+ return New(&FileMinioClient{
+ filename: filename,
+ alias: alias,
+ })
+}
+
+// Retrieve reads and extracts the shared credentials from the current
+// users home directory.
+func (p *FileMinioClient) Retrieve() (Value, error) {
+ if p.filename == "" {
+ homeDir, err := homedir.Dir()
+ if err != nil {
+ return Value{}, err
+ }
+ p.filename = filepath.Join(homeDir, ".mc", "config.json")
+ if runtime.GOOS == "windows" {
+ p.filename = filepath.Join(homeDir, "mc", "config.json")
+ }
+ }
+
+ if p.alias == "" {
+ p.alias = os.Getenv("MINIO_ALIAS")
+ if p.alias == "" {
+ p.alias = "s3"
+ }
+ }
+
+ p.retrieved = false
+
+ hostCfg, err := loadAlias(p.filename, p.alias)
+ if err != nil {
+ return Value{}, err
+ }
+
+ p.retrieved = true
+ return Value{
+ AccessKeyID: hostCfg.AccessKey,
+ SecretAccessKey: hostCfg.SecretKey,
+ SignerType: parseSignatureType(hostCfg.API),
+ }, nil
+}
+
+// IsExpired returns if the shared credentials have expired.
+func (p *FileMinioClient) IsExpired() bool {
+ return !p.retrieved
+}
+
+// hostConfig configuration of a host.
+type hostConfig struct {
+ URL string `json:"url"`
+ AccessKey string `json:"accessKey"`
+ SecretKey string `json:"secretKey"`
+ API string `json:"api"`
+}
+
+// config config version.
+type config struct {
+ Version string `json:"version"`
+ Hosts map[string]hostConfig `json:"hosts"`
+}
+
+// loadAliass loads from the file pointed to by shared credentials filename for alias.
+// The credentials retrieved from the alias will be returned or error. Error will be
+// returned if it fails to read from the file.
+func loadAlias(filename, alias string) (hostConfig, error) {
+ cfg := &config{}
+ configBytes, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return hostConfig{}, err
+ }
+ if err = json.Unmarshal(configBytes, cfg); err != nil {
+ return hostConfig{}, err
+ }
+ return cfg.Hosts[alias], nil
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/file_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/file_test.go
new file mode 100644
index 000000000..c62c53365
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/file_test.go
@@ -0,0 +1,189 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestFileAWS(t *testing.T) {
+ os.Clearenv()
+
+ creds := NewFileAWSCredentials("credentials.sample", "")
+ credValues, err := creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SessionToken != "token" {
+ t.Errorf("Expected 'token', got %s'", credValues.SessionToken)
+ }
+
+ os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "credentials.sample")
+ creds = NewFileAWSCredentials("", "")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SessionToken != "token" {
+ t.Errorf("Expected 'token', got %s'", credValues.SessionToken)
+ }
+
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ os.Setenv("AWS_SHARED_CREDENTIALS_FILE", filepath.Join(wd, "credentials.sample"))
+ creds = NewFileAWSCredentials("", "")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SessionToken != "token" {
+ t.Errorf("Expected 'token', got %s'", credValues.SessionToken)
+ }
+
+ os.Clearenv()
+ os.Setenv("AWS_PROFILE", "no_token")
+
+ creds = NewFileAWSCredentials("credentials.sample", "")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+
+ os.Clearenv()
+
+ creds = NewFileAWSCredentials("credentials.sample", "no_token")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+
+ creds = NewFileAWSCredentials("credentials-non-existent.sample", "no_token")
+ _, err = creds.Get()
+ if !os.IsNotExist(err) {
+ t.Errorf("Expected open non-existent.json: no such file or directory, got %s", err)
+ }
+ if !creds.IsExpired() {
+ t.Error("Should be expired if not loaded")
+ }
+}
+
+func TestFileMinioClient(t *testing.T) {
+ os.Clearenv()
+
+ creds := NewFileMinioClient("config.json.sample", "")
+ credValues, err := creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "accessKey" {
+ t.Errorf("Expected 'accessKey', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "secret" {
+ t.Errorf("Expected 'secret', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SignerType != SignatureV4 {
+ t.Errorf("Expected 'S3v4', got %s'", credValues.SignerType)
+ }
+
+ os.Clearenv()
+ os.Setenv("MINIO_ALIAS", "play")
+
+ creds = NewFileMinioClient("config.json.sample", "")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "Q3AM3UQ867SPQQA43P2F" {
+ t.Errorf("Expected 'Q3AM3UQ867SPQQA43P2F', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" {
+ t.Errorf("Expected 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SignerType != SignatureV2 {
+ t.Errorf("Expected 'S3v2', got %s'", credValues.SignerType)
+ }
+
+ os.Clearenv()
+
+ creds = NewFileMinioClient("config.json.sample", "play")
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if credValues.AccessKeyID != "Q3AM3UQ867SPQQA43P2F" {
+ t.Errorf("Expected 'Q3AM3UQ867SPQQA43P2F', got %s'", credValues.AccessKeyID)
+ }
+ if credValues.SecretAccessKey != "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" {
+ t.Errorf("Expected 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG', got %s'", credValues.SecretAccessKey)
+ }
+ if credValues.SignerType != SignatureV2 {
+ t.Errorf("Expected 'S3v2', got %s'", credValues.SignerType)
+ }
+
+ creds = NewFileMinioClient("non-existent.json", "play")
+ _, err = creds.Get()
+ if !os.IsNotExist(err) {
+ t.Errorf("Expected open non-existent.json: no such file or directory, got %s", err)
+ }
+ if !creds.IsExpired() {
+ t.Error("Should be expired if not loaded")
+ }
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws.go b/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws.go
new file mode 100644
index 000000000..ee24a213b
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws.go
@@ -0,0 +1,196 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import (
+ "bufio"
+ "encoding/json"
+ "errors"
+ "net/http"
+ "net/url"
+ "path"
+ "time"
+)
+
+// DefaultExpiryWindow - Default expiry window.
+// ExpiryWindow will allow the credentials to trigger refreshing
+// prior to the credentials actually expiring. This is beneficial
+// so race conditions with expiring credentials do not cause
+// request to fail unexpectedly due to ExpiredTokenException exceptions.
+const DefaultExpiryWindow = time.Second * 10 // 10 secs
+
+// A IAM retrieves credentials from the EC2 service, and keeps track if
+// those credentials are expired.
+type IAM struct {
+ Expiry
+
+ // Required http Client to use when connecting to IAM metadata service.
+ Client *http.Client
+
+ // Custom endpoint in place of
+ endpoint string
+}
+
+// redirectHeaders copies all headers when following a redirect URL.
+// This won't be needed anymore from go 1.8 (https://github.com/golang/go/issues/4800)
+func redirectHeaders(req *http.Request, via []*http.Request) error {
+ if len(via) == 0 {
+ return nil
+ }
+ for key, val := range via[0].Header {
+ req.Header[key] = val
+ }
+ return nil
+}
+
+// NewIAM returns a pointer to a new Credentials object wrapping
+// the IAM. Takes a ConfigProvider to create a EC2Metadata client.
+// The ConfigProvider is satisfied by the session.Session type.
+func NewIAM(endpoint string) *Credentials {
+ if endpoint == "" {
+ // IAM Roles for Amazon EC2
+ // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
+ endpoint = "http://169.254.169.254"
+ }
+ p := &IAM{
+ Client: &http.Client{
+ Transport: http.DefaultTransport,
+ CheckRedirect: redirectHeaders,
+ },
+ endpoint: endpoint,
+ }
+ return New(p)
+}
+
+// Retrieve retrieves credentials from the EC2 service.
+// Error will be returned if the request fails, or unable to extract
+// the desired
+func (m *IAM) Retrieve() (Value, error) {
+ credsList, err := requestCredList(m.Client, m.endpoint)
+ if err != nil {
+ return Value{}, err
+ }
+
+ if len(credsList) == 0 {
+ return Value{}, errors.New("empty EC2 Role list")
+ }
+ credsName := credsList[0]
+
+ roleCreds, err := requestCred(m.Client, m.endpoint, credsName)
+ if err != nil {
+ return Value{}, err
+ }
+
+ // Expiry window is set to 10secs.
+ m.SetExpiration(roleCreds.Expiration, DefaultExpiryWindow)
+
+ return Value{
+ AccessKeyID: roleCreds.AccessKeyID,
+ SecretAccessKey: roleCreds.SecretAccessKey,
+ SessionToken: roleCreds.Token,
+ SignerType: SignatureV4,
+ }, nil
+}
+
+// A ec2RoleCredRespBody provides the shape for unmarshaling credential
+// request responses.
+type ec2RoleCredRespBody struct {
+ // Success State
+ Expiration time.Time
+ AccessKeyID string
+ SecretAccessKey string
+ Token string
+
+ // Error state
+ Code string
+ Message string
+}
+
+const iamSecurityCredsPath = "/latest/meta-data/iam/security-credentials"
+
+// requestCredList requests a list of credentials from the EC2 service.
+// If there are no credentials, or there is an error making or receiving the request
+func requestCredList(client *http.Client, endpoint string) ([]string, error) {
+ u, err := url.Parse(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = iamSecurityCredsPath
+ req, err := http.NewRequest("GET", u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return nil, errors.New(resp.Status)
+ }
+
+ credsList := []string{}
+ s := bufio.NewScanner(resp.Body)
+ for s.Scan() {
+ credsList = append(credsList, s.Text())
+ }
+
+ if err := s.Err(); err != nil {
+ return nil, err
+ }
+
+ return credsList, nil
+}
+
+// requestCred requests the credentials for a specific credentials from the EC2 service.
+//
+// If the credentials cannot be found, or there is an error reading the response
+// and error will be returned.
+func requestCred(client *http.Client, endpoint string, credsName string) (ec2RoleCredRespBody, error) {
+ u, err := url.Parse(endpoint)
+ if err != nil {
+ return ec2RoleCredRespBody{}, err
+ }
+
+ u.Path = path.Join(iamSecurityCredsPath, credsName)
+ req, err := http.NewRequest("GET", u.String(), nil)
+ if err != nil {
+ return ec2RoleCredRespBody{}, err
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ return ec2RoleCredRespBody{}, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return ec2RoleCredRespBody{}, errors.New(resp.Status)
+ }
+
+ respCreds := ec2RoleCredRespBody{}
+ if err := json.NewDecoder(resp.Body).Decode(&respCreds); err != nil {
+ return ec2RoleCredRespBody{}, err
+ }
+
+ if respCreds.Code != "Success" {
+ // If an error code was returned something failed requesting the role.
+ return ec2RoleCredRespBody{}, errors.New(respCreds.Message)
+ }
+
+ return respCreds, nil
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws_test.go
new file mode 100644
index 000000000..19553945d
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/iam_aws_test.go
@@ -0,0 +1,180 @@
+package credentials
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+)
+
+const credsRespTmpl = `{
+ "Code": "Success",
+ "Type": "AWS-HMAC",
+ "AccessKeyId" : "accessKey",
+ "SecretAccessKey" : "secret",
+ "Token" : "token",
+ "Expiration" : "%s",
+ "LastUpdated" : "2009-11-23T0:00:00Z"
+}`
+
+const credsFailRespTmpl = `{
+ "Code": "ErrorCode",
+ "Message": "ErrorMsg",
+ "LastUpdated": "2009-11-23T0:00:00Z"
+}`
+
+func initTestFailServer() *httptest.Server {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, "Not allowed", http.StatusBadRequest)
+ }))
+ return server
+}
+
+func initTestServerNoRoles() *httptest.Server {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte(""))
+ }))
+ return server
+}
+
+func initTestServer(expireOn string, failAssume bool) *httptest.Server {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == "/latest/meta-data/iam/security-credentials" {
+ fmt.Fprintln(w, "RoleName")
+ } else if r.URL.Path == "/latest/meta-data/iam/security-credentials/RoleName" {
+ if failAssume {
+ fmt.Fprintf(w, credsFailRespTmpl)
+ } else {
+ fmt.Fprintf(w, credsRespTmpl, expireOn)
+ }
+ } else {
+ http.Error(w, "bad request", http.StatusBadRequest)
+ }
+ }))
+
+ return server
+}
+
+func TestIAMMalformedEndpoint(t *testing.T) {
+ creds := NewIAM("%%%%")
+ _, err := creds.Get()
+ if err == nil {
+ t.Fatal("Unexpected should fail here")
+ }
+ if err.Error() != `parse %%%%: invalid URL escape "%%%"` {
+ t.Fatalf("Expected parse %%%%%%%%: invalid URL escape \"%%%%%%\", got %s", err)
+ }
+}
+
+func TestIAMFailServer(t *testing.T) {
+ server := initTestFailServer()
+ defer server.Close()
+
+ creds := NewIAM(server.URL)
+
+ _, err := creds.Get()
+ if err == nil {
+ t.Fatal("Unexpected should fail here")
+ }
+ if err.Error() != "400 Bad Request" {
+ t.Fatalf("Expected '400 Bad Request', got %s", err)
+ }
+}
+
+func TestIAMNoRoles(t *testing.T) {
+ server := initTestServerNoRoles()
+ defer server.Close()
+
+ creds := NewIAM(server.URL)
+ _, err := creds.Get()
+ if err == nil {
+ t.Fatal("Unexpected should fail here")
+ }
+ if err.Error() != "empty EC2 Role list" {
+ t.Fatalf("Expected 'empty EC2 Role list', got %s", err)
+ }
+}
+
+func TestIAM(t *testing.T) {
+ server := initTestServer("2014-12-16T01:51:37Z", false)
+ defer server.Close()
+
+ p := &IAM{
+ Client: http.DefaultClient,
+ endpoint: server.URL,
+ }
+
+ creds, err := p.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if "accessKey" != creds.AccessKeyID {
+ t.Errorf("Expected \"accessKey\", got %s", creds.AccessKeyID)
+ }
+
+ if "secret" != creds.SecretAccessKey {
+ t.Errorf("Expected \"secret\", got %s", creds.SecretAccessKey)
+ }
+
+ if "token" != creds.SessionToken {
+ t.Errorf("Expected \"token\", got %s", creds.SessionToken)
+ }
+
+ if !p.IsExpired() {
+ t.Error("Expected creds to be expired.")
+ }
+}
+
+func TestIAMFailAssume(t *testing.T) {
+ server := initTestServer("2014-12-16T01:51:37Z", true)
+ defer server.Close()
+
+ p := &IAM{
+ Client: http.DefaultClient,
+ endpoint: server.URL,
+ }
+
+ _, err := p.Retrieve()
+ if err == nil {
+ t.Fatal("Unexpected success, should fail")
+ }
+ if err.Error() != "ErrorMsg" {
+ t.Errorf("Expected \"ErrorMsg\", got %s", err)
+ }
+}
+
+func TestIAMIsExpired(t *testing.T) {
+ server := initTestServer("2014-12-16T01:51:37Z", false)
+ defer server.Close()
+
+ p := &IAM{
+ Client: http.DefaultClient,
+ endpoint: server.URL,
+ }
+ p.CurrentTime = func() time.Time {
+ return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
+ }
+
+ if !p.IsExpired() {
+ t.Error("Expected creds to be expired before retrieve.")
+ }
+
+ _, err := p.Retrieve()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if p.IsExpired() {
+ t.Error("Expected creds to not be expired after retrieve.")
+ }
+
+ p.CurrentTime = func() time.Time {
+ return time.Date(3014, 12, 15, 21, 26, 0, 0, time.UTC)
+ }
+
+ if !p.IsExpired() {
+ t.Error("Expected creds to be expired when curren time has changed")
+ }
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/signature-type.go b/vendor/github.com/minio/minio-go/pkg/credentials/signature-type.go
new file mode 100644
index 000000000..c64ad6c23
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/signature-type.go
@@ -0,0 +1,76 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import "strings"
+
+// SignatureType is type of Authorization requested for a given HTTP request.
+type SignatureType int
+
+// Different types of supported signatures - default is SignatureV4 or SignatureDefault.
+const (
+ // SignatureDefault is always set to v4.
+ SignatureDefault SignatureType = iota
+ SignatureV4
+ SignatureV2
+ SignatureV4Streaming
+ SignatureAnonymous // Anonymous signature signifies, no signature.
+)
+
+// IsV2 - is signature SignatureV2?
+func (s SignatureType) IsV2() bool {
+ return s == SignatureV2
+}
+
+// IsV4 - is signature SignatureV4?
+func (s SignatureType) IsV4() bool {
+ return s == SignatureV4 || s == SignatureDefault
+}
+
+// IsStreamingV4 - is signature SignatureV4Streaming?
+func (s SignatureType) IsStreamingV4() bool {
+ return s == SignatureV4Streaming
+}
+
+// IsAnonymous - is signature empty?
+func (s SignatureType) IsAnonymous() bool {
+ return s == SignatureAnonymous
+}
+
+// Stringer humanized version of signature type,
+// strings returned here are case insensitive.
+func (s SignatureType) String() string {
+ if s.IsV2() {
+ return "S3v2"
+ } else if s.IsV4() {
+ return "S3v4"
+ } else if s.IsStreamingV4() {
+ return "S3v4Streaming"
+ }
+ return "Anonymous"
+}
+
+func parseSignatureType(str string) SignatureType {
+ if strings.EqualFold(str, "S3v4") {
+ return SignatureV4
+ } else if strings.EqualFold(str, "S3v2") {
+ return SignatureV2
+ } else if strings.EqualFold(str, "S3v4Streaming") {
+ return SignatureV4Streaming
+ }
+ return SignatureAnonymous
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/static.go b/vendor/github.com/minio/minio-go/pkg/credentials/static.go
new file mode 100644
index 000000000..25aff5696
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/static.go
@@ -0,0 +1,67 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+// A Static is a set of credentials which are set programmatically,
+// and will never expire.
+type Static struct {
+ Value
+}
+
+// NewStaticV2 returns a pointer to a new Credentials object
+// wrapping a static credentials value provider, signature is
+// set to v2. If access and secret are not specified then
+// regardless of signature type set it Value will return
+// as anonymous.
+func NewStaticV2(id, secret, token string) *Credentials {
+ return NewStatic(id, secret, token, SignatureV2)
+}
+
+// NewStaticV4 is similar to NewStaticV2 with similar considerations.
+func NewStaticV4(id, secret, token string) *Credentials {
+ return NewStatic(id, secret, token, SignatureV4)
+}
+
+// NewStatic returns a pointer to a new Credentials object
+// wrapping a static credentials value provider.
+func NewStatic(id, secret, token string, signerType SignatureType) *Credentials {
+ return New(&Static{
+ Value: Value{
+ AccessKeyID: id,
+ SecretAccessKey: secret,
+ SessionToken: token,
+ SignerType: signerType,
+ },
+ })
+}
+
+// Retrieve returns the static credentials.
+func (s *Static) Retrieve() (Value, error) {
+ if s.AccessKeyID == "" || s.SecretAccessKey == "" {
+ // Anonymous is not an error
+ return Value{SignerType: SignatureAnonymous}, nil
+ }
+ return s.Value, nil
+}
+
+// IsExpired returns if the credentials are expired.
+//
+// For Static, the credentials never expired.
+func (s *Static) IsExpired() bool {
+ return false
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/credentials/static_test.go b/vendor/github.com/minio/minio-go/pkg/credentials/static_test.go
new file mode 100644
index 000000000..491b1554b
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/credentials/static_test.go
@@ -0,0 +1,68 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible 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 credentials
+
+import "testing"
+
+func TestStaticGet(t *testing.T) {
+ creds := NewStatic("UXHW", "SECRET", "", SignatureV4)
+ credValues, err := creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if "UXHW" != credValues.AccessKeyID {
+ t.Errorf("Expected access key ID to match \"UXHW\", got %s", credValues.AccessKeyID)
+ }
+ if "SECRET" != credValues.SecretAccessKey {
+ t.Errorf("Expected secret access key to match \"SECRET\", got %s", credValues.SecretAccessKey)
+ }
+
+ if credValues.SessionToken != "" {
+ t.Error("Expected session token to match")
+ }
+
+ if credValues.SignerType != SignatureV4 {
+ t.Errorf("Expected 'S3v4', got %s", credValues.SignerType)
+ }
+
+ if creds.IsExpired() {
+ t.Error("Static credentials should never expire")
+ }
+
+ creds = NewStatic("", "", "", SignatureDefault)
+ credValues, err = creds.Get()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if "" != credValues.AccessKeyID {
+ t.Errorf("Expected access key ID to match empty string, got %s", credValues.AccessKeyID)
+ }
+ if "" != credValues.SecretAccessKey {
+ t.Errorf("Expected secret access key to match empty string, got %s", credValues.SecretAccessKey)
+ }
+
+ if !credValues.SignerType.IsAnonymous() {
+ t.Errorf("Expected 'Anonymous', got %s", credValues.SignerType)
+ }
+
+ if creds.IsExpired() {
+ t.Error("Static credentials should never expire")
+ }
+}