2015-03-15 21:42:05 +00:00
|
|
|
package vault
|
|
|
|
|
|
|
|
import (
|
2018-01-08 18:31:38 +00:00
|
|
|
"context"
|
2017-10-20 14:59:17 +00:00
|
|
|
"crypto/sha256"
|
|
|
|
"crypto/sha512"
|
2016-08-15 20:01:15 +00:00
|
|
|
"encoding/base64"
|
|
|
|
"encoding/hex"
|
2016-09-29 04:01:28 +00:00
|
|
|
"encoding/json"
|
2017-11-13 20:31:32 +00:00
|
|
|
"errors"
|
2015-05-28 17:24:41 +00:00
|
|
|
"fmt"
|
2017-10-20 14:59:17 +00:00
|
|
|
"hash"
|
2018-03-27 20:23:33 +00:00
|
|
|
"net/http"
|
2018-01-18 00:19:28 +00:00
|
|
|
"path/filepath"
|
2017-10-20 14:59:17 +00:00
|
|
|
"strconv"
|
2015-03-15 21:42:05 +00:00
|
|
|
"strings"
|
2016-05-03 18:24:04 +00:00
|
|
|
"sync"
|
2015-03-16 23:11:55 +00:00
|
|
|
"time"
|
2015-03-15 21:42:05 +00:00
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
"github.com/hashicorp/errwrap"
|
2018-04-03 00:46:59 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2017-10-20 14:59:17 +00:00
|
|
|
uuid "github.com/hashicorp/go-uuid"
|
2018-02-09 23:43:48 +00:00
|
|
|
"github.com/hashicorp/vault/helper/compressutil"
|
2017-02-16 21:29:30 +00:00
|
|
|
"github.com/hashicorp/vault/helper/consts"
|
2017-03-07 16:21:22 +00:00
|
|
|
"github.com/hashicorp/vault/helper/parseutil"
|
2017-04-24 19:15:01 +00:00
|
|
|
"github.com/hashicorp/vault/helper/wrapping"
|
2015-03-15 21:42:05 +00:00
|
|
|
"github.com/hashicorp/vault/logical"
|
2015-03-16 00:35:59 +00:00
|
|
|
"github.com/hashicorp/vault/logical/framework"
|
2015-08-31 18:27:49 +00:00
|
|
|
"github.com/mitchellh/mapstructure"
|
2015-03-15 21:42:05 +00:00
|
|
|
)
|
|
|
|
|
2015-05-28 17:24:41 +00:00
|
|
|
var (
|
|
|
|
// protectedPaths cannot be accessed via the raw APIs.
|
|
|
|
// This is both for security and to prevent disrupting Vault.
|
|
|
|
protectedPaths = []string{
|
2017-09-15 04:21:35 +00:00
|
|
|
keyringPath,
|
2017-10-23 19:35:28 +00:00
|
|
|
coreLocalClusterInfoPath,
|
2015-05-28 17:24:41 +00:00
|
|
|
}
|
2017-02-17 01:13:19 +00:00
|
|
|
|
2017-02-17 04:23:21 +00:00
|
|
|
replicationPaths = func(b *SystemBackend) []*framework.Path {
|
|
|
|
return []*framework.Path{
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "replication/status",
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2018-01-08 18:31:38 +00:00
|
|
|
logical.ReadOperation: func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-02-17 04:23:21 +00:00
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
2018-01-23 02:44:38 +00:00
|
|
|
"mode": "disabled",
|
2017-02-17 04:23:21 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
},
|
2017-02-17 01:13:19 +00:00
|
|
|
},
|
|
|
|
},
|
2017-02-17 04:23:21 +00:00
|
|
|
}
|
2017-02-17 01:13:19 +00:00
|
|
|
}
|
2015-05-28 17:24:41 +00:00
|
|
|
)
|
|
|
|
|
2018-04-03 00:46:59 +00:00
|
|
|
func NewSystemBackend(core *Core, logger log.Logger) *SystemBackend {
|
2015-08-27 15:51:35 +00:00
|
|
|
b := &SystemBackend{
|
2017-10-23 20:49:46 +00:00
|
|
|
Core: core,
|
2018-04-03 00:46:59 +00:00
|
|
|
logger: logger,
|
2015-08-27 15:51:35 +00:00
|
|
|
}
|
2015-09-04 20:58:12 +00:00
|
|
|
|
2015-05-16 00:19:32 +00:00
|
|
|
b.Backend = &framework.Backend{
|
2015-04-04 04:00:23 +00:00
|
|
|
Help: strings.TrimSpace(sysHelpRoot),
|
|
|
|
|
2015-03-31 00:46:18 +00:00
|
|
|
PathsSpecial: &logical.Paths{
|
|
|
|
Root: []string{
|
|
|
|
"auth/*",
|
|
|
|
"remount",
|
2015-03-31 23:45:00 +00:00
|
|
|
"audit",
|
|
|
|
"audit/*",
|
2017-09-15 04:21:35 +00:00
|
|
|
"raw",
|
2015-04-02 00:44:43 +00:00
|
|
|
"raw/*",
|
2017-02-16 21:29:30 +00:00
|
|
|
"replication/primary/secondary-token",
|
2017-02-17 04:36:06 +00:00
|
|
|
"replication/reindex",
|
2015-05-28 00:53:42 +00:00
|
|
|
"rotate",
|
2017-06-17 05:26:25 +00:00
|
|
|
"config/cors",
|
2017-02-02 19:49:20 +00:00
|
|
|
"config/auditing/*",
|
2018-03-27 20:23:33 +00:00
|
|
|
"config/ui/headers/*",
|
2017-04-24 18:35:32 +00:00
|
|
|
"plugins/catalog/*",
|
2017-05-04 02:03:42 +00:00
|
|
|
"revoke-prefix/*",
|
2017-07-25 15:59:43 +00:00
|
|
|
"revoke-force/*",
|
2017-05-04 02:03:42 +00:00
|
|
|
"leases/revoke-prefix/*",
|
|
|
|
"leases/revoke-force/*",
|
|
|
|
"leases/lookup/*",
|
2015-03-31 00:46:18 +00:00
|
|
|
},
|
2017-01-04 21:44:03 +00:00
|
|
|
|
|
|
|
Unauthenticated: []string{
|
2017-07-31 20:16:16 +00:00
|
|
|
"wrapping/lookup",
|
2017-01-04 21:44:03 +00:00
|
|
|
"wrapping/pubkey",
|
2017-02-16 21:29:30 +00:00
|
|
|
"replication/status",
|
2018-03-20 03:16:33 +00:00
|
|
|
"internal/ui/mounts",
|
2017-01-04 21:44:03 +00:00
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Paths: []*framework.Path{
|
2016-03-17 16:55:38 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "capabilities-accessor$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"accessor": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2016-03-17 19:23:36 +00:00
|
|
|
Description: "Accessor of the token for which capabilities are being queried.",
|
2016-03-17 16:55:38 +00:00
|
|
|
},
|
|
|
|
"path": &framework.FieldSchema{
|
2018-03-01 16:14:56 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "(DEPRECATED) Path on which capabilities are being queried. Use 'paths' instead.",
|
|
|
|
},
|
|
|
|
"paths": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "Paths on which capabilities are being queried.",
|
2016-03-17 16:55:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-03-17 17:33:49 +00:00
|
|
|
logical.UpdateOperation: b.handleCapabilitiesAccessor,
|
2016-03-17 16:55:38 +00:00
|
|
|
},
|
|
|
|
|
2016-03-17 19:23:36 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["capabilities_accessor"][0]),
|
2016-03-18 03:01:28 +00:00
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["capabilities_accessor"][1]),
|
2016-03-17 16:55:38 +00:00
|
|
|
},
|
2016-03-18 03:01:28 +00:00
|
|
|
|
2017-06-17 04:04:55 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "config/cors$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"enable": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Description: "Enables or disables CORS headers on requests.",
|
|
|
|
},
|
|
|
|
"allowed_origins": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
2017-06-17 05:26:25 +00:00
|
|
|
Description: "A comma-separated string or array of strings indicating origins that may make cross-origin requests.",
|
2017-06-17 04:04:55 +00:00
|
|
|
},
|
2017-08-07 14:03:30 +00:00
|
|
|
"allowed_headers": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "A comma-separated string or array of strings indicating headers that are allowed on cross-origin requests.",
|
|
|
|
},
|
2017-06-17 04:04:55 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleCORSRead,
|
|
|
|
logical.UpdateOperation: b.handleCORSUpdate,
|
|
|
|
logical.DeleteOperation: b.handleCORSDelete,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["config/cors"][0]),
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["config/cors"][1]),
|
|
|
|
},
|
|
|
|
|
2018-03-27 20:23:33 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "config/ui/headers/" + framework.GenericNameRegex("header"),
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"header": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "The name of the header.",
|
|
|
|
},
|
|
|
|
"values": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeStringSlice,
|
|
|
|
Description: "The values to set the header.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleConfigUIHeadersRead,
|
|
|
|
logical.UpdateOperation: b.handleConfigUIHeadersUpdate,
|
|
|
|
logical.DeleteOperation: b.handleConfigUIHeadersDelete,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["config/ui/headers"][0]),
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["config/ui/headers"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "config/ui/headers/$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ListOperation: b.handleConfigUIHeadersList,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["config/ui/headers"][0]),
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["config/ui/headers"][1]),
|
|
|
|
},
|
|
|
|
|
2016-03-17 17:33:49 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "capabilities$",
|
|
|
|
|
2016-03-18 02:52:03 +00:00
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"token": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "Token for which capabilities are being queried.",
|
|
|
|
},
|
|
|
|
"path": &framework.FieldSchema{
|
2018-03-01 16:14:56 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "(DEPRECATED) Path on which capabilities are being queried. Use 'paths' instead.",
|
|
|
|
},
|
|
|
|
"paths": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "Paths on which capabilities are being queried.",
|
2016-03-18 02:52:03 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleCapabilities,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["capabilities"][0]),
|
2016-03-18 03:01:28 +00:00
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["capabilities"][1]),
|
2016-03-18 02:52:03 +00:00
|
|
|
},
|
2016-04-13 21:15:54 +00:00
|
|
|
|
2016-03-18 02:52:03 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "capabilities-self$",
|
|
|
|
|
2016-03-17 17:33:49 +00:00
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"token": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2016-03-17 19:23:36 +00:00
|
|
|
Description: "Token for which capabilities are being queried.",
|
2016-03-17 17:33:49 +00:00
|
|
|
},
|
|
|
|
"path": &framework.FieldSchema{
|
2018-03-01 16:14:56 +00:00
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "(DEPRECATED) Path on which capabilities are being queried. Use 'paths' instead.",
|
|
|
|
},
|
|
|
|
"paths": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: "Paths on which capabilities are being queried.",
|
2016-03-17 17:33:49 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleCapabilities,
|
|
|
|
},
|
|
|
|
|
2016-03-18 03:01:28 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["capabilities_self"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["capabilities_self"][1]),
|
2016-03-17 17:33:49 +00:00
|
|
|
},
|
2016-03-17 16:55:38 +00:00
|
|
|
|
2016-04-13 21:15:54 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "generate-root(/attempt)?$",
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["generate-root"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["generate-root"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "init$",
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["init"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["init"][1]),
|
|
|
|
},
|
|
|
|
|
2015-12-16 21:56:15 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "rekey/backup$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-04-04 14:44:22 +00:00
|
|
|
logical.ReadOperation: b.handleRekeyRetrieveBarrier,
|
|
|
|
logical.DeleteOperation: b.handleRekeyDeleteBarrier,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["rekey_backup"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["rekey_backup"][0]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "rekey/recovery-key-backup$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleRekeyRetrieveRecovery,
|
|
|
|
logical.DeleteOperation: b.handleRekeyDeleteRecovery,
|
2015-12-16 21:56:15 +00:00
|
|
|
},
|
|
|
|
|
2016-03-10 02:04:54 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["rekey_backup"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["rekey_backup"][0]),
|
2015-12-16 21:56:15 +00:00
|
|
|
},
|
|
|
|
|
2016-06-15 16:35:30 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "auth/(?P<path>.+?)/tune$",
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_tune"][0]),
|
|
|
|
},
|
|
|
|
"default_lease_ttl": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
|
|
|
|
},
|
|
|
|
"max_lease_ttl": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
|
|
|
|
},
|
2017-09-05 14:57:25 +00:00
|
|
|
"description": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
|
|
|
|
},
|
2018-03-02 17:18:39 +00:00
|
|
|
"audit_non_hmac_request_keys": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
|
|
|
|
},
|
|
|
|
"audit_non_hmac_response_keys": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
|
|
|
|
},
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeKVPairs,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
|
|
|
|
},
|
2018-03-20 03:16:33 +00:00
|
|
|
"listing_visibility": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
|
|
|
|
},
|
2018-03-21 23:56:47 +00:00
|
|
|
"passthrough_request_headers": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
|
|
|
|
},
|
2016-06-15 16:35:30 +00:00
|
|
|
},
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleAuthTuneRead,
|
|
|
|
logical.UpdateOperation: b.handleAuthTuneWrite,
|
|
|
|
},
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["auth_tune"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["auth_tune"][1]),
|
|
|
|
},
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
&framework.Path{
|
2015-09-02 19:56:58 +00:00
|
|
|
Pattern: "mounts/(?P<path>.+?)/tune$",
|
2015-03-16 00:35:59 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
|
|
|
|
},
|
2015-09-09 19:24:45 +00:00
|
|
|
"default_lease_ttl": &framework.FieldSchema{
|
2015-09-25 13:46:20 +00:00
|
|
|
Type: framework.TypeString,
|
2015-09-09 19:24:45 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
|
|
|
|
},
|
|
|
|
"max_lease_ttl": &framework.FieldSchema{
|
2015-09-25 13:46:20 +00:00
|
|
|
Type: framework.TypeString,
|
2015-09-09 19:24:45 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
|
2015-09-02 19:56:58 +00:00
|
|
|
},
|
2017-09-05 14:57:25 +00:00
|
|
|
"description": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
|
|
|
|
},
|
2018-03-02 17:18:39 +00:00
|
|
|
"audit_non_hmac_request_keys": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
|
|
|
|
},
|
|
|
|
"audit_non_hmac_response_keys": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
|
|
|
|
},
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeKVPairs,
|
|
|
|
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
|
|
|
|
},
|
2018-03-20 03:16:33 +00:00
|
|
|
"listing_visibility": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
|
|
|
|
},
|
2018-03-21 23:56:47 +00:00
|
|
|
"passthrough_request_headers": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
|
|
|
|
},
|
2015-09-02 19:56:58 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 20:10:05 +00:00
|
|
|
logical.ReadOperation: b.handleMountTuneRead,
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleMountTuneWrite,
|
2015-09-02 19:56:58 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["mount_tune"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["mount_tune"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "mounts/(?P<path>.+?)",
|
2015-03-16 00:35:59 +00:00
|
|
|
|
2015-09-02 19:56:58 +00:00
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
|
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
"type": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
|
|
|
|
},
|
|
|
|
"description": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
|
|
|
|
},
|
2015-08-31 18:27:49 +00:00
|
|
|
"config": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeMap,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
|
|
|
|
},
|
2017-02-16 21:29:30 +00:00
|
|
|
"local": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Default: false,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
|
|
|
},
|
2017-11-13 16:22:22 +00:00
|
|
|
"seal_wrap": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Default: false,
|
|
|
|
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
|
|
|
|
},
|
2017-08-31 16:16:59 +00:00
|
|
|
"plugin_name": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_plugin_name"][0]),
|
|
|
|
},
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeKVPairs,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_options"][0]),
|
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 20:10:05 +00:00
|
|
|
logical.UpdateOperation: b.handleMount,
|
2015-03-16 00:35:59 +00:00
|
|
|
logical.DeleteOperation: b.handleUnmount,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["mount"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["mount"][1]),
|
|
|
|
},
|
|
|
|
|
2015-09-03 12:54:59 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "mounts$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleMountTable,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["mounts"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["mounts"][1]),
|
|
|
|
},
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "remount",
|
|
|
|
|
2015-03-19 14:05:22 +00:00
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"from": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2016-04-13 21:15:54 +00:00
|
|
|
Description: "The previous mount point.",
|
2015-03-19 14:05:22 +00:00
|
|
|
},
|
|
|
|
"to": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2016-04-13 21:15:54 +00:00
|
|
|
Description: "The new mount point.",
|
2015-03-19 14:05:22 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleRemount,
|
2015-03-16 00:35:59 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["remount"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["remount"][1]),
|
|
|
|
},
|
2015-03-16 23:11:55 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
2017-05-04 02:03:42 +00:00
|
|
|
Pattern: "leases/lookup/(?P<prefix>.+?)?",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"prefix": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["leases-list-prefix"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ListOperation: b.handleLeaseLookupList,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["leases"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["leases"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "leases/lookup",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"lease_id": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["lease_id"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleLeaseLookup,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["leases"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["leases"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "(leases/)?renew" + framework.OptionalParamRegex("url_lease_id"),
|
2015-03-16 23:11:55 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
2016-08-08 22:34:00 +00:00
|
|
|
"url_lease_id": &framework.FieldSchema{
|
2016-08-08 22:00:44 +00:00
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["lease_id"][0]),
|
|
|
|
},
|
2015-04-08 20:35:32 +00:00
|
|
|
"lease_id": &framework.FieldSchema{
|
2015-03-16 23:11:55 +00:00
|
|
|
Type: framework.TypeString,
|
2015-04-08 20:35:32 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["lease_id"][0]),
|
2015-03-16 23:11:55 +00:00
|
|
|
},
|
|
|
|
"increment": &framework.FieldSchema{
|
2015-06-17 22:58:20 +00:00
|
|
|
Type: framework.TypeDurationSecond,
|
2015-03-16 23:11:55 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["increment"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleRenew,
|
2015-03-16 23:11:55 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["renew"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["renew"][1]),
|
|
|
|
},
|
2015-03-16 23:26:34 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
2017-05-04 02:03:42 +00:00
|
|
|
Pattern: "(leases/)?revoke" + framework.OptionalParamRegex("url_lease_id"),
|
2015-03-16 23:26:34 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
2017-04-27 14:47:43 +00:00
|
|
|
"url_lease_id": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["lease_id"][0]),
|
|
|
|
},
|
2015-04-08 20:35:32 +00:00
|
|
|
"lease_id": &framework.FieldSchema{
|
2015-03-16 23:26:34 +00:00
|
|
|
Type: framework.TypeString,
|
2015-04-08 20:35:32 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["lease_id"][0]),
|
2015-03-16 23:26:34 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleRevoke,
|
2015-03-16 23:26:34 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["revoke"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["revoke"][1]),
|
|
|
|
},
|
2015-03-16 23:33:48 +00:00
|
|
|
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
&framework.Path{
|
2017-05-04 02:03:42 +00:00
|
|
|
Pattern: "(leases/)?revoke-force/(?P<prefix>.+)",
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"prefix": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["revoke-force-path"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleRevokeForce,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["revoke-force"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["revoke-force"][1]),
|
|
|
|
},
|
|
|
|
|
2015-03-16 23:33:48 +00:00
|
|
|
&framework.Path{
|
2017-05-04 02:03:42 +00:00
|
|
|
Pattern: "(leases/)?revoke-prefix/(?P<prefix>.+)",
|
2015-03-16 23:33:48 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"prefix": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["revoke-prefix-path"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleRevokePrefix,
|
2015-03-16 23:33:48 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["revoke-prefix"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["revoke-prefix"][1]),
|
|
|
|
},
|
2015-03-20 19:48:19 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
2017-05-04 13:40:11 +00:00
|
|
|
Pattern: "leases/tidy$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleTidyLeases,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["tidy_leases"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["tidy_leases"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
2015-03-20 19:48:19 +00:00
|
|
|
Pattern: "auth$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleAuthTable,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["auth-table"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["auth-table"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "auth/(?P<path>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_path"][0]),
|
|
|
|
},
|
|
|
|
"type": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_type"][0]),
|
|
|
|
},
|
|
|
|
"description": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
|
|
|
|
},
|
2017-08-31 16:16:59 +00:00
|
|
|
"config": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeMap,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_config"][0]),
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
},
|
2017-02-16 21:29:30 +00:00
|
|
|
"local": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Default: false,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
|
|
|
},
|
2017-11-13 16:22:22 +00:00
|
|
|
"seal_wrap": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Default: false,
|
|
|
|
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
|
|
|
|
},
|
2017-08-31 16:16:59 +00:00
|
|
|
"plugin_name": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_plugin"][0]),
|
|
|
|
},
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeKVPairs,
|
|
|
|
Description: strings.TrimSpace(sysHelp["auth_options"][0]),
|
|
|
|
},
|
2015-03-20 19:48:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 20:10:05 +00:00
|
|
|
logical.UpdateOperation: b.handleEnableAuth,
|
2015-03-20 19:48:19 +00:00
|
|
|
logical.DeleteOperation: b.handleDisableAuth,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["auth"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["auth"][1]),
|
|
|
|
},
|
2015-03-23 21:43:31 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
2017-10-23 19:35:28 +00:00
|
|
|
Pattern: "policy/?$",
|
2015-03-23 21:43:31 +00:00
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handlePolicyList,
|
2016-03-02 19:16:54 +00:00
|
|
|
logical.ListOperation: b.handlePolicyList,
|
2015-03-23 21:43:31 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["policy-list"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["policy-list"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "policy/(?P<name>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"name": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["policy-name"][0]),
|
|
|
|
},
|
|
|
|
"rules": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["policy-rules"][0]),
|
|
|
|
},
|
2017-10-23 19:35:28 +00:00
|
|
|
"policy": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["policy-rules"][0]),
|
|
|
|
},
|
2015-03-23 21:43:31 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handlePolicyRead,
|
2016-01-07 20:10:05 +00:00
|
|
|
logical.UpdateOperation: b.handlePolicySet,
|
2015-03-23 21:43:31 +00:00
|
|
|
logical.DeleteOperation: b.handlePolicyDelete,
|
|
|
|
},
|
2017-10-23 19:35:28 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "policies/acl/?$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ListOperation: b.handlePoliciesList(PolicyTypeACL),
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["policy-list"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["policy-list"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "policies/acl/(?P<name>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"name": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["policy-name"][0]),
|
|
|
|
},
|
|
|
|
"policy": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["policy-rules"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handlePoliciesRead(PolicyTypeACL),
|
|
|
|
logical.UpdateOperation: b.handlePoliciesSet(PolicyTypeACL),
|
|
|
|
logical.DeleteOperation: b.handlePoliciesDelete(PolicyTypeACL),
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["policy"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["policy"][1]),
|
|
|
|
},
|
|
|
|
|
2016-04-13 21:15:54 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "seal-status$",
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["seal-status"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["seal-status"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "seal$",
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["seal"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["seal"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "unseal$",
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["unseal"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["unseal"][1]),
|
|
|
|
},
|
|
|
|
|
2015-11-19 01:26:03 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "audit-hash/(?P<path>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["audit_path"][0]),
|
|
|
|
},
|
|
|
|
|
|
|
|
"input": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleAuditHash,
|
2015-11-19 01:26:03 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["audit-hash"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["audit-hash"][1]),
|
|
|
|
},
|
|
|
|
|
2015-03-31 23:45:00 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "audit$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleAuditTable,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["audit-table"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["audit-table"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "audit/(?P<path>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["audit_path"][0]),
|
|
|
|
},
|
|
|
|
"type": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["audit_type"][0]),
|
|
|
|
},
|
|
|
|
"description": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["audit_desc"][0]),
|
|
|
|
},
|
|
|
|
"options": &framework.FieldSchema{
|
2018-03-21 19:04:27 +00:00
|
|
|
Type: framework.TypeKVPairs,
|
2015-03-31 23:45:00 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["audit_opts"][0]),
|
|
|
|
},
|
2017-02-16 21:29:30 +00:00
|
|
|
"local": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
Default: false,
|
|
|
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
|
|
|
},
|
2015-03-31 23:45:00 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 20:10:05 +00:00
|
|
|
logical.UpdateOperation: b.handleEnableAudit,
|
2015-03-31 23:45:00 +00:00
|
|
|
logical.DeleteOperation: b.handleDisableAudit,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["audit"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["audit"][1]),
|
|
|
|
},
|
2015-04-02 00:44:43 +00:00
|
|
|
|
2015-05-28 00:53:42 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "key-status$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleKeyStatus,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["key-status"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["key-status"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "rotate$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: b.handleRotate,
|
2015-05-28 00:53:42 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["rotate"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["rotate"][1]),
|
|
|
|
},
|
2016-09-29 04:01:28 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "wrapping/wrap$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleWrappingWrap,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["wrap"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["wrap"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "wrapping/unwrap$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"token": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleWrappingUnwrap,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["unwrap"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["unwrap"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "wrapping/lookup$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"token": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleWrappingLookup,
|
2017-07-31 20:16:16 +00:00
|
|
|
logical.ReadOperation: b.handleWrappingLookup,
|
2016-09-29 04:01:28 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["wraplookup"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["wraplookup"][1]),
|
|
|
|
},
|
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "wrapping/rewrap$",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"token": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleWrappingRewrap,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["rewrap"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["rewrap"][1]),
|
|
|
|
},
|
2017-02-02 19:49:20 +00:00
|
|
|
|
|
|
|
&framework.Path{
|
|
|
|
Pattern: "config/auditing/request-headers/(?P<header>.+)",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"header": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
"hmac": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeBool,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handleAuditedHeaderUpdate,
|
|
|
|
logical.DeleteOperation: b.handleAuditedHeaderDelete,
|
|
|
|
logical.ReadOperation: b.handleAuditedHeaderRead,
|
|
|
|
},
|
|
|
|
|
2017-02-03 18:08:31 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["audited-headers-name"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["audited-headers-name"][1]),
|
2017-02-02 19:49:20 +00:00
|
|
|
},
|
2017-05-04 02:03:42 +00:00
|
|
|
|
2017-02-02 19:49:20 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "config/auditing/request-headers$",
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleAuditedHeadersRead,
|
|
|
|
},
|
|
|
|
|
2017-02-03 18:08:31 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["audited-headers"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["audited-headers"][1]),
|
2017-02-02 19:49:20 +00:00
|
|
|
},
|
2017-10-23 19:35:28 +00:00
|
|
|
|
2017-04-12 16:40:54 +00:00
|
|
|
&framework.Path{
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Pattern: "plugins/catalog/?$",
|
2017-04-12 16:40:54 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ListOperation: b.handlePluginCatalogList,
|
|
|
|
},
|
|
|
|
|
2017-04-12 17:01:36 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
2017-04-12 16:40:54 +00:00
|
|
|
},
|
2017-10-23 19:35:28 +00:00
|
|
|
|
2017-04-04 00:52:29 +00:00
|
|
|
&framework.Path{
|
2017-04-24 18:35:32 +00:00
|
|
|
Pattern: "plugins/catalog/(?P<name>.+)",
|
2017-04-04 00:52:29 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"name": &framework.FieldSchema{
|
2017-04-24 17:30:33 +00:00
|
|
|
Type: framework.TypeString,
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_name"][0]),
|
2017-04-04 00:52:29 +00:00
|
|
|
},
|
2017-08-16 15:17:50 +00:00
|
|
|
"sha256": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
|
|
|
},
|
2017-04-04 00:52:29 +00:00
|
|
|
"sha_256": &framework.FieldSchema{
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_sha-256"][0]),
|
2017-04-04 00:52:29 +00:00
|
|
|
},
|
|
|
|
"command": &framework.FieldSchema{
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_command"][0]),
|
2017-04-04 00:52:29 +00:00
|
|
|
},
|
2018-01-18 00:19:28 +00:00
|
|
|
"args": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-catalog_args"][0]),
|
|
|
|
},
|
2017-04-04 00:52:29 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handlePluginCatalogUpdate,
|
|
|
|
logical.DeleteOperation: b.handlePluginCatalogDelete,
|
|
|
|
logical.ReadOperation: b.handlePluginCatalogRead,
|
|
|
|
},
|
|
|
|
|
2017-04-12 17:01:36 +00:00
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-catalog"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-catalog"][1]),
|
2017-04-04 00:52:29 +00:00
|
|
|
},
|
2017-08-08 04:18:59 +00:00
|
|
|
&framework.Path{
|
2017-08-16 16:40:38 +00:00
|
|
|
Pattern: "plugins/reload/backend$",
|
2017-08-08 04:18:59 +00:00
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"plugin": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-backend-reload-plugin"][0]),
|
|
|
|
},
|
|
|
|
"mounts": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: strings.TrimSpace(sysHelp["plugin-backend-reload-mounts"][0]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.handlePluginReloadUpdate,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["plugin-reload"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["plugin-reload"][1]),
|
|
|
|
},
|
2017-10-20 14:59:17 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "tools/hash" + framework.OptionalParamRegex("urlalgorithm"),
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"input": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "The base64-encoded input data",
|
|
|
|
},
|
|
|
|
|
|
|
|
"algorithm": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Default: "sha2-256",
|
|
|
|
Description: `Algorithm to use (POST body parameter). Valid values are:
|
2017-10-23 20:49:46 +00:00
|
|
|
|
|
|
|
* sha2-224
|
|
|
|
* sha2-256
|
|
|
|
* sha2-384
|
|
|
|
* sha2-512
|
|
|
|
|
|
|
|
Defaults to "sha2-256".`,
|
2017-10-20 14:59:17 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
"urlalgorithm": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: `Algorithm to use (POST URL parameter)`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"format": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Default: "hex",
|
|
|
|
Description: `Encoding format to use. Can be "hex" or "base64". Defaults to "hex".`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.pathHashWrite,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["hash"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["hash"][1]),
|
|
|
|
},
|
2017-10-23 20:49:46 +00:00
|
|
|
|
2017-10-20 14:59:17 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "tools/random" + framework.OptionalParamRegex("urlbytes"),
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"urlbytes": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "The number of bytes to generate (POST URL parameter)",
|
|
|
|
},
|
|
|
|
|
|
|
|
"bytes": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeInt,
|
|
|
|
Default: 32,
|
|
|
|
Description: "The number of bytes to generate (POST body parameter). Defaults to 32 (256 bits).",
|
|
|
|
},
|
|
|
|
|
|
|
|
"format": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Default: "base64",
|
|
|
|
Description: `Encoding format to use. Can be "hex" or "base64". Defaults to "base64".`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.UpdateOperation: b.pathRandomWrite,
|
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["random"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["random"][1]),
|
|
|
|
},
|
2018-03-20 03:16:33 +00:00
|
|
|
&framework.Path{
|
|
|
|
Pattern: "internal/ui/mounts",
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.pathInternalUIMountsRead,
|
|
|
|
},
|
|
|
|
HelpSynopsis: strings.TrimSpace(sysHelp["internal-ui-mounts"][0]),
|
|
|
|
HelpDescription: strings.TrimSpace(sysHelp["internal-ui-mounts"][1]),
|
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
},
|
|
|
|
}
|
2015-09-04 20:58:12 +00:00
|
|
|
|
2017-02-17 04:23:21 +00:00
|
|
|
b.Backend.Paths = append(b.Backend.Paths, replicationPaths(b)...)
|
2017-02-16 21:29:30 +00:00
|
|
|
|
2017-09-15 04:21:35 +00:00
|
|
|
if core.rawEnabled {
|
|
|
|
b.Backend.Paths = append(b.Backend.Paths, &framework.Path{
|
|
|
|
Pattern: "(raw/?$|raw/(?P<path>.+))",
|
|
|
|
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"path": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
"value": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
|
|
logical.ReadOperation: b.handleRawRead,
|
|
|
|
logical.UpdateOperation: b.handleRawWrite,
|
|
|
|
logical.DeleteOperation: b.handleRawDelete,
|
|
|
|
logical.ListOperation: b.handleRawList,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
b.Backend.Invalidate = b.invalidate
|
|
|
|
|
2017-06-17 05:26:25 +00:00
|
|
|
return b
|
2015-03-16 00:35:59 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// SystemBackend implements logical.Backend and is used to interact with
|
|
|
|
// the core of the system. This backend is hardcoded to exist at the "sys"
|
|
|
|
// prefix. Conceptually it is similar to procfs on Linux.
|
2015-03-15 21:54:49 +00:00
|
|
|
type SystemBackend struct {
|
2017-06-17 05:26:25 +00:00
|
|
|
*framework.Backend
|
2017-10-23 20:49:46 +00:00
|
|
|
Core *Core
|
|
|
|
logger log.Logger
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
|
|
|
|
2017-06-17 04:04:55 +00:00
|
|
|
// handleCORSRead returns the current CORS configuration
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleCORSRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-06-17 04:04:55 +00:00
|
|
|
corsConf := b.Core.corsConfig
|
|
|
|
|
2017-06-17 05:26:25 +00:00
|
|
|
enabled := corsConf.IsEnabled()
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
2017-06-17 04:04:55 +00:00
|
|
|
Data: map[string]interface{}{
|
2017-06-17 05:26:25 +00:00
|
|
|
"enabled": enabled,
|
2017-06-17 04:04:55 +00:00
|
|
|
},
|
2017-06-17 05:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if enabled {
|
|
|
|
corsConf.RLock()
|
|
|
|
resp.Data["allowed_origins"] = corsConf.AllowedOrigins
|
2017-08-07 14:03:30 +00:00
|
|
|
resp.Data["allowed_headers"] = corsConf.AllowedHeaders
|
2017-06-17 05:26:25 +00:00
|
|
|
corsConf.RUnlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
2017-06-17 04:04:55 +00:00
|
|
|
}
|
|
|
|
|
2017-06-17 05:26:25 +00:00
|
|
|
// handleCORSUpdate sets the list of origins that are allowed to make
|
|
|
|
// cross-origin requests and sets the CORS enabled flag to true
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleCORSUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-06-17 04:04:55 +00:00
|
|
|
origins := d.Get("allowed_origins").([]string)
|
2017-08-07 14:03:30 +00:00
|
|
|
headers := d.Get("allowed_headers").([]string)
|
2017-06-17 04:04:55 +00:00
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
return nil, b.Core.corsConfig.Enable(ctx, origins, headers)
|
2017-06-17 04:04:55 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 14:03:30 +00:00
|
|
|
// handleCORSDelete sets the CORS enabled flag to false and clears the list of
|
|
|
|
// allowed origins & headers.
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleCORSDelete(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return nil, b.Core.corsConfig.Disable(ctx)
|
2017-06-17 04:04:55 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleTidyLeases(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-03-07 20:22:21 +00:00
|
|
|
err := b.Core.expiration.Tidy()
|
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("failed to tidy leases", "error", err)
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2017-03-07 20:22:21 +00:00
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *SystemBackend) invalidate(ctx context.Context, key string) {
|
2017-10-23 19:35:28 +00:00
|
|
|
/*
|
|
|
|
if b.Core.logger.IsTrace() {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Core.logger.Trace("invalidating key", "key", key)
|
2017-10-23 19:35:28 +00:00
|
|
|
}
|
|
|
|
*/
|
2017-02-16 21:29:30 +00:00
|
|
|
switch {
|
2017-10-23 19:35:28 +00:00
|
|
|
case strings.HasPrefix(key, policyACLSubPath):
|
2017-02-16 21:29:30 +00:00
|
|
|
b.Core.stateLock.RLock()
|
|
|
|
defer b.Core.stateLock.RUnlock()
|
|
|
|
if b.Core.policyStore != nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
b.Core.policyStore.invalidate(ctx, strings.TrimPrefix(key, policyACLSubPath), PolicyTypeACL)
|
2017-10-23 19:35:28 +00:00
|
|
|
}
|
|
|
|
case strings.HasPrefix(key, tokenSubPath):
|
|
|
|
b.Core.stateLock.RLock()
|
|
|
|
defer b.Core.stateLock.RUnlock()
|
|
|
|
if b.Core.tokenStore != nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
b.Core.tokenStore.Invalidate(ctx, key)
|
2017-02-16 21:29:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePluginCatalogList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
plugins, err := b.Core.pluginCatalog.List(ctx)
|
2017-04-12 16:40:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-04-24 17:30:33 +00:00
|
|
|
return logical.ListResponse(plugins), nil
|
2017-04-12 16:40:54 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePluginCatalogUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-04-04 00:52:29 +00:00
|
|
|
pluginName := d.Get("name").(string)
|
|
|
|
if pluginName == "" {
|
|
|
|
return logical.ErrorResponse("missing plugin name"), nil
|
|
|
|
}
|
|
|
|
|
2017-08-16 15:17:50 +00:00
|
|
|
sha256 := d.Get("sha256").(string)
|
2017-04-04 00:52:29 +00:00
|
|
|
if sha256 == "" {
|
2017-08-16 15:17:50 +00:00
|
|
|
sha256 = d.Get("sha_256").(string)
|
|
|
|
if sha256 == "" {
|
|
|
|
return logical.ErrorResponse("missing SHA-256 value"), nil
|
|
|
|
}
|
2017-04-04 00:52:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
command := d.Get("command").(string)
|
|
|
|
if command == "" {
|
|
|
|
return logical.ErrorResponse("missing command value"), nil
|
|
|
|
}
|
|
|
|
|
2018-01-18 00:19:28 +00:00
|
|
|
// For backwards compatibility, also accept args as part of command. Don't
|
|
|
|
// accepts args in both command and args.
|
|
|
|
args := d.Get("args").([]string)
|
|
|
|
parts := strings.Split(command, " ")
|
|
|
|
if len(parts) <= 0 {
|
|
|
|
return logical.ErrorResponse("missing command value"), nil
|
|
|
|
} else if len(parts) > 1 && len(args) > 0 {
|
2018-03-20 18:54:10 +00:00
|
|
|
return logical.ErrorResponse("must not specify args in command and args field"), nil
|
2018-01-18 00:19:28 +00:00
|
|
|
} else if len(parts) > 1 {
|
|
|
|
args = parts[1:]
|
|
|
|
}
|
|
|
|
|
2017-04-04 00:52:29 +00:00
|
|
|
sha256Bytes, err := hex.DecodeString(sha256)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse("Could not decode SHA-256 value from Hex"), err
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
err = b.Core.pluginCatalog.Set(ctx, pluginName, parts[0], args, sha256Bytes)
|
2017-04-04 00:52:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePluginCatalogRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-04-04 00:52:29 +00:00
|
|
|
pluginName := d.Get("name").(string)
|
|
|
|
if pluginName == "" {
|
|
|
|
return logical.ErrorResponse("missing plugin name"), nil
|
|
|
|
}
|
2018-01-19 06:44:44 +00:00
|
|
|
plugin, err := b.Core.pluginCatalog.Get(ctx, pluginName)
|
2017-04-04 00:52:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-04-25 01:31:27 +00:00
|
|
|
if plugin == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2017-04-04 00:52:29 +00:00
|
|
|
|
2018-01-18 00:19:28 +00:00
|
|
|
command := ""
|
|
|
|
if !plugin.Builtin {
|
|
|
|
command, err = filepath.Rel(b.Core.pluginCatalog.directory, plugin.Command)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data := map[string]interface{}{
|
|
|
|
"name": plugin.Name,
|
|
|
|
"args": plugin.Args,
|
|
|
|
"command": command,
|
|
|
|
"sha256": hex.EncodeToString(plugin.Sha256),
|
|
|
|
"builtin": plugin.Builtin,
|
|
|
|
}
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
|
2017-04-04 00:52:29 +00:00
|
|
|
return &logical.Response{
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Data: data,
|
2017-04-04 00:52:29 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePluginCatalogDelete(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-04-04 00:52:29 +00:00
|
|
|
pluginName := d.Get("name").(string)
|
|
|
|
if pluginName == "" {
|
|
|
|
return logical.ErrorResponse("missing plugin name"), nil
|
|
|
|
}
|
2018-01-19 06:44:44 +00:00
|
|
|
err := b.Core.pluginCatalog.Delete(ctx, pluginName)
|
2017-04-04 00:52:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-04-12 16:40:54 +00:00
|
|
|
return nil, nil
|
2017-04-04 00:52:29 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePluginReloadUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-08-08 04:18:59 +00:00
|
|
|
pluginName := d.Get("plugin").(string)
|
|
|
|
pluginMounts := d.Get("mounts").([]string)
|
|
|
|
|
|
|
|
if pluginName != "" && len(pluginMounts) > 0 {
|
|
|
|
return logical.ErrorResponse("plugin and mounts cannot be set at the same time"), nil
|
|
|
|
}
|
|
|
|
if pluginName == "" && len(pluginMounts) == 0 {
|
|
|
|
return logical.ErrorResponse("plugin or mounts must be provided"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if pluginName != "" {
|
2018-01-19 06:44:44 +00:00
|
|
|
err := b.Core.reloadMatchingPlugin(ctx, pluginName)
|
2017-08-08 04:18:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
} else if len(pluginMounts) > 0 {
|
2018-01-19 06:44:44 +00:00
|
|
|
err := b.Core.reloadMatchingPluginMounts(ctx, pluginMounts)
|
2017-08-08 04:18:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-02-02 19:49:20 +00:00
|
|
|
// handleAuditedHeaderUpdate creates or overwrites a header entry
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditedHeaderUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-02-02 19:49:20 +00:00
|
|
|
header := d.Get("header").(string)
|
|
|
|
hmac := d.Get("hmac").(bool)
|
|
|
|
if header == "" {
|
|
|
|
return logical.ErrorResponse("missing header name"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
headerConfig := b.Core.AuditedHeadersConfig()
|
2018-01-19 06:44:44 +00:00
|
|
|
err := headerConfig.add(ctx, header, hmac)
|
2017-02-02 19:49:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-03-20 18:54:10 +00:00
|
|
|
// handleAuditedHeaderDelete deletes the header with the given name
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditedHeaderDelete(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-02-02 19:49:20 +00:00
|
|
|
header := d.Get("header").(string)
|
|
|
|
if header == "" {
|
|
|
|
return logical.ErrorResponse("missing header name"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
headerConfig := b.Core.AuditedHeadersConfig()
|
2018-01-19 06:44:44 +00:00
|
|
|
err := headerConfig.remove(ctx, header)
|
2017-02-02 19:49:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleAuditedHeaderRead returns the header configuration for the given header name
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditedHeaderRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-02-02 19:49:20 +00:00
|
|
|
header := d.Get("header").(string)
|
|
|
|
if header == "" {
|
|
|
|
return logical.ErrorResponse("missing header name"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
headerConfig := b.Core.AuditedHeadersConfig()
|
2017-12-18 15:05:51 +00:00
|
|
|
settings, ok := headerConfig.Headers[strings.ToLower(header)]
|
2017-02-02 19:49:20 +00:00
|
|
|
if !ok {
|
|
|
|
return logical.ErrorResponse("Could not find header in config"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
header: settings,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleAuditedHeadersRead returns the whole audited headers config
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditedHeadersRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-02-02 19:49:20 +00:00
|
|
|
headerConfig := b.Core.AuditedHeadersConfig()
|
|
|
|
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"headers": headerConfig.Headers,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2017-06-17 04:04:55 +00:00
|
|
|
// handleCapabilitiesAccessor returns the ACL capabilities of the
|
2018-03-20 18:54:10 +00:00
|
|
|
// token associated with the given accessor for a given path.
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleCapabilitiesAccessor(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2016-03-17 18:07:55 +00:00
|
|
|
accessor := d.Get("accessor").(string)
|
|
|
|
if accessor == "" {
|
2016-03-17 19:39:58 +00:00
|
|
|
return logical.ErrorResponse("missing accessor"), nil
|
2016-03-17 18:07:55 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
aEntry, err := b.Core.tokenStore.lookupByAccessor(ctx, accessor, false)
|
2016-03-17 18:07:55 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-03-01 16:14:56 +00:00
|
|
|
d.Raw["token"] = aEntry.TokenID
|
|
|
|
return b.handleCapabilities(ctx, req, d)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleCapabilities returns the ACL capabilities of the token for a given path
|
|
|
|
func (b *SystemBackend) handleCapabilities(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
|
|
|
var token string
|
|
|
|
if strings.HasSuffix(req.Path, "capabilities-self") {
|
|
|
|
token = req.ClientToken
|
|
|
|
} else {
|
|
|
|
tokenRaw, ok := d.Raw["token"]
|
|
|
|
if ok {
|
|
|
|
token, _ = tokenRaw.(string)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if token == "" {
|
|
|
|
return nil, fmt.Errorf("no token found")
|
2016-03-17 16:55:38 +00:00
|
|
|
}
|
2016-03-17 18:07:55 +00:00
|
|
|
|
2018-03-01 16:14:56 +00:00
|
|
|
ret := &logical.Response{
|
|
|
|
Data: map[string]interface{}{},
|
|
|
|
}
|
|
|
|
|
|
|
|
paths := d.Get("paths").([]string)
|
|
|
|
if len(paths) == 0 {
|
|
|
|
// Read from the deprecated field
|
|
|
|
paths = d.Get("path").([]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(paths) == 0 {
|
|
|
|
return logical.ErrorResponse("paths must be supplied"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, path := range paths {
|
|
|
|
pathCap, err := b.Core.Capabilities(ctx, token, path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ret.Data[path] = pathCap
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is only here for backwards compatibility
|
|
|
|
if len(paths) == 1 {
|
|
|
|
ret.Data["capabilities"] = ret.Data[paths[0]]
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret, nil
|
2016-03-17 16:55:38 +00:00
|
|
|
}
|
|
|
|
|
2015-12-16 21:56:15 +00:00
|
|
|
// handleRekeyRetrieve returns backed-up, PGP-encrypted unseal keys from a
|
|
|
|
// rekey operation
|
|
|
|
func (b *SystemBackend) handleRekeyRetrieve(
|
2018-01-19 06:44:44 +00:00
|
|
|
ctx context.Context,
|
2016-04-04 14:44:22 +00:00
|
|
|
req *logical.Request,
|
|
|
|
data *framework.FieldData,
|
|
|
|
recovery bool) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
backup, err := b.Core.RekeyRetrieveBackup(ctx, recovery)
|
2015-12-16 21:56:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to look up backed-up keys: %v", err)
|
|
|
|
}
|
|
|
|
if backup == nil {
|
|
|
|
return logical.ErrorResponse("no backed-up keys found"), nil
|
|
|
|
}
|
|
|
|
|
2016-08-15 20:01:15 +00:00
|
|
|
keysB64 := map[string][]string{}
|
|
|
|
for k, v := range backup.Keys {
|
|
|
|
for _, j := range v {
|
|
|
|
currB64Keys := keysB64[k]
|
|
|
|
if currB64Keys == nil {
|
|
|
|
currB64Keys = []string{}
|
|
|
|
}
|
|
|
|
key, err := hex.DecodeString(j)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error decoding hex-encoded backup key: %v", err)
|
|
|
|
}
|
|
|
|
currB64Keys = append(currB64Keys, base64.StdEncoding.EncodeToString(key))
|
|
|
|
keysB64[k] = currB64Keys
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:56:15 +00:00
|
|
|
// Format the status
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
2016-08-15 20:01:15 +00:00
|
|
|
"nonce": backup.Nonce,
|
|
|
|
"keys": backup.Keys,
|
|
|
|
"keys_base64": keysB64,
|
2015-12-16 21:56:15 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRekeyRetrieveBarrier(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleRekeyRetrieve(ctx, req, data, false)
|
2016-04-04 14:44:22 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRekeyRetrieveRecovery(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleRekeyRetrieve(ctx, req, data, true)
|
2016-04-04 14:44:22 +00:00
|
|
|
}
|
|
|
|
|
2015-12-16 21:56:15 +00:00
|
|
|
// handleRekeyDelete deletes backed-up, PGP-encrypted unseal keys from a rekey
|
|
|
|
// operation
|
|
|
|
func (b *SystemBackend) handleRekeyDelete(
|
2018-01-19 06:44:44 +00:00
|
|
|
ctx context.Context,
|
2016-04-04 14:44:22 +00:00
|
|
|
req *logical.Request,
|
|
|
|
data *framework.FieldData,
|
|
|
|
recovery bool) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
err := b.Core.RekeyDeleteBackup(ctx, recovery)
|
2015-12-16 21:56:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error during deletion of backed-up keys: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
2016-09-29 04:01:28 +00:00
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRekeyDeleteBarrier(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleRekeyDelete(ctx, req, data, false)
|
2016-04-04 14:44:22 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRekeyDeleteRecovery(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleRekeyDelete(ctx, req, data, true)
|
2016-04-04 14:44:22 +00:00
|
|
|
}
|
2015-12-16 21:56:15 +00:00
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// handleMountTable handles the "mounts" endpoint to provide the mount table
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-11-11 16:44:07 +00:00
|
|
|
b.Core.mountsLock.RLock()
|
|
|
|
defer b.Core.mountsLock.RUnlock()
|
2015-03-15 21:42:05 +00:00
|
|
|
|
|
|
|
resp := &logical.Response{
|
2015-03-19 22:11:42 +00:00
|
|
|
Data: make(map[string]interface{}),
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2015-11-11 16:44:07 +00:00
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
for _, entry := range b.Core.mounts.Entries {
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
// Populate mount info
|
2015-08-31 18:27:49 +00:00
|
|
|
info := map[string]interface{}{
|
2015-03-15 21:42:05 +00:00
|
|
|
"type": entry.Type,
|
|
|
|
"description": entry.Description,
|
2017-06-26 17:14:36 +00:00
|
|
|
"accessor": entry.Accessor,
|
2018-03-09 19:32:28 +00:00
|
|
|
"local": entry.Local,
|
|
|
|
"seal_wrap": entry.SealWrap,
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": entry.Options,
|
2018-03-09 19:32:28 +00:00
|
|
|
}
|
|
|
|
entryConfig := map[string]interface{}{
|
|
|
|
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
|
|
|
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
|
|
|
"force_no_cache": entry.Config.ForceNoCache,
|
|
|
|
"plugin_name": entry.Config.PluginName,
|
|
|
|
}
|
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
|
|
|
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
|
|
|
|
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2018-03-20 03:16:33 +00:00
|
|
|
// Even though empty value is valid for ListingVisibility, we can ignore
|
|
|
|
// this case during mount since there's nothing to unset/hide.
|
|
|
|
if len(entry.Config.ListingVisibility) > 0 {
|
|
|
|
entryConfig["listing_visibility"] = entry.Config.ListingVisibility
|
|
|
|
}
|
2018-03-21 23:56:47 +00:00
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
|
|
|
|
entryConfig["passthrough_request_headers"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
|
2018-03-09 19:32:28 +00:00
|
|
|
info["config"] = entryConfig
|
2015-03-15 21:42:05 +00:00
|
|
|
resp.Data[entry.Path] = info
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleMount is used to mount a new path
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-02-16 21:29:30 +00:00
|
|
|
|
|
|
|
local := data.Get("local").(bool)
|
2017-09-04 23:38:37 +00:00
|
|
|
if !local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
// Get all the options
|
|
|
|
path := data.Get("path").(string)
|
2018-03-20 03:16:33 +00:00
|
|
|
path = sanitizeMountPath(path)
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
logicalType := data.Get("type").(string)
|
|
|
|
description := data.Get("description").(string)
|
2017-08-31 16:16:59 +00:00
|
|
|
pluginName := data.Get("plugin_name").(string)
|
2017-11-13 16:22:22 +00:00
|
|
|
sealWrap := data.Get("seal_wrap").(bool)
|
2018-03-21 19:04:27 +00:00
|
|
|
options := data.Get("options").(map[string]string)
|
2015-09-01 22:29:30 +00:00
|
|
|
|
|
|
|
var config MountConfig
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
var apiConfig APIMountConfig
|
2015-09-25 13:46:20 +00:00
|
|
|
|
2015-09-01 22:29:30 +00:00
|
|
|
configMap := data.Get("config").(map[string]interface{})
|
|
|
|
if configMap != nil && len(configMap) != 0 {
|
2015-09-25 13:46:20 +00:00
|
|
|
err := mapstructure.Decode(configMap, &apiConfig)
|
2015-09-01 22:29:30 +00:00
|
|
|
if err != nil {
|
2015-08-31 18:27:49 +00:00
|
|
|
return logical.ErrorResponse(
|
2015-09-01 22:29:30 +00:00
|
|
|
"unable to convert given mount config information"),
|
2015-08-31 18:27:49 +00:00
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
2015-03-15 21:42:05 +00:00
|
|
|
|
2015-09-25 13:46:20 +00:00
|
|
|
switch apiConfig.DefaultLeaseTTL {
|
|
|
|
case "":
|
|
|
|
case "system":
|
|
|
|
default:
|
2017-03-07 16:21:22 +00:00
|
|
|
tmpDef, err := parseutil.ParseDurationSecond(apiConfig.DefaultLeaseTTL)
|
2015-09-25 13:46:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"unable to parse default TTL of %s: %s", apiConfig.DefaultLeaseTTL, err)),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2016-07-11 18:19:35 +00:00
|
|
|
config.DefaultLeaseTTL = tmpDef
|
2015-09-25 13:46:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch apiConfig.MaxLeaseTTL {
|
|
|
|
case "":
|
|
|
|
case "system":
|
|
|
|
default:
|
2017-03-07 16:21:22 +00:00
|
|
|
tmpMax, err := parseutil.ParseDurationSecond(apiConfig.MaxLeaseTTL)
|
2015-09-25 13:46:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"unable to parse max TTL of %s: %s", apiConfig.MaxLeaseTTL, err)),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2016-07-11 18:19:35 +00:00
|
|
|
config.MaxLeaseTTL = tmpMax
|
2015-09-25 13:46:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if config.MaxLeaseTTL != 0 && config.DefaultLeaseTTL > config.MaxLeaseTTL {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"given default lease TTL greater than given max lease TTL"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
if config.DefaultLeaseTTL > b.Core.maxLeaseTTL && config.MaxLeaseTTL == 0 {
|
2015-09-25 13:46:20 +00:00
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"given default lease TTL greater than system max lease TTL of %d", int(b.Core.maxLeaseTTL.Seconds()))),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
switch logicalType {
|
|
|
|
case "":
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"backend type must be specified as a string"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
|
|
|
|
case "plugin":
|
|
|
|
// Only set plugin-name if mount is of type plugin, with apiConfig.PluginName
|
|
|
|
// option taking precedence.
|
2017-08-31 16:16:59 +00:00
|
|
|
switch {
|
|
|
|
case apiConfig.PluginName != "":
|
|
|
|
config.PluginName = apiConfig.PluginName
|
|
|
|
case pluginName != "":
|
|
|
|
config.PluginName = pluginName
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"plugin_name must be provided for plugin backend"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 14:20:09 +00:00
|
|
|
// Copy over the force no cache if set
|
|
|
|
if apiConfig.ForceNoCache {
|
|
|
|
config.ForceNoCache = true
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
if err := checkListingVisibility(apiConfig.ListingVisibility); err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("invalid listing_visibility %s", apiConfig.ListingVisibility)), nil
|
|
|
|
}
|
|
|
|
config.ListingVisibility = apiConfig.ListingVisibility
|
|
|
|
|
2018-03-09 19:32:28 +00:00
|
|
|
if len(apiConfig.AuditNonHMACRequestKeys) > 0 {
|
|
|
|
config.AuditNonHMACRequestKeys = apiConfig.AuditNonHMACRequestKeys
|
|
|
|
}
|
|
|
|
if len(apiConfig.AuditNonHMACResponseKeys) > 0 {
|
|
|
|
config.AuditNonHMACResponseKeys = apiConfig.AuditNonHMACResponseKeys
|
|
|
|
}
|
2018-03-21 23:56:47 +00:00
|
|
|
if len(apiConfig.PassthroughRequestHeaders) > 0 {
|
|
|
|
config.PassthroughRequestHeaders = apiConfig.PassthroughRequestHeaders
|
|
|
|
}
|
2018-03-09 19:32:28 +00:00
|
|
|
|
2018-04-03 00:51:35 +00:00
|
|
|
// Alias versioned KV
|
|
|
|
if logicalType == "vkv" {
|
|
|
|
logicalType = "kv"
|
|
|
|
if options == nil {
|
|
|
|
options = map[string]string{}
|
|
|
|
}
|
|
|
|
options["versioned"] = "true"
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// Create the mount entry
|
|
|
|
me := &MountEntry{
|
2016-05-26 16:55:00 +00:00
|
|
|
Table: mountTableType,
|
2015-03-16 00:35:59 +00:00
|
|
|
Path: path,
|
2015-03-15 21:42:05 +00:00
|
|
|
Type: logicalType,
|
|
|
|
Description: description,
|
2015-09-01 22:29:30 +00:00
|
|
|
Config: config,
|
2017-02-16 21:29:30 +00:00
|
|
|
Local: local,
|
2017-11-13 16:22:22 +00:00
|
|
|
SealWrap: sealWrap,
|
2018-03-21 19:04:27 +00:00
|
|
|
Options: options,
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2015-09-01 22:29:30 +00:00
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// Attempt mount
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.mount(ctx, me); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("mount failed", "path", me.Path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2015-08-10 17:27:25 +00:00
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-08-10 17:27:25 +00:00
|
|
|
// used to intercept an HTTPCodedError so it goes back to callee
|
|
|
|
func handleError(
|
|
|
|
err error) (*logical.Response, error) {
|
2018-03-18 01:29:17 +00:00
|
|
|
if strings.Contains(err.Error(), logical.ErrReadOnly.Error()) {
|
|
|
|
return logical.ErrorResponse(err.Error()), err
|
|
|
|
}
|
|
|
|
switch err.(type) {
|
|
|
|
case logical.HTTPCodedError:
|
|
|
|
return logical.ErrorResponse(err.Error()), err
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Performs a similar function to handleError, but upon seeing a ReadOnlyError
|
|
|
|
// will actually strip it out to prevent forwarding
|
|
|
|
func handleErrorNoReadOnlyForward(
|
|
|
|
err error) (*logical.Response, error) {
|
|
|
|
if strings.Contains(err.Error(), logical.ErrReadOnly.Error()) {
|
|
|
|
return nil, fmt.Errorf("operation could not be completed as storage is read-only")
|
|
|
|
}
|
2015-08-10 17:27:25 +00:00
|
|
|
switch err.(type) {
|
|
|
|
case logical.HTTPCodedError:
|
|
|
|
return logical.ErrorResponse(err.Error()), err
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// handleUnmount is used to unmount a path
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleUnmount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-07-13 17:57:14 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
path = sanitizeMountPath(path)
|
2016-03-03 18:13:47 +00:00
|
|
|
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-07-13 17:57:14 +00:00
|
|
|
entry := b.Core.router.MatchingMountEntry(path)
|
2017-09-04 23:38:37 +00:00
|
|
|
if entry != nil && !entry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot unmount a non-local mount on a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2017-07-13 17:57:14 +00:00
|
|
|
// We return success when the mount does not exists to not expose if the
|
|
|
|
// mount existed or not
|
|
|
|
match := b.Core.router.MatchingMount(path)
|
|
|
|
if match == "" || path != match {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// Attempt unmount
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.unmount(ctx, path); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("unmount failed", "path", path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRemount is used to remount a path
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRemount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-02-16 21:29:30 +00:00
|
|
|
|
2015-03-15 21:42:05 +00:00
|
|
|
// Get the paths
|
2015-03-19 22:11:42 +00:00
|
|
|
fromPath := data.Get("from").(string)
|
|
|
|
toPath := data.Get("to").(string)
|
2015-03-15 21:42:05 +00:00
|
|
|
if fromPath == "" || toPath == "" {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"both 'from' and 'to' path must be specified as a string"),
|
2015-03-15 21:53:41 +00:00
|
|
|
logical.ErrInvalidRequest
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2015-09-01 22:29:30 +00:00
|
|
|
|
2016-03-03 18:13:47 +00:00
|
|
|
fromPath = sanitizeMountPath(fromPath)
|
|
|
|
toPath = sanitizeMountPath(toPath)
|
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
entry := b.Core.router.MatchingMountEntry(fromPath)
|
2017-09-04 23:38:37 +00:00
|
|
|
if entry != nil && !entry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot remount a non-local mount on a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-09-02 19:56:58 +00:00
|
|
|
// Attempt remount
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.remount(ctx, fromPath, toPath); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("remount failed", "from_path", fromPath, "to_path", toPath, "error", err)
|
2015-09-02 19:56:58 +00:00
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-06-15 16:35:30 +00:00
|
|
|
// handleAuthTuneRead is used to get config settings on a auth path
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuthTuneRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2016-06-15 16:35:30 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
if path == "" {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"path must be specified as a string"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
return b.handleTuneReadCommon("auth/" + path)
|
|
|
|
}
|
|
|
|
|
2015-10-10 00:00:17 +00:00
|
|
|
// handleMountTuneRead is used to get config settings on a backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleMountTuneRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-09-02 19:56:58 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
if path == "" {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"path must be specified as a string"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2017-09-13 01:48:52 +00:00
|
|
|
// This call will read both logical backend's configuration as well as auth methods'.
|
2016-06-15 16:35:30 +00:00
|
|
|
// Retaining this behavior for backward compatibility. If this behavior is not desired,
|
|
|
|
// an error can be returned if path has a prefix of "auth/".
|
|
|
|
return b.handleTuneReadCommon(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleTuneReadCommon returns the config settings of a path
|
|
|
|
func (b *SystemBackend) handleTuneReadCommon(path string) (*logical.Response, error) {
|
2016-03-03 18:13:47 +00:00
|
|
|
path = sanitizeMountPath(path)
|
2015-09-04 20:58:12 +00:00
|
|
|
|
|
|
|
sysView := b.Core.router.MatchingSystemView(path)
|
|
|
|
if sysView == nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("cannot fetch sysview", "path", path)
|
2016-08-19 20:45:17 +00:00
|
|
|
return handleError(fmt.Errorf("sys: cannot fetch sysview for path %s", path))
|
2015-09-04 20:58:12 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 14:20:09 +00:00
|
|
|
mountEntry := b.Core.router.MatchingMountEntry(path)
|
|
|
|
if mountEntry == nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("cannot fetch mount entry", "path", path)
|
2017-03-08 14:20:09 +00:00
|
|
|
return handleError(fmt.Errorf("sys: cannot fetch mount entry for path %s", path))
|
|
|
|
}
|
|
|
|
|
2015-09-02 19:56:58 +00:00
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
2015-09-25 13:46:20 +00:00
|
|
|
"default_lease_ttl": int(sysView.DefaultLeaseTTL().Seconds()),
|
|
|
|
"max_lease_ttl": int(sysView.MaxLeaseTTL().Seconds()),
|
2017-03-08 14:20:09 +00:00
|
|
|
"force_no_cache": mountEntry.Config.ForceNoCache,
|
2015-09-02 19:56:58 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2018-03-02 17:18:39 +00:00
|
|
|
if rawVal, ok := mountEntry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
|
|
|
resp.Data["audit_non_hmac_request_keys"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if rawVal, ok := mountEntry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
|
|
|
|
resp.Data["audit_non_hmac_response_keys"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
if len(mountEntry.Config.ListingVisibility) > 0 {
|
|
|
|
resp.Data["listing_visibility"] = mountEntry.Config.ListingVisibility
|
|
|
|
}
|
|
|
|
|
2018-03-21 23:56:47 +00:00
|
|
|
if rawVal, ok := mountEntry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
|
|
|
|
resp.Data["passthrough_request_headers"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
if len(mountEntry.Options) > 0 {
|
|
|
|
resp.Data["options"] = mountEntry.Options
|
|
|
|
}
|
|
|
|
|
2015-09-02 19:56:58 +00:00
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2016-06-15 16:35:30 +00:00
|
|
|
// handleAuthTuneWrite is used to set config settings on an auth path
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuthTuneWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2016-06-15 16:35:30 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
if path == "" {
|
|
|
|
return logical.ErrorResponse("path must be specified as a string"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleTuneWriteCommon(ctx, "auth/"+path, data)
|
2016-06-15 16:35:30 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 00:00:17 +00:00
|
|
|
// handleMountTuneWrite is used to set config settings on a backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleMountTuneWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-09-02 19:56:58 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
if path == "" {
|
2016-06-15 16:35:30 +00:00
|
|
|
return logical.ErrorResponse("path must be specified as a string"),
|
2015-09-02 19:56:58 +00:00
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2017-09-13 01:48:52 +00:00
|
|
|
// This call will write both logical backend's configuration as well as auth methods'.
|
2016-06-15 16:35:30 +00:00
|
|
|
// Retaining this behavior for backward compatibility. If this behavior is not desired,
|
|
|
|
// an error can be returned if path has a prefix of "auth/".
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleTuneWriteCommon(ctx, path, data)
|
2016-06-15 16:35:30 +00:00
|
|
|
}
|
2015-09-02 19:56:58 +00:00
|
|
|
|
2016-06-15 16:35:30 +00:00
|
|
|
// handleTuneWriteCommon is used to set config settings on a path
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-02-16 21:29:30 +00:00
|
|
|
|
2016-03-03 18:13:47 +00:00
|
|
|
path = sanitizeMountPath(path)
|
2015-09-04 20:58:12 +00:00
|
|
|
|
2015-09-09 19:24:45 +00:00
|
|
|
// Prevent protected paths from being changed
|
2015-09-19 15:50:50 +00:00
|
|
|
for _, p := range untunableMounts {
|
2015-09-09 19:24:45 +00:00
|
|
|
if strings.HasPrefix(path, p) {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("cannot tune this mount", "path", path)
|
2016-08-19 20:45:17 +00:00
|
|
|
return handleError(fmt.Errorf("sys: cannot tune '%s'", path))
|
2015-09-09 19:24:45 +00:00
|
|
|
}
|
2015-08-31 18:27:49 +00:00
|
|
|
}
|
2015-03-15 21:42:05 +00:00
|
|
|
|
2015-09-09 19:24:45 +00:00
|
|
|
mountEntry := b.Core.router.MatchingMountEntry(path)
|
|
|
|
if mountEntry == nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("tune failed: no mount entry found", "path", path)
|
2016-08-19 20:45:17 +00:00
|
|
|
return handleError(fmt.Errorf("sys: tune of path '%s' failed: no mount entry found", path))
|
2015-09-02 19:56:58 +00:00
|
|
|
}
|
2017-09-04 23:38:37 +00:00
|
|
|
if mountEntry != nil && !mountEntry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot tune a non-local mount on a replication secondary"), nil
|
|
|
|
}
|
2015-09-03 12:54:59 +00:00
|
|
|
|
2016-05-03 18:24:04 +00:00
|
|
|
var lock *sync.RWMutex
|
|
|
|
switch {
|
2017-10-23 19:35:28 +00:00
|
|
|
case strings.HasPrefix(path, credentialRoutePrefix):
|
2016-05-03 18:24:04 +00:00
|
|
|
lock = &b.Core.authLock
|
|
|
|
default:
|
|
|
|
lock = &b.Core.mountsLock
|
|
|
|
}
|
|
|
|
|
2017-09-05 14:57:25 +00:00
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
|
|
|
|
// Check again after grabbing the lock
|
|
|
|
mountEntry = b.Core.router.MatchingMountEntry(path)
|
|
|
|
if mountEntry == nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("tune failed: no mount entry found", "path", path)
|
2017-09-05 14:57:25 +00:00
|
|
|
return handleError(fmt.Errorf("sys: tune of path '%s' failed: no mount entry found", path))
|
|
|
|
}
|
|
|
|
if mountEntry != nil && !mountEntry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
|
|
|
return logical.ErrorResponse("cannot tune a non-local mount on a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-09-09 19:24:45 +00:00
|
|
|
// Timing configuration parameters
|
|
|
|
{
|
2017-09-05 14:57:25 +00:00
|
|
|
var newDefault, newMax time.Duration
|
2015-09-25 13:46:20 +00:00
|
|
|
defTTL := data.Get("default_lease_ttl").(string)
|
|
|
|
switch defTTL {
|
|
|
|
case "":
|
2017-09-05 14:57:25 +00:00
|
|
|
newDefault = mountEntry.Config.DefaultLeaseTTL
|
2015-09-25 13:46:20 +00:00
|
|
|
case "system":
|
2017-09-05 14:57:25 +00:00
|
|
|
newDefault = time.Duration(0)
|
2015-09-25 13:46:20 +00:00
|
|
|
default:
|
2017-03-07 16:21:22 +00:00
|
|
|
tmpDef, err := parseutil.ParseDurationSecond(defTTL)
|
2015-09-25 13:46:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return handleError(err)
|
|
|
|
}
|
2017-09-05 14:57:25 +00:00
|
|
|
newDefault = tmpDef
|
2015-09-09 19:24:45 +00:00
|
|
|
}
|
2015-09-25 13:46:20 +00:00
|
|
|
|
|
|
|
maxTTL := data.Get("max_lease_ttl").(string)
|
|
|
|
switch maxTTL {
|
|
|
|
case "":
|
2017-09-05 14:57:25 +00:00
|
|
|
newMax = mountEntry.Config.MaxLeaseTTL
|
2015-09-25 13:46:20 +00:00
|
|
|
case "system":
|
2017-09-05 14:57:25 +00:00
|
|
|
newMax = time.Duration(0)
|
2015-09-25 13:46:20 +00:00
|
|
|
default:
|
2017-03-07 16:21:22 +00:00
|
|
|
tmpMax, err := parseutil.ParseDurationSecond(maxTTL)
|
2015-09-25 13:46:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return handleError(err)
|
|
|
|
}
|
2017-09-05 14:57:25 +00:00
|
|
|
newMax = tmpMax
|
2015-09-09 19:24:45 +00:00
|
|
|
}
|
2015-09-25 13:46:20 +00:00
|
|
|
|
2017-09-05 14:57:25 +00:00
|
|
|
if newDefault != mountEntry.Config.DefaultLeaseTTL ||
|
|
|
|
newMax != mountEntry.Config.MaxLeaseTTL {
|
2016-05-03 18:24:04 +00:00
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.tuneMountTTLs(ctx, path, mountEntry, newDefault, newMax); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("tuning failed", "path", path, "error", err)
|
2015-09-09 19:24:45 +00:00
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
}
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
|
|
|
|
2017-09-05 14:57:25 +00:00
|
|
|
description := data.Get("description").(string)
|
|
|
|
if description != "" {
|
|
|
|
oldDesc := mountEntry.Description
|
|
|
|
mountEntry.Description = description
|
|
|
|
|
|
|
|
// Update the mount table
|
|
|
|
var err error
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
2018-01-19 06:44:44 +00:00
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
2017-09-05 14:57:25 +00:00
|
|
|
default:
|
2018-01-19 06:44:44 +00:00
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
2017-09-05 14:57:25 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Description = oldDesc
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
if b.Core.logger.IsInfo() {
|
|
|
|
b.Core.logger.Info("core: mount tuning of description successful", "path", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-02 17:18:39 +00:00
|
|
|
if rawVal, ok := data.GetOk("audit_non_hmac_request_keys"); ok {
|
|
|
|
auditNonHMACRequestKeys := rawVal.([]string)
|
|
|
|
|
|
|
|
oldVal := mountEntry.Config.AuditNonHMACRequestKeys
|
|
|
|
mountEntry.Config.AuditNonHMACRequestKeys = auditNonHMACRequestKeys
|
|
|
|
|
|
|
|
// Update the mount table
|
|
|
|
var err error
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
|
|
|
default:
|
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Config.AuditNonHMACRequestKeys = oldVal
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mountEntry.SyncCache()
|
|
|
|
|
|
|
|
if b.Core.logger.IsInfo() {
|
|
|
|
b.Core.logger.Info("core: mount tuning of audit_non_hmac_request_keys successful", "path", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rawVal, ok := data.GetOk("audit_non_hmac_response_keys"); ok {
|
|
|
|
auditNonHMACResponseKeys := rawVal.([]string)
|
|
|
|
|
|
|
|
oldVal := mountEntry.Config.AuditNonHMACResponseKeys
|
|
|
|
mountEntry.Config.AuditNonHMACResponseKeys = auditNonHMACResponseKeys
|
|
|
|
|
|
|
|
// Update the mount table
|
|
|
|
var err error
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
|
|
|
default:
|
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Config.AuditNonHMACResponseKeys = oldVal
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mountEntry.SyncCache()
|
|
|
|
|
|
|
|
if b.Core.logger.IsInfo() {
|
|
|
|
b.Core.logger.Info("core: mount tuning of audit_non_hmac_response_keys successful", "path", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
if rawVal, ok := data.GetOk("listing_visibility"); ok {
|
|
|
|
lvString := rawVal.(string)
|
|
|
|
listingVisibility := ListingVisiblityType(lvString)
|
|
|
|
|
|
|
|
if err := checkListingVisibility(listingVisibility); err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("invalid listing_visibility %s", listingVisibility)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
oldVal := mountEntry.Config.ListingVisibility
|
|
|
|
mountEntry.Config.ListingVisibility = listingVisibility
|
|
|
|
|
|
|
|
// Update the mount table
|
|
|
|
var err error
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
|
|
|
default:
|
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Config.ListingVisibility = oldVal
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.Core.logger.IsInfo() {
|
|
|
|
b.Core.logger.Info("core: mount tuning of listing_visibility successful", "path", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 23:56:47 +00:00
|
|
|
if rawVal, ok := data.GetOk("passthrough_request_headers"); ok {
|
|
|
|
headers := rawVal.([]string)
|
|
|
|
|
|
|
|
oldVal := mountEntry.Config.PassthroughRequestHeaders
|
|
|
|
mountEntry.Config.PassthroughRequestHeaders = headers
|
|
|
|
|
|
|
|
// Update the mount table
|
|
|
|
var err error
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
|
|
|
default:
|
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Config.PassthroughRequestHeaders = oldVal
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mountEntry.SyncCache()
|
|
|
|
|
|
|
|
if b.Core.logger.IsInfo() {
|
|
|
|
b.Core.logger.Info("core: mount tuning of passthrough_request_headers successful", "path", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
var resp *logical.Response
|
|
|
|
if optionsRaw, ok := data.GetOk("options"); ok {
|
|
|
|
b.Core.logger.Info("core: mount tuning of options", "path", path)
|
|
|
|
options := optionsRaw.(map[string]string)
|
|
|
|
|
|
|
|
b.Core.logger.Info("core: mount tuning of options", "path", path, "options", options)
|
|
|
|
// Special case to make sure we can not disable versioning once it's
|
|
|
|
// enabeled. If the vkv backend suports downgrading this can be removed.
|
|
|
|
meVersioned, err := parseutil.ParseBool(mountEntry.Options["versioned"])
|
|
|
|
if err != nil {
|
|
|
|
return nil, errwrap.Wrapf("unable to parse mount entry: {{err}}", err)
|
|
|
|
}
|
|
|
|
optVersioned, err := parseutil.ParseBool(options["versioned"])
|
|
|
|
if err != nil {
|
|
|
|
return handleError(errwrap.Wrapf("unable to parse options: {{err}}", err))
|
|
|
|
}
|
|
|
|
if meVersioned && !optVersioned {
|
|
|
|
return logical.ErrorResponse("cannot disable versioning once it's enabled"), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
oldVal := mountEntry.Options
|
|
|
|
mountEntry.Options = options
|
|
|
|
// Update the mount table
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(path, "auth/"):
|
|
|
|
err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local)
|
|
|
|
default:
|
|
|
|
err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mountEntry.Options = oldVal
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
2018-04-03 18:37:34 +00:00
|
|
|
// Another special case to add a warning if we are going to be
|
|
|
|
// upgrading.
|
2018-03-21 19:04:27 +00:00
|
|
|
oldVersioned, err := parseutil.ParseBool(oldVal["versioned"])
|
|
|
|
if err != nil {
|
|
|
|
return nil, errwrap.Wrapf("unable to parse mount entry: {{err}}", err)
|
|
|
|
}
|
|
|
|
if !oldVersioned && optVersioned {
|
|
|
|
resp = &logical.Response{}
|
|
|
|
resp.AddWarning("Uprading from non-versioned to versioned data. This backend will be unavailable for a brief period and will resume service shortly.")
|
|
|
|
}
|
|
|
|
|
2018-04-03 18:37:34 +00:00
|
|
|
// Reload the backend to kick off the upgrade process.
|
2018-03-21 19:04:27 +00:00
|
|
|
b.Core.reloadBackendCommon(ctx, mountEntry, strings.HasPrefix(path, credentialRoutePrefix))
|
|
|
|
}
|
2018-03-21 23:56:47 +00:00
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
return resp, nil
|
2015-03-15 21:42:05 +00:00
|
|
|
}
|
2015-03-16 00:35:59 +00:00
|
|
|
|
2017-05-04 02:03:42 +00:00
|
|
|
// handleLease is use to view the metadata for a given LeaseID
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleLeaseLookup(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-05-04 02:03:42 +00:00
|
|
|
leaseID := data.Get("lease_id").(string)
|
|
|
|
if leaseID == "" {
|
|
|
|
return logical.ErrorResponse("lease_id must be specified"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
leaseTimes, err := b.Core.expiration.FetchLeaseTimes(leaseID)
|
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("error retrieving lease", "lease_id", leaseID, "error", err)
|
2017-05-04 02:03:42 +00:00
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
if leaseTimes == nil {
|
|
|
|
return logical.ErrorResponse("invalid lease"), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"id": leaseID,
|
|
|
|
"issue_time": leaseTimes.IssueTime,
|
|
|
|
"expire_time": nil,
|
|
|
|
"last_renewal": nil,
|
|
|
|
"ttl": int64(0),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
renewable, _ := leaseTimes.renewable()
|
|
|
|
resp.Data["renewable"] = renewable
|
|
|
|
|
|
|
|
if !leaseTimes.LastRenewalTime.IsZero() {
|
|
|
|
resp.Data["last_renewal"] = leaseTimes.LastRenewalTime
|
|
|
|
}
|
|
|
|
if !leaseTimes.ExpireTime.IsZero() {
|
|
|
|
resp.Data["expire_time"] = leaseTimes.ExpireTime
|
|
|
|
resp.Data["ttl"] = leaseTimes.ttl()
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleLeaseLookupList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-05-04 02:03:42 +00:00
|
|
|
prefix := data.Get("prefix").(string)
|
|
|
|
if prefix != "" && !strings.HasSuffix(prefix, "/") {
|
|
|
|
prefix = prefix + "/"
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
keys, err := b.Core.expiration.idView.List(ctx, prefix)
|
2017-05-04 02:03:42 +00:00
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("error listing leases", "prefix", prefix, "error", err)
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2017-05-04 02:03:42 +00:00
|
|
|
}
|
|
|
|
return logical.ListResponse(keys), nil
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:35:32 +00:00
|
|
|
// handleRenew is used to renew a lease with a given LeaseID
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRenew(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-16 23:11:55 +00:00
|
|
|
// Get all the options
|
2015-04-08 20:35:32 +00:00
|
|
|
leaseID := data.Get("lease_id").(string)
|
2016-08-08 22:00:44 +00:00
|
|
|
if leaseID == "" {
|
2016-08-08 22:34:00 +00:00
|
|
|
leaseID = data.Get("url_lease_id").(string)
|
2016-08-08 22:00:44 +00:00
|
|
|
}
|
2017-04-27 14:47:43 +00:00
|
|
|
if leaseID == "" {
|
|
|
|
return logical.ErrorResponse("lease_id must be specified"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2015-03-16 23:11:55 +00:00
|
|
|
incrementRaw := data.Get("increment").(int)
|
|
|
|
|
|
|
|
// Convert the increment
|
|
|
|
increment := time.Duration(incrementRaw) * time.Second
|
|
|
|
|
|
|
|
// Invoke the expiration manager directly
|
2015-04-08 20:35:32 +00:00
|
|
|
resp, err := b.Core.expiration.Renew(leaseID, increment)
|
2015-03-16 23:14:53 +00:00
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("lease renewal failed", "lease_id", leaseID, "error", err)
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2015-03-16 23:14:53 +00:00
|
|
|
}
|
|
|
|
return resp, err
|
2015-03-16 23:11:55 +00:00
|
|
|
}
|
|
|
|
|
2015-04-08 20:35:32 +00:00
|
|
|
// handleRevoke is used to revoke a given LeaseID
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRevoke(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-16 23:26:34 +00:00
|
|
|
// Get all the options
|
2015-04-08 20:35:32 +00:00
|
|
|
leaseID := data.Get("lease_id").(string)
|
2017-04-27 14:47:43 +00:00
|
|
|
if leaseID == "" {
|
|
|
|
leaseID = data.Get("url_lease_id").(string)
|
|
|
|
}
|
|
|
|
if leaseID == "" {
|
|
|
|
return logical.ErrorResponse("lease_id must be specified"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
2015-03-16 23:26:34 +00:00
|
|
|
|
|
|
|
// Invoke the expiration manager directly
|
2015-04-08 20:35:32 +00:00
|
|
|
if err := b.Core.expiration.Revoke(leaseID); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("lease revocation failed", "lease_id", leaseID, "error", err)
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2015-03-16 23:26:34 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:35:32 +00:00
|
|
|
// handleRevokePrefix is used to revoke a prefix with many LeaseIDs
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRevokePrefix(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
return b.handleRevokePrefixCommon(req, data, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRevokeForce is used to revoke a prefix with many LeaseIDs, ignoring errors
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRevokeForce(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
return b.handleRevokePrefixCommon(req, data, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRevokePrefixCommon is used to revoke a prefix with many LeaseIDs
|
|
|
|
func (b *SystemBackend) handleRevokePrefixCommon(
|
|
|
|
req *logical.Request, data *framework.FieldData, force bool) (*logical.Response, error) {
|
2015-03-16 23:33:48 +00:00
|
|
|
// Get all the options
|
|
|
|
prefix := data.Get("prefix").(string)
|
|
|
|
|
|
|
|
// Invoke the expiration manager directly
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
var err error
|
|
|
|
if force {
|
|
|
|
err = b.Core.expiration.RevokeForce(prefix)
|
|
|
|
} else {
|
|
|
|
err = b.Core.expiration.RevokePrefix(prefix)
|
|
|
|
}
|
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("revoke prefix failed", "prefix", prefix, "error", err)
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2015-03-16 23:33:48 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-03-20 19:48:19 +00:00
|
|
|
// handleAuthTable handles the "auth" endpoint to provide the auth table
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-11-11 16:44:07 +00:00
|
|
|
b.Core.authLock.RLock()
|
|
|
|
defer b.Core.authLock.RUnlock()
|
2015-03-20 19:48:19 +00:00
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: make(map[string]interface{}),
|
|
|
|
}
|
|
|
|
for _, entry := range b.Core.auth.Entries {
|
2016-06-15 16:35:30 +00:00
|
|
|
info := map[string]interface{}{
|
2015-03-20 19:48:19 +00:00
|
|
|
"type": entry.Type,
|
|
|
|
"description": entry.Description,
|
2017-06-26 17:14:36 +00:00
|
|
|
"accessor": entry.Accessor,
|
2018-03-09 19:32:28 +00:00
|
|
|
"local": entry.Local,
|
|
|
|
"seal_wrap": entry.SealWrap,
|
2018-03-21 19:04:27 +00:00
|
|
|
"options": entry.Options,
|
2018-03-09 19:32:28 +00:00
|
|
|
}
|
|
|
|
entryConfig := map[string]interface{}{
|
|
|
|
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
|
|
|
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
|
|
|
"plugin_name": entry.Config.PluginName,
|
|
|
|
}
|
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
|
|
|
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
|
|
|
|
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
2018-03-20 03:16:33 +00:00
|
|
|
// Even though empty value is valid for ListingVisibility, we can ignore
|
|
|
|
// this case during mount since there's nothing to unset/hide.
|
|
|
|
if len(entry.Config.ListingVisibility) > 0 {
|
|
|
|
entryConfig["listing_visibility"] = entry.Config.ListingVisibility
|
|
|
|
}
|
2018-03-21 23:56:47 +00:00
|
|
|
if rawVal, ok := entry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
|
|
|
|
entryConfig["passthrough_request_headers"] = rawVal.([]string)
|
|
|
|
}
|
|
|
|
|
2018-03-09 19:32:28 +00:00
|
|
|
info["config"] = entryConfig
|
2015-03-20 19:48:19 +00:00
|
|
|
resp.Data[entry.Path] = info
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleEnableAuth is used to enable a new credential backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-02-16 21:29:30 +00:00
|
|
|
local := data.Get("local").(bool)
|
2017-09-04 23:38:37 +00:00
|
|
|
if !local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-03-20 19:48:19 +00:00
|
|
|
// Get all the options
|
|
|
|
path := data.Get("path").(string)
|
2018-03-20 03:16:33 +00:00
|
|
|
path = sanitizeMountPath(path)
|
2015-03-20 19:48:19 +00:00
|
|
|
logicalType := data.Get("type").(string)
|
|
|
|
description := data.Get("description").(string)
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
pluginName := data.Get("plugin_name").(string)
|
2017-11-13 16:22:22 +00:00
|
|
|
sealWrap := data.Get("seal_wrap").(bool)
|
2018-03-21 19:04:27 +00:00
|
|
|
options := data.Get("options").(map[string]string)
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
|
|
|
|
var config MountConfig
|
2017-08-31 16:16:59 +00:00
|
|
|
var apiConfig APIMountConfig
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
|
2017-08-31 16:16:59 +00:00
|
|
|
configMap := data.Get("config").(map[string]interface{})
|
|
|
|
if configMap != nil && len(configMap) != 0 {
|
|
|
|
err := mapstructure.Decode(configMap, &apiConfig)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"unable to convert given auth config information"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-22 15:26:29 +00:00
|
|
|
switch apiConfig.DefaultLeaseTTL {
|
|
|
|
case "":
|
|
|
|
case "system":
|
|
|
|
default:
|
|
|
|
tmpDef, err := parseutil.ParseDurationSecond(apiConfig.DefaultLeaseTTL)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"unable to parse default TTL of %s: %s", apiConfig.DefaultLeaseTTL, err)),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
config.DefaultLeaseTTL = tmpDef
|
|
|
|
}
|
|
|
|
|
|
|
|
switch apiConfig.MaxLeaseTTL {
|
|
|
|
case "":
|
|
|
|
case "system":
|
|
|
|
default:
|
|
|
|
tmpMax, err := parseutil.ParseDurationSecond(apiConfig.MaxLeaseTTL)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"unable to parse max TTL of %s: %s", apiConfig.MaxLeaseTTL, err)),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
config.MaxLeaseTTL = tmpMax
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.MaxLeaseTTL != 0 && config.DefaultLeaseTTL > config.MaxLeaseTTL {
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"given default lease TTL greater than given max lease TTL"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.DefaultLeaseTTL > b.Core.maxLeaseTTL && config.MaxLeaseTTL == 0 {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf(
|
|
|
|
"given default lease TTL greater than system max lease TTL of %d", int(b.Core.maxLeaseTTL.Seconds()))),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
switch logicalType {
|
|
|
|
case "":
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"backend type must be specified as a string"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
|
|
|
|
case "plugin":
|
|
|
|
// Only set plugin name if mount is of type plugin, with apiConfig.PluginName
|
|
|
|
// option taking precedence.
|
2017-08-31 16:16:59 +00:00
|
|
|
switch {
|
|
|
|
case apiConfig.PluginName != "":
|
|
|
|
config.PluginName = apiConfig.PluginName
|
|
|
|
case pluginName != "":
|
|
|
|
config.PluginName = pluginName
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(
|
|
|
|
"plugin_name must be provided for plugin backend"),
|
|
|
|
logical.ErrInvalidRequest
|
|
|
|
}
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
}
|
2015-03-20 19:48:19 +00:00
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
if err := checkListingVisibility(apiConfig.ListingVisibility); err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("invalid listing_visibility %s", apiConfig.ListingVisibility)), nil
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
2018-03-20 03:16:33 +00:00
|
|
|
config.ListingVisibility = apiConfig.ListingVisibility
|
2016-03-03 18:13:47 +00:00
|
|
|
|
2018-03-09 19:32:28 +00:00
|
|
|
if len(apiConfig.AuditNonHMACRequestKeys) > 0 {
|
|
|
|
config.AuditNonHMACRequestKeys = apiConfig.AuditNonHMACRequestKeys
|
|
|
|
}
|
|
|
|
if len(apiConfig.AuditNonHMACResponseKeys) > 0 {
|
|
|
|
config.AuditNonHMACResponseKeys = apiConfig.AuditNonHMACResponseKeys
|
|
|
|
}
|
2018-03-21 23:56:47 +00:00
|
|
|
if len(apiConfig.PassthroughRequestHeaders) > 0 {
|
|
|
|
config.PassthroughRequestHeaders = apiConfig.PassthroughRequestHeaders
|
|
|
|
}
|
2018-03-09 19:32:28 +00:00
|
|
|
|
2015-03-20 19:48:19 +00:00
|
|
|
// Create the mount entry
|
|
|
|
me := &MountEntry{
|
2016-05-26 17:38:51 +00:00
|
|
|
Table: credentialTableType,
|
2015-03-20 19:48:19 +00:00
|
|
|
Path: path,
|
|
|
|
Type: logicalType,
|
|
|
|
Description: description,
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
Config: config,
|
2017-02-16 21:29:30 +00:00
|
|
|
Local: local,
|
2017-11-13 16:22:22 +00:00
|
|
|
SealWrap: sealWrap,
|
2018-03-21 19:04:27 +00:00
|
|
|
Options: options,
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt enabling
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.enableCredential(ctx, me); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("enable auth mount failed", "path", me.Path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleDisableAuth is used to disable a credential backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleDisableAuth(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-07-13 17:57:14 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
path = sanitizeMountPath(path)
|
2017-10-23 19:35:28 +00:00
|
|
|
|
2017-07-13 17:57:14 +00:00
|
|
|
fullPath := credentialRoutePrefix + path
|
|
|
|
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-07-13 17:57:14 +00:00
|
|
|
entry := b.Core.router.MatchingMountEntry(fullPath)
|
2017-09-04 23:38:37 +00:00
|
|
|
if entry != nil && !entry.Local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-07-13 17:57:14 +00:00
|
|
|
return logical.ErrorResponse("cannot unmount a non-local mount on a replication secondary"), nil
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 17:57:14 +00:00
|
|
|
// We return success when the mount does not exists to not expose if the
|
|
|
|
// mount existed or not
|
|
|
|
match := b.Core.router.MatchingMount(fullPath)
|
|
|
|
if match == "" || fullPath != match {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2016-03-03 18:13:47 +00:00
|
|
|
|
2015-03-20 19:48:19 +00:00
|
|
|
// Attempt disable
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.disableCredential(ctx, path); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("disable auth mount failed", "path", path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-20 19:48:19 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-03-23 21:43:31 +00:00
|
|
|
// handlePolicyList handles the "policy" endpoint to provide the enabled policies
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePolicyList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-23 21:43:31 +00:00
|
|
|
// Get all the configured policies
|
2018-01-19 06:44:44 +00:00
|
|
|
policies, err := b.Core.policyStore.ListPolicies(ctx, PolicyTypeACL)
|
2015-03-23 21:43:31 +00:00
|
|
|
|
|
|
|
// Add the special "root" policy
|
|
|
|
policies = append(policies, "root")
|
2016-03-02 19:16:54 +00:00
|
|
|
resp := logical.ListResponse(policies)
|
|
|
|
|
|
|
|
// Backwords compatibility
|
|
|
|
resp.Data["policies"] = resp.Data["keys"]
|
|
|
|
|
|
|
|
return resp, err
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePoliciesList(policyType PolicyType) framework.OperationFunc {
|
|
|
|
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
policies, err := b.Core.policyStore.ListPolicies(ctx, policyType)
|
2017-10-23 19:35:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
switch policyType {
|
|
|
|
case PolicyTypeACL:
|
|
|
|
// Add the special "root" policy if not egp
|
|
|
|
policies = append(policies, "root")
|
|
|
|
return logical.ListResponse(policies), nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return logical.ErrorResponse("unknown policy type"), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePoliciesRead(policyType PolicyType) framework.OperationFunc {
|
|
|
|
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-10-23 19:35:28 +00:00
|
|
|
name := data.Get("name").(string)
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
policy, err := b.Core.policyStore.GetPolicy(ctx, name, policyType)
|
2017-10-23 19:35:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if policy == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"name": policy.Name,
|
|
|
|
"policy": policy.Raw,
|
|
|
|
},
|
|
|
|
}
|
2017-10-23 20:49:46 +00:00
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
2017-10-23 19:35:28 +00:00
|
|
|
}
|
|
|
|
|
2015-03-23 21:43:31 +00:00
|
|
|
// handlePolicyRead handles the "policy/<name>" endpoint to read a policy
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePolicyRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-23 21:43:31 +00:00
|
|
|
name := data.Get("name").(string)
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
policy, err := b.Core.policyStore.GetPolicy(ctx, name, PolicyTypeACL)
|
2015-03-23 21:43:31 +00:00
|
|
|
if err != nil {
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if policy == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
resp := &logical.Response{
|
2015-03-23 21:43:31 +00:00
|
|
|
Data: map[string]interface{}{
|
2017-08-18 23:47:23 +00:00
|
|
|
"name": policy.Name,
|
2015-03-23 21:43:31 +00:00
|
|
|
"rules": policy.Raw,
|
|
|
|
},
|
2017-10-23 19:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePoliciesSet(policyType PolicyType) framework.OperationFunc {
|
|
|
|
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-10-23 19:35:28 +00:00
|
|
|
policy := &Policy{
|
|
|
|
Name: strings.ToLower(data.Get("name").(string)),
|
|
|
|
Type: policyType,
|
|
|
|
}
|
|
|
|
if policy.Name == "" {
|
|
|
|
return logical.ErrorResponse("policy name must be provided in the URL"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
policy.Raw = data.Get("policy").(string)
|
|
|
|
if policy.Raw == "" {
|
|
|
|
return logical.ErrorResponse("'policy' parameter not supplied or empty"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if polBytes, err := base64.StdEncoding.DecodeString(policy.Raw); err == nil {
|
|
|
|
policy.Raw = string(polBytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch policyType {
|
|
|
|
case PolicyTypeACL:
|
|
|
|
p, err := ParseACLPolicy(policy.Raw)
|
|
|
|
if err != nil {
|
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
policy.Paths = p.Paths
|
|
|
|
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse("unknown policy type"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the policy
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.policyStore.SetPolicy(ctx, policy); err != nil {
|
2017-10-23 19:35:28 +00:00
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handlePolicySet handles the "policy/<name>" endpoint to set a policy
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePolicySet(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-05-26 14:48:41 +00:00
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
policy := &Policy{
|
|
|
|
Type: PolicyTypeACL,
|
|
|
|
Name: strings.ToLower(data.Get("name").(string)),
|
|
|
|
}
|
|
|
|
if policy.Name == "" {
|
|
|
|
return logical.ErrorResponse("policy name must be provided in the URL"), nil
|
2017-05-26 14:48:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
var resp *logical.Response
|
|
|
|
|
|
|
|
policy.Raw = data.Get("policy").(string)
|
|
|
|
if policy.Raw == "" {
|
|
|
|
policy.Raw = data.Get("rules").(string)
|
|
|
|
if resp == nil {
|
|
|
|
resp = &logical.Response{}
|
|
|
|
}
|
|
|
|
resp.AddWarning("'rules' is deprecated, please use 'policy' instead")
|
|
|
|
}
|
|
|
|
if policy.Raw == "" {
|
|
|
|
return logical.ErrorResponse("'policy' parameter not supplied or empty"), nil
|
2017-05-26 14:48:41 +00:00
|
|
|
}
|
2015-03-23 21:43:31 +00:00
|
|
|
|
2017-10-23 19:35:28 +00:00
|
|
|
p, err := ParseACLPolicy(policy.Raw)
|
2015-03-23 21:43:31 +00:00
|
|
|
if err != nil {
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
2017-10-23 19:35:28 +00:00
|
|
|
policy.Paths = p.Paths
|
2015-03-23 21:43:31 +00:00
|
|
|
|
|
|
|
// Update the policy
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.policyStore.SetPolicy(ctx, policy); err != nil {
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
2017-10-23 19:35:28 +00:00
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePoliciesDelete(policyType PolicyType) framework.OperationFunc {
|
|
|
|
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-10-23 19:35:28 +00:00
|
|
|
name := data.Get("name").(string)
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.policyStore.DeletePolicy(ctx, name, policyType); err != nil {
|
2017-10-23 19:35:28 +00:00
|
|
|
return handleError(err)
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handlePolicyDelete handles the "policy/<name>" endpoint to delete a policy
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handlePolicyDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-23 21:43:31 +00:00
|
|
|
name := data.Get("name").(string)
|
2016-05-02 04:08:07 +00:00
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.policyStore.DeletePolicy(ctx, name, PolicyTypeACL); err != nil {
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-23 21:43:31 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-03-31 23:45:00 +00:00
|
|
|
// handleAuditTable handles the "audit" endpoint to provide the audit table
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditTable(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-11-11 16:44:07 +00:00
|
|
|
b.Core.auditLock.RLock()
|
|
|
|
defer b.Core.auditLock.RUnlock()
|
2015-03-31 23:45:00 +00:00
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: make(map[string]interface{}),
|
|
|
|
}
|
|
|
|
for _, entry := range b.Core.audit.Entries {
|
|
|
|
info := map[string]interface{}{
|
2016-03-14 21:15:07 +00:00
|
|
|
"path": entry.Path,
|
2015-03-31 23:45:00 +00:00
|
|
|
"type": entry.Type,
|
|
|
|
"description": entry.Description,
|
|
|
|
"options": entry.Options,
|
2017-02-16 21:29:30 +00:00
|
|
|
"local": entry.Local,
|
2015-03-31 23:45:00 +00:00
|
|
|
}
|
|
|
|
resp.Data[entry.Path] = info
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2015-11-19 01:26:03 +00:00
|
|
|
// handleAuditHash is used to fetch the hash of the given input data with the
|
|
|
|
// specified audit backend's salt
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleAuditHash(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-11-19 01:26:03 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
input := data.Get("input").(string)
|
|
|
|
if input == "" {
|
|
|
|
return logical.ErrorResponse("the \"input\" parameter is empty"), nil
|
|
|
|
}
|
|
|
|
|
2016-03-03 18:13:47 +00:00
|
|
|
path = sanitizeMountPath(path)
|
2015-11-19 01:26:03 +00:00
|
|
|
|
2018-03-08 19:21:11 +00:00
|
|
|
hash, err := b.Core.auditBroker.GetHash(ctx, path, input)
|
2015-11-19 01:26:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(err.Error()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"hash": hash,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2015-03-31 23:45:00 +00:00
|
|
|
// handleEnableAudit is used to enable a new audit backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleEnableAudit(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-02-16 21:29:30 +00:00
|
|
|
|
|
|
|
local := data.Get("local").(bool)
|
2017-09-04 23:38:37 +00:00
|
|
|
if !local && repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-03-31 23:45:00 +00:00
|
|
|
// Get all the options
|
|
|
|
path := data.Get("path").(string)
|
|
|
|
backendType := data.Get("type").(string)
|
|
|
|
description := data.Get("description").(string)
|
2018-03-21 19:04:27 +00:00
|
|
|
options := data.Get("options").(map[string]string)
|
2015-03-31 23:45:00 +00:00
|
|
|
|
|
|
|
// Create the mount entry
|
|
|
|
me := &MountEntry{
|
2016-05-26 17:38:51 +00:00
|
|
|
Table: auditTableType,
|
2015-03-31 23:45:00 +00:00
|
|
|
Path: path,
|
|
|
|
Type: backendType,
|
|
|
|
Description: description,
|
2018-03-21 19:04:27 +00:00
|
|
|
Options: options,
|
2017-02-16 21:29:30 +00:00
|
|
|
Local: local,
|
2015-03-31 23:45:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt enabling
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.enableAudit(ctx, me); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("enable audit mount failed", "path", me.Path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-31 23:45:00 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleDisableAudit is used to disable an audit backend
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleDisableAudit(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-03-31 23:45:00 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
|
|
|
|
// Attempt disable
|
2018-01-19 06:44:44 +00:00
|
|
|
if existed, err := b.Core.disableAudit(ctx, path); existed && err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("disable audit mount failed", "path", path, "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-03-31 23:45:00 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-03-27 20:23:33 +00:00
|
|
|
func (b *SystemBackend) handleConfigUIHeadersRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
|
|
header := data.Get("header").(string)
|
|
|
|
|
|
|
|
value, err := b.Core.uiConfig.GetHeader(ctx, header)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if value == "" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"value": value,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *SystemBackend) handleConfigUIHeadersList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
|
|
headers, err := b.Core.uiConfig.HeaderKeys(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(headers) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return logical.ListResponse(headers), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *SystemBackend) handleConfigUIHeadersUpdate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
|
|
header := data.Get("header").(string)
|
|
|
|
values := data.Get("values").([]string)
|
|
|
|
if header == "" || len(values) == 0 {
|
|
|
|
return logical.ErrorResponse("header and values must be specified"), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2018-03-28 20:57:58 +00:00
|
|
|
lowerHeader := strings.ToLower(header)
|
|
|
|
if strings.HasPrefix(lowerHeader, "x-vault-") {
|
2018-03-27 20:23:33 +00:00
|
|
|
return logical.ErrorResponse("X-Vault headers cannot be set"), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
// Translate the list of values to the valid header string
|
2018-03-28 20:57:58 +00:00
|
|
|
value := http.Header{}
|
|
|
|
for _, v := range values {
|
|
|
|
value.Add(header, v)
|
2018-03-27 20:23:33 +00:00
|
|
|
}
|
|
|
|
err := b.Core.uiConfig.SetHeader(ctx, header, value.Get(header))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-03-28 20:57:58 +00:00
|
|
|
// Warn when overriding the CSP
|
|
|
|
resp := &logical.Response{}
|
|
|
|
if lowerHeader == "content-security-policy" {
|
|
|
|
resp.AddWarning("overriding default Content-Security-Policy which is secure by default, proceed with caution")
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
2018-03-27 20:23:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *SystemBackend) handleConfigUIHeadersDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
|
|
header := data.Get("header").(string)
|
|
|
|
err := b.Core.uiConfig.DeleteHeader(ctx, header)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-04-02 00:44:43 +00:00
|
|
|
// handleRawRead is used to read directly from the barrier
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRawRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-04-02 00:44:43 +00:00
|
|
|
path := data.Get("path").(string)
|
2015-05-28 17:24:41 +00:00
|
|
|
|
|
|
|
// Prevent access of protected paths
|
|
|
|
for _, p := range protectedPaths {
|
|
|
|
if strings.HasPrefix(path, p) {
|
|
|
|
err := fmt.Sprintf("cannot read '%s'", path)
|
|
|
|
return logical.ErrorResponse(err), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
entry, err := b.Core.barrier.Get(ctx, path)
|
2015-04-02 00:44:43 +00:00
|
|
|
if err != nil {
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2015-04-02 00:44:43 +00:00
|
|
|
}
|
|
|
|
if entry == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2018-02-09 23:43:48 +00:00
|
|
|
|
|
|
|
// Run this through the decompression helper to see if it's been compressed.
|
|
|
|
// If the input contained the compression canary, `outputBytes` will hold
|
|
|
|
// the decompressed data. If the input was not compressed, then `outputBytes`
|
|
|
|
// will be nil.
|
|
|
|
outputBytes, _, err := compressutil.Decompress(entry.Value)
|
|
|
|
if err != nil {
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2018-02-09 23:43:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// `outputBytes` is nil if the input is uncompressed. In that case set it to the original input.
|
|
|
|
if outputBytes == nil {
|
|
|
|
outputBytes = entry.Value
|
|
|
|
}
|
|
|
|
|
2015-04-02 00:44:43 +00:00
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
2018-02-09 23:43:48 +00:00
|
|
|
"value": string(outputBytes),
|
2015-04-02 00:44:43 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRawWrite is used to write directly to the barrier
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRawWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-04-02 00:44:43 +00:00
|
|
|
path := data.Get("path").(string)
|
2015-05-28 17:24:41 +00:00
|
|
|
|
|
|
|
// Prevent access of protected paths
|
|
|
|
for _, p := range protectedPaths {
|
|
|
|
if strings.HasPrefix(path, p) {
|
|
|
|
err := fmt.Sprintf("cannot write '%s'", path)
|
|
|
|
return logical.ErrorResponse(err), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-02 00:44:43 +00:00
|
|
|
value := data.Get("value").(string)
|
|
|
|
entry := &Entry{
|
|
|
|
Key: path,
|
|
|
|
Value: []byte(value),
|
|
|
|
}
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.barrier.Put(ctx, entry); err != nil {
|
2015-04-02 00:44:43 +00:00
|
|
|
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRawDelete is used to delete directly from the barrier
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRawDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-04-02 00:44:43 +00:00
|
|
|
path := data.Get("path").(string)
|
2015-05-28 17:24:41 +00:00
|
|
|
|
|
|
|
// Prevent access of protected paths
|
|
|
|
for _, p := range protectedPaths {
|
|
|
|
if strings.HasPrefix(path, p) {
|
|
|
|
err := fmt.Sprintf("cannot delete '%s'", path)
|
|
|
|
return logical.ErrorResponse(err), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.barrier.Delete(ctx, path); err != nil {
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2015-04-02 00:44:43 +00:00
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-09-15 04:21:35 +00:00
|
|
|
// handleRawList is used to list directly from the barrier
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRawList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-09-15 04:21:35 +00:00
|
|
|
path := data.Get("path").(string)
|
|
|
|
if path != "" && !strings.HasSuffix(path, "/") {
|
|
|
|
path = path + "/"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent access of protected paths
|
|
|
|
for _, p := range protectedPaths {
|
|
|
|
if strings.HasPrefix(path, p) {
|
|
|
|
err := fmt.Sprintf("cannot list '%s'", path)
|
|
|
|
return logical.ErrorResponse(err), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
keys, err := b.Core.barrier.List(ctx, path)
|
2017-09-15 04:21:35 +00:00
|
|
|
if err != nil {
|
2018-03-18 01:29:17 +00:00
|
|
|
return handleErrorNoReadOnlyForward(err)
|
2017-09-15 04:21:35 +00:00
|
|
|
}
|
|
|
|
return logical.ListResponse(keys), nil
|
|
|
|
}
|
|
|
|
|
2015-05-28 00:53:42 +00:00
|
|
|
// handleKeyStatus returns status information about the backend key
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleKeyStatus(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2015-05-28 00:53:42 +00:00
|
|
|
// Get the key info
|
|
|
|
info, err := b.Core.barrier.ActiveKeyInfo()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"term": info.Term,
|
2016-07-25 18:11:57 +00:00
|
|
|
"install_time": info.InstallTime.Format(time.RFC3339Nano),
|
2015-05-28 00:53:42 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleRotate is used to trigger a key rotation
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleRotate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2018-01-16 18:51:55 +00:00
|
|
|
repState := b.Core.ReplicationState()
|
2017-09-04 23:38:37 +00:00
|
|
|
if repState.HasState(consts.ReplicationPerformanceSecondary) {
|
2017-02-16 21:29:30 +00:00
|
|
|
return logical.ErrorResponse("cannot rotate on a replication secondary"), nil
|
|
|
|
}
|
|
|
|
|
2015-05-28 23:43:15 +00:00
|
|
|
// Rotate to the new term
|
2018-01-19 06:44:44 +00:00
|
|
|
newTerm, err := b.Core.barrier.Rotate(ctx)
|
2015-05-28 23:43:15 +00:00
|
|
|
if err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("failed to create new encryption key", "error", err)
|
2015-08-10 17:27:25 +00:00
|
|
|
return handleError(err)
|
2015-05-28 00:53:42 +00:00
|
|
|
}
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Info("installed new encryption key")
|
2015-05-28 23:43:15 +00:00
|
|
|
|
2015-08-20 20:20:35 +00:00
|
|
|
// In HA mode, we need to an upgrade path for the standby instances
|
2015-05-28 23:43:15 +00:00
|
|
|
if b.Core.ha != nil {
|
|
|
|
// Create the upgrade path to the new term
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.barrier.CreateUpgrade(ctx, newTerm); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("failed to create new upgrade", "term", newTerm, "error", err)
|
2015-05-28 23:43:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Schedule the destroy of the upgrade path
|
|
|
|
time.AfterFunc(keyRotateGracePeriod, func() {
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.barrier.DestroyUpgrade(ctx, newTerm); err != nil {
|
2018-04-03 00:46:59 +00:00
|
|
|
b.Backend.Logger().Error("failed to destroy upgrade", "term", newTerm, "error", err)
|
2015-05-28 23:43:15 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-02-16 21:29:30 +00:00
|
|
|
|
|
|
|
// Write to the canary path, which will force a synchronous truing during
|
|
|
|
// replication
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Core.barrier.Put(ctx, &Entry{
|
2017-02-16 21:29:30 +00:00
|
|
|
Key: coreKeyringCanaryPath,
|
|
|
|
Value: []byte(fmt.Sprintf("new-rotation-term-%d", newTerm)),
|
|
|
|
}); err != nil {
|
|
|
|
b.Core.logger.Error("core: error saving keyring canary", "error", err)
|
|
|
|
return nil, fmt.Errorf("failed to save keyring canary: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-05-28 00:53:42 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleWrappingPubkey(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-01-04 21:44:03 +00:00
|
|
|
x, _ := b.Core.wrappingJWTKey.X.MarshalText()
|
|
|
|
y, _ := b.Core.wrappingJWTKey.Y.MarshalText()
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"jwt_x": string(x),
|
|
|
|
"jwt_y": string(y),
|
|
|
|
"jwt_curve": corePrivateKeyTypeP521,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleWrappingWrap(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-01-04 21:44:03 +00:00
|
|
|
if req.WrapInfo == nil || req.WrapInfo.TTL == 0 {
|
2016-09-29 04:01:28 +00:00
|
|
|
return logical.ErrorResponse("endpoint requires response wrapping to be used"), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
2017-02-22 16:13:40 +00:00
|
|
|
// N.B.: Do *NOT* allow JWT wrapping tokens to be created through this
|
|
|
|
// endpoint. JWTs are signed so if we don't allow users to create wrapping
|
|
|
|
// tokens using them we can ensure that an operator can't spoof a legit JWT
|
|
|
|
// wrapped token, which makes certain init/rekey/generate-root cases have
|
|
|
|
// better properties.
|
|
|
|
req.WrapInfo.Format = "uuid"
|
|
|
|
|
2016-09-29 04:01:28 +00:00
|
|
|
return &logical.Response{
|
|
|
|
Data: data.Raw,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleWrappingUnwrap(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2016-09-29 04:01:28 +00:00
|
|
|
// If a third party is unwrapping (rather than the calling token being the
|
|
|
|
// wrapping token) we detect this so that we can revoke the original
|
|
|
|
// wrapping token after reading it
|
|
|
|
var thirdParty bool
|
|
|
|
|
|
|
|
token := data.Get("token").(string)
|
|
|
|
if token != "" {
|
|
|
|
thirdParty = true
|
|
|
|
} else {
|
|
|
|
token = req.ClientToken
|
|
|
|
}
|
|
|
|
|
2017-11-13 20:31:32 +00:00
|
|
|
// Get the policies so we can determine if this is a normal response
|
|
|
|
// wrapping request or a control group token.
|
|
|
|
//
|
|
|
|
// We use lookupTainted here because the token might have already been used
|
|
|
|
// by handleRequest(), this happens when it's a normal response wrapping
|
|
|
|
// request and the token was provided "first party". We want to inspect the
|
|
|
|
// token policies but will not use this token entry for anything else.
|
2018-01-19 06:44:44 +00:00
|
|
|
te, err := b.Core.tokenStore.lookupTainted(ctx, token)
|
2017-11-13 20:31:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if te == nil {
|
|
|
|
return nil, errors.New("could not find token")
|
|
|
|
}
|
|
|
|
if len(te.Policies) != 1 {
|
|
|
|
return nil, errors.New("token is not a valid unwrap token")
|
|
|
|
}
|
|
|
|
|
|
|
|
var response string
|
|
|
|
switch te.Policies[0] {
|
|
|
|
case responseWrappingPolicyName:
|
2018-01-08 18:31:38 +00:00
|
|
|
response, err = b.responseWrappingUnwrap(ctx, token, thirdParty)
|
2017-11-13 20:31:32 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
var respErr *logical.Response
|
|
|
|
if len(response) > 0 {
|
|
|
|
respErr = logical.ErrorResponse(response)
|
|
|
|
}
|
|
|
|
|
|
|
|
return respErr, err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{},
|
|
|
|
}
|
|
|
|
if len(response) == 0 {
|
|
|
|
resp.Data[logical.HTTPStatusCode] = 204
|
|
|
|
} else {
|
|
|
|
resp.Data[logical.HTTPStatusCode] = 200
|
|
|
|
resp.Data[logical.HTTPRawBody] = []byte(response)
|
|
|
|
resp.Data[logical.HTTPContentType] = "application/json"
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// responseWrappingUnwrap will read the stored response in the cubbyhole and
|
|
|
|
// return the raw HTTP response.
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) responseWrappingUnwrap(ctx context.Context, token string, thirdParty bool) (string, error) {
|
2016-09-29 04:01:28 +00:00
|
|
|
if thirdParty {
|
|
|
|
// Use the token to decrement the use count to avoid a second operation on the token.
|
2018-01-19 06:44:44 +00:00
|
|
|
_, err := b.Core.tokenStore.UseTokenByID(ctx, token)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "", fmt.Errorf("error decrementing wrapping token's use-count: %v", err)
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
defer b.Core.tokenStore.Revoke(ctx, token)
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cubbyReq := &logical.Request{
|
|
|
|
Operation: logical.ReadOperation,
|
|
|
|
Path: "cubbyhole/response",
|
|
|
|
ClientToken: token,
|
|
|
|
}
|
2018-01-08 18:31:38 +00:00
|
|
|
cubbyResp, err := b.Core.router.Route(ctx, cubbyReq)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "", fmt.Errorf("error looking up wrapping information: %v", err)
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
if cubbyResp == nil {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "no information found; wrapping token may be from a previous Vault version", ErrInternalError
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
if cubbyResp != nil && cubbyResp.IsError() {
|
2017-11-13 20:31:32 +00:00
|
|
|
return cubbyResp.Error().Error(), nil
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
if cubbyResp.Data == nil {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "wrapping information was nil; wrapping token may be from a previous Vault version", ErrInternalError
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
responseRaw := cubbyResp.Data["response"]
|
|
|
|
if responseRaw == nil {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "", fmt.Errorf("no response found inside the cubbyhole")
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
response, ok := responseRaw.(string)
|
|
|
|
if !ok {
|
2017-11-13 20:31:32 +00:00
|
|
|
return "", fmt.Errorf("could not decode response inside the cubbyhole")
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
2017-11-13 20:31:32 +00:00
|
|
|
return response, nil
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleWrappingLookup(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2017-07-31 20:16:16 +00:00
|
|
|
// This ordering of lookups has been validated already in the wrapping
|
|
|
|
// validation func, we're just doing this for a safety check
|
2016-09-29 04:01:28 +00:00
|
|
|
token := data.Get("token").(string)
|
|
|
|
if token == "" {
|
2017-07-31 20:16:16 +00:00
|
|
|
token = req.ClientToken
|
|
|
|
if token == "" {
|
|
|
|
return logical.ErrorResponse("missing \"token\" value in input"), logical.ErrInvalidRequest
|
|
|
|
}
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cubbyReq := &logical.Request{
|
|
|
|
Operation: logical.ReadOperation,
|
|
|
|
Path: "cubbyhole/wrapinfo",
|
|
|
|
ClientToken: token,
|
|
|
|
}
|
2018-01-08 18:31:38 +00:00
|
|
|
cubbyResp, err := b.Core.router.Route(ctx, cubbyReq)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error looking up wrapping information: %v", err)
|
|
|
|
}
|
|
|
|
if cubbyResp == nil {
|
|
|
|
return logical.ErrorResponse("no information found; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
if cubbyResp != nil && cubbyResp.IsError() {
|
|
|
|
return cubbyResp, nil
|
|
|
|
}
|
|
|
|
if cubbyResp.Data == nil {
|
|
|
|
return logical.ErrorResponse("wrapping information was nil; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
creationTTLRaw := cubbyResp.Data["creation_ttl"]
|
|
|
|
creationTime := cubbyResp.Data["creation_time"]
|
2017-08-02 22:28:58 +00:00
|
|
|
creationPath := cubbyResp.Data["creation_path"]
|
2016-09-29 04:01:28 +00:00
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{},
|
|
|
|
}
|
|
|
|
if creationTTLRaw != nil {
|
|
|
|
creationTTL, err := creationTTLRaw.(json.Number).Int64()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error reading creation_ttl value from wrapping information: %v", err)
|
|
|
|
}
|
|
|
|
resp.Data["creation_ttl"] = time.Duration(creationTTL).Seconds()
|
|
|
|
}
|
|
|
|
if creationTime != nil {
|
|
|
|
// This was JSON marshaled so it's already a string in RFC3339 format
|
|
|
|
resp.Data["creation_time"] = cubbyResp.Data["creation_time"]
|
|
|
|
}
|
2017-08-02 22:28:58 +00:00
|
|
|
if creationPath != nil {
|
|
|
|
resp.Data["creation_path"] = cubbyResp.Data["creation_path"]
|
|
|
|
}
|
2016-09-29 04:01:28 +00:00
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) handleWrappingRewrap(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
2016-09-29 04:01:28 +00:00
|
|
|
// If a third party is rewrapping (rather than the calling token being the
|
|
|
|
// wrapping token) we detect this so that we can revoke the original
|
|
|
|
// wrapping token after reading it. Right now wrapped tokens can't unwrap
|
|
|
|
// themselves, but in case we change it, this will be ready to do the right
|
|
|
|
// thing.
|
|
|
|
var thirdParty bool
|
|
|
|
|
|
|
|
token := data.Get("token").(string)
|
|
|
|
if token != "" {
|
|
|
|
thirdParty = true
|
|
|
|
} else {
|
|
|
|
token = req.ClientToken
|
|
|
|
}
|
|
|
|
|
|
|
|
if thirdParty {
|
|
|
|
// Use the token to decrement the use count to avoid a second operation on the token.
|
2018-01-19 06:44:44 +00:00
|
|
|
_, err := b.Core.tokenStore.UseTokenByID(ctx, token)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error decrementing wrapping token's use-count: %v", err)
|
|
|
|
}
|
2018-01-19 06:44:44 +00:00
|
|
|
defer b.Core.tokenStore.Revoke(ctx, token)
|
2016-09-29 04:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch the original TTL
|
|
|
|
cubbyReq := &logical.Request{
|
|
|
|
Operation: logical.ReadOperation,
|
|
|
|
Path: "cubbyhole/wrapinfo",
|
|
|
|
ClientToken: token,
|
|
|
|
}
|
2018-01-08 18:31:38 +00:00
|
|
|
cubbyResp, err := b.Core.router.Route(ctx, cubbyReq)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error looking up wrapping information: %v", err)
|
|
|
|
}
|
|
|
|
if cubbyResp == nil {
|
|
|
|
return logical.ErrorResponse("no information found; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
if cubbyResp != nil && cubbyResp.IsError() {
|
|
|
|
return cubbyResp, nil
|
|
|
|
}
|
|
|
|
if cubbyResp.Data == nil {
|
|
|
|
return logical.ErrorResponse("wrapping information was nil; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the creation TTL on the request
|
|
|
|
creationTTLRaw := cubbyResp.Data["creation_ttl"]
|
|
|
|
if creationTTLRaw == nil {
|
|
|
|
return nil, fmt.Errorf("creation_ttl value in wrapping information was nil")
|
|
|
|
}
|
|
|
|
creationTTL, err := cubbyResp.Data["creation_ttl"].(json.Number).Int64()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error reading creation_ttl value from wrapping information: %v", err)
|
|
|
|
}
|
|
|
|
|
2017-08-02 22:28:58 +00:00
|
|
|
// Get creation_path to return as the response later
|
|
|
|
creationPathRaw := cubbyResp.Data["creation_path"]
|
|
|
|
if creationPathRaw == nil {
|
|
|
|
return nil, fmt.Errorf("creation_path value in wrapping information was nil")
|
|
|
|
}
|
|
|
|
creationPath := creationPathRaw.(string)
|
|
|
|
|
2016-09-29 04:01:28 +00:00
|
|
|
// Fetch the original response and return it as the data for the new response
|
|
|
|
cubbyReq = &logical.Request{
|
|
|
|
Operation: logical.ReadOperation,
|
|
|
|
Path: "cubbyhole/response",
|
|
|
|
ClientToken: token,
|
|
|
|
}
|
2018-01-08 18:31:38 +00:00
|
|
|
cubbyResp, err = b.Core.router.Route(ctx, cubbyReq)
|
2016-09-29 04:01:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error looking up response: %v", err)
|
|
|
|
}
|
|
|
|
if cubbyResp == nil {
|
|
|
|
return logical.ErrorResponse("no information found; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
if cubbyResp != nil && cubbyResp.IsError() {
|
|
|
|
return cubbyResp, nil
|
|
|
|
}
|
|
|
|
if cubbyResp.Data == nil {
|
|
|
|
return logical.ErrorResponse("wrapping information was nil; wrapping token may be from a previous Vault version"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response := cubbyResp.Data["response"]
|
|
|
|
if response == nil {
|
|
|
|
return nil, fmt.Errorf("no response found inside the cubbyhole")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return response in "response"; wrapping code will detect the rewrap and
|
|
|
|
// slot in instead of nesting
|
|
|
|
return &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"response": response,
|
|
|
|
},
|
2017-04-24 19:15:01 +00:00
|
|
|
WrapInfo: &wrapping.ResponseWrapInfo{
|
2017-08-02 22:28:58 +00:00
|
|
|
TTL: time.Duration(creationTTL),
|
|
|
|
CreationPath: creationPath,
|
2016-11-11 20:12:11 +00:00
|
|
|
},
|
2016-09-29 04:01:28 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) pathHashWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-10-20 14:59:17 +00:00
|
|
|
inputB64 := d.Get("input").(string)
|
|
|
|
format := d.Get("format").(string)
|
|
|
|
algorithm := d.Get("urlalgorithm").(string)
|
|
|
|
if algorithm == "" {
|
|
|
|
algorithm = d.Get("algorithm").(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
input, err := base64.StdEncoding.DecodeString(inputB64)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("unable to decode input as base64: %s", err)), logical.ErrInvalidRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
switch format {
|
|
|
|
case "hex":
|
|
|
|
case "base64":
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("unsupported encoding format %s; must be \"hex\" or \"base64\"", format)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var hf hash.Hash
|
|
|
|
switch algorithm {
|
|
|
|
case "sha2-224":
|
|
|
|
hf = sha256.New224()
|
|
|
|
case "sha2-256":
|
|
|
|
hf = sha256.New()
|
|
|
|
case "sha2-384":
|
|
|
|
hf = sha512.New384()
|
|
|
|
case "sha2-512":
|
|
|
|
hf = sha512.New()
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("unsupported algorithm %s", algorithm)), nil
|
|
|
|
}
|
|
|
|
hf.Write(input)
|
|
|
|
retBytes := hf.Sum(nil)
|
|
|
|
|
|
|
|
var retStr string
|
|
|
|
switch format {
|
|
|
|
case "hex":
|
|
|
|
retStr = hex.EncodeToString(retBytes)
|
|
|
|
case "base64":
|
|
|
|
retStr = base64.StdEncoding.EncodeToString(retBytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the response
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"sum": retStr,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *SystemBackend) pathRandomWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2017-10-20 14:59:17 +00:00
|
|
|
bytes := 0
|
|
|
|
var err error
|
|
|
|
strBytes := d.Get("urlbytes").(string)
|
|
|
|
if strBytes != "" {
|
|
|
|
bytes, err = strconv.Atoi(strBytes)
|
|
|
|
if err != nil {
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("error parsing url-set byte count: %s", err)), nil
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bytes = d.Get("bytes").(int)
|
|
|
|
}
|
|
|
|
format := d.Get("format").(string)
|
|
|
|
|
|
|
|
if bytes < 1 {
|
|
|
|
return logical.ErrorResponse(`"bytes" cannot be less than 1`), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
switch format {
|
|
|
|
case "hex":
|
|
|
|
case "base64":
|
|
|
|
default:
|
|
|
|
return logical.ErrorResponse(fmt.Sprintf("unsupported encoding format %s; must be \"hex\" or \"base64\"", format)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
randBytes, err := uuid.GenerateRandomBytes(bytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var retStr string
|
|
|
|
switch format {
|
|
|
|
case "hex":
|
|
|
|
retStr = hex.EncodeToString(randBytes)
|
|
|
|
case "base64":
|
|
|
|
retStr = base64.StdEncoding.EncodeToString(randBytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the response
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: map[string]interface{}{
|
|
|
|
"random_bytes": retStr,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
func (b *SystemBackend) pathInternalUIMountsRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
|
|
|
b.Core.mountsLock.RLock()
|
|
|
|
defer b.Core.mountsLock.RUnlock()
|
|
|
|
|
|
|
|
resp := &logical.Response{
|
|
|
|
Data: make(map[string]interface{}),
|
|
|
|
}
|
|
|
|
|
|
|
|
secretMounts := make(map[string]interface{})
|
|
|
|
authMounts := make(map[string]interface{})
|
|
|
|
resp.Data["secret"] = secretMounts
|
|
|
|
resp.Data["auth"] = authMounts
|
|
|
|
|
|
|
|
for _, entry := range b.Core.mounts.Entries {
|
|
|
|
if entry.Config.ListingVisibility == ListingVisibilityUnauth {
|
|
|
|
info := map[string]interface{}{
|
|
|
|
"type": entry.Type,
|
|
|
|
"description": entry.Description,
|
|
|
|
}
|
|
|
|
secretMounts[entry.Path] = info
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, entry := range b.Core.auth.Entries {
|
|
|
|
if entry.Config.ListingVisibility == ListingVisibilityUnauth {
|
|
|
|
info := map[string]interface{}{
|
|
|
|
"type": entry.Type,
|
|
|
|
"description": entry.Description,
|
|
|
|
}
|
|
|
|
authMounts[entry.Path] = info
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2016-03-03 18:13:47 +00:00
|
|
|
func sanitizeMountPath(path string) string {
|
|
|
|
if !strings.HasSuffix(path, "/") {
|
|
|
|
path += "/"
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.HasPrefix(path, "/") {
|
|
|
|
path = path[1:]
|
|
|
|
}
|
|
|
|
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
|
2018-03-20 03:16:33 +00:00
|
|
|
func checkListingVisibility(visibility ListingVisiblityType) error {
|
|
|
|
switch visibility {
|
|
|
|
case ListingVisibilityHidden:
|
|
|
|
case ListingVisibilityUnauth:
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("invalid listing visilibity type")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-04-04 04:00:23 +00:00
|
|
|
const sysHelpRoot = `
|
|
|
|
The system backend is built-in to Vault and cannot be remounted or
|
|
|
|
unmounted. It contains the paths that are used to configure Vault itself
|
|
|
|
as well as perform core operations.
|
|
|
|
`
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
// sysHelp is all the help text for the sys backend.
|
|
|
|
var sysHelp = map[string][2]string{
|
2017-06-17 04:04:55 +00:00
|
|
|
"config/cors": {
|
|
|
|
"Configures or returns the current configuration of CORS settings.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
Returns the configuration of the CORS setting.
|
|
|
|
|
|
|
|
POST /
|
|
|
|
Sets the comma-separated list of origins that can make cross-origin requests.
|
|
|
|
|
|
|
|
DELETE /
|
|
|
|
Clears the CORS configuration and disables acceptance of CORS requests.
|
|
|
|
`,
|
|
|
|
},
|
2018-03-27 20:23:33 +00:00
|
|
|
"config/ui/headers": {
|
|
|
|
"Configures response headers that should be returned from the UI.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
GET /<header>
|
|
|
|
Returns the header value.
|
|
|
|
POST /<header>
|
|
|
|
Sets the header value for the UI.
|
|
|
|
DELETE /<header>
|
|
|
|
Clears the header value for UI.
|
|
|
|
|
|
|
|
LIST /
|
|
|
|
List the headers configured for the UI.
|
|
|
|
`,
|
|
|
|
},
|
2016-04-13 21:15:54 +00:00
|
|
|
"init": {
|
|
|
|
"Initializes or returns the initialization status of the Vault.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
Returns the initialization status of the Vault.
|
|
|
|
|
|
|
|
POST /
|
|
|
|
Initializes a new vault.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
"generate-root": {
|
|
|
|
"Reads, generates, or deletes a root token regeneration process.",
|
|
|
|
`
|
|
|
|
This path responds to multiple HTTP methods which change the behavior. Those
|
|
|
|
HTTP methods are listed below.
|
|
|
|
|
|
|
|
GET /attempt
|
|
|
|
Reads the configuration and progress of the current root generation
|
|
|
|
attempt.
|
|
|
|
|
|
|
|
POST /attempt
|
|
|
|
Initializes a new root generation attempt. Only a single root generation
|
|
|
|
attempt can take place at a time. One (and only one) of otp or pgp_key
|
|
|
|
are required.
|
|
|
|
|
|
|
|
DELETE /attempt
|
|
|
|
Cancels any in-progress root generation attempt. This clears any
|
|
|
|
progress made. This must be called to change the OTP or PGP key being
|
|
|
|
used.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
"seal-status": {
|
|
|
|
"Returns the seal status of the Vault.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
Returns the seal status of the Vault. This is an unauthenticated
|
|
|
|
endpoint.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
"seal": {
|
|
|
|
"Seals the Vault.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
PUT /
|
|
|
|
Seals the Vault.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
"unseal": {
|
|
|
|
"Unseals the Vault.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
PUT /
|
|
|
|
Unseals the Vault.
|
|
|
|
`,
|
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
"mounts": {
|
|
|
|
"List the currently mounted backends.",
|
|
|
|
`
|
2016-04-13 21:15:54 +00:00
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
Lists all the mounted secret backends.
|
|
|
|
|
|
|
|
GET /<mount point>
|
|
|
|
Get information about the mount at the specified path.
|
|
|
|
|
|
|
|
POST /<mount point>
|
|
|
|
Mount a new secret backend to the mount point in the URL.
|
|
|
|
|
|
|
|
POST /<mount point>/tune
|
|
|
|
Tune configuration parameters for the given mount point.
|
|
|
|
|
|
|
|
DELETE /<mount point>
|
|
|
|
Unmount the specified mount point.
|
2015-03-16 00:35:59 +00:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"mount": {
|
|
|
|
`Mount a new backend at a new path.`,
|
|
|
|
`
|
|
|
|
Mount a backend at a new path. A backend can be mounted multiple times at
|
|
|
|
multiple paths in order to configure multiple separately configured backends.
|
|
|
|
Example: you might have an AWS backend for the east coast, and one for the
|
|
|
|
west coast.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"mount_path": {
|
|
|
|
`The path to mount to. Example: "aws/east"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"mount_type": {
|
|
|
|
`The type of the backend. Example: "passthrough"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"mount_desc": {
|
|
|
|
`User-friendly description for this mount.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
2015-08-31 18:27:49 +00:00
|
|
|
"mount_config": {
|
|
|
|
`Configuration for this mount, such as default_lease_ttl
|
|
|
|
and max_lease_ttl.`,
|
|
|
|
},
|
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
"mount_local": {
|
|
|
|
`Mark the mount as a local mount, which is not replicated
|
|
|
|
and is unaffected by replication.`,
|
|
|
|
},
|
|
|
|
|
2017-08-31 16:16:59 +00:00
|
|
|
"mount_plugin_name": {
|
2017-10-19 20:29:59 +00:00
|
|
|
`Name of the plugin to mount based from the name registered
|
2017-08-31 16:16:59 +00:00
|
|
|
in the plugin catalog.`,
|
|
|
|
},
|
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
"mount_options": {
|
|
|
|
`The options to pass into the backend. Should be a json object with string keys and values.`,
|
|
|
|
},
|
|
|
|
|
2017-11-13 16:22:22 +00:00
|
|
|
"seal_wrap": {
|
|
|
|
`Whether to turn on seal wrapping for the mount.`,
|
|
|
|
},
|
|
|
|
|
2015-09-09 19:24:45 +00:00
|
|
|
"tune_default_lease_ttl": {
|
|
|
|
`The default lease TTL for this mount.`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"tune_max_lease_ttl": {
|
|
|
|
`The max lease TTL for this mount.`,
|
|
|
|
},
|
|
|
|
|
2018-03-02 17:18:39 +00:00
|
|
|
"tune_audit_non_hmac_request_keys": {
|
|
|
|
`The list of keys in the request data object that will not be HMAC'ed by audit devices.`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"tune_audit_non_hmac_response_keys": {
|
|
|
|
`The list of keys in the response data object that will not be HMAC'ed by audit devices.`,
|
|
|
|
},
|
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
"tune_mount_options": {
|
|
|
|
`The options to pass into the backend. Should be a json object with string keys and values.`,
|
|
|
|
},
|
|
|
|
|
2015-03-16 00:35:59 +00:00
|
|
|
"remount": {
|
|
|
|
"Move the mount point of an already-mounted backend.",
|
|
|
|
`
|
2016-04-13 21:15:54 +00:00
|
|
|
This path responds to the following HTTP methods.
|
2015-03-19 14:05:22 +00:00
|
|
|
|
2016-04-13 21:15:54 +00:00
|
|
|
POST /sys/remount
|
|
|
|
Changes the mount point of an already-mounted backend.
|
|
|
|
`,
|
2015-03-19 14:05:22 +00:00
|
|
|
},
|
|
|
|
|
2016-06-15 16:35:30 +00:00
|
|
|
"auth_tune": {
|
|
|
|
"Tune the configuration parameters for an auth path.",
|
|
|
|
`Read and write the 'default-lease-ttl' and 'max-lease-ttl' values of
|
|
|
|
the auth path.`,
|
|
|
|
},
|
|
|
|
|
2015-09-02 19:56:58 +00:00
|
|
|
"mount_tune": {
|
|
|
|
"Tune backend configuration parameters for this mount.",
|
2016-06-15 16:35:30 +00:00
|
|
|
`Read and write the 'default-lease-ttl' and 'max-lease-ttl' values of
|
|
|
|
the mount.`,
|
2015-09-02 19:56:58 +00:00
|
|
|
},
|
|
|
|
|
2015-03-16 23:11:55 +00:00
|
|
|
"renew": {
|
|
|
|
"Renew a lease on a secret",
|
|
|
|
`
|
|
|
|
When a secret is read, it may optionally include a lease interval
|
|
|
|
and a boolean indicating if renew is possible. For secrets that support
|
|
|
|
lease renewal, this endpoint is used to extend the validity of the
|
|
|
|
lease and to prevent an automatic revocation.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
2015-04-08 20:35:32 +00:00
|
|
|
"lease_id": {
|
|
|
|
"The lease identifier to renew. This is included with a lease.",
|
2015-03-16 23:11:55 +00:00
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"increment": {
|
|
|
|
"The desired increment in seconds to the lease",
|
|
|
|
"",
|
|
|
|
},
|
2015-03-16 23:26:34 +00:00
|
|
|
|
|
|
|
"revoke": {
|
|
|
|
"Revoke a leased secret immediately",
|
|
|
|
`
|
|
|
|
When a secret is generated with a lease, it is automatically revoked
|
|
|
|
at the end of the lease period if not renewed. However, in some cases
|
|
|
|
you may want to force an immediate revocation. This endpoint can be
|
2015-04-08 20:35:32 +00:00
|
|
|
used to revoke the secret with the given Lease ID.
|
2015-03-16 23:26:34 +00:00
|
|
|
`,
|
|
|
|
},
|
2015-03-16 23:33:48 +00:00
|
|
|
|
|
|
|
"revoke-prefix": {
|
|
|
|
"Revoke all secrets generated in a given prefix",
|
|
|
|
`
|
|
|
|
Revokes all the secrets generated under a given mount prefix. As
|
|
|
|
an example, "prod/aws/" might be the AWS logical backend, and due to
|
|
|
|
a change in the "ops" policy, we may want to invalidate all the secrets
|
|
|
|
generated. We can do a revoke prefix at "prod/aws/ops" to revoke all
|
2015-04-08 20:35:32 +00:00
|
|
|
the ops secrets. This does a prefix match on the Lease IDs and revokes
|
2015-03-16 23:33:48 +00:00
|
|
|
all matching leases.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"revoke-prefix-path": {
|
|
|
|
`The path to revoke keys under. Example: "prod/aws/ops"`,
|
|
|
|
"",
|
|
|
|
},
|
2015-03-20 19:48:19 +00:00
|
|
|
|
Add forced revocation.
In some situations, it can be impossible to revoke leases (for instance,
if someone has gone and manually removed users created by Vault). This
can not only cause Vault to cycle trying to revoke them, but it also
prevents mounts from being unmounted, leaving them in a tainted state
where the only operations allowed are to revoke (or rollback), which
will never successfully complete.
This adds a new endpoint that works similarly to `revoke-prefix` but
ignores errors coming from a backend upon revocation (it does not ignore
errors coming from within the expiration manager, such as errors
accessing the data store). This can be used to force Vault to abandon
leases.
Like `revoke-prefix`, this is a very sensitive operation and requires
`sudo`. It is implemented as a separate endpoint, rather than an
argument to `revoke-prefix`, to ensure that control can be delegated
appropriately, as even most administrators should not normally have
this privilege.
Fixes #1135
2016-03-03 01:26:38 +00:00
|
|
|
"revoke-force": {
|
|
|
|
"Revoke all secrets generated in a given prefix, ignoring errors.",
|
|
|
|
`
|
|
|
|
See the path help for 'revoke-prefix'; this behaves the same, except that it
|
|
|
|
ignores errors encountered during revocation. This can be used in certain
|
|
|
|
recovery situations; for instance, when you want to unmount a backend, but it
|
|
|
|
is impossible to fix revocation errors and these errors prevent the unmount
|
|
|
|
from proceeding. This is a DANGEROUS operation as it removes Vault's oversight
|
|
|
|
of external secrets. Access to this prefix should be tightly controlled.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"revoke-force-path": {
|
|
|
|
`The path to revoke keys under. Example: "prod/aws/ops"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
2015-03-20 19:48:19 +00:00
|
|
|
"auth-table": {
|
|
|
|
"List the currently enabled credential backends.",
|
|
|
|
`
|
2016-04-13 21:15:54 +00:00
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
List the currently enabled credential backends: the name, the type of
|
|
|
|
the backend, and a user friendly description of the purpose for the
|
|
|
|
credential backend.
|
|
|
|
|
|
|
|
POST /<mount point>
|
2017-09-13 01:48:52 +00:00
|
|
|
Enable a new auth method.
|
2016-04-13 21:15:54 +00:00
|
|
|
|
|
|
|
DELETE /<mount point>
|
2017-09-13 01:48:52 +00:00
|
|
|
Disable the auth method at the given mount point.
|
2015-03-20 19:48:19 +00:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"auth": {
|
|
|
|
`Enable a new credential backend with a name.`,
|
|
|
|
`
|
|
|
|
Enable a credential mechanism at a new path. A backend can be mounted multiple times at
|
|
|
|
multiple paths in order to configure multiple separately configured backends.
|
|
|
|
Example: you might have an OAuth backend for GitHub, and one for Google Apps.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"auth_path": {
|
|
|
|
`The path to mount to. Cannot be delimited. Example: "user"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"auth_type": {
|
|
|
|
`The type of the backend. Example: "userpass"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"auth_desc": {
|
2018-03-20 18:54:10 +00:00
|
|
|
`User-friendly description for this credential backend.`,
|
2015-03-20 19:48:19 +00:00
|
|
|
"",
|
|
|
|
},
|
2015-03-23 21:43:31 +00:00
|
|
|
|
2017-08-31 16:16:59 +00:00
|
|
|
"auth_config": {
|
|
|
|
`Configuration for this mount, such as plugin_name.`,
|
|
|
|
},
|
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
"auth_plugin": {
|
|
|
|
`Name of the auth plugin to use based from the name in the plugin catalog.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
2018-03-21 19:04:27 +00:00
|
|
|
"auth_options": {
|
|
|
|
`The options to pass into the backend. Should be a json object with string keys and values.`,
|
|
|
|
},
|
|
|
|
|
2015-03-23 21:43:31 +00:00
|
|
|
"policy-list": {
|
|
|
|
`List the configured access control policies.`,
|
|
|
|
`
|
2016-04-13 21:15:54 +00:00
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
List the names of the configured access control policies.
|
|
|
|
|
|
|
|
GET /<name>
|
|
|
|
Retrieve the rules for the named policy.
|
|
|
|
|
|
|
|
PUT /<name>
|
|
|
|
Add or update a policy.
|
|
|
|
|
|
|
|
DELETE /<name>
|
|
|
|
Delete the policy with the given name.
|
2015-03-23 21:43:31 +00:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"policy": {
|
|
|
|
`Read, Modify, or Delete an access control policy.`,
|
|
|
|
`
|
|
|
|
Read the rules of an existing policy, create or update the rules of a policy,
|
|
|
|
or delete a policy.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"policy-name": {
|
|
|
|
`The name of the policy. Example: "ops"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"policy-rules": {
|
|
|
|
`The rules of the policy. Either given in HCL or JSON format.`,
|
|
|
|
"",
|
|
|
|
},
|
2015-03-31 23:45:00 +00:00
|
|
|
|
2015-11-19 01:26:03 +00:00
|
|
|
"audit-hash": {
|
|
|
|
"The hash of the given string via the given audit backend",
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
2015-03-31 23:45:00 +00:00
|
|
|
"audit-table": {
|
|
|
|
"List the currently enabled audit backends.",
|
|
|
|
`
|
2016-04-13 21:15:54 +00:00
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /
|
|
|
|
List the currently enabled audit backends.
|
|
|
|
|
|
|
|
PUT /<path>
|
|
|
|
Enable an audit backend at the given path.
|
|
|
|
|
|
|
|
DELETE /<path>
|
|
|
|
Disable the given audit backend.
|
2015-03-31 23:45:00 +00:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"audit_path": {
|
|
|
|
`The name of the backend. Cannot be delimited. Example: "mysql"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"audit_type": {
|
|
|
|
`The type of the backend. Example: "mysql"`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"audit_desc": {
|
|
|
|
`User-friendly description for this audit backend.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"audit_opts": {
|
|
|
|
`Configuration options for the audit backend.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
|
|
|
|
"audit": {
|
|
|
|
`Enable or disable audit backends.`,
|
|
|
|
`
|
|
|
|
Enable a new audit backend or disable an existing backend.
|
|
|
|
`,
|
|
|
|
},
|
2015-05-28 00:53:42 +00:00
|
|
|
|
|
|
|
"key-status": {
|
|
|
|
"Provides information about the backend encryption key.",
|
|
|
|
`
|
|
|
|
Provides the current backend encryption key term and installation time.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"rotate": {
|
|
|
|
"Rotates the backend encryption key used to persist data.",
|
|
|
|
`
|
|
|
|
Rotate generates a new encryption key which is used to encrypt all
|
|
|
|
data going to the storage backend. The old encryption keys are kept so
|
|
|
|
that data encrypted using those keys can still be decrypted.
|
|
|
|
`,
|
|
|
|
},
|
2016-03-10 02:04:54 +00:00
|
|
|
|
|
|
|
"rekey_backup": {
|
|
|
|
"Allows fetching or deleting the backup of the rotated unseal keys.",
|
|
|
|
"",
|
|
|
|
},
|
2016-03-17 19:23:36 +00:00
|
|
|
|
|
|
|
"capabilities": {
|
|
|
|
"Fetches the capabilities of the given token on the given path.",
|
2016-03-18 03:01:28 +00:00
|
|
|
`Returns the capabilities of the given token on the path.
|
|
|
|
The path will be searched for a path match in all the policies associated with the token.`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"capabilities_self": {
|
|
|
|
"Fetches the capabilities of the given token on the given path.",
|
|
|
|
`Returns the capabilities of the client token on the path.
|
|
|
|
The path will be searched for a path match in all the policies associated with the client token.`,
|
2016-03-17 19:23:36 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
"capabilities_accessor": {
|
|
|
|
"Fetches the capabilities of the token associated with the given token, on the given path.",
|
2016-03-18 03:01:28 +00:00
|
|
|
`When there is no access to the token, token accessor can be used to fetch the token's capabilities
|
|
|
|
on a given path.`,
|
2016-03-17 19:23:36 +00:00
|
|
|
},
|
2016-09-29 04:01:28 +00:00
|
|
|
|
2017-03-07 20:22:21 +00:00
|
|
|
"tidy_leases": {
|
|
|
|
`This endpoint performs cleanup tasks that can be run if certain error
|
|
|
|
conditions have occurred.`,
|
2017-03-07 21:06:05 +00:00
|
|
|
`This endpoint performs cleanup tasks that can be run to clean up the
|
2017-03-07 20:22:21 +00:00
|
|
|
lease entries after certain error conditions. Usually running this is not
|
|
|
|
necessary, and is only required if upgrade notes or support personnel suggest
|
|
|
|
it.`,
|
|
|
|
},
|
|
|
|
|
2016-09-29 04:01:28 +00:00
|
|
|
"wrap": {
|
|
|
|
"Response-wraps an arbitrary JSON object.",
|
|
|
|
`Round trips the given input data into a response-wrapped token.`,
|
|
|
|
},
|
|
|
|
|
2017-01-04 21:44:03 +00:00
|
|
|
"wrappubkey": {
|
|
|
|
"Returns pubkeys used in some wrapping formats.",
|
|
|
|
"Returns pubkeys used in some wrapping formats.",
|
|
|
|
},
|
|
|
|
|
2016-09-29 04:01:28 +00:00
|
|
|
"unwrap": {
|
|
|
|
"Unwraps a response-wrapped token.",
|
|
|
|
`Unwraps a response-wrapped token. Unlike simply reading from cubbyhole/response,
|
|
|
|
this provides additional validation on the token, and rather than a JSON-escaped
|
|
|
|
string, the returned response is the exact same as the contained wrapped response.`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"wraplookup": {
|
|
|
|
"Looks up the properties of a response-wrapped token.",
|
|
|
|
`Returns the creation TTL and creation time of a response-wrapped token.`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"rewrap": {
|
|
|
|
"Rotates a response-wrapped token.",
|
|
|
|
`Rotates a response-wrapped token; the output is a new token with the same
|
|
|
|
response wrapped inside and the same creation TTL. The original token is revoked.`,
|
|
|
|
},
|
2017-02-03 18:08:31 +00:00
|
|
|
"audited-headers-name": {
|
|
|
|
"Configures the headers sent to the audit logs.",
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
GET /<name>
|
|
|
|
Returns the setting for the header with the given name.
|
|
|
|
|
|
|
|
POST /<name>
|
|
|
|
Enable auditing of the given header.
|
|
|
|
|
|
|
|
DELETE /<path>
|
|
|
|
Disable auditing of the given header.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
"audited-headers": {
|
|
|
|
"Lists the headers configured to be audited.",
|
|
|
|
`Returns a list of headers that have been configured to be audited.`,
|
|
|
|
},
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
"plugin-catalog": {
|
|
|
|
"Configures the plugins known to vault",
|
2017-04-12 17:01:36 +00:00
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
LIST /
|
|
|
|
Returns a list of names of configured plugins.
|
2017-05-04 02:03:42 +00:00
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
GET /<name>
|
|
|
|
Retrieve the metadata for the named plugin.
|
2017-04-12 17:01:36 +00:00
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
PUT /<name>
|
|
|
|
Add or update plugin.
|
2017-04-12 17:01:36 +00:00
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
DELETE /<name>
|
|
|
|
Delete the plugin with the given name.
|
2017-04-12 17:01:36 +00:00
|
|
|
`,
|
|
|
|
},
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
"plugin-catalog_name": {
|
|
|
|
"The name of the plugin",
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
"plugin-catalog_sha-256": {
|
2017-10-19 20:29:59 +00:00
|
|
|
`The SHA256 sum of the executable used in the
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
command field. This should be HEX encoded.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
"plugin-catalog_command": {
|
|
|
|
`The command used to start the plugin. The
|
|
|
|
executable defined in this command must exist in vault's
|
|
|
|
plugin directory.`,
|
|
|
|
"",
|
|
|
|
},
|
2018-01-18 00:19:28 +00:00
|
|
|
"plugin-catalog_args": {
|
|
|
|
`The args passed to plugin command.`,
|
|
|
|
"",
|
|
|
|
},
|
2017-05-04 02:03:42 +00:00
|
|
|
"leases": {
|
|
|
|
`View or list lease metadata.`,
|
|
|
|
`
|
|
|
|
This path responds to the following HTTP methods.
|
|
|
|
|
|
|
|
PUT /
|
|
|
|
Retrieve the metadata for the provided lease id.
|
|
|
|
|
|
|
|
LIST /<prefix>
|
|
|
|
Lists the leases for the named prefix.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
"leases-list-prefix": {
|
|
|
|
`The path to list leases under. Example: "aws/creds/deploy"`,
|
|
|
|
"",
|
|
|
|
},
|
2017-08-08 04:18:59 +00:00
|
|
|
"plugin-reload": {
|
|
|
|
"Reload mounts that use a particular backend plugin.",
|
|
|
|
`Reload mounts that use a particular backend plugin. Either the plugin name
|
|
|
|
or the desired plugin backend mounts must be provided, but not both. In the
|
|
|
|
case that the plugin name is provided, all mounted paths that use that plugin
|
|
|
|
backend will be reloaded.`,
|
|
|
|
},
|
|
|
|
"plugin-backend-reload-plugin": {
|
|
|
|
`The name of the plugin to reload, as registered in the plugin catalog.`,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
"plugin-backend-reload-mounts": {
|
|
|
|
`The mount paths of the plugin backends to reload.`,
|
|
|
|
"",
|
|
|
|
},
|
2017-10-20 14:59:17 +00:00
|
|
|
"hash": {
|
|
|
|
"Generate a hash sum for input data",
|
|
|
|
"Generates a hash sum of the given algorithm against the given input data.",
|
|
|
|
},
|
|
|
|
"random": {
|
|
|
|
"Generate random bytes",
|
|
|
|
"This function can be used to generate high-entropy random bytes.",
|
|
|
|
},
|
2018-03-20 03:16:33 +00:00
|
|
|
"listing_visibility": {
|
|
|
|
"Determines the visibility of the mount in the UI-specific listing endpoint.",
|
|
|
|
},
|
2018-03-21 23:56:47 +00:00
|
|
|
"passthrough_request_headers": {
|
|
|
|
"A list of headers to whitelist and pass from the request to the backend.",
|
|
|
|
},
|
2015-03-16 00:35:59 +00:00
|
|
|
}
|