vault: require root token for seal

This commit is contained in:
Mitchell Hashimoto 2015-03-31 09:59:02 -07:00
parent 04c80a81bc
commit 0666bda865
5 changed files with 72 additions and 85 deletions

View File

@ -47,10 +47,10 @@ func TestSysSealStatus_uninit(t *testing.T) {
}
func TestSysSeal(t *testing.T) {
core := vault.TestCore(t)
vault.TestCoreInit(t, core)
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
resp := testHttpPut(t, addr+"/v1/sys/seal", nil)
testResponseStatus(t, resp, 204)

View File

@ -225,38 +225,21 @@ func (c *Core) HandleRequest(req *logical.Request) (*logical.Response, error) {
}
func (c *Core) handleRequest(req *logical.Request) (*logical.Response, error) {
// Ensure there is a client token
if req.ClientToken == "" {
return logical.ErrorResponse("missing client token"), logical.ErrInvalidRequest
}
// Resolve the token policy
te, err := c.tokenStore.Lookup(req.ClientToken)
// Validate the token
err := c.checkToken(
req.Operation, req.Path, req.ClientToken, c.router.RootPath(req.Path))
if err != nil {
c.logger.Printf("[ERR] core: failed to lookup token: %v", err)
return nil, ErrInternalError
}
// If it is an internal error we return that, otherwise we
// return invalid request so that the status codes can be correct
errType := logical.ErrInvalidRequest
switch err {
case ErrInternalError:
fallthrough
case logical.ErrPermissionDenied:
errType = err
}
// Ensure the token is valid
if te == nil {
return logical.ErrorResponse("invalid client token"), logical.ErrInvalidRequest
}
// Construct the corresponding ACL object
acl, err := c.policy.ACL(te.Policies...)
if err != nil {
c.logger.Printf("[ERR] core: failed to construct ACL: %v", err)
return nil, ErrInternalError
}
// Check if this is a root protected path
if c.router.RootPath(req.Path) && !acl.RootPrivilege(req.Path) {
return nil, logical.ErrPermissionDenied
}
// Check the standard non-root ACLs
if !acl.AllowOperation(req.Operation, req.Path) {
return nil, logical.ErrPermissionDenied
return logical.ErrorResponse(err.Error()), errType
}
// Route the request
@ -321,6 +304,45 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, erro
return resp, err
}
func (c *Core) checkToken(
op logical.Operation, path string, token string, root bool) error {
// Ensure there is a client token
if token == "" {
return fmt.Errorf("missing client token")
}
// Resolve the token policy
te, err := c.tokenStore.Lookup(token)
if err != nil {
c.logger.Printf("[ERR] core: failed to lookup token: %v", err)
return ErrInternalError
}
// Ensure the token is valid
if te == nil {
return fmt.Errorf("invalid client token")
}
// Construct the corresponding ACL object
acl, err := c.policy.ACL(te.Policies...)
if err != nil {
c.logger.Printf("[ERR] core: failed to construct ACL: %v", err)
return ErrInternalError
}
// Check if this is a root protected path
if root && !acl.RootPrivilege(path) {
return logical.ErrPermissionDenied
}
// Check the standard non-root ACLs
if !acl.AllowOperation(op, path) {
return logical.ErrPermissionDenied
}
return nil
}
// Initialized checks if the Vault is already initialized
func (c *Core) Initialized() (bool, error) {
// Check the barrier first
@ -586,12 +608,23 @@ func (c *Core) Unseal(key []byte) (bool, error) {
// Seal is used to re-seal the Vault. This requires the Vault to
// be unsealed again to perform any further operations.
func (c *Core) Seal() error {
func (c *Core) Seal(token string) error {
c.stateLock.Lock()
defer c.stateLock.Unlock()
if c.sealed {
return nil
}
// Validate the token is a root token
err := c.checkToken(
logical.WriteOperation,
"sys/seal",
token,
true)
if err != nil {
return err
}
c.sealed = true
// Do pre-seal teardown

View File

@ -202,13 +202,13 @@ func TestCore_Unseal_MultiShare(t *testing.T) {
t.Fatalf("should not be sealed")
}
err = c.Seal()
err = c.Seal(res.RootToken)
if err != nil {
t.Fatalf("err: %v", err)
}
// Ignore redundant
err = c.Seal()
err = c.Seal(res.RootToken)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -312,8 +312,8 @@ func TestCore_Route_Sealed(t *testing.T) {
// Attempt to unseal after doing a first seal
func TestCore_SealUnseal(t *testing.T) {
c, key, _ := TestCoreUnsealed(t)
if err := c.Seal(); err != nil {
c, key, root := TestCoreUnsealed(t)
if err := c.Seal(root); err != nil {
t.Fatalf("err: %v", err)
}
if unseal, err := c.Unseal(key); err != nil || !unseal {
@ -416,10 +416,7 @@ func TestCore_HandleRequest_RootPath(t *testing.T) {
}
resp, err := c.HandleRequest(req)
if err != logical.ErrPermissionDenied {
t.Fatalf("err: %v", err)
}
if resp != nil {
t.Fatalf("bad: %#v", resp)
t.Fatalf("err: %v, resp: %v", err, resp)
}
}
@ -476,10 +473,7 @@ func TestCore_HandleRequest_PermissionDenied(t *testing.T) {
}
resp, err := c.HandleRequest(req)
if err != logical.ErrPermissionDenied {
t.Fatalf("err: %v", err)
}
if resp != nil {
t.Fatalf("bad: %#v", resp)
t.Fatalf("err: %v, resp: %v", err, resp)
}
}

View File

@ -20,7 +20,6 @@ func NewSystemBackend(core *Core) logical.Backend {
"revoke-prefix/*",
"policy",
"policy/*",
"seal",
},
},
@ -216,17 +215,6 @@ func NewSystemBackend(core *Core) logical.Backend {
HelpSynopsis: strings.TrimSpace(sysHelp["policy"][0]),
HelpDescription: strings.TrimSpace(sysHelp["policy"][1]),
},
&framework.Path{
Pattern: "seal$",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.WriteOperation: b.handleSeal,
},
HelpSynopsis: strings.TrimSpace(sysHelp["seal"][0]),
HelpDescription: strings.TrimSpace(sysHelp["seal"][1]),
},
},
}
}
@ -238,17 +226,6 @@ type SystemBackend struct {
Core *Core
}
// handleSeal is used to mount a new path
func (b *SystemBackend) handleSeal(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
// Attempt seal
if err := b.Core.Seal(); err != nil {
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
}
return nil, nil
}
// handleMountTable handles the "mounts" endpoint to provide the mount table
func (b *SystemBackend) handleMountTable(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

View File

@ -15,7 +15,6 @@ func TestSystemBackend_RootPaths(t *testing.T) {
"revoke-prefix/*",
"policy",
"policy/*",
"seal",
}
b := testSystemBackend(t)
@ -25,22 +24,6 @@ func TestSystemBackend_RootPaths(t *testing.T) {
}
}
func TestSystemBackend_seal(t *testing.T) {
core, b, _ := testCoreSystemBackend(t)
req := logical.TestRequest(t, logical.WriteOperation, "seal")
_, err := b.HandleRequest(req)
if err != nil {
t.Fatalf("err: %v", err)
}
sealed, err := core.Sealed()
if err != nil {
t.Fatalf("err: %v", err)
}
if !sealed {
t.Fatal("should be sealed")
}
}
func TestSystemBackend_mounts(t *testing.T) {
b := testSystemBackend(t)
req := logical.TestRequest(t, logical.ReadOperation, "mounts")