Rejig how dynamic values are represented in system view and location of some functions in various packages; create mount-tune command and API analogues; update documentation
This commit is contained in:
parent
4239f9d243
commit
488d33c70a
|
@ -54,7 +54,7 @@ func (c *Sys) Unmount(path string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Sys) Remount(from, to string, config vault.MountConfig) error {
|
func (c *Sys) Remount(from, to string) error {
|
||||||
if err := c.checkMountPath(from); err != nil {
|
if err := c.checkMountPath(from); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,8 @@ func (c *Sys) Remount(from, to string, config vault.MountConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"from": from,
|
"from": from,
|
||||||
"to": to,
|
"to": to,
|
||||||
"config": config,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r := c.c.NewRequest("POST", "/v1/sys/remount")
|
r := c.c.NewRequest("POST", "/v1/sys/remount")
|
||||||
|
@ -80,6 +79,41 @@ func (c *Sys) Remount(from, to string, config vault.MountConfig) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Sys) TuneMount(path string, config vault.MountConfig) error {
|
||||||
|
if err := c.checkMountPath(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
body := map[string]interface{}{
|
||||||
|
"config": config,
|
||||||
|
}
|
||||||
|
|
||||||
|
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
|
||||||
|
if err := r.SetJSONBody(body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.c.RawRequest(r)
|
||||||
|
if err == nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Sys) MountConfig(path string) error {
|
||||||
|
if err := c.checkMountPath(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := c.c.NewRequest("GET", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
|
||||||
|
|
||||||
|
resp, err := c.c.RawRequest(r)
|
||||||
|
if err == nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Sys) checkMountPath(path string) error {
|
func (c *Sys) checkMountPath(path string) error {
|
||||||
if path[0] == '/' {
|
if path[0] == '/' {
|
||||||
return fmt.Errorf("path must not start with /: %s", path)
|
return fmt.Errorf("path must not start with /: %s", path)
|
||||||
|
|
|
@ -114,7 +114,10 @@ func (b *backend) pathIssueCert(
|
||||||
|
|
||||||
var ttl time.Duration
|
var ttl time.Duration
|
||||||
if len(ttlField) == 0 {
|
if len(ttlField) == 0 {
|
||||||
ttl = b.System.DefaultLeaseTTL()
|
ttl, err = b.System().DefaultLeaseTTL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error fetching default TTL: %s", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ttl, err = time.ParseDuration(ttlField)
|
ttl, err = time.ParseDuration(ttlField)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -125,7 +128,10 @@ func (b *backend) pathIssueCert(
|
||||||
|
|
||||||
var maxTTL time.Duration
|
var maxTTL time.Duration
|
||||||
if len(role.MaxTTL) == 0 {
|
if len(role.MaxTTL) == 0 {
|
||||||
maxTTL = b.System.MaxLeaseTTL()
|
maxTTL, err = b.System().MaxLeaseTTL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error fetching max TTL: %s", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
maxTTL, err = time.ParseDuration(role.MaxTTL)
|
maxTTL, err = time.ParseDuration(role.MaxTTL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -256,10 +256,13 @@ func (b *backend) pathRoleCreate(
|
||||||
if len(entry.MaxTTL) == 0 {
|
if len(entry.MaxTTL) == 0 {
|
||||||
entry.MaxTTL = data.Get("lease_max").(string)
|
entry.MaxTTL = data.Get("lease_max").(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxTTL time.Duration
|
var maxTTL time.Duration
|
||||||
|
maxSystemTTL, err := b.System().MaxLeaseTTL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error fetching max TTL: %s", err)
|
||||||
|
}
|
||||||
if len(entry.MaxTTL) == 0 {
|
if len(entry.MaxTTL) == 0 {
|
||||||
maxTTL = b.System.MaxLeaseTTL()
|
maxTTL = maxSystemTTL
|
||||||
} else {
|
} else {
|
||||||
maxTTL, err = time.ParseDuration(entry.MaxTTL)
|
maxTTL, err = time.ParseDuration(entry.MaxTTL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -267,18 +270,18 @@ func (b *backend) pathRoleCreate(
|
||||||
"Invalid ttl: %s", err)), nil
|
"Invalid ttl: %s", err)), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if maxTTL > b.System.MaxLeaseTTL() {
|
if maxTTL > maxSystemTTL {
|
||||||
return logical.ErrorResponse("Requested max TTL is higher than system maximum"), nil
|
return logical.ErrorResponse("Requested max TTL is higher than system maximum"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ttl time.Duration
|
|
||||||
if len(entry.TTL) == 0 {
|
if len(entry.TTL) == 0 {
|
||||||
entry.TTL = data.Get("lease").(string)
|
entry.TTL = data.Get("lease").(string)
|
||||||
}
|
}
|
||||||
switch len(entry.TTL) {
|
ttl, err := b.System().DefaultLeaseTTL()
|
||||||
case 0:
|
if err != nil {
|
||||||
ttl = b.System.DefaultLeaseTTL()
|
return nil, fmt.Errorf("Error fetching max TTL: %s", err)
|
||||||
default:
|
}
|
||||||
|
if len(entry.TTL) != 0 {
|
||||||
ttl, err = time.ParseDuration(entry.TTL)
|
ttl, err = time.ParseDuration(entry.TTL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logical.ErrorResponse(fmt.Sprintf(
|
return logical.ErrorResponse(fmt.Sprintf(
|
||||||
|
|
|
@ -226,6 +226,12 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"mount-tune": func() (cli.Command, error) {
|
||||||
|
return &command.MountTuneCommand{
|
||||||
|
Meta: meta,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
|
||||||
"remount": func() (cli.Command, error) {
|
"remount": func() (cli.Command, error) {
|
||||||
return &command.RemountCommand{
|
return &command.RemountCommand{
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
|
|
|
@ -35,17 +35,17 @@ func (c *MountsCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
paths := make([]string, 0, len(mounts))
|
paths := make([]string, 0, len(mounts))
|
||||||
for path, _ := range mounts {
|
for path := range mounts {
|
||||||
paths = append(paths, path)
|
paths = append(paths, path)
|
||||||
}
|
}
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
columns := []string{"Path | Type | Description"}
|
columns := []string{"Path | Type | Default TTL | Max TTL | Description"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
mount := mounts[path]
|
mount := mounts[path]
|
||||||
|
|
||||||
columns = append(columns, fmt.Sprintf(
|
columns = append(columns, fmt.Sprintf(
|
||||||
"%s | %s | %s", path, mount.Type, mount.Description))
|
"%s | %s | %s | %s | %s", path, mount.Type, mount.Config.DefaultLeaseTTL, mount.Config.MaxLeaseTTL, mount.Description))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(columnize.SimpleFormat(columns))
|
c.Ui.Output(columnize.SimpleFormat(columns))
|
||||||
|
@ -62,8 +62,9 @@ Usage: vault mounts [options]
|
||||||
|
|
||||||
Outputs information about the mounted backends.
|
Outputs information about the mounted backends.
|
||||||
|
|
||||||
This command lists the mounted backends, their mount points, and
|
This command lists the mounted backends, their mount points, the
|
||||||
a human-friendly description of the mount point.
|
configured TTLs, and a human-friendly description of the mount point.
|
||||||
|
A TTL of '0' indicates that the system default is being used.
|
||||||
|
|
||||||
General Options:
|
General Options:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/vault"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemountCommand is a Command that remounts a mounted secret backend
|
||||||
|
// to a new endpoint.
|
||||||
|
type MountTuneCommand struct {
|
||||||
|
Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MountTuneCommand) Run(args []string) int {
|
||||||
|
var defaultLeaseTTL, maxLeaseTTL string
|
||||||
|
flags := c.Meta.FlagSet("mount-tune", FlagSetDefault)
|
||||||
|
flags.StringVar(&defaultLeaseTTL, "default-lease-ttl", "", "")
|
||||||
|
flags.StringVar(&maxLeaseTTL, "max-lease-ttl", "", "")
|
||||||
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
|
if err := flags.Parse(args); err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
args = flags.Args()
|
||||||
|
if len(args) != 1 {
|
||||||
|
flags.Usage()
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"\n'mount-tune' expects one arguments: the mount path"))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
path := args[0]
|
||||||
|
|
||||||
|
mountConfig := vault.MountConfig{}
|
||||||
|
if defaultLeaseTTL != "" {
|
||||||
|
defTTL, err := time.ParseDuration(defaultLeaseTTL)
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"Error parsing default lease TTL duration: %s", err))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
mountConfig.DefaultLeaseTTL = &defTTL
|
||||||
|
}
|
||||||
|
if maxLeaseTTL != "" {
|
||||||
|
maxTTL, err := time.ParseDuration(maxLeaseTTL)
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"Error parsing max lease TTL duration: %s", err))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
mountConfig.MaxLeaseTTL = &maxTTL
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := c.Client()
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"Error initializing client: %s", err))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.Sys().TuneMount(path, mountConfig); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"Mount tune error: %s", err))
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Ui.Output(fmt.Sprintf(
|
||||||
|
"Successfully tuned mount '%s'!", path))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MountTuneCommand) Synopsis() string {
|
||||||
|
return "Tune mount configuration parameters"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MountTuneCommand) Help() string {
|
||||||
|
helpText := `
|
||||||
|
Usage: vault mount-tune [options] path
|
||||||
|
|
||||||
|
Tune configuration options fro a mounted secret backend.
|
||||||
|
|
||||||
|
Example: vault tune-mount -default-lease-ttl="24h" secret/
|
||||||
|
|
||||||
|
General Options:
|
||||||
|
|
||||||
|
` + generalOptionsUsage() + `
|
||||||
|
|
||||||
|
Mount Options:
|
||||||
|
|
||||||
|
-default-lease-ttl=<duration> Default lease time-to-live for this backend.
|
||||||
|
If not specified, uses the global default, or
|
||||||
|
the previously set value. Set to '0' to
|
||||||
|
explicitly set it to use the global default.
|
||||||
|
|
||||||
|
-max-lease-ttl=<duration> Max lease time-to-live for this backend.
|
||||||
|
If not specified, uses the global default, or
|
||||||
|
the previously set value. Set to '0' to
|
||||||
|
explicitly set it to use the global default.
|
||||||
|
|
||||||
|
`
|
||||||
|
return strings.TrimSpace(helpText)
|
||||||
|
}
|
|
@ -3,9 +3,6 @@ package command
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vault/vault"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemountCommand is a Command that remounts a mounted secret backend
|
// RemountCommand is a Command that remounts a mounted secret backend
|
||||||
|
@ -15,10 +12,7 @@ type RemountCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemountCommand) Run(args []string) int {
|
func (c *RemountCommand) Run(args []string) int {
|
||||||
var defaultLeaseTTL, maxLeaseTTL string
|
|
||||||
flags := c.Meta.FlagSet("remount", FlagSetDefault)
|
flags := c.Meta.FlagSet("remount", FlagSetDefault)
|
||||||
flags.StringVar(&defaultLeaseTTL, "default-lease-ttl", "", "")
|
|
||||||
flags.StringVar(&maxLeaseTTL, "max-lease-ttl", "", "")
|
|
||||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
|
@ -35,26 +29,6 @@ func (c *RemountCommand) Run(args []string) int {
|
||||||
from := args[0]
|
from := args[0]
|
||||||
to := args[1]
|
to := args[1]
|
||||||
|
|
||||||
mountConfig := vault.MountConfig{}
|
|
||||||
if defaultLeaseTTL != "" {
|
|
||||||
defTTL, err := time.ParseDuration(defaultLeaseTTL)
|
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
|
||||||
"Error parsing default lease TTL duration: %s", err))
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
mountConfig.DefaultLeaseTTL = &defTTL
|
|
||||||
}
|
|
||||||
if maxLeaseTTL != "" {
|
|
||||||
maxTTL, err := time.ParseDuration(maxLeaseTTL)
|
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
|
||||||
"Error parsing max lease TTL duration: %s", err))
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
mountConfig.MaxLeaseTTL = &maxTTL
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
@ -62,7 +36,7 @@ func (c *RemountCommand) Run(args []string) int {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.Sys().Remount(from, to, mountConfig); err != nil {
|
if err := client.Sys().Remount(from, to); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"Unmount error: %s", err))
|
"Unmount error: %s", err))
|
||||||
return 2
|
return 2
|
||||||
|
@ -89,27 +63,11 @@ Usage: vault remount [options] from to
|
||||||
the Vault data associated with the backend will be preserved (such
|
the Vault data associated with the backend will be preserved (such
|
||||||
as configuration data).
|
as configuration data).
|
||||||
|
|
||||||
If the 'from' and 'to' values of the same, performs an in-place
|
|
||||||
remount. This allows you to change mount options.
|
|
||||||
|
|
||||||
Example: vault remount secret/ generic/
|
Example: vault remount secret/ generic/
|
||||||
|
|
||||||
General Options:
|
General Options:
|
||||||
|
|
||||||
` + generalOptionsUsage() + `
|
` + generalOptionsUsage()
|
||||||
|
|
||||||
Mount Options:
|
|
||||||
|
|
||||||
-default-lease-ttl=<duration> Default lease time-to-live for this backend.
|
|
||||||
If not specified, uses the global default, or
|
|
||||||
the previously set value. Set to '0' to
|
|
||||||
explicitly set it to use the global default.
|
|
||||||
|
|
||||||
-max-lease-ttl=<duration> Max lease time-to-live for this backend.
|
|
||||||
If not specified, uses the global default, or
|
|
||||||
the previously set value. Set to '0' to
|
|
||||||
explicitly set it to use the global default.
|
|
||||||
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,8 @@ type Backend struct {
|
||||||
// See the built-in AuthRenew helpers in lease.go for common callbacks.
|
// See the built-in AuthRenew helpers in lease.go for common callbacks.
|
||||||
AuthRenew OperationFunc
|
AuthRenew OperationFunc
|
||||||
|
|
||||||
// System provides an interface to access certain system configuration
|
|
||||||
// information, such as globally configured default and max lease TTLs.
|
|
||||||
System logical.SystemView
|
|
||||||
|
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
system logical.SystemView
|
||||||
once sync.Once
|
once sync.Once
|
||||||
pathsRe []*regexp.Regexp
|
pathsRe []*regexp.Regexp
|
||||||
}
|
}
|
||||||
|
@ -146,7 +143,7 @@ func (b *Backend) SpecialPaths() *logical.Paths {
|
||||||
// Setup is used to initialize the backend with the initial backend configuration
|
// Setup is used to initialize the backend with the initial backend configuration
|
||||||
func (b *Backend) Setup(config *logical.BackendConfig) (logical.Backend, error) {
|
func (b *Backend) Setup(config *logical.BackendConfig) (logical.Backend, error) {
|
||||||
b.logger = config.Logger
|
b.logger = config.Logger
|
||||||
b.System = config.System
|
b.system = config.System
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +157,10 @@ func (b *Backend) Logger() *log.Logger {
|
||||||
return log.New(ioutil.Discard, "", 0)
|
return log.New(ioutil.Discard, "", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Backend) System() logical.SystemView {
|
||||||
|
return b.system
|
||||||
|
}
|
||||||
|
|
||||||
// Route looks up the path that would be used for a given path string.
|
// Route looks up the path that would be used for a given path string.
|
||||||
func (b *Backend) Route(path string) *Path {
|
func (b *Backend) Route(path string) *Path {
|
||||||
result, _ := b.route(path)
|
result, _ := b.route(path)
|
||||||
|
|
|
@ -22,6 +22,10 @@ type Backend interface {
|
||||||
// ends in '*' then it is a prefix-based match. The '*' can only appear
|
// ends in '*' then it is a prefix-based match. The '*' can only appear
|
||||||
// at the end.
|
// at the end.
|
||||||
SpecialPaths() *Paths
|
SpecialPaths() *Paths
|
||||||
|
|
||||||
|
// System provides an interface to access certain system configuration
|
||||||
|
// information, such as globally configured default and max lease TTLs.
|
||||||
|
System() SystemView
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendConfig is provided to the factory to initialize the backend
|
// BackendConfig is provided to the factory to initialize the backend
|
||||||
|
|
|
@ -6,12 +6,12 @@ import "time"
|
||||||
// for logical backends to consume
|
// for logical backends to consume
|
||||||
type SystemView interface {
|
type SystemView interface {
|
||||||
// DefaultLeaseTTL returns the default lease TTL set in Vault configuration
|
// DefaultLeaseTTL returns the default lease TTL set in Vault configuration
|
||||||
DefaultLeaseTTL() time.Duration
|
DefaultLeaseTTL() (time.Duration, error)
|
||||||
|
|
||||||
// MaxLeaseTTL returns the max lease TTL set in Vault configuration; backend
|
// MaxLeaseTTL returns the max lease TTL set in Vault configuration; backend
|
||||||
// authors should take care not to issue credentials that last longer than
|
// authors should take care not to issue credentials that last longer than
|
||||||
// this value, as Vault will revoke them
|
// this value, as Vault will revoke them
|
||||||
MaxLeaseTTL() time.Duration
|
MaxLeaseTTL() (time.Duration, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type StaticSystemView struct {
|
type StaticSystemView struct {
|
||||||
|
@ -19,29 +19,10 @@ type StaticSystemView struct {
|
||||||
MaxLeaseTTLVal time.Duration
|
MaxLeaseTTLVal time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *StaticSystemView) DefaultLeaseTTL() time.Duration {
|
func (d StaticSystemView) DefaultLeaseTTL() (time.Duration, error) {
|
||||||
return d.DefaultLeaseTTLVal
|
return d.DefaultLeaseTTLVal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *StaticSystemView) MaxLeaseTTL() time.Duration {
|
func (d StaticSystemView) MaxLeaseTTL() (time.Duration, error) {
|
||||||
return d.MaxLeaseTTLVal
|
return d.MaxLeaseTTLVal, nil
|
||||||
}
|
|
||||||
|
|
||||||
type DynamicSystemView struct {
|
|
||||||
DefaultLeaseTTLVal **time.Duration
|
|
||||||
MaxLeaseTTLVal **time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DynamicSystemView) DefaultLeaseTTL() time.Duration {
|
|
||||||
if *d.DefaultLeaseTTLVal == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return **d.DefaultLeaseTTLVal
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DynamicSystemView) MaxLeaseTTL() time.Duration {
|
|
||||||
if *d.MaxLeaseTTLVal == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return **d.MaxLeaseTTLVal
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -478,7 +478,7 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
|
||||||
// We exclude renewal of a lease, since it does not need to be re-registered
|
// We exclude renewal of a lease, since it does not need to be re-registered
|
||||||
if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/renew/") {
|
if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/renew/") {
|
||||||
// Get the SystemView for the mount
|
// Get the SystemView for the mount
|
||||||
sysView, err := c.PathSysView(req.Path)
|
sysView, err := c.sysViewByPath(req.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Println(err)
|
c.logger.Println(err)
|
||||||
return nil, auth, ErrInternalError
|
return nil, auth, ErrInternalError
|
||||||
|
@ -486,12 +486,22 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
|
||||||
|
|
||||||
// Apply the default lease if none given
|
// Apply the default lease if none given
|
||||||
if resp.Secret.TTL == 0 {
|
if resp.Secret.TTL == 0 {
|
||||||
resp.Secret.TTL = sysView.DefaultLeaseTTL()
|
ttl, err := sysView.DefaultLeaseTTL()
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Println(err)
|
||||||
|
return nil, auth, ErrInternalError
|
||||||
|
}
|
||||||
|
resp.Secret.TTL = ttl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit the lease duration
|
// Limit the lease duration
|
||||||
if resp.Secret.TTL > sysView.MaxLeaseTTL() {
|
maxTTL, err := sysView.MaxLeaseTTL()
|
||||||
resp.Secret.TTL = sysView.MaxLeaseTTL()
|
if err != nil {
|
||||||
|
c.logger.Println(err)
|
||||||
|
return nil, auth, ErrInternalError
|
||||||
|
}
|
||||||
|
if resp.Secret.TTL > maxTTL {
|
||||||
|
resp.Secret.TTL = maxTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the lease
|
// Register the lease
|
||||||
|
|
|
@ -56,14 +56,36 @@ func NewSystemBackend(core *Core) logical.Backend {
|
||||||
},
|
},
|
||||||
|
|
||||||
&framework.Path{
|
&framework.Path{
|
||||||
Pattern: "mounts/(?P<path>.+)",
|
Pattern: "mounts/(?P<path>.+?)/tune$",
|
||||||
|
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
"path": &framework.FieldSchema{
|
"path": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
|
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
|
||||||
},
|
},
|
||||||
|
"config": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeMap,
|
||||||
|
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
|
logical.ReadOperation: b.handleMountConfig,
|
||||||
|
logical.WriteOperation: b.handleMountTune,
|
||||||
|
},
|
||||||
|
|
||||||
|
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.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
|
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
|
||||||
|
@ -99,10 +121,6 @@ func NewSystemBackend(core *Core) logical.Backend {
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: strings.TrimSpace(sysHelp["remount_to"][0]),
|
Description: strings.TrimSpace(sysHelp["remount_to"][0]),
|
||||||
},
|
},
|
||||||
"config": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeMap,
|
|
||||||
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
|
@ -449,20 +467,73 @@ func (b *SystemBackend) handleRemount(
|
||||||
logical.ErrInvalidRequest
|
logical.ErrInvalidRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
var config MountConfig
|
// Attempt remount
|
||||||
configMap := data.Get("config").(map[string]interface{})
|
if err := b.Core.remount(fromPath, toPath); err != nil {
|
||||||
if configMap != nil && len(configMap) != 0 {
|
b.Backend.Logger().Printf("[ERR] sys: remount '%s' to '%s' failed: %v", fromPath, toPath, err)
|
||||||
err := mapstructure.Decode(configMap, &config)
|
return handleError(err)
|
||||||
if err != nil {
|
|
||||||
return logical.ErrorResponse(fmt.Sprintf(
|
|
||||||
"unable to convert given mount config information: %s", err)),
|
|
||||||
logical.ErrInvalidRequest
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt remount
|
return nil, nil
|
||||||
if err := b.Core.remount(fromPath, toPath, config); err != nil {
|
}
|
||||||
b.Backend.Logger().Printf("[ERR] sys: remount '%s' to '%s' failed: %v", fromPath, toPath, err)
|
|
||||||
|
// handleMountConfig is used to get config settings on a backend
|
||||||
|
func (b *SystemBackend) handleMountConfig(
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
def, max, err := b.Core.TTLsByPath(path)
|
||||||
|
if err != nil {
|
||||||
|
b.Backend.Logger().Printf("[ERR] sys: fetching config of path '%s' failed: %v", path, err)
|
||||||
|
return handleError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := MountConfig{
|
||||||
|
DefaultLeaseTTL: &def,
|
||||||
|
MaxLeaseTTL: &max,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &logical.Response{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"config": config,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleMountTune is used to set config settings on a backend
|
||||||
|
func (b *SystemBackend) handleMountTune(
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
var config MountConfig
|
||||||
|
configMap := data.Get("config").(map[string]interface{})
|
||||||
|
if configMap == nil || len(configMap) == 0 {
|
||||||
|
return logical.ErrorResponse(
|
||||||
|
"invalid parameters; 'config' empty or not supplied"),
|
||||||
|
logical.ErrInvalidRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(configMap, &config)
|
||||||
|
if err != nil {
|
||||||
|
return logical.ErrorResponse(fmt.Sprintf(
|
||||||
|
"unable to convert given mount config information: %s", err)),
|
||||||
|
logical.ErrInvalidRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt tune
|
||||||
|
if err := b.Core.tuneMount(path, config); err != nil {
|
||||||
|
b.Backend.Logger().Printf("[ERR] sys: tune of path '%s' failed: %v", path, err)
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,6 +964,10 @@ Change the mount point of an already-mounted backend.
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"mount_tune": {
|
||||||
|
"Tune backend configuration parameters for this mount.",
|
||||||
|
},
|
||||||
|
|
||||||
"renew": {
|
"renew": {
|
||||||
"Renew a lease on a secret",
|
"Renew a lease on a secret",
|
||||||
`
|
`
|
||||||
|
|
198
vault/mount.go
198
vault/mount.go
|
@ -40,6 +40,27 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type dynamicSystemView struct {
|
||||||
|
core *Core
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d dynamicSystemView) DefaultLeaseTTL() (time.Duration, error) {
|
||||||
|
def, _, err := d.core.TTLsByPath(d.path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d dynamicSystemView) MaxLeaseTTL() (time.Duration, error) {
|
||||||
|
def, _, err := d.core.TTLsByPath(d.path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MountTable is used to represent the internal mount table
|
// MountTable is used to represent the internal mount table
|
||||||
type MountTable struct {
|
type MountTable struct {
|
||||||
// This lock should be held whenever modifying the Entries field.
|
// This lock should be held whenever modifying the Entries field.
|
||||||
|
@ -118,8 +139,8 @@ type MountEntry struct {
|
||||||
|
|
||||||
// MountConfig is used to hold settable options
|
// MountConfig is used to hold settable options
|
||||||
type MountConfig struct {
|
type MountConfig struct {
|
||||||
DefaultLeaseTTL *time.Duration `json:"default_lease_ttl" structs:"default_lease_ttl"` // Override for global default
|
DefaultLeaseTTL *time.Duration `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` // Override for global default
|
||||||
MaxLeaseTTL *time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl"` // Override for global default
|
MaxLeaseTTL *time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` // Override for global default
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a deep copy of the mount entry
|
// Returns a deep copy of the mount entry
|
||||||
|
@ -165,7 +186,7 @@ func (c *Core) mount(me *MountEntry) error {
|
||||||
view := NewBarrierView(c.barrier, backendBarrierPrefix+me.UUID+"/")
|
view := NewBarrierView(c.barrier, backendBarrierPrefix+me.UUID+"/")
|
||||||
|
|
||||||
// Create the new backend
|
// Create the new backend
|
||||||
sysView, err := c.MountEntrySysView(me)
|
sysView, err := c.mountEntrySysView(me)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -283,7 +304,7 @@ func (c *Core) taintMountEntry(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remount is used to remount a path at a new mount point.
|
// Remount is used to remount a path at a new mount point.
|
||||||
func (c *Core) remount(src, dst string, config MountConfig) error {
|
func (c *Core) remount(src, dst string) error {
|
||||||
c.mounts.Lock()
|
c.mounts.Lock()
|
||||||
defer c.mounts.Unlock()
|
defer c.mounts.Unlock()
|
||||||
|
|
||||||
|
@ -302,48 +323,12 @@ func (c *Core) remount(src, dst string, config MountConfig) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inPlace := false
|
|
||||||
if src == dst {
|
|
||||||
inPlace = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify exact match of the route
|
// Verify exact match of the route
|
||||||
match := c.router.MatchingMount(src)
|
match := c.router.MatchingMount(src)
|
||||||
if match == "" || src != match {
|
if match == "" || src != match {
|
||||||
return fmt.Errorf("no matching mount at '%s'", src)
|
return fmt.Errorf("no matching mount at '%s'", src)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify there is no conflicting mount
|
|
||||||
if inPlace {
|
|
||||||
for _, ent := range c.mounts.Entries {
|
|
||||||
if ent.Path == src {
|
|
||||||
if config.DefaultLeaseTTL != nil {
|
|
||||||
if *config.DefaultLeaseTTL == 0 {
|
|
||||||
ent.Config.DefaultLeaseTTL = &c.defaultLeaseTTL
|
|
||||||
} else {
|
|
||||||
ent.Config.DefaultLeaseTTL = config.DefaultLeaseTTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.MaxLeaseTTL != nil {
|
|
||||||
if *config.MaxLeaseTTL == 0 {
|
|
||||||
ent.Config.MaxLeaseTTL = &c.maxLeaseTTL
|
|
||||||
} else {
|
|
||||||
ent.Config.MaxLeaseTTL = config.MaxLeaseTTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the mount table
|
|
||||||
if err := c.persistMounts(c.mounts); err != nil {
|
|
||||||
return errors.New("failed to update mount table")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.logger.Printf("[INFO] core: remounted '%s' in-place", src)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if match := c.router.MatchingMount(dst); match != "" {
|
if match := c.router.MatchingMount(dst); match != "" {
|
||||||
return fmt.Errorf("existing mount at '%s'", match)
|
return fmt.Errorf("existing mount at '%s'", match)
|
||||||
}
|
}
|
||||||
|
@ -371,23 +356,10 @@ func (c *Core) remount(src, dst string, config MountConfig) error {
|
||||||
// Update the entry in the mount table
|
// Update the entry in the mount table
|
||||||
newTable := c.mounts.Clone()
|
newTable := c.mounts.Clone()
|
||||||
for _, ent := range newTable.Entries {
|
for _, ent := range newTable.Entries {
|
||||||
|
//FIXME: Update systemview in each logical backend
|
||||||
if ent.Path == src {
|
if ent.Path == src {
|
||||||
ent.Path = dst
|
ent.Path = dst
|
||||||
ent.Tainted = false
|
ent.Tainted = false
|
||||||
if config.DefaultLeaseTTL != nil {
|
|
||||||
if *config.DefaultLeaseTTL == 0 {
|
|
||||||
ent.Config.DefaultLeaseTTL = &c.defaultLeaseTTL
|
|
||||||
} else {
|
|
||||||
ent.Config.DefaultLeaseTTL = config.DefaultLeaseTTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.MaxLeaseTTL != nil {
|
|
||||||
if *config.MaxLeaseTTL == 0 {
|
|
||||||
ent.Config.MaxLeaseTTL = &c.maxLeaseTTL
|
|
||||||
} else {
|
|
||||||
ent.Config.MaxLeaseTTL = config.MaxLeaseTTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,6 +384,67 @@ func (c *Core) remount(src, dst string, config MountConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tuneMount is used to set config on a mount point
|
||||||
|
func (c *Core) tuneMount(path string, config MountConfig) error {
|
||||||
|
// Ensure we end the path in a slash
|
||||||
|
if !strings.HasSuffix(path, "/") {
|
||||||
|
path += "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent protected paths from being changed
|
||||||
|
for _, p := range protectedMounts {
|
||||||
|
if strings.HasPrefix(path, p) {
|
||||||
|
return fmt.Errorf("cannot tune '%s'", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify exact match of the route
|
||||||
|
match := c.router.MatchingMount(path)
|
||||||
|
if match == "" || path != match {
|
||||||
|
return fmt.Errorf("no matching mount at '%s'", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and modify mount
|
||||||
|
for _, ent := range c.mounts.Entries {
|
||||||
|
if ent.Path == path {
|
||||||
|
if config.MaxLeaseTTL != nil {
|
||||||
|
if *config.MaxLeaseTTL == 0 {
|
||||||
|
*ent.Config.MaxLeaseTTL = 0
|
||||||
|
} else {
|
||||||
|
ent.Config.MaxLeaseTTL = config.MaxLeaseTTL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.DefaultLeaseTTL != nil {
|
||||||
|
if *ent.Config.MaxLeaseTTL == 0 {
|
||||||
|
if *config.DefaultLeaseTTL > c.maxLeaseTTL {
|
||||||
|
return fmt.Errorf("Given default lease TTL of %d greater than system default lease TTL of %d",
|
||||||
|
*config.DefaultLeaseTTL, c.maxLeaseTTL)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if *ent.Config.MaxLeaseTTL != 0 && *ent.Config.MaxLeaseTTL < *config.DefaultLeaseTTL {
|
||||||
|
return fmt.Errorf("Given default lease TTL of %d greater than backend max lease TTL of %d",
|
||||||
|
*config.DefaultLeaseTTL, *ent.Config.MaxLeaseTTL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if *config.DefaultLeaseTTL == 0 {
|
||||||
|
*ent.Config.DefaultLeaseTTL = 0
|
||||||
|
} else {
|
||||||
|
ent.Config.DefaultLeaseTTL = config.DefaultLeaseTTL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the mount table
|
||||||
|
if err := c.persistMounts(c.mounts); err != nil {
|
||||||
|
return errors.New("failed to update mount table")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.Printf("[INFO] core: tuned '%s'", path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// loadMounts is invoked as part of postUnseal to load the mount table
|
// loadMounts is invoked as part of postUnseal to load the mount table
|
||||||
func (c *Core) loadMounts() error {
|
func (c *Core) loadMounts() error {
|
||||||
// Load the existing mount table
|
// Load the existing mount table
|
||||||
|
@ -481,7 +514,7 @@ func (c *Core) setupMounts() error {
|
||||||
|
|
||||||
// Initialize the backend
|
// Initialize the backend
|
||||||
// Create the new backend
|
// Create the new backend
|
||||||
sysView, err := c.MountEntrySysView(entry)
|
sysView, err := c.mountEntrySysView(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -542,32 +575,32 @@ func (c *Core) newLogicalBackend(t string, sysView logical.SystemView, view logi
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MountEntrySysView creates a logical.SystemView from global and
|
// mountEntrySysView creates a logical.SystemView from global and
|
||||||
// mount-specific entries
|
// mount-specific entries
|
||||||
func (c *Core) MountEntrySysView(me *MountEntry) (logical.SystemView, error) {
|
func (c *Core) mountEntrySysView(me *MountEntry) (logical.SystemView, error) {
|
||||||
if me == nil {
|
if me == nil {
|
||||||
return nil, fmt.Errorf("[ERR] core: nil MountEntry when generating SystemView")
|
return nil, fmt.Errorf("[ERR] core: nil MountEntry when generating SystemView")
|
||||||
}
|
}
|
||||||
|
|
||||||
sysDefaultLeaseTTLPtr := &c.defaultLeaseTTL
|
sysView := dynamicSystemView{
|
||||||
sysMaxLeaseTTLPtr := &c.maxLeaseTTL
|
core: c,
|
||||||
sysView := &logical.DynamicSystemView{
|
path: me.Path,
|
||||||
DefaultLeaseTTLVal: &sysDefaultLeaseTTLPtr,
|
|
||||||
MaxLeaseTTLVal: &sysMaxLeaseTTLPtr,
|
|
||||||
}
|
|
||||||
|
|
||||||
if me.Config.DefaultLeaseTTL != nil && *me.Config.DefaultLeaseTTL != 0 {
|
|
||||||
sysView.DefaultLeaseTTLVal = &me.Config.DefaultLeaseTTL
|
|
||||||
}
|
|
||||||
if me.Config.MaxLeaseTTL != nil && *me.Config.MaxLeaseTTL != 0 {
|
|
||||||
sysView.MaxLeaseTTLVal = &me.Config.MaxLeaseTTL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sysView, nil
|
return sysView, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathSysView is a simple helper for MountEntrySysView
|
// sysViewByPath is a simple helper for MountEntrySysView
|
||||||
func (c *Core) PathSysView(path string) (logical.SystemView, error) {
|
func (c *Core) sysViewByPath(path string) (logical.SystemView, error) {
|
||||||
|
me, err := c.mountEntryByPath(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.mountEntrySysView(me)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mountEntryByPath searches across all tables to find the MountEntry
|
||||||
|
func (c *Core) mountEntryByPath(path string) (*MountEntry, error) {
|
||||||
pathSep := strings.IndexRune(path, '/')
|
pathSep := strings.IndexRune(path, '/')
|
||||||
if pathSep == -1 {
|
if pathSep == -1 {
|
||||||
return nil, fmt.Errorf("[ERR] core: failed to find separator for path %s", path)
|
return nil, fmt.Errorf("[ERR] core: failed to find separator for path %s", path)
|
||||||
|
@ -582,7 +615,28 @@ func (c *Core) PathSysView(path string) (logical.SystemView, error) {
|
||||||
if me == nil {
|
if me == nil {
|
||||||
return nil, fmt.Errorf("[ERR] core: failed to find mount entry for path %s", path)
|
return nil, fmt.Errorf("[ERR] core: failed to find mount entry for path %s", path)
|
||||||
}
|
}
|
||||||
return c.MountEntrySysView(me)
|
return me, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTLsByPath returns the default and max TTLs corresponding to a particular
|
||||||
|
// mount point, or the system default
|
||||||
|
func (c *Core) TTLsByPath(path string) (def, max time.Duration, retErr error) {
|
||||||
|
me, err := c.mountEntryByPath(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
def = c.defaultLeaseTTL
|
||||||
|
max = c.maxLeaseTTL
|
||||||
|
|
||||||
|
if me.Config.DefaultLeaseTTL != nil && *me.Config.DefaultLeaseTTL != 0 {
|
||||||
|
def = *me.Config.DefaultLeaseTTL
|
||||||
|
}
|
||||||
|
if me.Config.MaxLeaseTTL != nil && *me.Config.MaxLeaseTTL != 0 {
|
||||||
|
max = *me.Config.MaxLeaseTTL
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultMountTable creates a default mount table
|
// defaultMountTable creates a default mount table
|
||||||
|
|
|
@ -91,6 +91,15 @@ func (r *Router) Remount(src, dst string) error {
|
||||||
|
|
||||||
// Update the mount point
|
// Update the mount point
|
||||||
r.root.Delete(src)
|
r.root.Delete(src)
|
||||||
|
mountEntry, ok := raw.(*mountEntry)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Unable to retrieve mount entry at '%s'", src)
|
||||||
|
}
|
||||||
|
sysView := mountEntry.backend.System()
|
||||||
|
dynSysView, ok := sysView.(dynamicSystemView)
|
||||||
|
if ok {
|
||||||
|
dynSysView.path = dst
|
||||||
|
}
|
||||||
r.root.Insert(dst, raw)
|
r.root.Insert(dst, raw)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/uuid"
|
"github.com/hashicorp/vault/helper/uuid"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
|
@ -41,6 +42,13 @@ func (n *NoopBackend) SpecialPaths() *logical.Paths {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NoopBackend) System() logical.SystemView {
|
||||||
|
return logical.StaticSystemView{
|
||||||
|
DefaultLeaseTTLVal: time.Hour * 24,
|
||||||
|
MaxLeaseTTLVal: time.Hour * 24 * 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRouter_Mount(t *testing.T) {
|
func TestRouter_Mount(t *testing.T) {
|
||||||
r := NewRouter()
|
r := NewRouter()
|
||||||
_, barrier, _ := mockBarrier(t)
|
_, barrier, _ := mockBarrier(t)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
|
@ -262,3 +263,10 @@ func (n *rawHTTP) HandleRequest(req *logical.Request) (*logical.Response, error)
|
||||||
func (n *rawHTTP) SpecialPaths() *logical.Paths {
|
func (n *rawHTTP) SpecialPaths() *logical.Paths {
|
||||||
return &logical.Paths{Unauthenticated: []string{"*"}}
|
return &logical.Paths{Unauthenticated: []string{"*"}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *rawHTTP) System() logical.SystemView {
|
||||||
|
return logical.StaticSystemView{
|
||||||
|
DefaultLeaseTTLVal: time.Hour * 24,
|
||||||
|
MaxLeaseTTLVal: time.Hour * 24 * 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ description: |-
|
||||||
<dt>Method</dt>
|
<dt>Method</dt>
|
||||||
<dd>GET</dd>
|
<dd>GET</dd>
|
||||||
|
|
||||||
|
<dt>URL</dt>
|
||||||
|
<dd>`/sys/mounts`</dd>
|
||||||
|
|
||||||
<dt>Parameters</dt>
|
<dt>Parameters</dt>
|
||||||
<dd>
|
<dd>
|
||||||
None
|
None
|
||||||
|
@ -54,6 +57,40 @@ description: |-
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Description</dt>
|
||||||
|
<dd>
|
||||||
|
List the given secret backends configuration. `default_lease_ttl`
|
||||||
|
or `max_lease_ttl` values of `0` mean that the system
|
||||||
|
defaults are used by this backend.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Method</dt>
|
||||||
|
<dd>GET</dd>
|
||||||
|
|
||||||
|
<dt>URL</dt>
|
||||||
|
<dd>`/sys/mounts/<mount point>/tune`</dd>
|
||||||
|
|
||||||
|
<dt>Parameters</dt>
|
||||||
|
<dd>
|
||||||
|
None
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Returns</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"default_lease_ttl": 0,
|
||||||
|
"max_lease_ttl": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
## POST
|
## POST
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
|
@ -99,6 +136,39 @@ description: |-
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Description</dt>
|
||||||
|
<dd>
|
||||||
|
Tune configuration parameters for a given mount point.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Method</dt>
|
||||||
|
<dd>POST</dd>
|
||||||
|
|
||||||
|
<dt>URL</dt>
|
||||||
|
<dd>`/sys/mounts/<mount point>/tune`</dd>
|
||||||
|
|
||||||
|
<dt>Parameters</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<span class="param">config</span>
|
||||||
|
<span class="param-flags">required</span>
|
||||||
|
Config options for this mount. This is an object with
|
||||||
|
two possible values: `default_lease_ttl` and
|
||||||
|
`max_lease_ttl`. These control the default and
|
||||||
|
maximum lease time-to-live, respectively. If set
|
||||||
|
on a specific mount, this overrides the global
|
||||||
|
defaults.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Returns</dt>
|
||||||
|
<dd>`204` response code.
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
## DELETE
|
## DELETE
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
|
|
|
@ -28,21 +28,8 @@ description: |-
|
||||||
<li>
|
<li>
|
||||||
<span class="param">to</span>
|
<span class="param">to</span>
|
||||||
<span class="param-flags">required</span>
|
<span class="param-flags">required</span>
|
||||||
The new mount point. This can be the same
|
The new mount point.
|
||||||
as `from` if you simply want to change
|
|
||||||
backend configuration with the `config`
|
|
||||||
parameter.
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<span class="param">config</span>
|
|
||||||
<span class="param-flags">optional</span>
|
|
||||||
Config options for this mount. This is an object with
|
|
||||||
two possible values: `default_lease_ttl` and
|
|
||||||
`max_lease_ttl`. These control the default and
|
|
||||||
maximum lease time-to-live, respectively. If set
|
|
||||||
on a specific mount, this overrides the global
|
|
||||||
defaults.
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue