diff --git a/builtin/credential/aws/backend_test.go b/builtin/credential/aws/backend_test.go index 0924d291b..93feb62e2 100644 --- a/builtin/credential/aws/backend_test.go +++ b/builtin/credential/aws/backend_test.go @@ -467,6 +467,37 @@ func TestBackend_ConfigClient(t *testing.T) { if !exists { t.Fatal("existence check should have returned 'true' for 'config/client'") } + + endpointData := map[string]interface{}{ + "secret_key": "secretkey", + "access_key": "accesskey", + "endpoint": "endpointvalue", + } + + endpointReq := &logical.Request{ + Operation: logical.UpdateOperation, + Path: "config/client", + Storage: storage, + Data: endpointData, + } + _, err = b.HandleRequest(endpointReq) + if err != nil { + t.Fatal(err) + } + + endpointReq.Operation = logical.ReadOperation + resp, err := b.HandleRequest(endpointReq) + if err != nil { + t.Fatal(err) + } + if resp == nil || + resp.IsError() { + t.Fatalf("") + } + actual := resp.Data["endpoint"].(string) + if actual != "endpointvalue" { + t.Fatalf("bad: endpoint: expected:endpointvalue actual:%s\n", actual) + } } func TestBackend_pathConfigCertificate(t *testing.T) { diff --git a/builtin/credential/aws/client.go b/builtin/credential/aws/client.go index 92e82f306..cdebab534 100644 --- a/builtin/credential/aws/client.go +++ b/builtin/credential/aws/client.go @@ -65,11 +65,17 @@ func (b *backend) getClientConfig(s logical.Storage, region string) (*aws.Config } // Create a config that can be used to make the API calls. - return &aws.Config{ + cfg := &aws.Config{ Credentials: creds, Region: aws.String(region), HTTPClient: cleanhttp.DefaultClient(), - }, nil + } + + // Override the default endpoint with the configured endpoint. + if config.Endpoint != "" { + cfg.Endpoint = aws.String(config.Endpoint) + } + return cfg, nil } // flushCachedEC2Clients deletes all the cached ec2 client objects from the backend. diff --git a/builtin/credential/aws/path_config_client.go b/builtin/credential/aws/path_config_client.go index 20b2aabd8..4cdf00c66 100644 --- a/builtin/credential/aws/path_config_client.go +++ b/builtin/credential/aws/path_config_client.go @@ -19,6 +19,11 @@ func pathConfigClient(b *backend) *framework.Path { Type: framework.TypeString, Description: "AWS Secret key with permissions to query EC2 instance metadata.", }, + + "endpoint": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "The endpoint to be used to make API calls to AWS EC2.", + }, }, ExistenceCheck: b.pathConfigClientExistenceCheck, @@ -134,6 +139,16 @@ func (b *backend) pathConfigClientCreateUpdate( configEntry.SecretKey = data.Get("secret_key").(string) } + endpointStr, ok := data.GetOk("endpoint") + if ok { + if configEntry.Endpoint != endpointStr.(string) { + changedCreds = true + configEntry.Endpoint = endpointStr.(string) + } + } else if req.Operation == logical.CreateOperation { + configEntry.Endpoint = data.Get("endpoint").(string) + } + b.configMutex.Lock() defer b.configMutex.Unlock() @@ -158,6 +173,7 @@ func (b *backend) pathConfigClientCreateUpdate( type clientConfig struct { AccessKey string `json:"access_key" structs:"access_key" mapstructure:"access_key"` SecretKey string `json:"secret_key" structs:"secret_key" mapstructure:"secret_key"` + Endpoint string `json:"endpoint" structs:"endpoint" mapstructure:"endpoint"` } const pathConfigClientHelpSyn = ` diff --git a/website/source/docs/auth/aws.html.md b/website/source/docs/auth/aws.html.md index 7bff93b81..0d6568ee6 100644 --- a/website/source/docs/auth/aws.html.md +++ b/website/source/docs/auth/aws.html.md @@ -383,6 +383,13 @@ The response will be in JSON. For example: AWS Secret key with permissions to query EC2 instance metadata. +