From 603b0ee34f56bc572493e9fe3a5a47b11b8dfa17 Mon Sep 17 00:00:00 2001 From: Joel Thompson Date: Sat, 3 Aug 2019 15:23:48 -0400 Subject: [PATCH 1/4] Add reading AWS root/config endpoint Previously, there was no read listener on the AWS config/root endpoint, so clients couldn't read any of the config options that were set. This adds a read operation so that all configured values can be read, except for the secret_key, which is filtered out and never returned. --- builtin/logical/aws/path_config_root.go | 30 +++++++++++ builtin/logical/aws/path_config_root_test.go | 54 ++++++++++++++++++++ website/source/api/secret/aws/index.html.md | 31 +++++++++++ 3 files changed, 115 insertions(+) create mode 100644 builtin/logical/aws/path_config_root_test.go diff --git a/builtin/logical/aws/path_config_root.go b/builtin/logical/aws/path_config_root.go index badf93ba189c..ab8f05a6abe1 100644 --- a/builtin/logical/aws/path_config_root.go +++ b/builtin/logical/aws/path_config_root.go @@ -42,6 +42,7 @@ func pathConfigRoot(b *backend) *framework.Path { }, Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.ReadOperation: b.pathConfigRootRead, logical.UpdateOperation: b.pathConfigRootWrite, }, @@ -50,6 +51,35 @@ func pathConfigRoot(b *backend) *framework.Path { } } +func (b *backend) pathConfigRootRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + b.clientMutex.RLock() + defer b.clientMutex.RUnlock() + + entry, err := req.Storage.Get(ctx, "config/root") + if err != nil { + return nil, err + } + var config rootConfig + + if entry != nil { + if err := entry.DecodeJSON(&config); err != nil { + return nil, err + } + } + + configData := map[string]interface{}{ + "access_key": config.AccessKey, + "secret_key": "", + "region": config.Region, + "iam_endpoint": config.IAMEndpoint, + "sts_endpoint": config.STSEndpoint, + "max_retries": config.MaxRetries, + } + return &logical.Response{ + Data: configData, + }, nil +} + func (b *backend) pathConfigRootWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { region := data.Get("region").(string) iamendpoint := data.Get("iam_endpoint").(string) diff --git a/builtin/logical/aws/path_config_root_test.go b/builtin/logical/aws/path_config_root_test.go new file mode 100644 index 000000000000..a9c66e5d4d3d --- /dev/null +++ b/builtin/logical/aws/path_config_root_test.go @@ -0,0 +1,54 @@ +package aws + +import ( + "context" + "reflect" + "testing" + + "github.com/hashicorp/vault/sdk/logical" +) + +func TestBackend_PathConfigRoot(t *testing.T) { + config := logical.TestBackendConfig() + config.StorageView = &logical.InmemStorage{} + + b := Backend() + if err := b.Setup(context.Background(), config); err != nil { + t.Fatal(err) + } + + configData := map[string]interface{}{ + "access_key": "AKIAEXAMPLE", + "secret_key": "RandomData", + "region": "us-west-2", + "iam_endpoint": "https://iam.amazonaws.com", + "sts_endpoint": "https://sts.us-west-2.amazonaws.com", + "max_retries": 10, + } + + configReq := &logical.Request{ + Operation: logical.UpdateOperation, + Storage: config.StorageView, + Path: "config/root", + Data: configData, + } + + resp, err := b.HandleRequest(context.Background(), configReq) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: config writing failed: resp:%#v\n err: %v", resp, err) + } + + resp, err = b.HandleRequest(context.Background(), &logical.Request{ + Operation: logical.ReadOperation, + Storage: config.StorageView, + Path: "config/root", + }) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("bad: config reading failed: resp:%#v\n err: %v", resp, err) + } + + configData["secret_key"] = "" + if !reflect.DeepEqual(resp.Data, configData) { + t.Errorf("bad: expected to read config root as %#v, got %#v instead", configData, resp.Data) + } +} diff --git a/website/source/api/secret/aws/index.html.md b/website/source/api/secret/aws/index.html.md index aa5dafecd53b..03644d88cfdc 100644 --- a/website/source/api/secret/aws/index.html.md +++ b/website/source/api/secret/aws/index.html.md @@ -81,6 +81,37 @@ $ curl \ http://127.0.0.1:8200/v1/aws/config/root ``` +## Read Root Configuration + +This endpoint allows you to read non-secure values that have been configured in the +`config/root` endpoint. In particular, the `secret_key` parameter is never returned. + +| Method | Path | +| :--------------------------- | :--------------------- | +| `GET` | `/aws/config/root` | + +### Sample Request +``` +$ curl + --header "X-Vault-Token: ..." \ + http://127.0.0.1:8200/v1/aws/config/root + +``` + +### Sample Response +```json +{ + "data": { + "access_key": "AKIAEXAMPLE", + "secret_key": "", + "region": "us-west-2", + "iam_endpoint": "https://iam.amazonaws.com", + "sts_endpoint": "https://sts.us-west-2.amazonaws.com", + "max_retries": -1 + } +} +``` + ## Rotate Root IAM Credentials When you have configured Vault with static credentials, you can use this From d5f3f1b335bd0a6ea578842b810962bd72f635b7 Mon Sep 17 00:00:00 2001 From: Joel Thompson Date: Sun, 11 Aug 2019 21:22:25 -0400 Subject: [PATCH 2/4] Return nil on no existing root config --- builtin/logical/aws/path_config_root.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/builtin/logical/aws/path_config_root.go b/builtin/logical/aws/path_config_root.go index ab8f05a6abe1..3d5145cf4d40 100644 --- a/builtin/logical/aws/path_config_root.go +++ b/builtin/logical/aws/path_config_root.go @@ -59,12 +59,14 @@ func (b *backend) pathConfigRootRead(ctx context.Context, req *logical.Request, if err != nil { return nil, err } + if entry == nil { + return nil, nil + } + var config rootConfig - if entry != nil { - if err := entry.DecodeJSON(&config); err != nil { - return nil, err - } + if err := entry.DecodeJSON(&config); err != nil { + return nil, err } configData := map[string]interface{}{ From cc72902b0f15cf07b96469dd217237c0f4ab74f0 Mon Sep 17 00:00:00 2001 From: Joel Thompson Date: Sun, 11 Aug 2019 21:32:01 -0400 Subject: [PATCH 3/4] Remove secret_key from reading aws/config/root --- builtin/logical/aws/path_config_root.go | 1 - builtin/logical/aws/path_config_root_test.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/builtin/logical/aws/path_config_root.go b/builtin/logical/aws/path_config_root.go index 3d5145cf4d40..4c854121a641 100644 --- a/builtin/logical/aws/path_config_root.go +++ b/builtin/logical/aws/path_config_root.go @@ -71,7 +71,6 @@ func (b *backend) pathConfigRootRead(ctx context.Context, req *logical.Request, configData := map[string]interface{}{ "access_key": config.AccessKey, - "secret_key": "", "region": config.Region, "iam_endpoint": config.IAMEndpoint, "sts_endpoint": config.STSEndpoint, diff --git a/builtin/logical/aws/path_config_root_test.go b/builtin/logical/aws/path_config_root_test.go index a9c66e5d4d3d..89a9b04d8567 100644 --- a/builtin/logical/aws/path_config_root_test.go +++ b/builtin/logical/aws/path_config_root_test.go @@ -47,7 +47,7 @@ func TestBackend_PathConfigRoot(t *testing.T) { t.Fatalf("bad: config reading failed: resp:%#v\n err: %v", resp, err) } - configData["secret_key"] = "" + delete(configData, "secret_key") if !reflect.DeepEqual(resp.Data, configData) { t.Errorf("bad: expected to read config root as %#v, got %#v instead", configData, resp.Data) } From 9c494831f846e1110a3779e7762e47e874a0ed0d Mon Sep 17 00:00:00 2001 From: Joel Thompson Date: Thu, 12 Sep 2019 22:25:54 -0700 Subject: [PATCH 4/4] Update website/source/api/secret/aws/index.html.md Co-Authored-By: Jim Kalafut --- website/source/api/secret/aws/index.html.md | 1 - 1 file changed, 1 deletion(-) diff --git a/website/source/api/secret/aws/index.html.md b/website/source/api/secret/aws/index.html.md index 6946d477e6e3..e2bbbf30b4f1 100644 --- a/website/source/api/secret/aws/index.html.md +++ b/website/source/api/secret/aws/index.html.md @@ -103,7 +103,6 @@ $ curl { "data": { "access_key": "AKIAEXAMPLE", - "secret_key": "", "region": "us-west-2", "iam_endpoint": "https://iam.amazonaws.com", "sts_endpoint": "https://sts.us-west-2.amazonaws.com",