From 60488687ad0f6f73b69c4c9c68366b6c02f21136 Mon Sep 17 00:00:00 2001 From: Daniel Huckins Date: Thu, 16 Feb 2023 15:04:37 -0500 Subject: [PATCH] VAULT-12112: add openapi response structures for /sys/capabilities* endpoints (#18468) * add capabilities Signed-off-by: Daniel Huckins * added change log Signed-off-by: Daniel Huckins * add test Signed-off-by: Daniel Huckins * use nil for dynamic fields Signed-off-by: Daniel Huckins --------- Signed-off-by: Daniel Huckins --- changelog/18468.txt | 3 ++ vault/logical_system_paths.go | 39 +++++++++++++++++---- vault/logical_system_test.go | 66 ++++++++++++++++++++++++++++------- 3 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 changelog/18468.txt diff --git a/changelog/18468.txt b/changelog/18468.txt new file mode 100644 index 000000000..362bf0501 --- /dev/null +++ b/changelog/18468.txt @@ -0,0 +1,3 @@ +```release-note:improvement +openapi: add openapi response defintions to /sys/capabilities endpoints +``` \ No newline at end of file diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index e09e485b4..4fffcdd30 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -1520,8 +1520,17 @@ func (b *SystemBackend) capabilitiesPaths() []*framework.Path { }, }, - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.UpdateOperation: b.handleCapabilitiesAccessor, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.UpdateOperation: &framework.PathOperation{ + Callback: b.handleCapabilitiesAccessor, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + // response keys are dynamic + Fields: nil, + }}, + }, + }, }, HelpSynopsis: strings.TrimSpace(sysHelp["capabilities_accessor"][0]), @@ -1547,8 +1556,17 @@ func (b *SystemBackend) capabilitiesPaths() []*framework.Path { }, }, - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.UpdateOperation: b.handleCapabilities, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.UpdateOperation: &framework.PathOperation{ + Callback: b.handleCapabilities, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + // response keys are dynamic + Fields: nil, + }}, + }, + }, }, HelpSynopsis: strings.TrimSpace(sysHelp["capabilities"][0]), @@ -1574,8 +1592,17 @@ func (b *SystemBackend) capabilitiesPaths() []*framework.Path { }, }, - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.UpdateOperation: b.handleCapabilities, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.UpdateOperation: &framework.PathOperation{ + Callback: b.handleCapabilities, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + // response keys are dynamic + Fields: nil, + }}, + }, + }, }, HelpSynopsis: strings.TrimSpace(sysHelp["capabilities_self"][0]), diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 4f18c3a9a..68e6b50a1 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -501,31 +501,45 @@ func TestSystemBackend_PathCapabilities(t *testing.T) { } // Check the capabilities using the root token - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req := &logical.Request{ Path: "capabilities", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, "token": rootToken, }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) rootCheckFunc(t, resp) // Check the capabilities using capabilities-self - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req = &logical.Request{ ClientToken: rootToken, Path: "capabilities-self", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) rootCheckFunc(t, resp) // Lookup the accessor of the root token @@ -535,17 +549,24 @@ func TestSystemBackend_PathCapabilities(t *testing.T) { } // Check the capabilities using capabilities-accessor endpoint - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req = &logical.Request{ Path: "capabilities-accessor", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, "accessor": te.Accessor, }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) rootCheckFunc(t, resp) // Create a non-root token @@ -566,32 +587,46 @@ func TestSystemBackend_PathCapabilities(t *testing.T) { } // Check the capabilities using a non-root token - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req = &logical.Request{ Path: "capabilities", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, "token": "tokenid", }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) nonRootCheckFunc(t, resp) // Check the capabilities of a non-root token using capabilities-self // endpoint - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req = &logical.Request{ ClientToken: "tokenid", Path: "capabilities-self", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) nonRootCheckFunc(t, resp) // Lookup the accessor of the non-root token @@ -602,17 +637,24 @@ func TestSystemBackend_PathCapabilities(t *testing.T) { // Check the capabilities using a non-root token using // capabilities-accessor endpoint - resp, err = b.HandleRequest(namespace.RootContext(nil), &logical.Request{ + req = &logical.Request{ Path: "capabilities-accessor", Operation: logical.UpdateOperation, Data: map[string]interface{}{ "paths": []string{path1, path2, path3, path4}, "accessor": te.Accessor, }, - }) + } + resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) nonRootCheckFunc(t, resp) }