Fix up comments and improve readability

This commit is contained in:
Theodor S. Midtlien
2026-07-25 20:51:29 +02:00
parent 11642aeb44
commit bbf326e22c
6 changed files with 105 additions and 35 deletions

View File

@@ -305,10 +305,23 @@ func (s *Server) authorizeTargetProfile(ctx context.Context, target *profilemana
return nil
}
// AddOwner adds a principal to the daemon-wide owner set. The interceptor has
// already confirmed the caller is an owner or privileged, the handler just
// validates and persists.
func (s *Server) AddOwner(_ context.Context, msg *proto.AddOwnerRequest) (*proto.AddOwnerResponse, error) {
// requireDaemonOwnerLocked fails closed unless the caller is a daemon owner or
// privileged. Defense in depth for the owner-set mutations, which the interceptor
// owner tier already gates. Caller must hold s.mutex.
func (s *Server) requireDaemonOwnerLocked(ctx context.Context) error {
id, ok := ipcauth.IdentityFromContext(ctx)
if !ok {
return gstatus.Error(codes.PermissionDenied, "caller identity could not be verified")
}
if id.IsPrivileged() || ipcauth.Authorize(s.owners, id, s.groupResolver) {
return nil
}
return gstatus.Error(codes.PermissionDenied, "not authorized: managing daemon owners requires a daemon owner or root/administrator")
}
// AddOwner adds a principal to the daemon-wide owner set. The owner tier gates
// this, the handler re-checks (defense in depth), validates, and persists.
func (s *Server) AddOwner(ctx context.Context, msg *proto.AddOwnerRequest) (*proto.AddOwnerResponse, error) {
principal := msg.GetPrincipal()
if _, ok := ipcauth.ParsePrincipal(principal); !ok {
return nil, gstatus.Errorf(codes.InvalidArgument, "invalid owner principal %q (expected uid:/gid:/group:/sid:)", principal)
@@ -317,6 +330,9 @@ func (s *Server) AddOwner(_ context.Context, msg *proto.AddOwnerRequest) (*proto
s.mutex.Lock()
defer s.mutex.Unlock()
if err := s.requireDaemonOwnerLocked(ctx); err != nil {
return nil, err
}
if s.daemonOwnerStore == nil {
return nil, gstatus.Error(codes.Unavailable, "daemon owner store unavailable")
}
@@ -356,12 +372,15 @@ func (s *Server) ResetOwner(ctx context.Context, _ *proto.ResetOwnerRequest) (*p
}
// ShareProfile marks the daemon shared or unshared. When shared, any authenticated
// local caller may control the daemon and its default profile. The interceptor has
// already confirmed the caller is an owner or privileged.
func (s *Server) ShareProfile(_ context.Context, msg *proto.ShareProfileRequest) (*proto.ShareProfileResponse, error) {
// local caller may control the daemon and its default profile. The owner tier
// gates this, the handler re-checks (defense in depth).
func (s *Server) ShareProfile(ctx context.Context, msg *proto.ShareProfileRequest) (*proto.ShareProfileResponse, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
if err := s.requireDaemonOwnerLocked(ctx); err != nil {
return nil, err
}
if s.daemonOwnerStore == nil {
return nil, gstatus.Error(codes.Unavailable, "daemon owner store unavailable")
}

View File

@@ -71,8 +71,9 @@ func TestDaemonOwnerPolicyDefaultProfile(t *testing.T) {
require.NoError(t, err)
assert.False(t, claimed)
// AddOwner appends a daemon-wide principal (persisted).
_, err = s.AddOwner(context.Background(), &proto.AddOwnerRequest{Principal: "uid:1001"})
// AddOwner appends a daemon-wide principal (persisted). The caller must be a
// daemon owner: uid:1000 claimed ownership above.
_, err = s.AddOwner(ctxWithIdentity(ipcauth.Identity{UID: 1000}), &proto.AddOwnerRequest{Principal: "uid:1001"})
require.NoError(t, err)
assert.Equal(t, []string{"uid:1000", "uid:1001"}, store.owners)
@@ -83,6 +84,42 @@ func TestDaemonOwnerPolicyDefaultProfile(t *testing.T) {
assert.False(t, store.shared)
}
// TestOwnerMutationsRequireDaemonOwner checks the handler defense-in-depth: a
// caller who is neither a daemon owner nor privileged is denied at the handler.
func TestOwnerMutationsRequireDaemonOwner(t *testing.T) {
store := &fakeOwnerStore{owners: []string{"uid:1000"}}
s := &Server{groupResolver: ipcauth.NewDefaultGroupResolver()}
s.SetDaemonOwnerStore(store) // loads {uid:1000} into s.owners
owner := ctxWithIdentity(ipcauth.Identity{UID: 1000})
nonOwner := ctxWithIdentity(ipcauth.Identity{UID: 2000})
root := ctxWithIdentity(ipcauth.Identity{UID: 0})
t.Run("AddOwner denied for non-daemon-owner", func(t *testing.T) {
_, err := s.AddOwner(nonOwner, &proto.AddOwnerRequest{Principal: "uid:2000"})
assert.Equal(t, codes.PermissionDenied, gstatus.Code(err))
assert.Equal(t, []string{"uid:1000"}, store.owners, "owner set must be unchanged")
})
t.Run("ShareProfile denied for non-daemon-owner", func(t *testing.T) {
_, err := s.ShareProfile(nonOwner, &proto.ShareProfileRequest{Shared: true})
assert.Equal(t, codes.PermissionDenied, gstatus.Code(err))
assert.False(t, store.shared, "shared flag must be unchanged")
})
t.Run("AddOwner allowed for daemon owner", func(t *testing.T) {
_, err := s.AddOwner(owner, &proto.AddOwnerRequest{Principal: "uid:2000"})
require.NoError(t, err)
assert.Equal(t, []string{"uid:1000", "uid:2000"}, store.owners)
})
t.Run("ShareProfile allowed for root", func(t *testing.T) {
_, err := s.ShareProfile(root, &proto.ShareProfileRequest{Shared: true})
require.NoError(t, err)
assert.True(t, store.shared)
})
}
// TestDaemonOwnerAllOwnersUseDefault verifies every daemon owner is authorized
// for the default profile, while a non-owner is denied.
func TestDaemonOwnerAllOwnersUseDefault(t *testing.T) {