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 <dhuckins@users.noreply.github.com>

* use nil for dynamic fields

Signed-off-by: Daniel Huckins <dhuckins@users.noreply.github.com>

* test auth endpoint schema

Signed-off-by: Daniel Huckins <dhuckins@users.noreply.github.com>

* kicking off ci

---------

Signed-off-by: Daniel Huckins <dhuckins@users.noreply.github.com>
Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com>
This commit is contained in:
Daniel Huckins 2023-02-16 15:03:19 -05:00 committed by GitHub
parent c48d36eb8a
commit a9d15f1252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 217 additions and 2 deletions

3
changelog/18465.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
openapi: add openapi response defintions to /sys/auth endpoints
```

View File

@ -2075,8 +2075,17 @@ func (b *SystemBackend) authPaths() []*framework.Path {
return []*framework.Path{ return []*framework.Path{
{ {
Pattern: "auth$", Pattern: "auth$",
Callbacks: map[logical.Operation]framework.OperationFunc{ Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: b.handleAuthTable, 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]), HelpSynopsis: strings.TrimSpace(sysHelp["auth-table"][0]),
HelpDescription: strings.TrimSpace(sysHelp["auth-table"][1]), HelpDescription: strings.TrimSpace(sysHelp["auth-table"][1]),
@ -2142,11 +2151,95 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Callback: b.handleAuthTuneRead, Callback: b.handleAuthTuneRead,
Summary: "Reads the given auth path's configuration.", 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`.", 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{ logical.UpdateOperation: &framework.PathOperation{
Callback: b.handleAuthTuneWrite, Callback: b.handleAuthTuneWrite,
Summary: "Tune configuration parameters for a given auth path.", 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`.", 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]), HelpSynopsis: strings.TrimSpace(sysHelp["auth_tune"][0]),
@ -2203,6 +2296,65 @@ func (b *SystemBackend) authPaths() []*framework.Path {
logical.ReadOperation: &framework.PathOperation{ logical.ReadOperation: &framework.PathOperation{
Callback: b.handleReadAuth, Callback: b.handleReadAuth,
Summary: "Read the configuration of the auth engine at the given path.", 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{ logical.UpdateOperation: &framework.PathOperation{
Callback: b.handleEnableAuth, 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. 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.`, 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{ logical.DeleteOperation: &framework.PathOperation{
Callback: b.handleDisableAuth, Callback: b.handleDisableAuth,
Summary: "Disable the auth method at the given auth path", 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]), HelpSynopsis: strings.TrimSpace(sysHelp["auth"][0]),

View File

@ -1904,6 +1904,12 @@ func TestSystemBackend_authTable(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
schema.ValidateResponse(
t,
schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation),
resp,
true,
)
exp := map[string]interface{}{ exp := map[string]interface{}{
"token/": map[string]interface{}{ "token/": map[string]interface{}{
@ -1935,6 +1941,13 @@ func TestSystemBackend_authTable(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) 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 { if diff := deep.Equal(resp.Data, exp["token/"]); diff != nil {
t.Fatal(diff) t.Fatal(diff)
} }
@ -1962,6 +1975,12 @@ func TestSystemBackend_enableAuth(t *testing.T) {
if resp != nil { if resp != nil {
t.Fatalf("bad: %v", resp) 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") req = logical.TestRequest(t, logical.ReadOperation, "auth")
resp, err = b.HandleRequest(namespace.RootContext(nil), req) resp, err = b.HandleRequest(namespace.RootContext(nil), req)
@ -1971,6 +1990,12 @@ func TestSystemBackend_enableAuth(t *testing.T) {
if resp == nil { if resp == nil {
t.Fatal("resp is 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{}{ exp := map[string]interface{}{
"foo/": map[string]interface{}{ "foo/": map[string]interface{}{
@ -2050,6 +2075,12 @@ func TestSystemBackend_disableAuth(t *testing.T) {
if resp != nil { if resp != nil {
t.Fatalf("bad: %v", resp) 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) { func TestSystemBackend_tuneAuth(t *testing.T) {
@ -2066,6 +2097,12 @@ func TestSystemBackend_tuneAuth(t *testing.T) {
if resp == nil { if resp == nil {
t.Fatal("resp is 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{}{ exp := map[string]interface{}{
"description": "token based credentials", "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) 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. // Register the plugin in the catalog, and then try the same request again.
{ {
tempDir, err := filepath.EvalSymlinks(t.TempDir()) tempDir, err := filepath.EvalSymlinks(t.TempDir())
@ -2120,6 +2164,12 @@ func TestSystemBackend_tuneAuth(t *testing.T) {
if resp == nil { if resp == nil {
t.Fatal("resp is 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"] != "" { if resp.Data["description"] != "" {
t.Fatalf("got: %#v expect: %#v", resp.Data["description"], "") t.Fatalf("got: %#v expect: %#v", resp.Data["description"], "")