added OpenAPI response objects for sys endpoints (#18633)
* added response objects for sys 3 section * Update vault/logical_system_paths.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_raw.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_system_paths.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_system_quotas.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_system_quotas.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_system_quotas.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * add tests and update based on reviews * added changelog file * finally got make fmt to work... * fixed copy pasta test case * updated based on review * Update vault/logical_system_quotas.go Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> * Update vault/logical_system_test.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> * Update vault/logical_system_test.go Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> --------- Co-authored-by: lursu <leland.ursu@hashicorp.com> Co-authored-by: Daniel Huckins <dhuckins@users.noreply.github.com> Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com>
This commit is contained in:
parent
6425130605
commit
0704127020
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
openapi: Add openapi response definitions to /sys defined endpoints.
|
||||
```
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
|
@ -315,23 +316,60 @@ func rawPaths(prefix string, r *RawBackend) []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: r.handleRawRead,
|
||||
Summary: "Read the value of the key at the given path.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"value": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Read the value of the key at the given path.",
|
||||
},
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: r.handleRawWrite,
|
||||
Summary: "Update the value of the key at the given path.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
Summary: "Update the value of the key at the given path.",
|
||||
},
|
||||
logical.CreateOperation: &framework.PathOperation{
|
||||
Callback: r.handleRawWrite,
|
||||
Summary: "Create a key with value at the given path.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
Summary: "Create a key with value at the given path.",
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: r.handleRawDelete,
|
||||
Summary: "Delete the key with given path.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
Summary: "Delete the key with given path.",
|
||||
},
|
||||
logical.ListOperation: &framework.PathOperation{
|
||||
Callback: r.handleRawList,
|
||||
Summary: "Return a list keys for a given path prefix.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"keys": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Return a list keys for a given path prefix.",
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -375,6 +375,47 @@ func (b *SystemBackend) configPaths() []*framework.Path {
|
|||
}
|
||||
|
||||
func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
||||
respFields := map[string]*framework.FieldSchema{
|
||||
"nounce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"started": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"t": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"n": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"progress": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"required": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"verification_required": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"verification_nonce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"backup": {
|
||||
Type: framework.TypeBool,
|
||||
},
|
||||
"pgp_fingerprints": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
},
|
||||
}
|
||||
|
||||
return []*framework.Path{
|
||||
{
|
||||
Pattern: "rekey/init",
|
||||
|
@ -404,13 +445,30 @@ func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
|||
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: respFields,
|
||||
}},
|
||||
},
|
||||
Summary: "Reads the configuration and progress of the current rekey attempt.",
|
||||
},
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: respFields,
|
||||
}},
|
||||
},
|
||||
Summary: "Initializes a new rekey attempt.",
|
||||
Description: "Only a single rekey attempt can take place at a time, and changing the parameters of a rekey requires canceling and starting a new rekey, which will also provide a new nonce.",
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
Summary: "Cancels any in-progress rekey.",
|
||||
Description: "This clears the rekey settings as well as any progress made. This must be called to change the parameters of the rekey. Note: verification is still a part of a rekey. If rekeying is canceled during the verification flow, the current unseal keys remain valid.",
|
||||
},
|
||||
|
@ -424,11 +482,35 @@ func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.handleRekeyRetrieveBarrier,
|
||||
Summary: "Return the backup copy of PGP-encrypted unseal keys.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nonce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"keys": {
|
||||
Type: framework.TypeMap,
|
||||
Required: true,
|
||||
},
|
||||
"keys_base64": {
|
||||
Type: framework.TypeMap,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Return the backup copy of PGP-encrypted unseal keys.",
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: b.handleRekeyDeleteBarrier,
|
||||
Summary: "Delete the backup copy of PGP-encrypted unseal keys.",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
Summary: "Delete the backup copy of PGP-encrypted unseal keys.",
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -441,9 +523,37 @@ func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
|||
|
||||
Fields: map[string]*framework.FieldSchema{},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: b.handleRekeyRetrieveRecovery,
|
||||
logical.DeleteOperation: b.handleRekeyDeleteRecovery,
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.handleRekeyRetrieveRecovery,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nonce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"keys": {
|
||||
Type: framework.TypeMap,
|
||||
Required: true,
|
||||
},
|
||||
"keys_base64": {
|
||||
Type: framework.TypeMap,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: b.handleRekeyDeleteRecovery,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["rekey_backup"][0]),
|
||||
|
@ -465,6 +575,55 @@ func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
|||
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nounce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"complete": {
|
||||
Type: framework.TypeBool,
|
||||
},
|
||||
"started": {
|
||||
Type: framework.TypeString,
|
||||
},
|
||||
"t": {
|
||||
Type: framework.TypeInt,
|
||||
},
|
||||
"n": {
|
||||
Type: framework.TypeInt,
|
||||
},
|
||||
"progress": {
|
||||
Type: framework.TypeInt,
|
||||
},
|
||||
"required": {
|
||||
Type: framework.TypeInt,
|
||||
},
|
||||
"keys": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
},
|
||||
"keys_base64": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
},
|
||||
"verification_required": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"verification_nonce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"backup": {
|
||||
Type: framework.TypeBool,
|
||||
},
|
||||
"pgp_fingerprints": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Enter a single unseal key share to progress the rekey of the Vault.",
|
||||
},
|
||||
},
|
||||
|
@ -485,13 +644,81 @@ func (b *SystemBackend) rekeyPaths() []*framework.Path {
|
|||
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nounce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"started": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"t": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"n": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"progress": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Read the configuration and progress of the current rekey verification attempt.",
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nounce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"started": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"t": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"n": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"progress": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Cancel any in-progress rekey verification operation.",
|
||||
Description: "This clears any progress made and resets the nonce. Unlike a `DELETE` against `sys/rekey/init`, this only resets the current verification operation, not the entire rekey atttempt.",
|
||||
},
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"nounce": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"complete": {
|
||||
Type: framework.TypeBool,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Enter a single new key share to progress the rekey verification operation.",
|
||||
},
|
||||
},
|
||||
|
@ -1706,7 +1933,18 @@ func (b *SystemBackend) remountPaths() []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.handleRemount,
|
||||
Summary: "Initiate a mount migration",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"migration_id": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Initiate a mount migration",
|
||||
},
|
||||
},
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["remount"][0]),
|
||||
|
@ -1725,7 +1963,22 @@ func (b *SystemBackend) remountPaths() []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.handleRemountStatusCheck,
|
||||
Summary: "Check status of a mount migration",
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"migration_id": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"migration_info": {
|
||||
Type: framework.TypeMap,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Summary: "Check status of a mount migration",
|
||||
},
|
||||
},
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["remount-status"][0]),
|
||||
|
|
|
@ -2,6 +2,7 @@ package vault
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -34,9 +35,33 @@ func (b *SystemBackend) quotasPaths() []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.handleQuotasConfigUpdate(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.handleQuotasConfigRead(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"enable_rate_limit_audit_logging": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"enable_rate_limit_response_headers": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"rate_limit_exempt_paths": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
HelpSynopsis: strings.TrimSpace(quotasHelp["quotas-config"][0]),
|
||||
|
@ -47,6 +72,17 @@ func (b *SystemBackend) quotasPaths() []*framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ListOperation: &framework.PathOperation{
|
||||
Callback: b.handleRateLimitQuotasList(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"keys": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
HelpSynopsis: strings.TrimSpace(quotasHelp["rate-limit-list"][0]),
|
||||
|
@ -92,12 +128,57 @@ from any further requests until after the 'block_interval' has elapsed.`,
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.handleRateLimitQuotasUpdate(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: http.StatusText(http.StatusNoContent),
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.handleRateLimitQuotasRead(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"type": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"name": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"path": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"role": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"rate": {
|
||||
Type: framework.TypeFloat,
|
||||
Required: true,
|
||||
},
|
||||
"interval": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"block_interval": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: b.handleRateLimitQuotasDelete(),
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
HelpSynopsis: strings.TrimSpace(quotasHelp["rate-limit"][0]),
|
||||
|
|
|
@ -758,12 +758,29 @@ func TestSystemBackend_remount_auth(t *testing.T) {
|
|||
req.Data["config"] = structs.Map(MountConfig{})
|
||||
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
|
||||
|
||||
// validate the response structure for remount named read
|
||||
schema.ValidateResponse(
|
||||
t,
|
||||
schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation),
|
||||
resp,
|
||||
true,
|
||||
)
|
||||
|
||||
corehelpers.RetryUntil(t, 5*time.Second, func() error {
|
||||
req = logical.TestRequest(t, logical.ReadOperation, fmt.Sprintf("remount/status/%s", resp.Data["migration_id"]))
|
||||
resp, err = b.HandleRequest(namespace.RootContext(nil), req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// validate the response structure for remount status read
|
||||
schema.ValidateResponse(
|
||||
t,
|
||||
schema.GetResponseSchema(t, b.(*SystemBackend).Route(req.Path), req.Operation),
|
||||
resp,
|
||||
true,
|
||||
)
|
||||
|
||||
migrationInfo := resp.Data["migration_info"].(*MountMigrationInfo)
|
||||
if migrationInfo.MigrationStatus != MigrationSuccessStatus.String() {
|
||||
return fmt.Errorf("Expected migration status to be successful, got %q", migrationInfo.MigrationStatus)
|
||||
|
|
Loading…
Reference in New Issue