2015-03-11 22:19:41 +00:00
package vault
import (
2015-04-04 00:46:57 +00:00
"crypto/sha1"
2015-03-11 22:19:41 +00:00
"encoding/json"
"errors"
2015-03-12 01:19:40 +00:00
"fmt"
"strings"
2015-08-28 21:25:09 +00:00
"time"
2015-03-15 21:53:41 +00:00
2015-12-16 17:56:20 +00:00
"github.com/hashicorp/go-uuid"
2016-07-06 16:25:40 +00:00
"github.com/hashicorp/vault/helper/jsonutil"
2015-03-15 21:53:41 +00:00
"github.com/hashicorp/vault/logical"
2015-03-11 22:19:41 +00:00
)
const (
// coreMountConfigPath is used to store the mount configuration.
// Mounts are protected within the Vault itself, which means they
// can only be viewed or modified after an unseal.
coreMountConfigPath = "core/mounts"
2015-03-11 22:50:27 +00:00
// backendBarrierPrefix is the prefix to the UUID used in the
// barrier view for the backends.
backendBarrierPrefix = "logical/"
2015-03-12 19:41:12 +00:00
2015-08-10 17:27:25 +00:00
// systemBarrierPrefix is the prefix used for the
2015-03-12 19:41:12 +00:00
// system logical backend.
systemBarrierPrefix = "sys/"
2016-05-26 16:55:00 +00:00
2016-05-26 17:38:51 +00:00
// mountTableType is the value we expect to find for the mount table and
// corresponding entries
2016-05-26 16:55:00 +00:00
mountTableType = "mounts"
2015-03-11 22:50:27 +00:00
)
var (
// loadMountsFailed if loadMounts encounters an error
2015-08-28 21:25:09 +00:00
errLoadMountsFailed = errors . New ( "failed to setup mount table" )
2015-03-12 19:09:30 +00:00
// protectedMounts cannot be remounted
protectedMounts = [ ] string {
2015-03-27 21:00:57 +00:00
"audit/" ,
2015-03-18 22:16:52 +00:00
"auth/" ,
2015-03-12 19:09:30 +00:00
"sys/" ,
2015-09-10 01:58:09 +00:00
"cubbyhole/" ,
}
2015-09-19 15:50:50 +00:00
untunableMounts = [ ] string {
"cubbyhole/" ,
"sys/" ,
"audit/" ,
}
2015-09-10 01:58:09 +00:00
// singletonMounts can only exist in one location and are
// loaded by default. These are types, not paths.
singletonMounts = [ ] string {
"cubbyhole" ,
"system" ,
2015-03-12 19:09:30 +00:00
}
2015-03-11 22:19:41 +00:00
)
// MountTable is used to represent the internal mount table
type MountTable struct {
2016-05-26 16:55:00 +00:00
Type string ` json:"type" `
2015-03-11 22:19:41 +00:00
Entries [ ] * MountEntry ` json:"entries" `
}
2015-09-10 02:17:49 +00:00
// ShallowClone returns a copy of the mount table that
// keeps the MountEntry locations, so as not to invalidate
// other locations holding pointers. Care needs to be taken
// if modifying entries rather than modifying the table itself
func ( t * MountTable ) ShallowClone ( ) * MountTable {
2015-03-12 01:19:40 +00:00
mt := & MountTable {
2016-05-26 16:55:00 +00:00
Type : t . Type ,
2015-03-12 01:19:40 +00:00
Entries : make ( [ ] * MountEntry , len ( t . Entries ) ) ,
}
for i , e := range t . Entries {
2015-09-10 02:17:49 +00:00
mt . Entries [ i ] = e
2015-03-12 01:19:40 +00:00
}
return mt
}
2015-04-04 00:46:57 +00:00
// Hash is used to generate a hash value for the mount table
func ( t * MountTable ) Hash ( ) ( [ ] byte , error ) {
buf , err := json . Marshal ( t )
if err != nil {
return nil , err
}
hash := sha1 . Sum ( buf )
return hash [ : ] , nil
}
2015-04-03 22:59:30 +00:00
// Find is used to lookup an entry
func ( t * MountTable ) Find ( path string ) * MountEntry {
n := len ( t . Entries )
for i := 0 ; i < n ; i ++ {
if t . Entries [ i ] . Path == path {
return t . Entries [ i ]
}
}
return nil
}
// SetTaint is used to set the taint on given entry
2015-04-03 23:07:45 +00:00
func ( t * MountTable ) SetTaint ( path string , value bool ) bool {
2015-04-03 22:59:30 +00:00
n := len ( t . Entries )
for i := 0 ; i < n ; i ++ {
if t . Entries [ i ] . Path == path {
t . Entries [ i ] . Tainted = value
2015-04-03 23:07:45 +00:00
return true
2015-04-03 22:59:30 +00:00
}
}
2015-04-03 23:07:45 +00:00
return false
2015-04-03 22:59:30 +00:00
}
// Remove is used to remove a given path entry
2015-04-03 23:00:46 +00:00
func ( t * MountTable ) Remove ( path string ) bool {
2015-04-03 22:59:30 +00:00
n := len ( t . Entries )
for i := 0 ; i < n ; i ++ {
if t . Entries [ i ] . Path == path {
t . Entries [ i ] , t . Entries [ n - 1 ] = t . Entries [ n - 1 ] , nil
t . Entries = t . Entries [ : n - 1 ]
2015-04-03 23:00:46 +00:00
return true
2015-04-03 22:59:30 +00:00
}
}
2015-04-03 23:00:46 +00:00
return false
2015-04-03 22:59:30 +00:00
}
2015-03-11 22:19:41 +00:00
// MountEntry is used to represent a mount table entry
type MountEntry struct {
2016-05-26 16:55:00 +00:00
Table string ` json:"table" ` // The table it belongs to
2015-04-02 01:04:36 +00:00
Path string ` json:"path" ` // Mount Path
Type string ` json:"type" ` // Logical backend Type
Description string ` json:"description" ` // User-provided description
UUID string ` json:"uuid" ` // Barrier view UUID
2015-08-29 13:02:46 +00:00
Config MountConfig ` json:"config" ` // Configuration related to this mount (but not backend-derived)
2015-08-28 21:25:09 +00:00
Options map [ string ] string ` json:"options" ` // Backend options
2015-04-02 01:04:36 +00:00
Tainted bool ` json:"tainted,omitempty" ` // Set as a Write-Ahead flag for unmount/remount
2015-03-11 22:19:41 +00:00
}
2015-08-29 13:02:46 +00:00
// MountConfig is used to hold settable options
type MountConfig struct {
2015-09-09 19:24:45 +00:00
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" mapstructure:"max_lease_ttl" ` // Override for global default
2015-08-28 21:25:09 +00:00
}
2015-03-12 01:19:40 +00:00
// Returns a deep copy of the mount entry
func ( e * MountEntry ) Clone ( ) * MountEntry {
2015-03-31 20:14:08 +00:00
optClone := make ( map [ string ] string )
for k , v := range e . Options {
optClone [ k ] = v
}
2015-03-12 01:19:40 +00:00
return & MountEntry {
2016-05-26 16:55:00 +00:00
Table : e . Table ,
2015-03-12 01:19:40 +00:00
Path : e . Path ,
Type : e . Type ,
Description : e . Description ,
UUID : e . UUID ,
2015-08-28 21:25:09 +00:00
Config : e . Config ,
2015-03-31 20:14:08 +00:00
Options : optClone ,
2015-03-12 01:19:40 +00:00
}
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
// Mount is used to mount a new backend to the mount table.
2015-03-15 01:31:31 +00:00
func ( c * Core ) mount ( me * MountEntry ) error {
2015-03-12 01:19:40 +00:00
// Ensure we end the path in a slash
if ! strings . HasSuffix ( me . Path , "/" ) {
me . Path += "/"
}
2015-08-10 17:27:25 +00:00
// Prevent protected paths from being mounted
2015-03-18 22:16:52 +00:00
for _ , p := range protectedMounts {
if strings . HasPrefix ( me . Path , p ) {
2015-08-10 17:27:25 +00:00
return logical . CodedError ( 403 , fmt . Sprintf ( "cannot mount '%s'" , me . Path ) )
2015-03-18 22:16:52 +00:00
}
}
2015-09-10 01:58:09 +00:00
// Do not allow more than one instance of a singleton mount
for _ , p := range singletonMounts {
if me . Type == p {
return logical . CodedError ( 403 , fmt . Sprintf ( "Cannot mount more than one instance of '%s'" , me . Type ) )
}
}
2015-03-12 01:19:40 +00:00
// Verify there is no conflicting mount
if match := c . router . MatchingMount ( me . Path ) ; match != "" {
2015-08-10 17:27:25 +00:00
return logical . CodedError ( 409 , fmt . Sprintf ( "existing mount at %s" , match ) )
2015-03-12 01:19:40 +00:00
}
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
2015-03-12 01:19:40 +00:00
// Generate a new UUID and view
2016-01-13 18:40:08 +00:00
meUUID , err := uuid . GenerateUUID ( )
if err != nil {
return err
}
me . UUID = meUUID
2015-03-12 01:19:40 +00:00
view := NewBarrierView ( c . barrier , backendBarrierPrefix + me . UUID + "/" )
2015-09-04 20:58:12 +00:00
backend , err := c . newLogicalBackend ( me . Type , c . mountEntrySysView ( me ) , view , nil )
2015-07-01 00:30:43 +00:00
if err != nil {
return err
}
2015-03-12 01:19:40 +00:00
// Update the mount table
2015-09-10 02:17:49 +00:00
newTable := c . mounts . ShallowClone ( )
2015-03-12 01:19:40 +00:00
newTable . Entries = append ( newTable . Entries , me )
if err := c . persistMounts ( newTable ) ; err != nil {
2016-08-04 13:11:24 +00:00
return logical . CodedError ( 500 , "failed to update mount table" )
2015-03-12 01:19:40 +00:00
}
c . mounts = newTable
// Mount the backend
2015-09-04 20:58:12 +00:00
if err := c . router . Mount ( backend , me . Path , me , view ) ; err != nil {
2015-03-12 01:19:40 +00:00
return err
}
2016-08-19 20:45:17 +00:00
if c . logger . IsInfo ( ) {
c . logger . Info ( "core: successful mount" , "path" , me . Path , "type" , me . Type )
}
2015-03-12 01:19:40 +00:00
return nil
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
// Unmount is used to unmount a path.
2015-03-15 01:31:31 +00:00
func ( c * Core ) unmount ( path string ) error {
2015-03-12 01:19:40 +00:00
// Ensure we end the path in a slash
if ! strings . HasSuffix ( path , "/" ) {
path += "/"
}
2015-03-18 22:16:52 +00:00
// Prevent protected paths from being unmounted
for _ , p := range protectedMounts {
if strings . HasPrefix ( path , p ) {
return fmt . Errorf ( "cannot unmount '%s'" , path )
}
}
2015-03-12 01:19:40 +00:00
// Verify exact match of the route
2015-09-11 23:49:20 +00:00
match := c . router . MatchingMount ( path )
if match == "" || path != match {
2015-03-12 01:19:40 +00:00
return fmt . Errorf ( "no matching mount" )
}
2015-04-02 18:17:55 +00:00
// Store the view for this backend
2015-09-15 16:27:22 +00:00
view := c . router . MatchingStorageView ( path )
2015-04-02 18:17:55 +00:00
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
2015-04-02 01:04:36 +00:00
// Mark the entry as tainted
if err := c . taintMountEntry ( path ) ; err != nil {
return err
}
2015-04-02 18:17:55 +00:00
// Taint the router path to prevent routing
if err := c . router . Taint ( path ) ; err != nil {
2015-04-02 01:04:36 +00:00
return err
}
2015-04-02 18:17:55 +00:00
// Invoke the rollback manager a final time
if err := c . rollback . Rollback ( path ) ; err != nil {
return err
}
2015-04-02 05:13:08 +00:00
2015-04-02 18:17:55 +00:00
// Revoke all the dynamic keys
if err := c . expiration . RevokePrefix ( path ) ; err != nil {
return err
}
2015-04-02 05:13:08 +00:00
2015-04-02 18:17:55 +00:00
// Unmount the backend entirely
if err := c . router . Unmount ( path ) ; err != nil {
return err
}
// Clear the data in the view
if err := ClearView ( view ) ; err != nil {
return err
}
2015-04-02 05:13:08 +00:00
// Remove the mount table entry
if err := c . removeMountEntry ( path ) ; err != nil {
return err
}
2016-08-19 20:45:17 +00:00
if c . logger . IsInfo ( ) {
c . logger . Info ( "core: successful unmounted" , "path" , path )
}
2015-04-02 01:04:36 +00:00
return nil
}
// removeMountEntry is used to remove an entry from the mount table
func ( c * Core ) removeMountEntry ( path string ) error {
2015-03-12 01:19:40 +00:00
// Remove the entry from the mount table
2015-09-10 02:17:49 +00:00
newTable := c . mounts . ShallowClone ( )
2015-04-03 22:59:30 +00:00
newTable . Remove ( path )
2015-03-12 01:19:40 +00:00
// Update the mount table
if err := c . persistMounts ( newTable ) ; err != nil {
2016-08-04 13:11:24 +00:00
return logical . CodedError ( 500 , "failed to update mount table" )
2015-03-12 01:19:40 +00:00
}
2015-11-11 16:44:07 +00:00
2015-03-12 01:19:40 +00:00
c . mounts = newTable
2015-04-02 01:04:36 +00:00
return nil
}
2015-03-12 01:19:40 +00:00
2015-04-02 01:04:36 +00:00
// taintMountEntry is used to mark an entry in the mount table as tainted
func ( c * Core ) taintMountEntry ( path string ) error {
2015-11-11 16:44:07 +00:00
// As modifying the taint of an entry affects shallow clones,
// we simply use the original
c . mounts . SetTaint ( path , true )
2015-03-12 01:19:40 +00:00
2015-04-02 01:04:36 +00:00
// Update the mount table
2015-11-11 16:44:07 +00:00
if err := c . persistMounts ( c . mounts ) ; err != nil {
2016-08-04 13:11:24 +00:00
return logical . CodedError ( 500 , "failed to update mount table" )
2015-04-02 01:04:36 +00:00
}
2015-11-11 16:44:07 +00:00
2015-03-12 01:19:40 +00:00
return nil
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
// Remount is used to remount a path at a new mount point.
2015-09-02 19:56:58 +00:00
func ( c * Core ) remount ( src , dst string ) error {
2015-03-12 19:09:30 +00:00
// Ensure we end the path in a slash
if ! strings . HasSuffix ( src , "/" ) {
src += "/"
}
if ! strings . HasSuffix ( dst , "/" ) {
dst += "/"
}
2015-03-18 22:16:52 +00:00
// Prevent protected paths from being remounted
2015-03-12 19:09:30 +00:00
for _ , p := range protectedMounts {
2015-03-18 22:16:52 +00:00
if strings . HasPrefix ( src , p ) {
return fmt . Errorf ( "cannot remount '%s'" , src )
2015-03-12 19:09:30 +00:00
}
}
// Verify exact match of the route
2015-09-11 23:49:20 +00:00
match := c . router . MatchingMount ( src )
if match == "" || src != match {
2015-03-12 19:09:30 +00:00
return fmt . Errorf ( "no matching mount at '%s'" , src )
}
if match := c . router . MatchingMount ( dst ) ; match != "" {
return fmt . Errorf ( "existing mount at '%s'" , match )
}
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
2015-04-02 19:03:00 +00:00
// Mark the entry as tainted
if err := c . taintMountEntry ( src ) ; err != nil {
return err
}
// Taint the router path to prevent routing
if err := c . router . Taint ( src ) ; err != nil {
return err
}
// Invoke the rollback manager a final time
if err := c . rollback . Rollback ( src ) ; err != nil {
return err
}
// Revoke all the dynamic keys
if err := c . expiration . RevokePrefix ( src ) ; err != nil {
return err
}
2015-09-10 02:17:49 +00:00
var ent * MountEntry
2015-11-11 16:44:07 +00:00
for _ , ent = range c . mounts . Entries {
2015-03-12 19:09:30 +00:00
if ent . Path == src {
ent . Path = dst
2015-04-02 19:03:00 +00:00
ent . Tainted = false
2015-03-12 19:09:30 +00:00
break
}
}
// Update the mount table
2015-11-11 16:44:07 +00:00
if err := c . persistMounts ( c . mounts ) ; err != nil {
2015-09-10 02:17:49 +00:00
ent . Path = src
ent . Tainted = true
2016-08-04 13:11:24 +00:00
return logical . CodedError ( 500 , "failed to update mount table" )
2015-03-12 19:09:30 +00:00
}
// Remount the backend
if err := c . router . Remount ( src , dst ) ; err != nil {
return err
}
2015-04-02 19:03:00 +00:00
// Un-taint the path
if err := c . router . Untaint ( dst ) ; err != nil {
return err
}
2016-08-19 20:45:17 +00:00
if c . logger . IsInfo ( ) {
c . logger . Info ( "core: successful remount" , "old_path" , src , "new_path" , dst )
}
2015-03-12 19:09:30 +00:00
return nil
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
// loadMounts is invoked as part of postUnseal to load the mount table
func ( c * Core ) loadMounts ( ) error {
2015-11-11 16:44:07 +00:00
mountTable := & MountTable { }
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
// Load the existing mount table
raw , err := c . barrier . Get ( coreMountConfigPath )
if err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to read mount table" , "error" , err )
2015-08-28 21:25:09 +00:00
return errLoadMountsFailed
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
if raw != nil {
2016-08-04 21:20:37 +00:00
// Check if the persisted value has canary in the beginning. If
// yes, decompress the table and then JSON decode it. If not,
// simply JSON decode it.
2016-08-09 14:33:41 +00:00
if err := jsonutil . DecodeJSON ( raw . Value , mountTable ) ; err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to decompress and/or decode the mount table" , "error" , err )
2016-08-04 21:20:37 +00:00
return err
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
2015-11-11 16:44:07 +00:00
c . mounts = mountTable
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
2015-09-21 21:54:36 +00:00
// Ensure that required entries are loaded, or new ones
// added may never get loaded at all. Note that this
// is only designed to work with singletons, as it checks
// by type only.
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
if c . mounts != nil {
2015-09-21 21:54:36 +00:00
needPersist := false
2016-05-26 16:55:00 +00:00
// Upgrade to typed mount table
if c . mounts . Type == "" {
c . mounts . Type = mountTableType
needPersist = true
}
2015-09-21 21:54:36 +00:00
for _ , requiredMount := range requiredMountTable ( ) . Entries {
foundRequired := false
for _ , coreMount := range c . mounts . Entries {
if coreMount . Type == requiredMount . Type {
foundRequired = true
break
}
}
if ! foundRequired {
c . mounts . Entries = append ( c . mounts . Entries , requiredMount )
needPersist = true
}
}
2016-05-26 16:55:00 +00:00
// Upgrade to table-scoped entries
for _ , entry := range c . mounts . Entries {
if entry . Table == "" {
entry . Table = c . mounts . Type
needPersist = true
}
}
2015-09-21 21:54:36 +00:00
// Done if we have restored the mount table and we don't need
// to persist
if ! needPersist {
return nil
}
} else {
// Create and persist the default mount table
c . mounts = defaultMountTable ( )
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
if err := c . persistMounts ( c . mounts ) ; err != nil {
2015-08-28 21:25:09 +00:00
return errLoadMountsFailed
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
return nil
}
// persistMounts is used to persist the mount table after modification
func ( c * Core ) persistMounts ( table * MountTable ) error {
2016-05-26 16:55:00 +00:00
if table . Type != mountTableType {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: given table to persist has wrong type" , "actual_type" , table . Type , "expected_type" , mountTableType )
2016-05-26 16:55:00 +00:00
return fmt . Errorf ( "invalid table type given, not persisting" )
}
for _ , entry := range table . Entries {
if entry . Table != table . Type {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: given entry to persist in mount table has wrong table value" , "path" , entry . Path , "entry_table_type" , entry . Table , "actual_type" , table . Type )
2016-05-26 16:55:00 +00:00
return fmt . Errorf ( "invalid mount entry found, not persisting" )
}
}
2016-08-04 21:20:37 +00:00
// Encode the mount table into JSON and compress it (lzw).
2016-08-09 14:33:41 +00:00
compressedBytes , err := jsonutil . EncodeJSONAndCompress ( table , nil )
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
if err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to encode and/or compress the mount table" , "error" , err )
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
return err
}
// Create an entry
entry := & Entry {
Key : coreMountConfigPath ,
2016-08-04 21:20:37 +00:00
Value : compressedBytes ,
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
// Write to the physical backend
if err := c . barrier . Put ( entry ) ; err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to persist mount table" , "error" , err )
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
return err
}
return nil
}
// setupMounts is invoked after we've loaded the mount table to
// initialize the logical backends and setup the router
func ( c * Core ) setupMounts ( ) error {
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
2015-03-15 21:53:41 +00:00
var backend logical . Backend
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
var view * BarrierView
2015-09-04 20:58:12 +00:00
var err error
2015-11-11 16:44:07 +00:00
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
for _ , entry := range c . mounts . Entries {
// Initialize the backend, special casing for system
2015-04-02 00:24:22 +00:00
barrierPath := backendBarrierPrefix + entry . UUID + "/"
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
if entry . Type == "system" {
2015-04-02 00:24:22 +00:00
barrierPath = systemBarrierPrefix
2015-03-15 23:25:38 +00:00
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
2015-07-01 00:30:43 +00:00
// Create a barrier view using the UUID
view = NewBarrierView ( c . barrier , barrierPath )
// Initialize the backend
2015-08-28 21:25:09 +00:00
// Create the new backend
2015-09-04 20:58:12 +00:00
backend , err = c . newLogicalBackend ( entry . Type , c . mountEntrySysView ( entry ) , view , nil )
2015-03-15 23:25:38 +00:00
if err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to create mount entry" , "path" , entry . Path , "error" , err )
2015-08-28 21:25:09 +00:00
return errLoadMountsFailed
2015-03-15 23:25:38 +00:00
}
2015-09-15 17:49:53 +00:00
switch entry . Type {
case "system" :
2015-09-04 20:58:12 +00:00
c . systemBarrierView = view
2015-09-15 17:49:53 +00:00
case "cubbyhole" :
ch := backend . ( * CubbyholeBackend )
ch . saltUUID = entry . UUID
ch . storageView = view
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
// Mount the backend
2015-09-04 20:58:12 +00:00
err = c . router . Mount ( backend , entry . Path , entry , view )
2015-03-15 23:25:38 +00:00
if err != nil {
2016-08-19 20:45:17 +00:00
c . logger . Error ( "core: failed to mount entry" , "path" , entry . Path , "error" , err )
2015-08-28 21:25:09 +00:00
return errLoadMountsFailed
2015-09-21 21:54:36 +00:00
} else {
2016-08-19 20:45:17 +00:00
if c . logger . IsInfo ( ) {
c . logger . Info ( "core: successfully mounted backend" , "type" , entry . Type , "path" , entry . Path )
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
2015-04-02 18:17:55 +00:00
// Ensure the path is tainted if set in the mount table
if entry . Tainted {
c . router . Taint ( entry . Path )
}
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
}
return nil
}
// unloadMounts is used before we seal the vault to reset the mounts to
2015-09-10 14:11:37 +00:00
// their unloaded state, calling Cleanup if defined. This is reversed by load and setup mounts.
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
func ( c * Core ) unloadMounts ( ) error {
2015-11-11 16:44:07 +00:00
c . mountsLock . Lock ( )
defer c . mountsLock . Unlock ( )
2015-09-10 14:11:37 +00:00
if c . mounts != nil {
2015-11-11 16:44:07 +00:00
mountTable := c . mounts . ShallowClone ( )
for _ , e := range mountTable . Entries {
2015-09-10 14:11:37 +00:00
prefix := e . Path
b , ok := c . router . root . Get ( prefix )
if ok {
2015-09-11 10:40:31 +00:00
b . ( * routeEntry ) . backend . Cleanup ( )
2015-09-10 14:11:37 +00:00
}
}
}
2015-11-11 16:44:07 +00:00
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
c . mounts = nil
c . router = NewRouter ( )
2015-09-04 20:58:12 +00:00
c . systemBarrierView = nil
vault: make Mount related core functions public
/cc @armon - So I know the conversation we had related to this about
auth, but I think we still need to export these and do auth only at the
external API layer. If you're writing to the internal API, then all bets
are off.
The reason is simply that if you have access to the code, you can
already work around it anyways (you can disable auth or w/e), so a
compromised Vault source/binary is already a failure, and that is the
only thing that our previous unexported methods were protecting against.
If you write an external tool to access a Vault, it still needs to be
unsealed so _that_ is the primary security mechanism from an API
perspective. Once it is unsealed then the core API has full access to
the Vault, and identity/auth is only done at the external API layer, not
at the internal API layer.
The benefits of this approach is that it lets us still treat the "sys"
mount specially but at least have sys adopt helper/backend and use that
machinery and it can still be the only backend which actually has a
reference to *vault.Core to do core things (a key difference). So, an
AWS backend still will never be able to muck with things it can't, but
we're explicitly giving Sys (via struct initialization in Go itself)
a reference to *vault.Core.
2015-03-15 00:26:59 +00:00
return nil
}
2015-03-18 22:46:07 +00:00
// newLogicalBackend is used to create and configure a new logical backend by name
2015-08-28 21:25:09 +00:00
func ( c * Core ) newLogicalBackend ( t string , sysView logical . SystemView , view logical . Storage , conf map [ string ] string ) ( logical . Backend , error ) {
2015-03-18 22:21:41 +00:00
f , ok := c . logicalBackends [ t ]
2015-03-15 23:25:38 +00:00
if ! ok {
return nil , fmt . Errorf ( "unknown backend type: %s" , t )
}
2015-07-01 00:30:43 +00:00
config := & logical . BackendConfig {
2015-09-09 19:42:29 +00:00
StorageView : view ,
Logger : c . logger ,
Config : conf ,
2015-09-10 01:58:09 +00:00
System : sysView ,
2015-07-01 00:30:43 +00:00
}
b , err := f ( config )
2015-04-04 18:39:58 +00:00
if err != nil {
return nil , err
}
return b , nil
2015-03-15 23:25:38 +00:00
}
2015-09-02 19:56:58 +00:00
// mountEntrySysView creates a logical.SystemView from global and
2015-09-04 20:58:12 +00:00
// mount-specific entries; because this should be called when setting
// up a mountEntry, it doesn't check to ensure that me is not nil
func ( c * Core ) mountEntrySysView ( me * MountEntry ) logical . SystemView {
return dynamicSystemView {
2015-09-10 02:17:49 +00:00
core : c ,
mountEntry : me ,
2015-08-28 21:25:09 +00:00
}
}
2015-03-11 22:19:41 +00:00
// defaultMountTable creates a default mount table
func defaultMountTable ( ) * MountTable {
2016-05-26 16:55:00 +00:00
table := & MountTable {
Type : mountTableType ,
}
2016-01-13 18:40:08 +00:00
mountUUID , err := uuid . GenerateUUID ( )
if err != nil {
panic ( fmt . Sprintf ( "could not create default mount table UUID: %v" , err ) )
}
2015-03-11 22:19:41 +00:00
genericMount := & MountEntry {
2016-05-26 16:55:00 +00:00
Table : mountTableType ,
2015-03-11 22:19:41 +00:00
Path : "secret/" ,
Type : "generic" ,
Description : "generic secret storage" ,
2016-01-13 18:40:08 +00:00
UUID : mountUUID ,
2015-03-11 22:19:41 +00:00
}
2015-09-21 21:54:36 +00:00
table . Entries = append ( table . Entries , genericMount )
table . Entries = append ( table . Entries , requiredMountTable ( ) . Entries ... )
return table
}
// requiredMountTable() creates a mount table with entries required
// to be available
func requiredMountTable ( ) * MountTable {
2016-05-26 16:55:00 +00:00
table := & MountTable {
Type : mountTableType ,
}
2016-01-13 18:40:08 +00:00
cubbyholeUUID , err := uuid . GenerateUUID ( )
if err != nil {
panic ( fmt . Sprintf ( "could not create cubbyhole UUID: %v" , err ) )
}
2015-09-10 01:58:09 +00:00
cubbyholeMount := & MountEntry {
2016-05-26 16:55:00 +00:00
Table : mountTableType ,
2015-09-10 01:58:09 +00:00
Path : "cubbyhole/" ,
Type : "cubbyhole" ,
Description : "per-token private secret storage" ,
2016-01-13 18:40:08 +00:00
UUID : cubbyholeUUID ,
}
sysUUID , err := uuid . GenerateUUID ( )
if err != nil {
panic ( fmt . Sprintf ( "could not create sys UUID: %v" , err ) )
2015-09-10 01:58:09 +00:00
}
2015-03-11 22:19:41 +00:00
sysMount := & MountEntry {
2016-05-26 16:55:00 +00:00
Table : mountTableType ,
2015-03-11 22:19:41 +00:00
Path : "sys/" ,
Type : "system" ,
Description : "system endpoints used for control, policy and debugging" ,
2016-01-13 18:40:08 +00:00
UUID : sysUUID ,
2015-03-11 22:19:41 +00:00
}
2015-09-10 01:58:09 +00:00
table . Entries = append ( table . Entries , cubbyholeMount )
2015-03-11 22:19:41 +00:00
table . Entries = append ( table . Entries , sysMount )
return table
}