func (b *SystemBackend) handleMountTuneRead(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	path := data.Get("path").(string)
	if path == "" {
		return logical.ErrorResponse(
				"path must be specified as a string"),
			logical.ErrInvalidRequest
	}
	return b.handleTuneReadCommon(path)
}
handleMountTuneRead is used to get config settings on a backend
package vault
import (
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strings"
	"sync"
	"time"
	"github.com/hashicorp/vault/helper/duration"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
	"github.com/mitchellh/mapstructure"
)
var (
	protectedPaths = []string{
		"core",
	}
)
func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backend, error) {
	b := &SystemBackend{
		Core: core,
	}
	b.Backend = &framework.Backend{
		Help: strings.TrimSpace(sysHelpRoot),
		PathsSpecial: &logical.Paths{
			Root: []string{
				"auth/*",
				"remount",
				"revoke-prefix/*",
				"audit",
				"audit/*",
				"raw/*",
				"rotate",
			},
		},
		Paths: []*framework.Path{
			&framework.Path{
				Pattern: "capabilities-accessor$",
				Fields: map[string]*framework.FieldSchema{
					"accessor": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Accessor of the token for which capabilities are being queried.",
					},
					"path": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Path on which capabilities are being queried.",
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleCapabilitiesAccessor,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["capabilities_accessor"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["capabilities_accessor"][1]),
			},
			&framework.Path{
				Pattern: "capabilities$",
				Fields: map[string]*framework.FieldSchema{
					"token": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Token for which capabilities are being queried.",
					},
					"path": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Path on which capabilities are being queried.",
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleCapabilities,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["capabilities"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["capabilities"][1]),
			},
			&framework.Path{
				Pattern: "capabilities-self$",
				Fields: map[string]*framework.FieldSchema{
					"token": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Token for which capabilities are being queried.",
					},
					"path": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "Path on which capabilities are being queried.",
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleCapabilities,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["capabilities_self"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["capabilities_self"][1]),
			},
			&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]),
			},
			&framework.Path{
				Pattern: "rekey/backup$",
				Fields: map[string]*framework.FieldSchema{},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					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,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["rekey_backup"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["rekey_backup"][0]),
			},
			&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]),
					},
				},
				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]),
			},
			&framework.Path{
				Pattern: "mounts/(?P<path>.+?)/tune$",
				Fields: map[string]*framework.FieldSchema{
					"path": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: strings.TrimSpace(sysHelp["mount_path"][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]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.ReadOperation:   b.handleMountTuneRead,
					logical.UpdateOperation: b.handleMountTuneWrite,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["mount_tune"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["mount_tune"][1]),
			},
			&framework.Path{
				Pattern: "mounts/(?P<path>.+?)",
				Fields: map[string]*framework.FieldSchema{
					"path": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: strings.TrimSpace(sysHelp["mount_path"][0]),
					},
					"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]),
					},
					"config": &framework.FieldSchema{
						Type:        framework.TypeMap,
						Description: strings.TrimSpace(sysHelp["mount_config"][0]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleMount,
					logical.DeleteOperation: b.handleUnmount,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["mount"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["mount"][1]),
			},
			&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]),
			},
			&framework.Path{
				Pattern: "remount",
				Fields: map[string]*framework.FieldSchema{
					"from": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "The previous mount point.",
					},
					"to": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: "The new mount point.",
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleRemount,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["remount"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["remount"][1]),
			},
			&framework.Path{
				Pattern: "renew" + framework.OptionalParamRegex("url_lease_id"),
				Fields: map[string]*framework.FieldSchema{
					"url_lease_id": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: strings.TrimSpace(sysHelp["lease_id"][0]),
					},
					"lease_id": &framework.FieldSchema{
						Type:        framework.TypeString,
						Description: strings.TrimSpace(sysHelp["lease_id"][0]),
					},
					"increment": &framework.FieldSchema{
						Type:        framework.TypeDurationSecond,
						Description: strings.TrimSpace(sysHelp["increment"][0]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleRenew,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["renew"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["renew"][1]),
			},
			&framework.Path{
				Pattern: "revoke/(?P<lease_id>.+)",
				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.handleRevoke,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["revoke"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["revoke"][1]),
			},
			&framework.Path{
				Pattern: "revoke-force/(?P<prefix>.+)",
				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]),
			},
			&framework.Path{
				Pattern: "revoke-prefix/(?P<prefix>.+)",
				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{
					logical.UpdateOperation: b.handleRevokePrefix,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["revoke-prefix"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["revoke-prefix"][1]),
			},
			&framework.Path{
				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]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleEnableAuth,
					logical.DeleteOperation: b.handleDisableAuth,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["auth"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["auth"][1]),
			},
			&framework.Path{
				Pattern: "policy$",
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.ReadOperation: b.handlePolicyList,
					logical.ListOperation: b.handlePolicyList,
				},
				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]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.ReadOperation:   b.handlePolicyRead,
					logical.UpdateOperation: b.handlePolicySet,
					logical.DeleteOperation: b.handlePolicyDelete,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["policy"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["policy"][1]),
			},
			&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]),
			},
			&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{
					logical.UpdateOperation: b.handleAuditHash,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["audit-hash"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["audit-hash"][1]),
			},
			&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{
						Type:        framework.TypeMap,
						Description: strings.TrimSpace(sysHelp["audit_opts"][0]),
					},
				},
				Callbacks: map[logical.Operation]framework.OperationFunc{
					logical.UpdateOperation: b.handleEnableAudit,
					logical.DeleteOperation: b.handleDisableAudit,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["audit"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["audit"][1]),
			},
			&framework.Path{
				Pattern: "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,
				},
			},
			&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{
					logical.UpdateOperation: b.handleRotate,
				},
				HelpSynopsis:    strings.TrimSpace(sysHelp["rotate"][0]),
				HelpDescription: strings.TrimSpace(sysHelp["rotate"][1]),
			},
			&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,
				},
				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]),
			},
		},
	}
	return b.Backend.Setup(config)
}
type SystemBackend struct {
	Core    *Core
	Backend *framework.Backend
}
func (b *SystemBackend) handleCapabilities(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	token := d.Get("token").(string)
	if token == "" {
		token = req.ClientToken
	}
	capabilities, err := b.Core.Capabilities(token, d.Get("path").(string))
	if err != nil {
		return nil, err
	}
	return &logical.Response{
		Data: map[string]interface{}{
			"capabilities": capabilities,
		},
	}, nil
}
func (b *SystemBackend) handleCapabilitiesAccessor(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	accessor := d.Get("accessor").(string)
	if accessor == "" {
		return logical.ErrorResponse("missing accessor"), nil
	}
	aEntry, err := b.Core.tokenStore.lookupByAccessor(accessor)
	if err != nil {
		return nil, err
	}
	capabilities, err := b.Core.Capabilities(aEntry.TokenID, d.Get("path").(string))
	if err != nil {
		return nil, err
	}
	return &logical.Response{
		Data: map[string]interface{}{
			"capabilities": capabilities,
		},
	}, nil
}
func (b *SystemBackend) handleRekeyRetrieve(
	req *logical.Request,
	data *framework.FieldData,
	recovery bool) (*logical.Response, error) {
	backup, err := b.Core.RekeyRetrieveBackup(recovery)
	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
	}
	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
		}
	}
	resp := &logical.Response{
		Data: map[string]interface{}{
			"nonce":       backup.Nonce,
			"keys":        backup.Keys,
			"keys_base64": keysB64,
		},
	}
	return resp, nil
}
func (b *SystemBackend) handleRekeyRetrieveBarrier(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	return b.handleRekeyRetrieve(req, data, false)
}
func (b *SystemBackend) handleRekeyRetrieveRecovery(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	return b.handleRekeyRetrieve(req, data, true)
}
func (b *SystemBackend) handleRekeyDelete(
	req *logical.Request,
	data *framework.FieldData,
	recovery bool) (*logical.Response, error) {
	err := b.Core.RekeyDeleteBackup(recovery)
	if err != nil {
		return nil, fmt.Errorf("error during deletion of backed-up keys: %v", err)
	}
	return nil, nil
}
func (b *SystemBackend) handleRekeyDeleteBarrier(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	return b.handleRekeyDelete(req, data, false)
}
func (b *SystemBackend) handleRekeyDeleteRecovery(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	return b.handleRekeyDelete(req, data, true)
}
func (b *SystemBackend) handleMountTable(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	b.Core.mountsLock.RLock()
	defer b.Core.mountsLock.RUnlock()
	resp := &logical.Response{
		Data: make(map[string]interface{}),
	}
	for _, entry := range b.Core.mounts.Entries {
		info := map[string]interface{}{
			"type":        entry.Type,
			"description": entry.Description,
			"config": map[string]interface{}{
				"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
				"max_lease_ttl":     int64(entry.Config.MaxLeaseTTL.Seconds()),
			},
		}
		resp.Data[entry.Path] = info
	}
	return resp, nil
}
func (b *SystemBackend) handleMount(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	path := data.Get("path").(string)
	logicalType := data.Get("type").(string)
	description := data.Get("description").(string)
	path = sanitizeMountPath(path)
	var config MountConfig
	var apiConfig struct {
		DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
		MaxLeaseTTL     string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
	}
	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 mount config information"),
				logical.ErrInvalidRequest
		}
	}
	switch apiConfig.DefaultLeaseTTL {
	case "":
	case "system":
	default:
		tmpDef, err := duration.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 := duration.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 {
		return logical.ErrorResponse(fmt.Sprintf(
				"given default lease TTL greater than system max lease TTL of %d", int(b.Core.maxLeaseTTL.Seconds()))),
			logical.ErrInvalidRequest
	}
	if logicalType == "" {
		return logical.ErrorResponse(
				"backend type must be specified as a string"),
			logical.ErrInvalidRequest
	}
	me := &MountEntry{
		Table:       mountTableType,
		Path:        path,
		Type:        logicalType,
		Description: description,
		Config:      config,
	}
	if err := b.Core.mount(me); err != nil {
		b.Backend.Logger().Error("sys: mount failed", "path", me.Path, "error", err)
		return handleError(err)
	}
	return nil, nil
}
func handleError(
	err error) (*logical.Response, error) {
	switch err.(type) {
	case logical.HTTPCodedError:
		return logical.ErrorResponse(err.Error()), err
	default:
		return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
	}
}
func (b *SystemBackend) handleUnmount(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	suffix := strings.TrimPrefix(req.Path, "mounts/")
	if len(suffix) == 0 {
		return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest
	}
	suffix = sanitizeMountPath(suffix)
	if existed, err := b.Core.unmount(suffix); existed && err != nil {
		b.Backend.Logger().Error("sys: unmount failed", "path", suffix, "error", err)
		return handleError(err)
	}
	return nil, nil
}
func (b *SystemBackend) handleRemount(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	fromPath := data.Get("from").(string)
	toPath := data.Get("to").(string)
	if fromPath == "" || toPath == "" {
		return logical.ErrorResponse(
				"both 'from' and 'to' path must be specified as a string"),
			logical.ErrInvalidRequest
	}
	fromPath = sanitizeMountPath(fromPath)
	toPath = sanitizeMountPath(toPath)
	if err := b.Core.remount(fromPath, toPath); err != nil {
		b.Backend.Logger().Error("sys: remount failed", "from_path", fromPath, "to_path", toPath, "error", err)
		return handleError(err)
	}
	return nil, nil
}
func (b *SystemBackend) handleAuthTuneRead(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	path := data.Get("path").(string)
	if path == "" {
		return logical.ErrorResponse(
				"path must be specified as a string"),
			logical.ErrInvalidRequest
	}
	return b.handleTuneReadCommon("auth/" + path)
}