From a9d15f12525b87955a55969ad4318702f011fb5a Mon Sep 17 00:00:00 2001 From: Daniel Huckins Date: Thu, 16 Feb 2023 15:03:19 -0500 Subject: [PATCH] VAULT-12112: add openapi response structures for `/sys/auth/*` endpoints (#18465) * added responses to /sys/auth/.../tune * add response structure for auth/... * added changelog * Update vault/logical_system_paths.go Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> * its TypeString Signed-off-by: Daniel Huckins * use nil for dynamic fields Signed-off-by: Daniel Huckins * test auth endpoint schema Signed-off-by: Daniel Huckins * kicking off ci --------- Signed-off-by: Daniel Huckins Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> --- changelog/18465.txt | 3 + vault/logical_system_paths.go | 166 +++++++++++++++++++++++++++++++++- vault/logical_system_test.go | 50 ++++++++++ 3 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 changelog/18465.txt diff --git a/changelog/18465.txt b/changelog/18465.txt new file mode 100644 index 000000000..928da99bc --- /dev/null +++ b/changelog/18465.txt @@ -0,0 +1,3 @@ +```release-note:improvement +openapi: add openapi response defintions to /sys/auth endpoints +``` \ No newline at end of file diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index 94d6e0cf3..e09e485b4 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -2075,8 +2075,17 @@ func (b *SystemBackend) authPaths() []*framework.Path { return []*framework.Path{ { Pattern: "auth$", - Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.ReadOperation: b.handleAuthTable, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.ReadOperation: &framework.PathOperation{ + Callback: b.handleAuthTable, + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + // response keys are dynamic + Fields: nil, + }}, + }, + }, }, HelpSynopsis: strings.TrimSpace(sysHelp["auth-table"][0]), HelpDescription: strings.TrimSpace(sysHelp["auth-table"][1]), @@ -2142,11 +2151,95 @@ func (b *SystemBackend) authPaths() []*framework.Path { Callback: b.handleAuthTuneRead, Summary: "Reads the given auth path's configuration.", Description: "This endpoint requires sudo capability on the final path, but the same functionality can be achieved without sudo via `sys/mounts/auth/[auth-path]/tune`.", + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + Fields: map[string]*framework.FieldSchema{ + "description": { + Type: framework.TypeString, + Required: true, + }, + "default_lease_ttl": { + Type: framework.TypeInt, + Required: true, + }, + "max_lease_ttl": { + Type: framework.TypeInt, + Required: true, + }, + "force_no_cache": { + Type: framework.TypeBool, + Required: true, + }, + "external_entropy_access": { + Type: framework.TypeBool, + Required: false, + }, + "token_type": { + Type: framework.TypeString, + Required: false, + }, + "audit_non_hmac_request_keys": { + Type: framework.TypeCommaStringSlice, + Required: false, + }, + "audit_non_hmac_response_keys": { + Type: framework.TypeCommaStringSlice, + Required: false, + }, + "listing_visibility": { + Type: framework.TypeString, + Required: false, + }, + "passthrough_request_headers": { + Type: framework.TypeCommaStringSlice, + Required: false, + }, + "allowed_response_headers": { + Type: framework.TypeCommaStringSlice, + Required: false, + }, + "allowed_managed_keys": { + Type: framework.TypeCommaStringSlice, + Required: false, + }, + "user_lockout_counter_reset_duration": { + Type: framework.TypeInt64, + Required: false, + }, + "user_lockout_threshold": { + Type: framework.TypeInt64, // uint64 + Required: false, + }, + "user_lockout_duration": { + Type: framework.TypeInt64, + Required: false, + }, + "user_lockout_disable": { + Type: framework.TypeBool, + Required: false, + }, + "options": { + Type: framework.TypeMap, + Required: false, + }, + "plugin_version": { + Type: framework.TypeString, + Required: false, + }, + }, + }}, + }, }, logical.UpdateOperation: &framework.PathOperation{ Callback: b.handleAuthTuneWrite, Summary: "Tune configuration parameters for a given auth path.", Description: "This endpoint requires sudo capability on the final path, but the same functionality can be achieved without sudo via `sys/mounts/auth/[auth-path]/tune`.", + Responses: map[int][]framework.Response{ + http.StatusNoContent: {{ + Description: "OK", + }}, + }, }, }, HelpSynopsis: strings.TrimSpace(sysHelp["auth_tune"][0]), @@ -2203,6 +2296,65 @@ func (b *SystemBackend) authPaths() []*framework.Path { logical.ReadOperation: &framework.PathOperation{ Callback: b.handleReadAuth, Summary: "Read the configuration of the auth engine at the given path.", + Responses: map[int][]framework.Response{ + http.StatusOK: {{ + Description: "OK", + Fields: map[string]*framework.FieldSchema{ + "type": { + Type: framework.TypeString, + Required: true, + }, + "description": { + Type: framework.TypeString, + Required: true, + }, + "accessor": { + Type: framework.TypeString, + Required: true, + }, + "local": { + Type: framework.TypeBool, + Required: true, + }, + "seal_wrap": { + Type: framework.TypeBool, + Required: true, + }, + "external_entropy_access": { + Type: framework.TypeBool, + Required: true, + }, + "options": { + Type: framework.TypeMap, + Required: true, + }, + "uuid": { + Type: framework.TypeString, + Required: true, + }, + "plugin_version": { + Type: framework.TypeString, + Required: true, + }, + "running_plugin_version": { + Type: framework.TypeString, + Required: true, + }, + "running_sha256": { + Type: framework.TypeString, + Required: true, + }, + "deprecation_status": { + Type: framework.TypeString, + Required: false, + }, + "config": { + Type: framework.TypeMap, + Required: true, + }, + }, + }}, + }, }, logical.UpdateOperation: &framework.PathOperation{ Callback: b.handleEnableAuth, @@ -2210,10 +2362,20 @@ func (b *SystemBackend) authPaths() []*framework.Path { Description: `After enabling, the auth method can be accessed and configured via the auth path specified as part of the URL. This auth path will be nested under the auth prefix. For example, enable the "foo" auth method will make it accessible at /auth/foo.`, + Responses: map[int][]framework.Response{ + http.StatusNoContent: {{ + Description: "OK", + }}, + }, }, logical.DeleteOperation: &framework.PathOperation{ Callback: b.handleDisableAuth, Summary: "Disable the auth method at the given auth path", + Responses: map[int][]framework.Response{ + http.StatusNoContent: {{ + Description: "OK", + }}, + }, }, }, HelpSynopsis: strings.TrimSpace(sysHelp["auth"][0]), diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index c872f0c09..4f18c3a9a 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -1904,6 +1904,12 @@ func TestSystemBackend_authTable(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) exp := map[string]interface{}{ "token/": map[string]interface{}{ @@ -1935,6 +1941,13 @@ func TestSystemBackend_authTable(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) + if diff := deep.Equal(resp.Data, exp["token/"]); diff != nil { t.Fatal(diff) } @@ -1962,6 +1975,12 @@ func TestSystemBackend_enableAuth(t *testing.T) { if resp != nil { t.Fatalf("bad: %v", resp) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) req = logical.TestRequest(t, logical.ReadOperation, "auth") resp, err = b.HandleRequest(namespace.RootContext(nil), req) @@ -1971,6 +1990,12 @@ func TestSystemBackend_enableAuth(t *testing.T) { if resp == nil { t.Fatal("resp is nil") } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) exp := map[string]interface{}{ "foo/": map[string]interface{}{ @@ -2050,6 +2075,12 @@ func TestSystemBackend_disableAuth(t *testing.T) { if resp != nil { t.Fatalf("bad: %v", resp) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) } func TestSystemBackend_tuneAuth(t *testing.T) { @@ -2066,6 +2097,12 @@ func TestSystemBackend_tuneAuth(t *testing.T) { if resp == nil { t.Fatal("resp is nil") } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) exp := map[string]interface{}{ "description": "token based credentials", @@ -2087,6 +2124,13 @@ func TestSystemBackend_tuneAuth(t *testing.T) { t.Fatalf("expected tune request to fail, but got resp: %#v, err: %s", resp, err) } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) + // Register the plugin in the catalog, and then try the same request again. { tempDir, err := filepath.EvalSymlinks(t.TempDir()) @@ -2120,6 +2164,12 @@ func TestSystemBackend_tuneAuth(t *testing.T) { if resp == nil { t.Fatal("resp is nil") } + schema.ValidateResponse( + t, + schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation), + resp, + true, + ) if resp.Data["description"] != "" { t.Fatalf("got: %#v expect: %#v", resp.Data["description"], "")