From 5f0beb733099aa6c127d2c4eb528120c3fecb06f Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 3 Mar 2016 13:13:47 -0500 Subject: [PATCH] Create a unified function to sanitize mount paths. This allows mount paths to start with '/' in addition to ensuring they end in '/' before leaving the system backend. --- api/sys_auth.go | 16 ---------------- api/sys_mounts.go | 31 ------------------------------- vault/logical_system.go | 35 ++++++++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 56 deletions(-) diff --git a/api/sys_auth.go b/api/sys_auth.go index bdc19489180c3..8e1cdec390466 100644 --- a/api/sys_auth.go +++ b/api/sys_auth.go @@ -18,10 +18,6 @@ func (c *Sys) ListAuth() (map[string]*AuthMount, error) { } func (c *Sys) EnableAuth(path, authType, desc string) error { - if err := c.checkAuthPath(path); err != nil { - return err - } - body := map[string]string{ "type": authType, "description": desc, @@ -42,10 +38,6 @@ func (c *Sys) EnableAuth(path, authType, desc string) error { } func (c *Sys) DisableAuth(path string) error { - if err := c.checkAuthPath(path); err != nil { - return err - } - r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/auth/%s", path)) resp, err := c.c.RawRequest(r) if err == nil { @@ -54,14 +46,6 @@ func (c *Sys) DisableAuth(path string) error { return err } -func (c *Sys) checkAuthPath(path string) error { - if path[0] == '/' { - return fmt.Errorf("path must not start with /: %s", path) - } - - return nil -} - // Structures for the requests/resposne are all down here. They aren't // individually documentd because the map almost directly to the raw HTTP API // documentation. Please refer to that documentation for more details. diff --git a/api/sys_mounts.go b/api/sys_mounts.go index 4fd5e8b169c80..623a146286530 100644 --- a/api/sys_mounts.go +++ b/api/sys_mounts.go @@ -20,10 +20,6 @@ func (c *Sys) ListMounts() (map[string]*MountOutput, error) { } func (c *Sys) Mount(path string, mountInfo *MountInput) error { - if err := c.checkMountPath(path); err != nil { - return err - } - body := structs.Map(mountInfo) r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s", path)) @@ -41,10 +37,6 @@ func (c *Sys) Mount(path string, mountInfo *MountInput) error { } func (c *Sys) Unmount(path string) error { - if err := c.checkMountPath(path); err != nil { - return err - } - r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/mounts/%s", path)) resp, err := c.c.RawRequest(r) if err == nil { @@ -54,13 +46,6 @@ func (c *Sys) Unmount(path string) error { } func (c *Sys) Remount(from, to string) error { - if err := c.checkMountPath(from); err != nil { - return err - } - if err := c.checkMountPath(to); err != nil { - return err - } - body := map[string]interface{}{ "from": from, "to": to, @@ -79,10 +64,6 @@ func (c *Sys) Remount(from, to string) error { } func (c *Sys) TuneMount(path string, config MountConfigInput) error { - if err := c.checkMountPath(path); err != nil { - return err - } - body := structs.Map(config) r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s/tune", path)) if err := r.SetJSONBody(body); err != nil { @@ -97,10 +78,6 @@ func (c *Sys) TuneMount(path string, config MountConfigInput) error { } func (c *Sys) MountConfig(path string) (*MountConfigOutput, error) { - if err := c.checkMountPath(path); err != nil { - return nil, err - } - r := c.c.NewRequest("GET", fmt.Sprintf("/v1/sys/mounts/%s/tune", path)) resp, err := c.c.RawRequest(r) @@ -113,14 +90,6 @@ func (c *Sys) MountConfig(path string) (*MountConfigOutput, error) { return &result, err } -func (c *Sys) checkMountPath(path string) error { - if path[0] == '/' { - return fmt.Errorf("path must not start with /: %s", path) - } - - return nil -} - type MountInput struct { Type string `json:"type" structs:"type"` Description string `json:"description" structs:"description"` diff --git a/vault/logical_system.go b/vault/logical_system.go index e2eac88e396bb..5217c97e7abbf 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -466,6 +466,8 @@ func (b *SystemBackend) handleMount( logicalType := data.Get("type").(string) description := data.Get("description").(string) + path = sanitizeMountPath(path) + var config MountConfig var apiConfig struct { @@ -562,6 +564,8 @@ func (b *SystemBackend) handleUnmount( return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest } + suffix = sanitizeMountPath(suffix) + // Attempt unmount if err := b.Core.unmount(suffix); err != nil { b.Backend.Logger().Printf("[ERR] sys: unmount '%s' failed: %v", suffix, err) @@ -583,6 +587,9 @@ func (b *SystemBackend) handleRemount( logical.ErrInvalidRequest } + fromPath = sanitizeMountPath(fromPath) + toPath = sanitizeMountPath(toPath) + // Attempt remount if err := b.Core.remount(fromPath, toPath); err != nil { b.Backend.Logger().Printf("[ERR] sys: remount '%s' to '%s' failed: %v", fromPath, toPath, err) @@ -602,9 +609,7 @@ func (b *SystemBackend) handleMountTuneRead( logical.ErrInvalidRequest } - if !strings.HasSuffix(path, "/") { - path += "/" - } + path = sanitizeMountPath(path) sysView := b.Core.router.MatchingSystemView(path) if sysView == nil { @@ -633,9 +638,7 @@ func (b *SystemBackend) handleMountTuneWrite( logical.ErrInvalidRequest } - if !strings.HasSuffix(path, "/") { - path += "/" - } + path = sanitizeMountPath(path) // Prevent protected paths from being changed for _, p := range untunableMounts { @@ -777,6 +780,8 @@ func (b *SystemBackend) handleEnableAuth( logical.ErrInvalidRequest } + path = sanitizeMountPath(path) + // Create the mount entry me := &MountEntry{ Path: path, @@ -800,6 +805,8 @@ func (b *SystemBackend) handleDisableAuth( return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest } + suffix = sanitizeMountPath(suffix) + // Attempt disable if err := b.Core.disableCredential(suffix); err != nil { b.Backend.Logger().Printf("[ERR] sys: disable auth '%s' failed: %v", suffix, err) @@ -908,9 +915,7 @@ func (b *SystemBackend) handleAuditHash( return logical.ErrorResponse("the \"input\" parameter is empty"), nil } - if !strings.HasSuffix(path, "/") { - path += "/" - } + path = sanitizeMountPath(path) hash, err := b.Core.auditBroker.GetHash(path, input) if err != nil { @@ -1089,6 +1094,18 @@ func (b *SystemBackend) handleRotate( return nil, nil } +func sanitizeMountPath(path string) string { + if !strings.HasSuffix(path, "/") { + path += "/" + } + + if strings.HasPrefix(path, "/") { + path = path[1:] + } + + return path +} + 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