Exemplo n.º 1
0
// Mount is used to mount a new backend to the mount table.
func (c *Core) mount(me *MountEntry) error {
	// Ensure we end the path in a slash
	if !strings.HasSuffix(me.Path, "/") {
		me.Path += "/"
	}

	// Prevent protected paths from being mounted
	for _, p := range protectedMounts {
		if strings.HasPrefix(me.Path, p) {
			return logical.CodedError(403, fmt.Sprintf("cannot mount '%s'", me.Path))
		}
	}

	// 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))
		}
	}

	// Verify there is no conflicting mount
	if match := c.router.MatchingMount(me.Path); match != "" {
		return logical.CodedError(409, fmt.Sprintf("existing mount at %s", match))
	}

	// Generate a new UUID and view
	meUUID, err := uuid.GenerateUUID()
	if err != nil {
		return err
	}
	me.UUID = meUUID
	view := NewBarrierView(c.barrier, backendBarrierPrefix+me.UUID+"/")

	backend, err := c.newLogicalBackend(me.Type, c.mountEntrySysView(me), view, nil)
	if err != nil {
		return err
	}

	// Update the mount table
	c.mountsLock.Lock()
	newTable := c.mounts.shallowClone()
	newTable.Entries = append(newTable.Entries, me)
	if err := c.persistMounts(newTable); err != nil {
		c.mountsLock.Unlock()
		return logical.CodedError(500, "failed to update mount table")
	}
	c.mounts = newTable
	c.mountsLock.Unlock()

	// Mount the backend
	if err := c.router.Mount(backend, me.Path, me, view); err != nil {
		return err
	}
	if c.logger.IsInfo() {
		c.logger.Info("core: successful mount", "path", me.Path, "type", me.Type)
	}
	return nil
}
Exemplo n.º 2
0
func TestHandler_error(t *testing.T) {
	w := httptest.NewRecorder()

	respondError(w, 500, errors.New("Test Error"))

	if w.Code != 500 {
		t.Fatalf("expected 500, got %d", w.Code)
	}

	// The code inside of the error should override
	// the argument to respondError
	w2 := httptest.NewRecorder()
	e := logical.CodedError(403, "error text")

	respondError(w2, 500, e)

	if w2.Code != 403 {
		t.Fatalf("expected 403, got %d", w2.Code)
	}

	// vault.ErrSealed is a special case
	w3 := httptest.NewRecorder()

	respondError(w3, 400, vault.ErrSealed)

	if w3.Code != 503 {
		t.Fatalf("expected 503, got %d", w3.Code)
	}

}
Exemplo n.º 3
0
// enableCredential is used to enable a new credential backend
func (c *Core) enableCredential(entry *MountEntry) error {
	// Ensure we end the path in a slash
	if !strings.HasSuffix(entry.Path, "/") {
		entry.Path += "/"
	}

	// Ensure there is a name
	if entry.Path == "/" {
		return fmt.Errorf("backend path must be specified")
	}

	c.authLock.Lock()
	defer c.authLock.Unlock()

	// Look for matching name
	for _, ent := range c.auth.Entries {
		switch {
		// Existing is oauth/github/ new is oauth/ or
		// existing is oauth/ and new is oauth/github/
		case strings.HasPrefix(ent.Path, entry.Path):
			fallthrough
		case strings.HasPrefix(entry.Path, ent.Path):
			return logical.CodedError(409, "path is already in use")
		}
	}

	// Ensure the token backend is a singleton
	if entry.Type == "token" {
		return fmt.Errorf("token credential backend cannot be instantiated")
	}

	// Generate a new UUID and view
	entry.UUID = uuid.GenerateUUID()
	view := NewBarrierView(c.barrier, credentialBarrierPrefix+entry.UUID+"/")

	// Create the new backend
	backend, err := c.newCredentialBackend(entry.Type, c.mountEntrySysView(entry), view, nil)
	if err != nil {
		return err
	}

	// Update the auth table
	newTable := c.auth.ShallowClone()
	newTable.Entries = append(newTable.Entries, entry)
	if err := c.persistAuth(newTable); err != nil {
		return errors.New("failed to update auth table")
	}

	c.auth = newTable

	// Mount the backend
	path := credentialRoutePrefix + entry.Path
	if err := c.router.Mount(backend, path, entry, view); err != nil {
		return err
	}
	c.logger.Printf("[INFO] core: enabled credential backend '%s' type: %s",
		entry.Path, entry.Type)
	return nil
}
Exemplo n.º 4
0
// Mount is used to mount a new backend to the mount table.
func (c *Core) mount(me *MountEntry) error {
	c.mounts.Lock()
	defer c.mounts.Unlock()

	// Ensure we end the path in a slash
	if !strings.HasSuffix(me.Path, "/") {
		me.Path += "/"
	}

	// Prevent protected paths from being mounted
	for _, p := range protectedMounts {
		if strings.HasPrefix(me.Path, p) {
			return logical.CodedError(403, fmt.Sprintf("cannot mount '%s'", me.Path))
		}
	}

	// Verify there is no conflicting mount
	if match := c.router.MatchingMount(me.Path); match != "" {
		return logical.CodedError(409, fmt.Sprintf("existing mount at %s", match))
	}

	// Generate a new UUID and view
	me.UUID = uuid.GenerateUUID()
	view := NewBarrierView(c.barrier, backendBarrierPrefix+me.UUID+"/")

	// Create the new backend
	backend, err := c.newLogicalBackend(me.Type, view, nil)
	if err != nil {
		return err
	}

	// Update the mount table
	newTable := c.mounts.Clone()
	newTable.Entries = append(newTable.Entries, me)
	if err := c.persistMounts(newTable); err != nil {
		return errors.New("failed to update mount table")
	}
	c.mounts = newTable

	// Mount the backend
	if err := c.router.Mount(backend, me.Path, me.UUID, view); err != nil {
		return err
	}
	c.logger.Printf("[INFO] core: mounted '%s' type: %s", me.Path, me.Type)
	return nil
}
Exemplo n.º 5
0
// taintMountEntry is used to mark an entry in the mount table as tainted
func (c *Core) taintMountEntry(path string) error {
	// As modifying the taint of an entry affects shallow clones,
	// we simply use the original
	c.mounts.SetTaint(path, true)

	// Update the mount table
	if err := c.persistMounts(c.mounts); err != nil {
		return logical.CodedError(500, "failed to update mount table")
	}

	return nil
}
Exemplo n.º 6
0
// removeMountEntry is used to remove an entry from the mount table
func (c *Core) removeMountEntry(path string) error {
	// Remove the entry from the mount table
	newTable := c.mounts.ShallowClone()
	newTable.Remove(path)

	// Update the mount table
	if err := c.persistMounts(newTable); err != nil {
		return logical.CodedError(500, "failed to update mount table")
	}

	c.mounts = newTable
	return nil
}
Exemplo n.º 7
0
// Remount is used to remount a path at a new mount point.
func (c *Core) remount(src, dst string) error {
	// Ensure we end the path in a slash
	if !strings.HasSuffix(src, "/") {
		src += "/"
	}
	if !strings.HasSuffix(dst, "/") {
		dst += "/"
	}

	// Prevent protected paths from being remounted
	for _, p := range protectedMounts {
		if strings.HasPrefix(src, p) {
			return fmt.Errorf("cannot remount '%s'", src)
		}
	}

	// Verify exact match of the route
	match := c.router.MatchingMount(src)
	if match == "" || src != match {
		return fmt.Errorf("no matching mount at '%s'", src)
	}

	if match := c.router.MatchingMount(dst); match != "" {
		return fmt.Errorf("existing mount at '%s'", match)
	}

	// 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
	}

	c.mountsLock.Lock()
	var ent *MountEntry
	for _, ent = range c.mounts.Entries {
		if ent.Path == src {
			ent.Path = dst
			ent.Tainted = false
			break
		}
	}

	// Update the mount table
	if err := c.persistMounts(c.mounts); err != nil {
		ent.Path = src
		ent.Tainted = true
		c.mountsLock.Unlock()
		return logical.CodedError(500, "failed to update mount table")
	}
	c.mountsLock.Unlock()

	// Remount the backend
	if err := c.router.Remount(src, dst); err != nil {
		return err
	}

	// Un-taint the path
	if err := c.router.Untaint(dst); err != nil {
		return err
	}

	if c.logger.IsInfo() {
		c.logger.Info("core: successful remount", "old_path", src, "new_path", dst)
	}
	return nil
}