2015-03-06 01:23:56 +00:00
|
|
|
package vault
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
2015-03-15 21:53:41 +00:00
|
|
|
|
2015-03-23 18:47:55 +00:00
|
|
|
"github.com/hashicorp/vault/credential"
|
2015-03-15 21:53:41 +00:00
|
|
|
"github.com/hashicorp/vault/logical"
|
2015-03-06 01:23:56 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type NoopBackend struct {
|
2015-03-16 20:58:22 +00:00
|
|
|
Root []string
|
|
|
|
Paths []string
|
|
|
|
Requests []*logical.Request
|
|
|
|
Response *logical.Response
|
2015-03-06 01:23:56 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:53:41 +00:00
|
|
|
func (n *NoopBackend) HandleRequest(req *logical.Request) (*logical.Response, error) {
|
2015-03-06 01:23:56 +00:00
|
|
|
n.Paths = append(n.Paths, req.Path)
|
2015-03-16 20:58:22 +00:00
|
|
|
n.Requests = append(n.Requests, req)
|
2015-03-15 20:54:20 +00:00
|
|
|
if req.Storage == nil {
|
2015-03-06 01:23:56 +00:00
|
|
|
return nil, fmt.Errorf("missing view")
|
|
|
|
}
|
2015-03-16 20:58:22 +00:00
|
|
|
return n.Response, nil
|
2015-03-06 01:23:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *NoopBackend) RootPaths() []string {
|
|
|
|
return n.Root
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRouter_Mount(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "logical/")
|
|
|
|
|
|
|
|
n := &NoopBackend{}
|
2015-03-18 22:48:14 +00:00
|
|
|
err := r.Mount(n, "prod/aws/", view)
|
2015-03-06 01:23:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-18 22:48:14 +00:00
|
|
|
err = r.Mount(n, "prod/aws/", view)
|
2015-03-06 01:23:56 +00:00
|
|
|
if !strings.Contains(err.Error(), "cannot mount under existing mount") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-12 00:56:01 +00:00
|
|
|
if path := r.MatchingMount("prod/aws/foo"); path != "prod/aws/" {
|
|
|
|
t.Fatalf("bad: %s", path)
|
|
|
|
}
|
|
|
|
|
|
|
|
if path := r.MatchingMount("stage/aws/foo"); path != "" {
|
|
|
|
t.Fatalf("bad: %s", path)
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:53:41 +00:00
|
|
|
req := &logical.Request{
|
2015-03-06 01:23:56 +00:00
|
|
|
Path: "prod/aws/foo",
|
|
|
|
}
|
|
|
|
resp, err := r.Route(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("bad: %v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the path
|
|
|
|
if len(n.Paths) != 1 || n.Paths[0] != "foo" {
|
|
|
|
t.Fatalf("bad: %v", n.Paths)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRouter_Unmount(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "logical/")
|
|
|
|
|
|
|
|
n := &NoopBackend{}
|
2015-03-18 22:48:14 +00:00
|
|
|
err := r.Mount(n, "prod/aws/", view)
|
2015-03-06 01:23:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = r.Unmount("prod/aws/")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:53:41 +00:00
|
|
|
req := &logical.Request{
|
2015-03-06 01:23:56 +00:00
|
|
|
Path: "prod/aws/foo",
|
|
|
|
}
|
|
|
|
_, err = r.Route(req)
|
|
|
|
if !strings.Contains(err.Error(), "no handler for route") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRouter_Remount(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "logical/")
|
|
|
|
|
|
|
|
n := &NoopBackend{}
|
2015-03-18 22:48:14 +00:00
|
|
|
err := r.Mount(n, "prod/aws/", view)
|
2015-03-06 01:23:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = r.Remount("prod/aws/", "stage/aws/")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = r.Remount("prod/aws/", "stage/aws/")
|
|
|
|
if !strings.Contains(err.Error(), "no mount at") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:53:41 +00:00
|
|
|
req := &logical.Request{
|
2015-03-06 01:23:56 +00:00
|
|
|
Path: "prod/aws/foo",
|
|
|
|
}
|
|
|
|
_, err = r.Route(req)
|
|
|
|
if !strings.Contains(err.Error(), "no handler for route") {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:53:41 +00:00
|
|
|
req = &logical.Request{
|
2015-03-06 01:23:56 +00:00
|
|
|
Path: "stage/aws/foo",
|
|
|
|
}
|
|
|
|
_, err = r.Route(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the path
|
|
|
|
if len(n.Paths) != 1 || n.Paths[0] != "foo" {
|
|
|
|
t.Fatalf("bad: %v", n.Paths)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRouter_RootPath(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "logical/")
|
|
|
|
|
|
|
|
n := &NoopBackend{
|
|
|
|
Root: []string{
|
|
|
|
"root",
|
|
|
|
"policy/*",
|
|
|
|
},
|
|
|
|
}
|
2015-03-18 22:48:14 +00:00
|
|
|
err := r.Mount(n, "prod/aws/", view)
|
2015-03-06 01:23:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
type tcase struct {
|
|
|
|
path string
|
|
|
|
expect bool
|
|
|
|
}
|
|
|
|
tcases := []tcase{
|
|
|
|
{"random", false},
|
|
|
|
{"prod/aws/foo", false},
|
|
|
|
{"prod/aws/root", true},
|
|
|
|
{"prod/aws/root-more", false},
|
|
|
|
{"prod/aws/policy", false},
|
|
|
|
{"prod/aws/policy/", true},
|
|
|
|
{"prod/aws/policy/ops", true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tcases {
|
|
|
|
out := r.RootPath(tc.path)
|
|
|
|
if out != tc.expect {
|
|
|
|
t.Fatalf("bad: path: %s expect: %v got %v", tc.path, tc.expect, out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-23 18:47:55 +00:00
|
|
|
|
|
|
|
func TestRouter_RouteLogin(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "auth/")
|
|
|
|
|
|
|
|
n := &NoopCred{
|
|
|
|
Login: []string{"bar"},
|
|
|
|
}
|
|
|
|
err := r.Mount(n, "auth/foo/", view)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if path := r.MatchingMount("auth/foo/bar"); path != "auth/foo/" {
|
|
|
|
t.Fatalf("bad: %s", path)
|
|
|
|
}
|
|
|
|
|
|
|
|
req := &credential.Request{
|
|
|
|
Path: "auth/foo/bar",
|
|
|
|
}
|
|
|
|
resp, err := r.RouteLogin(req)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("bad: %v", resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the path
|
|
|
|
if len(n.LPaths) != 1 || n.LPaths[0] != "bar" {
|
|
|
|
t.Fatalf("bad: %v", n.Paths)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRouter_LoginPath(t *testing.T) {
|
|
|
|
r := NewRouter()
|
|
|
|
_, barrier, _ := mockBarrier(t)
|
|
|
|
view := NewBarrierView(barrier, "auth/")
|
|
|
|
|
|
|
|
n := &NoopCred{
|
|
|
|
Login: []string{
|
|
|
|
"login",
|
|
|
|
"oauth/*",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
err := r.Mount(n, "auth/foo/", view)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
type tcase struct {
|
|
|
|
path string
|
|
|
|
expect bool
|
|
|
|
}
|
|
|
|
tcases := []tcase{
|
|
|
|
{"random", false},
|
|
|
|
{"auth/foo/bar", false},
|
|
|
|
{"auth/foo/login", true},
|
|
|
|
{"auth/foo/oauth", false},
|
|
|
|
{"auth/foo/oauth/redirect", true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tcases {
|
|
|
|
out := r.LoginPath(tc.path)
|
|
|
|
if out != tc.expect {
|
|
|
|
t.Fatalf("bad: path: %s expect: %v got %v", tc.path, tc.expect, out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPathsToRadix(t *testing.T) {
|
|
|
|
// Provide real paths
|
|
|
|
paths := []string{
|
|
|
|
"foo",
|
|
|
|
"foo/*",
|
|
|
|
"sub/bar*",
|
|
|
|
}
|
|
|
|
r := pathsToRadix(paths)
|
|
|
|
|
|
|
|
raw, ok := r.Get("foo")
|
|
|
|
if !ok || raw.(bool) != false {
|
|
|
|
t.Fatalf("bad: %v (foo)", raw)
|
|
|
|
}
|
|
|
|
|
|
|
|
raw, ok = r.Get("foo/")
|
|
|
|
if !ok || raw.(bool) != true {
|
|
|
|
t.Fatalf("bad: %v (foo/)", raw)
|
|
|
|
}
|
|
|
|
|
|
|
|
raw, ok = r.Get("sub/bar")
|
|
|
|
if !ok || raw.(bool) != true {
|
|
|
|
t.Fatalf("bad: %v (sub/bar)", raw)
|
|
|
|
}
|
|
|
|
}
|