blob: 83bf71488e626a40ce9f3235ce7f51104777f9a3 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"testing"
"v.io/v23"
"v.io/v23/options"
"v.io/v23/security"
"v.io/v23/security/access"
"v.io/x/ref/runtime/internal/naming"
"v.io/x/ref/test/testutil"
)
func TestServerAuthorizer(t *testing.T) {
var (
pclient = testutil.NewPrincipal()
pserver = testutil.NewPrincipal()
pother = testutil.NewPrincipal()
ali, _ = pserver.BlessSelf("ali")
bob, _ = pserver.BlessSelf("bob")
che, _ = pserver.BlessSelf("che")
otherAli, _ = pother.BlessSelf("ali")
ctx, shutdown = initForTest()
U = func(blessings ...security.Blessings) security.Blessings {
u, err := security.UnionOfBlessings(blessings...)
if err != nil {
t.Fatal(err)
}
return u
}
ACL = func(patterns ...string) security.Authorizer {
var acl access.AccessList
for _, p := range patterns {
acl.In = append(acl.In, security.BlessingPattern(p))
}
return acl
}
)
defer shutdown()
ctx, _ = v23.WithPrincipal(ctx, pclient)
// Make client recognize ali, bob and otherAli blessings
for _, b := range []security.Blessings{ali, bob, otherAli} {
if err := security.AddToRoots(pclient, b); err != nil {
t.Fatal(err)
}
}
// All tests are run as if pclient is the client end and pserver is remote end.
tests := []struct {
serverBlessingNames []string
auth security.Authorizer
authorizedServers []security.Blessings
unauthorizedServers []security.Blessings
}{
{
// No blessings in the endpoint means that all servers are authorized.
nil,
newServerAuthorizer(""),
[]security.Blessings{ali, otherAli, bob, che},
[]security.Blessings{},
},
{
// Endpoint sets the expectations for "ali" and "bob".
// Since no options.ServerAuthorizer was provided, use the blessing names in the endpoint.
[]string{"ali", "bob"},
newServerAuthorizer(""),
[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
[]security.Blessings{che},
},
{
// Still only ali, otherAli and bob are authorized (che is not
// authorized since it is not recognized by the client)
[]string{"ali", "bob", "che"},
newServerAuthorizer(""),
[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
[]security.Blessings{che},
},
{
// Only ali and otherAli are authorized (since the
// policy does not allow "bob")
[]string{"ali", "bob", "che"},
newServerAuthorizer("", options.ServerAuthorizer{ACL("ali", "dan")}),
[]security.Blessings{ali, otherAli, U(ali, che), U(ali, bob)},
[]security.Blessings{bob, che},
},
{
// Only otherAli is authorized (since only pother's public key is
// authorized)
[]string{"ali"},
newServerAuthorizer("", options.ServerAuthorizer{security.PublicKeyAuthorizer(pother.PublicKey())}),
[]security.Blessings{otherAli},
[]security.Blessings{ali, bob, che},
},
{
// Blessings in endpoint can be ignored by security.AllowEveryone.
[]string{"ali"},
newServerAuthorizer("", options.ServerAuthorizer{security.AllowEveryone()}),
[]security.Blessings{ali, bob, che, otherAli},
nil,
},
{
// Pattern provied to newServerAuthorizer is respected.
nil,
newServerAuthorizer("bob"),
[]security.Blessings{bob, U(ali, bob)},
[]security.Blessings{ali, otherAli, che},
},
{
// And if the intersection of the policy and the
// pattern is empty, then so be it.
[]string{"ali", "bob", "che"},
newServerAuthorizer("bob", options.ServerAuthorizer{ACL("ali", "che")}),
[]security.Blessings{U(ali, bob), U(ali, bob, che)},
[]security.Blessings{ali, otherAli, bob, che, U(ali, che)},
},
}
for _, test := range tests {
call := &mockCall{
p: pclient,
rep: &naming.Endpoint{Blessings: test.serverBlessingNames},
}
for _, s := range test.authorizedServers {
call.r = s
if err := test.auth.Authorize(ctx, call); err != nil {
t.Errorf("serverAuthorizer: %#v failed to authorize server: %v", test.auth, s)
}
}
for _, s := range test.unauthorizedServers {
call.r = s
if err := test.auth.Authorize(ctx, call); err == nil {
t.Errorf("serverAuthorizer: %#v authorized server: %v", test.auth, s)
}
}
}
}