Merge "veyron/runtimes/google/naming: Bugfix in error propagation and test setup."
diff --git a/lib/flags/doc.go b/lib/flags/doc.go
index 8681ac4..ff98c9d 100644
--- a/lib/flags/doc.go
+++ b/lib/flags/doc.go
@@ -1,3 +1,36 @@
-// Package flags provides implementations of the flag.Value interface
-// that are commonly used.
+// Package flags provides flag definitions for commonly used flags and
+// and, where appropriate, implementations of the flag.Value interface
+// for those flags to ensure that only valid values of those flags
+// are supplied.
+// In general, this package will be used by veyron profiles and the
+// runtime implementations, but can also be used by any application
+// that wants access to the flags and environment variables it supports.
+//
+// TODO(cnicolaou): move reading of environment variables to here also,
+// flags will override the environment variable settings.
package flags
+
+import "flag"
+
+type Flags struct {
+ ListenProtocolFlag TCPProtocolFlag
+ ListenAddressFlag IPHostPortFlag
+ ListenProxyFlag string
+ NamespaceRootsFlag string // TODO(cnicolaou): provide flag.Value impl
+ CredentialsFlag string // TODO(cnicolaou): provide flag.Value impl
+}
+
+// New returns a new instance of flags.Flags. Calling Parse on the supplied
+// flagSet will populate the fields of the return flags.Flags with the appropriate
+// values.
+func New(fs *flag.FlagSet) *Flags {
+ t := &Flags{}
+ t.ListenProtocolFlag = TCPProtocolFlag{"tcp"}
+ t.ListenAddressFlag = IPHostPortFlag{Port: "0"}
+ fs.Var(&t.ListenProtocolFlag, "veyron.tcp.protocol", "protocol to listen with")
+ fs.Var(&t.ListenAddressFlag, "veyron.tcp.address", "address to listen on")
+ fs.StringVar(&t.ListenProxyFlag, "veyron.proxy", "", "object name of proxy service to use to export services across network boundaries")
+ fs.StringVar(&t.NamespaceRootsFlag, "veyron.namespace.roots", "", ": separated list of roots for the local namespace")
+ fs.StringVar(&t.CredentialsFlag, "veyron.credentials", "", "directory to use for storing security credentials")
+ return t
+}
diff --git a/lib/flags/flags_test.go b/lib/flags/flags_test.go
new file mode 100644
index 0000000..4030af6
--- /dev/null
+++ b/lib/flags/flags_test.go
@@ -0,0 +1,24 @@
+package flags_test
+
+import (
+ "flag"
+ "testing"
+
+ "veyron.io/veyron/veyron/lib/flags"
+)
+
+func TestFlags(t *testing.T) {
+ fs := flag.NewFlagSet("test", flag.ContinueOnError)
+ fl := flags.New(fs)
+
+ addr := "192.168.10.1:0"
+ roots := "ab:cd:ef"
+ args := []string{"--veyron.tcp.address=" + addr, "--veyron.namespace.roots=" + roots}
+ fs.Parse(args)
+ if got, want := fl.NamespaceRootsFlag, roots; got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ if got, want := fl.ListenAddressFlag.String(), addr; got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
+}
diff --git a/profiles/roaming/roaming.go b/profiles/roaming/roaming.go
index d9314bb..2f9381f 100644
--- a/profiles/roaming/roaming.go
+++ b/profiles/roaming/roaming.go
@@ -30,19 +30,14 @@
)
var (
- listenProtocolFlag = flags.TCPProtocolFlag{"tcp"}
- listenAddressFlag = flags.IPHostPortFlag{Port: "0"}
- listenProxyFlag string
-
+ commonFlags *flags.Flags
// ListenSpec is an initialized instance of ipc.ListenSpec that can
// be used with ipc.Listen.
ListenSpec ipc.ListenSpec
)
func init() {
- flag.Var(&listenProtocolFlag, "veyron.tcp.protocol", "protocol to listen with")
- flag.Var(&listenAddressFlag, "veyron.tcp.address", "address to listen on")
- flag.StringVar(&listenProxyFlag, "veyron.proxy", "", "object name of proxy service to use to export services across network boundaries")
+ commonFlags = flags.New(flag.CommandLine)
rt.RegisterProfile(New())
}
@@ -75,9 +70,9 @@
log := rt.Logger()
ListenSpec = ipc.ListenSpec{
- Protocol: listenProtocolFlag.Protocol,
- Address: listenAddressFlag.String(),
- Proxy: listenProxyFlag,
+ Protocol: commonFlags.ListenProtocolFlag.Protocol,
+ Address: commonFlags.ListenAddressFlag.String(),
+ Proxy: commonFlags.ListenProxyFlag,
}
// Our address is private, so we test for running on GCE and for its
diff --git a/profiles/static/static.go b/profiles/static/static.go
index 960f347..4997720 100644
--- a/profiles/static/static.go
+++ b/profiles/static/static.go
@@ -18,19 +18,14 @@
)
var (
- listenProtocolFlag = flags.TCPProtocolFlag{"tcp"}
- listenAddressFlag = flags.IPHostPortFlag{Port: "0"}
- listenProxyFlag string
-
+ commonFlags *flags.Flags
// ListenSpec is an initialized instance of ipc.ListenSpec that can
// be used with ipc.Listen.
ListenSpec ipc.ListenSpec
)
func init() {
- flag.Var(&listenProtocolFlag, "veyron.tcp.protocol", "protocol to listen with")
- flag.Var(&listenAddressFlag, "veyron.tcp.address", "address to listen on")
- flag.StringVar(&listenProxyFlag, "veyron.proxy", "", "object name of proxy service to use to export services across network boundaries")
+ commonFlags = flags.New(flag.CommandLine)
rt.RegisterProfile(New())
}
@@ -61,9 +56,9 @@
log := rt.Logger()
ListenSpec = ipc.ListenSpec{
- Protocol: listenProtocolFlag.Protocol,
- Address: listenAddressFlag.String(),
- Proxy: listenProxyFlag,
+ Protocol: commonFlags.ListenProtocolFlag.Protocol,
+ Address: commonFlags.ListenAddressFlag.String(),
+ Proxy: commonFlags.ListenProxyFlag,
}
// Our address is private, so we test for running on GCE and for its
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index a0d207d..514377f 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -37,10 +37,6 @@
errServerStopped = verror.Abortedf("ipc: server is stopped")
)
-func errNotAuthorized(err error) verror.E {
- return verror.NoAccessf("ipc: not authorized(%v)", err)
-}
-
type server struct {
sync.Mutex
ctx context.T // context used by the server to make internal RPCs.
@@ -850,21 +846,20 @@
}
if remoteID := fs.flow.RemoteID(); remoteID != nil {
// TODO(ashankar): This whole check goes away once the old security model is ripped out.
- if fs.authorizedRemoteID, err = remoteID.Authorize(isecurity.NewContext(
- isecurity.ContextArgs{
- LocalID: fs.flow.LocalID(),
- RemoteID: fs.flow.RemoteID(),
- Method: fs.method,
- Suffix: fs.suffix,
- Discharges: fs.discharges,
- Label: fs.label})); err != nil {
- return nil, errNotAuthorized(err)
+ if fs.authorizedRemoteID, err = remoteID.Authorize(isecurity.NewContext(isecurity.ContextArgs{
+ LocalID: fs.flow.LocalID(),
+ RemoteID: fs.flow.RemoteID(),
+ Method: fs.method,
+ Suffix: fs.suffix,
+ Discharges: fs.discharges,
+ Label: fs.label,
+ })); err != nil {
+ return nil, verror.NoAccessf("%v is not authorized to call %q.%q (%v)", fs.RemoteID(), fs.Name(), fs.Method(), err)
}
}
// Check application's authorization policy and invoke the method.
if err := fs.authorize(auth); err != nil {
- // TODO(ataly, ashankar): For privacy reasons, should we hide the authorizer error (err)?
- return nil, errNotAuthorized(fmt.Errorf("%v (PublicID:%v) not authorized for %q.%q: %v", fs.RemoteBlessings(), fs.RemoteID(), fs.Name(), fs.Method(), err))
+ return nil, err
}
// Check if the caller is permitted to view debug information.
fs.allowDebug = fs.authorizeForDebug(auth) == nil
@@ -955,7 +950,7 @@
return verror.Makef(verror.ErrorID(err), "%s", err)
}
if err := i.fs.authorize(auth); err != nil {
- return errNotAuthorized(fmt.Errorf("%q not authorized for method %q: %v", i.fs.RemoteID(), i.fs.Method(), err))
+ return err
}
leafCall := &localServerCall{call, prefix}
argptrs[0] = &pattern
@@ -997,11 +992,18 @@
return c.ServerCall.Send(me)
}
-func (fs *flowServer) authorize(auth security.Authorizer) error {
+func (fs *flowServer) authorize(auth security.Authorizer) verror.E {
if auth == nil {
auth = defaultAuthorizer(fs)
}
- return auth.Authorize(fs)
+ if err := auth.Authorize(fs); err != nil {
+ // TODO(ataly, ashankar): For privacy reasons, should we hide the authorizer error?
+ if fs.RemoteBlessings() != nil {
+ return verror.NoAccessf("ipc: %v not authorized to call %q.%q (%v)", fs.RemoteBlessings(), fs.Name(), fs.Method(), err)
+ }
+ return verror.NoAccessf("ipc: %v (deprecated security model) is not authorized to call %q.%q (%v)", fs.RemoteID(), fs.Name(), fs.Method(), err)
+ }
+ return nil
}
// debugContext is a context which wraps another context but always returns