From 0f64e3e992d67f2fcd13e76da5647e6c2a9fd8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Mon, 8 Nov 2021 19:32:01 +0100 Subject: [PATCH] Add read support to sys/mounts/:path (#12792) * Add read support to sys/mounts/:path Closes https://github.com/hashicorp/vault/issues/12349 * Add changelog entry * Empty commit to trigger CI * Empty commit to trigger CI --- changelog/12792.txt | 3 ++ vault/logical_system.go | 15 ++++++ vault/logical_system_paths.go | 4 ++ vault/logical_system_test.go | 11 ++++ website/content/api-docs/system/mounts.mdx | 59 ++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 changelog/12792.txt diff --git a/changelog/12792.txt b/changelog/12792.txt new file mode 100644 index 000000000000..2785d111bd1b --- /dev/null +++ b/changelog/12792.txt @@ -0,0 +1,3 @@ +```release-note: feature +core: reading `sys/mounts/:path` now returns the configuration for the secret engine at the given path +``` diff --git a/vault/logical_system.go b/vault/logical_system.go index 5c8278464473..34ee83a01dae 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -1036,6 +1036,21 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d return nil, nil } +func (b *SystemBackend) handleReadMount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + path := data.Get("path").(string) + path = sanitizePath(path) + + entry := b.Core.router.MatchingMountEntry(ctx, path) + + if entry == nil { + return logical.ErrorResponse("No secret engine mount at %s", path), nil + } + + return &logical.Response{ + Data: mountInfo(entry), + }, nil +} + // used to intercept an HTTPCodedError so it goes back to callee func handleError( err error) (*logical.Response, error) { diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index b38b293dee8f..5b028823897a 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -1826,6 +1826,10 @@ func (b *SystemBackend) mountPaths() []*framework.Path { }, Operations: map[logical.Operation]framework.OperationHandler{ + logical.ReadOperation: &framework.PathOperation{ + Callback: b.handleReadMount, + Summary: "Read the configuration of the secret engine at the given path.", + }, logical.UpdateOperation: &framework.PathOperation{ Callback: b.handleMount, Summary: "Enable a new secrets engine at the given path.", diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index b3548e2f6788..bf9acd189931 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -219,6 +219,17 @@ func TestSystemBackend_mounts(t *testing.T) { if diff := deep.Equal(resp.Data, exp); len(diff) > 0 { t.Fatalf("bad, diff: %#v", diff) } + + for name, conf := range exp { + req := logical.TestRequest(t, logical.ReadOperation, "mounts/"+name) + resp, err = b.HandleRequest(namespace.RootContext(nil), req) + if err != nil { + t.Fatalf("err: %v", err) + } + if diff := deep.Equal(resp.Data, conf); len(diff) > 0 { + t.Fatalf("bad, diff: %#v", diff) + } + } } func TestSystemBackend_mount(t *testing.T) { diff --git a/website/content/api-docs/system/mounts.mdx b/website/content/api-docs/system/mounts.mdx index 44839ca18fee..1edd4a3e29b3 100644 --- a/website/content/api-docs/system/mounts.mdx +++ b/website/content/api-docs/system/mounts.mdx @@ -212,6 +212,65 @@ $ curl \ http://127.0.0.1:8200/v1/sys/mounts/my-mount ``` +## Get the configuration of a Secret Engine + +This endpoint returns the configuration of a specific secret engine. + +| Method | Path | +| :----- | :------------------ | +| `GET` | `/sys/mounts/:path` | + + +### Sample Request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + http://127.0.0.1:8200/v1/sys/mounts/cubbyhole +``` + +### Sample Response + +```json +{ + "config": { + "default_lease_ttl": 0, + "force_no_cache": false, + "max_lease_ttl": 0 + }, + "description": "per-token private secret storage", + "accessor": "cubbyhole_db85f061", + "external_entropy_access": false, + "options": null, + "uuid": "9c0e211a-904d-e41d-e1a2-7f1ff2bb8461", + "type": "cubbyhole", + "local": true, + "seal_wrap": false, + "request_id": "efdab917-ade2-1802-b8fa-fe2e6486d4e5", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "accessor": "cubbyhole_db85f061", + "config": { + "default_lease_ttl": 0, + "force_no_cache": false, + "max_lease_ttl": 0 + }, + "description": "per-token private secret storage", + "external_entropy_access": false, + "local": true, + "options": null, + "seal_wrap": false, + "type": "cubbyhole", + "uuid": "9c0e211a-904d-e41d-e1a2-7f1ff2bb8461" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + ## Read Mount Configuration This endpoint reads the given mount's configuration. Unlike the `mounts`