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"], "")