mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-12 17:59:06 +02:00
114 lines
3.8 KiB
Go
114 lines
3.8 KiB
Go
package ipcauth
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
|
|
|
nbproto "github.com/netbirdio/netbird/client/proto"
|
|
)
|
|
|
|
// requestPrototypes returns a zero value of each RPC's request message, keyed by
|
|
// method name.
|
|
func requestPrototypes(t *testing.T) map[string]any {
|
|
t.Helper()
|
|
|
|
sd := nbproto.File_daemon_proto.Services().ByName("DaemonService")
|
|
require.NotNil(t, sd, "DaemonService is missing from the daemon proto descriptor")
|
|
|
|
out := make(map[string]any, sd.Methods().Len())
|
|
for i := 0; i < sd.Methods().Len(); i++ {
|
|
md := sd.Methods().Get(i)
|
|
mt, err := protoregistry.GlobalTypes.FindMessageByName(md.Input().FullName())
|
|
require.NoError(t, err, "request type for %s is not registered", md.Name())
|
|
out[string(md.Name())] = mt.New().Interface()
|
|
}
|
|
return out
|
|
}
|
|
|
|
// Every RPC on DaemonService must carry an explicit policy.
|
|
func TestMethodPoliciesCoverService(t *testing.T) {
|
|
registered := make(map[string]bool, len(methodPolicies))
|
|
for method := range methodPolicies {
|
|
registered[strings.TrimPrefix(method, servicePath)] = true
|
|
}
|
|
|
|
for _, m := range nbproto.DaemonService_ServiceDesc.Methods {
|
|
assert.True(t, registered[m.MethodName],
|
|
"%s has no entry in methodPolicies, add one in methods.go", m.MethodName)
|
|
delete(registered, m.MethodName)
|
|
}
|
|
for _, s := range nbproto.DaemonService_ServiceDesc.Streams {
|
|
assert.True(t, registered[s.StreamName],
|
|
"%s has no entry in methodPolicies, add one in methods.go", s.StreamName)
|
|
delete(registered, s.StreamName)
|
|
}
|
|
|
|
for stale := range registered {
|
|
assert.Fail(t, "stale policy entry",
|
|
"methodPolicies has %s, which DaemonService no longer defines", stale)
|
|
}
|
|
}
|
|
|
|
// A key without the service prefix can never matched.
|
|
func TestMethodPolicyKeysAreFullMethodNames(t *testing.T) {
|
|
for method := range methodPolicies {
|
|
assert.True(t, strings.HasPrefix(method, servicePath),
|
|
"%q is not a full gRPC method name and can never match a request", method)
|
|
}
|
|
}
|
|
|
|
// TargetsProfile promises the request names a profile.
|
|
func TestTargetScopedRequestsExposeATarget(t *testing.T) {
|
|
prototypes := requestPrototypes(t)
|
|
|
|
for method, policy := range methodPolicies {
|
|
if !policy.TargetsProfile {
|
|
continue
|
|
}
|
|
name := strings.TrimPrefix(method, servicePath)
|
|
msg, ok := prototypes[name]
|
|
require.True(t, ok, "%s is marked TargetsProfile but is not a unary method on DaemonService", name)
|
|
|
|
_, named := targetProfile(msg)
|
|
assert.True(t, named,
|
|
"%s is marked TargetsProfile but its request exposes neither GetHandle nor GetProfileName", name)
|
|
}
|
|
}
|
|
|
|
// Ensure that we are not missing request that names a profile.
|
|
func TestRequestsWithATargetAreDeclared(t *testing.T) {
|
|
// AddProfileRequest.ProfileName is the name of the profile to create. It
|
|
// does not exist yet, so there is no owner to authorize against.
|
|
exceptions := map[string]string{
|
|
"AddProfile": "ProfileName names the profile to create, not one to authorize",
|
|
}
|
|
|
|
for name, msg := range requestPrototypes(t) {
|
|
if _, named := targetProfile(msg); !named {
|
|
continue
|
|
}
|
|
policy := methodPolicies[servicePath+name]
|
|
|
|
if reason, excepted := exceptions[name]; excepted {
|
|
assert.False(t, policy.TargetsProfile,
|
|
"%s is listed as an exception (%s) but is marked TargetsProfile", name, reason)
|
|
continue
|
|
}
|
|
assert.True(t, policy.TargetsProfile,
|
|
"%s carries a profile target but is not marked TargetsProfile", name)
|
|
}
|
|
}
|
|
|
|
// The stream interceptor runs before any message is read, so msg is nil and no
|
|
// target can be extracted.
|
|
func TestNoStreamingMethodTargetsProfile(t *testing.T) {
|
|
for _, s := range nbproto.DaemonService_ServiceDesc.Streams {
|
|
assert.False(t, methodPolicies[servicePath+s.StreamName].TargetsProfile,
|
|
"%s is a stream and cannot carry a profile target", s.StreamName)
|
|
}
|
|
}
|