mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-27 23:09:08 +01:00
Refactor gatePolicy to gateRule
This commit is contained in:
@@ -46,7 +46,7 @@ type program struct {
|
|||||||
jsonServMu sync.Mutex
|
jsonServMu sync.Mutex
|
||||||
serverInstance *server.Server
|
serverInstance *server.Server
|
||||||
serverInstanceMu sync.Mutex
|
serverInstanceMu sync.Mutex
|
||||||
policyGate *ipcauth.PolicyGate
|
ruleGate *ipcauth.RuleGate
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -80,12 +80,12 @@ func (p *program) Start(svc service.Service) error {
|
|||||||
return fmt.Errorf("parse daemon address: %w", err)
|
return fmt.Errorf("parse daemon address: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.policyGate = ipcauth.NewPolicyGate()
|
p.ruleGate = ipcauth.NewRuleGate()
|
||||||
|
|
||||||
// in any case, even if configuration does not exists we run daemon to serve CLI gRPC API.
|
// in any case, even if configuration does not exists we run daemon to serve CLI gRPC API.
|
||||||
opts := append(daemonServerOptions(network),
|
opts := append(daemonServerOptions(network),
|
||||||
grpc.ChainUnaryInterceptor(p.policyGate.UnaryPolicyInterceptor()),
|
grpc.ChainUnaryInterceptor(p.ruleGate.UnaryPolicyInterceptor()),
|
||||||
grpc.ChainStreamInterceptor(p.policyGate.StreamPolicyInterceptor()),
|
grpc.ChainStreamInterceptor(p.ruleGate.StreamPolicyInterceptor()),
|
||||||
)
|
)
|
||||||
p.serv = grpc.NewServer(opts...)
|
p.serv = grpc.NewServer(opts...)
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ func (p *program) serve(daemonListener, jsonListener *socketListener) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverInstance := server.New(p.ctx, util.FindFirstLogPath(logFiles), configPath, profilesDisabled, updateSettingsDisabled, captureEnabled, networksDisabled)
|
serverInstance := server.New(p.ctx, util.FindFirstLogPath(logFiles), configPath, profilesDisabled, updateSettingsDisabled, captureEnabled, networksDisabled)
|
||||||
p.policyGate.SetPolicy(serverInstance)
|
p.ruleGate.SetState(serverInstance)
|
||||||
if err := serverInstance.Start(); err != nil {
|
if err := serverInstance.Start(); err != nil {
|
||||||
return fmt.Errorf("start daemon: %w", err)
|
return fmt.Errorf("start daemon: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,70 +10,78 @@ import (
|
|||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Policy interface {
|
type DaemonState interface {
|
||||||
SessionHolder() (Identity, bool)
|
SessionHolder() (Identity, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PolicyGate struct {
|
type Rule func(id Identity, st DaemonState) error
|
||||||
mu sync.Mutex
|
|
||||||
policy Policy
|
type RuleGate struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
rules []Rule
|
||||||
|
st DaemonState
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPolicyGate() *PolicyGate {
|
func NewRuleGate() *RuleGate {
|
||||||
return &PolicyGate{}
|
return &RuleGate{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *PolicyGate) SetPolicy(p Policy) {
|
func (g *RuleGate) SetState(st DaemonState) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
defer g.mu.Unlock()
|
||||||
g.policy = p
|
g.st = st
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *PolicyGate) SessionHolder() (Identity, bool) {
|
func (g *RuleGate) SetRule(r Rule) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
defer g.mu.Unlock()
|
||||||
if g.policy == nil {
|
g.rules = append(g.rules, r)
|
||||||
return Identity{}, false
|
}
|
||||||
|
|
||||||
|
func (g *RuleGate) state() DaemonState {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
return g.st
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequireSessionHolder(id Identity, st DaemonState) error {
|
||||||
|
holder, running := st.SessionHolder()
|
||||||
|
log.Debugf("id : %v, session holder: %v", id, holder)
|
||||||
|
if !running || holder.SameUser(id) || holder.IsPrivileged() {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return g.policy.SessionHolder()
|
return status.Errorf(codes.PermissionDenied, "session is held by another user (%v)", holder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *PolicyGate) StreamPolicyInterceptor() grpc.StreamServerInterceptor {
|
func (g *RuleGate) StreamPolicyInterceptor() grpc.StreamServerInterceptor {
|
||||||
return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||||
if !g.authorize(ss.Context()) {
|
if authErr := g.authorize(ss.Context()); authErr != nil {
|
||||||
return status.Error(codes.PermissionDenied, "caller is not session owner")
|
return authErr
|
||||||
}
|
}
|
||||||
return handler(ss.Context(), ss)
|
return handler(ss.Context(), ss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *PolicyGate) UnaryPolicyInterceptor() grpc.UnaryServerInterceptor {
|
func (g *RuleGate) UnaryPolicyInterceptor() grpc.UnaryServerInterceptor {
|
||||||
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
|
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
|
||||||
if !g.authorize(ctx) {
|
if authErr := g.authorize(ctx); authErr != nil {
|
||||||
return nil, status.Error(codes.PermissionDenied, "caller is not session owner")
|
return nil, authErr
|
||||||
}
|
}
|
||||||
return handler(ctx, req)
|
return handler(ctx, req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *PolicyGate) authorize(ctx context.Context) bool {
|
func (g *RuleGate) authorize(ctx context.Context) error {
|
||||||
id, ok := CallerIdentity(ctx)
|
id, ok := CallerIdentity(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return status.Error(codes.PermissionDenied, "caller cannot be verified")
|
||||||
}
|
}
|
||||||
g.mu.Lock()
|
state := g.state()
|
||||||
if g.policy == nil {
|
for _, rule := range g.rules {
|
||||||
g.mu.Unlock()
|
ruleErr := rule(id, state)
|
||||||
return false
|
if ruleErr != nil {
|
||||||
|
return ruleErr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sessionId, running := g.policy.SessionHolder()
|
return nil
|
||||||
// TODO improve logging
|
|
||||||
log.Infof("id : %v, session holder: %v", id, sessionId)
|
|
||||||
g.mu.Unlock()
|
|
||||||
// TODO windows
|
|
||||||
// TODO allow root
|
|
||||||
if running && sessionId.UID != id.UID {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import (
|
|||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/internal"
|
"github.com/netbirdio/netbird/client/internal"
|
||||||
"github.com/netbirdio/netbird/client/internal/ipcauth"
|
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||||
"github.com/netbirdio/netbird/client/internal/updater"
|
"github.com/netbirdio/netbird/client/internal/updater"
|
||||||
|
|||||||
Reference in New Issue
Block a user