Merge "security: Make Blessings a struct instead of an interface."
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index 7d5cf9d..5baf9d5 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -526,3 +526,4 @@
func (e endpoint) RoutingID() naming.RoutingID { return naming.RoutingID(e) }
func (e endpoint) Addr() net.Addr { return nil }
func (e endpoint) ServesMountTable() bool { return false }
+func (e endpoint) BlessingNames() []string { return nil }
diff --git a/runtimes/google/naming/endpoint.go b/runtimes/google/naming/endpoint.go
index daba3b1..1300684 100644
--- a/runtimes/google/naming/endpoint.go
+++ b/runtimes/google/naming/endpoint.go
@@ -4,6 +4,7 @@
"errors"
"fmt"
"net"
+ "regexp"
"strconv"
"strings"
@@ -12,11 +13,15 @@
)
const (
- separator = "@"
- suffix = "@@"
+ separator = "@"
+ suffix = "@@"
+ blessingsSeparator = ","
)
-var errInvalidEndpointString = errors.New("invalid endpoint string")
+var (
+ errInvalidEndpointString = errors.New("invalid endpoint string")
+ hostportEP = regexp.MustCompile("^(?:(.*)@)?([^@]+)$")
+)
// Network is the string returned by naming.Endpoint.Network implementations
// defined in this package.
@@ -29,6 +34,7 @@
RID naming.RoutingID
MinIPCVersion version.IPCVersion
MaxIPCVersion version.IPCVersion
+ Blessings []string
IsMountTable bool
}
@@ -39,15 +45,19 @@
// We have to guess this is a mount table if we don't know.
ep.IsMountTable = true
- // The prefix and suffix are optional.
- input = strings.TrimPrefix(strings.TrimSuffix(input, suffix), separator)
-
- parts := strings.Split(input, separator)
- if len(parts) == 1 {
- err := ep.parseHostPort(parts[0])
+ // If the endpoint does not end in a @, it must be in [blessing@]host:port format.
+ if parts := hostportEP.FindStringSubmatch(input); len(parts) > 0 {
+ hostport := parts[len(parts)-1]
+ var blessing string
+ if len(parts) > 2 {
+ blessing = parts[1]
+ }
+ err := ep.parseHostPort(blessing, hostport)
return ep, err
}
-
+ // Trim the prefix and suffix and parse the rest.
+ input = strings.TrimPrefix(strings.TrimSuffix(input, suffix), separator)
+ parts := strings.Split(input, separator)
version, err := strconv.ParseUint(parts[0], 10, 16)
if err != nil {
return nil, fmt.Errorf("invalid version: %v", err)
@@ -60,21 +70,25 @@
err = ep.parseV2(parts)
case 3:
err = ep.parseV3(parts)
+ case 4:
+ err = ep.parseV4(parts)
default:
err = errInvalidEndpointString
}
return ep, err
}
-func (ep *Endpoint) parseHostPort(input string) error {
+func (ep *Endpoint) parseHostPort(blessing, hostport string) error {
// Could be in host:port format.
- if _, _, err := net.SplitHostPort(input); err != nil {
+ if _, _, err := net.SplitHostPort(hostport); err != nil {
return errInvalidEndpointString
}
ep.Protocol = naming.UnknownProtocol
- ep.Address = input
+ ep.Address = hostport
ep.RID = naming.NullRoutingID
-
+ if len(blessing) > 0 {
+ ep.Blessings = []string{blessing}
+ }
return nil
}
@@ -166,6 +180,20 @@
return nil
}
+func (ep *Endpoint) parseV4(parts []string) error {
+ if len(parts) < 7 {
+ return errInvalidEndpointString
+ }
+ if err := ep.parseV3(parts[:7]); err != nil {
+ return err
+ }
+ // Join the remaining and re-split.
+ if str := strings.Join(parts[7:], separator); len(str) > 0 {
+ ep.Blessings = strings.Split(str, blessingsSeparator)
+ }
+ return nil
+}
+
func (ep *Endpoint) RoutingID() naming.RoutingID {
//nologcall
return ep.RID
@@ -175,7 +203,7 @@
return Network
}
-var defaultVersion = 3
+var defaultVersion = 3 // TODO(ashankar): Change to 4?
func (ep *Endpoint) VersionedString(version int) string {
switch version {
@@ -196,12 +224,27 @@
ep.Protocol, ep.Address, ep.RID,
printIPCVersion(ep.MinIPCVersion), printIPCVersion(ep.MaxIPCVersion),
mt)
+ case 4:
+ mt := "s"
+ blessings := strings.Join(ep.Blessings, blessingsSeparator)
+ if ep.IsMountTable {
+ mt = "m"
+ }
+ return fmt.Sprintf("@4@%s@%s@%s@%s@%s@%s@%s@@",
+ ep.Protocol, ep.Address, ep.RID,
+ printIPCVersion(ep.MinIPCVersion), printIPCVersion(ep.MaxIPCVersion),
+ mt, blessings)
}
}
func (ep *Endpoint) String() string {
//nologcall
- return ep.VersionedString(defaultVersion)
+ // Use version 4 if blessings are present, otherwise there is a loss of information.
+ v := defaultVersion
+ if len(ep.Blessings) > 0 && v < 4 {
+ v = 4
+ }
+ return ep.VersionedString(v)
}
func (ep *Endpoint) Name() string {
@@ -219,6 +262,11 @@
return ep.IsMountTable
}
+func (ep *Endpoint) BlessingNames() []string {
+ //nologcall
+ return ep.Blessings
+}
+
type addr struct {
network, address string
}
diff --git a/runtimes/google/naming/endpoint_test.go b/runtimes/google/naming/endpoint_test.go
index 303d3fe..de13f54 100644
--- a/runtimes/google/naming/endpoint_test.go
+++ b/runtimes/google/naming/endpoint_test.go
@@ -10,6 +10,10 @@
)
func TestEndpoint(t *testing.T) {
+ defver := defaultVersion
+ defer func() {
+ defaultVersion = defver
+ }()
v1 := &Endpoint{
Protocol: naming.UnknownProtocol,
Address: "batman.com:1234",
@@ -64,6 +68,25 @@
MaxIPCVersion: 3,
IsMountTable: false,
}
+ v4 := &Endpoint{
+ Protocol: "tcp",
+ Address: "batman.com:2345",
+ RID: naming.FixedRoutingID(0xba77),
+ MinIPCVersion: 4,
+ MaxIPCVersion: 5,
+ IsMountTable: true,
+ Blessings: []string{"dev.v.io/foo@bar.com", "dev.v.io/bar@bar.com/delegate"},
+ }
+ v4b := &Endpoint{
+ Protocol: "tcp",
+ Address: "batman.com:2345",
+ RID: naming.FixedRoutingID(0xba77),
+ MinIPCVersion: 4,
+ MaxIPCVersion: 5,
+ IsMountTable: true,
+ // Blessings that look similar to other parts of the endpoint.
+ Blessings: []string{"@@", "@s", "@m"},
+ }
testcasesA := []struct {
endpoint naming.Endpoint
@@ -80,42 +103,32 @@
}
}
- // Test v3 endpoints.
- defaultVersion = 3
+ // Test v3 & v4 endpoints.
testcasesC := []struct {
Endpoint naming.Endpoint
String string
- Input string
- min, max version.IPCVersion
- servesMT bool
+ Version int
}{
- {v3s, "@3@@batman.com:2345@00000000000000000000000000000000@2@3@s@@", "", 2, 3, false},
- {v3m, "@3@@batman.com:2345@000000000000000000000000dabbad00@2@3@m@@", "", 2, 3, true},
- {v3tcp, "@3@tcp@batman.com:2345@00000000000000000000000000000000@2@3@s@@", "", 2, 3, false},
- {v3ws6, "@3@ws6@batman.com:2345@00000000000000000000000000000000@2@3@s@@", "", 2, 3, false},
+ {v3s, "@3@@batman.com:2345@00000000000000000000000000000000@2@3@s@@", 3},
+ {v3m, "@3@@batman.com:2345@000000000000000000000000dabbad00@2@3@m@@", 3},
+ {v3tcp, "@3@tcp@batman.com:2345@00000000000000000000000000000000@2@3@s@@", 3},
+ {v3ws6, "@3@ws6@batman.com:2345@00000000000000000000000000000000@2@3@s@@", 3},
+ {v3s, "@4@@batman.com:2345@00000000000000000000000000000000@2@3@s@@@", 4},
+ {v4, "@4@tcp@batman.com:2345@0000000000000000000000000000ba77@4@5@m@dev.v.io/foo@bar.com,dev.v.io/bar@bar.com/delegate@@", 4},
+ {v4b, "@4@tcp@batman.com:2345@0000000000000000000000000000ba77@4@5@m@@@,@s,@m@@", 4},
}
for _, test := range testcasesC {
- if got, want := test.Endpoint.String(), test.String; got != want {
- t.Errorf("Got %q want %q for endpoint %T = %#v", got, want, test.Endpoint, test.Endpoint)
+ if got, want := test.Endpoint.VersionedString(test.Version), test.String; got != want {
+ t.Errorf("Got %q want %q for endpoint (v%d): %#v", got, want, test.Version, test.Endpoint)
}
- str := test.Input
- var ep naming.Endpoint
- var err error
- if str == "" {
- str = test.String
- ep, err = NewEndpoint(str)
- } else {
- ep, err = NewEndpoint(naming.FormatEndpoint("tcp", str,
- version.IPCVersionRange{test.min, test.max},
- naming.ServesMountTableOpt(test.servesMT)))
- }
+ ep, err := NewEndpoint(test.String)
if err != nil {
- t.Errorf("Endpoint(%q) failed with %v", str, err)
+ t.Errorf("Endpoint(%q) failed with %v", test.String, err)
continue
}
if !reflect.DeepEqual(ep, test.Endpoint) {
- t.Errorf("Got endpoint %T = %#v, want %T = %#v for string %q", ep, ep, test.Endpoint, test.Endpoint, str)
+ t.Errorf("Got endpoint %#v, want %#v for string %q", ep, test.Endpoint, test.String)
}
}
@@ -156,7 +169,6 @@
t.Errorf("Got endpoint %T = %#v, want %T = %#v for string %q", ep, ep, test.Endpoint, test.Endpoint, str)
}
}
- defaultVersion = 3
}
type endpointTest struct {
@@ -171,7 +183,6 @@
{"@1@@@@@", "@3@@:0@00000000000000000000000000000000@@@m@@", nil},
{"@2@@@@@@@", "@3@@:0@00000000000000000000000000000000@@@m@@", nil},
{"@1@tcp@batman:12@@@", "@3@tcp@batman:12@00000000000000000000000000000000@@@m@@", nil},
- {"@host:10@@", "@3@@host:10@00000000000000000000000000000000@@@m@@", nil},
{"@2@tcp@foo:12@@9@@@", "@3@tcp@foo:12@00000000000000000000000000000000@9@@m@@", nil},
{"@2@tcp@foo:12@@@4@@", "@3@tcp@foo:12@00000000000000000000000000000000@@4@m@@", nil},
{"@2@tcp@foo:12@@2@4@@", "@3@tcp@foo:12@00000000000000000000000000000000@2@4@m@@", nil},
@@ -202,10 +213,18 @@
}
func TestHostPortEndpoint(t *testing.T) {
+ defver := defaultVersion
+ defer func() {
+ defaultVersion = defver
+ }()
+ defaultVersion = 4
testcases := []endpointTest{
- {"localhost:10", "@3@@localhost:10@00000000000000000000000000000000@@@m@@", nil},
- {"localhost:", "@3@@localhost:@00000000000000000000000000000000@@@m@@", nil},
+ {"localhost:10", "@4@@localhost:10@00000000000000000000000000000000@@@m@@@", nil},
+ {"localhost:", "@4@@localhost:@00000000000000000000000000000000@@@m@@@", nil},
{"localhost", "", errInvalidEndpointString},
+ {"dev.v.io/service/mounttabled@ns.dev.v.io:8101", "@4@@ns.dev.v.io:8101@00000000000000000000000000000000@@@m@dev.v.io/service/mounttabled@@", nil},
+ {"dev.v.io/users/foo@bar.com@ns.dev.v.io:8101", "@4@@ns.dev.v.io:8101@00000000000000000000000000000000@@@m@dev.v.io/users/foo@bar.com@@", nil},
+ {"@1@tcp@ns.dev.v.io:8101", "@4@@ns.dev.v.io:8101@00000000000000000000000000000000@@@m@@1@tcp@@", nil},
}
runEndpointTests(t, testcases)
}
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index b61188f..bf0cb04 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -576,7 +576,6 @@
doMount(t, rootCtx, estr, "endpoint", naming.JoinAddressName(estr, "life/on/the/mississippi"), nil, true)
doMount(t, rootCtx, estr, "hostport", "/atrampabroad:8000", nil, true)
- doMount(t, rootCtx, estr, "hostport-endpoint-platypus", "/@atrampabroad:8000@@", nil, true)
doMount(t, rootCtx, estr, "invalid/not/rooted", "atrampabroad:8000", nil, false)
doMount(t, rootCtx, estr, "invalid/no/port", "/atrampabroad", nil, false)
doMount(t, rootCtx, estr, "invalid/endpoint", "/@following the equator:8000@@@", nil, false)