From 8238e085978d2541e9d274f41cf19a69273f18d6 Mon Sep 17 00:00:00 2001 From: "Theodor S. Midtlien" Date: Mon, 7 Sep 2026 18:20:23 +0200 Subject: [PATCH] Add owners to list profile ipc --- .../internal/profilemanager/profilemanager.go | 2 ++ client/internal/profilemanager/service.go | 25 ++++++++++++------- client/proto/daemon.pb.go | 13 ++++++++-- client/proto/daemon.proto | 1 + 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/client/internal/profilemanager/profilemanager.go b/client/internal/profilemanager/profilemanager.go index d2ed92bc5..b6eb735fa 100644 --- a/client/internal/profilemanager/profilemanager.go +++ b/client/internal/profilemanager/profilemanager.go @@ -8,6 +8,7 @@ import ( "sync" "unicode" + "github.com/netbirdio/netbird/client/internal/ipcauth" log "github.com/sirupsen/logrus" ) @@ -30,6 +31,7 @@ type Profile struct { // loader so callers do not have to reconstruct it from ID + dir. Path string IsActive bool + Owners []ipcauth.Identity } func (p *Profile) FilePath() (string, error) { diff --git a/client/internal/profilemanager/service.go b/client/internal/profilemanager/service.go index 956b6f02c..5c93e9176 100644 --- a/client/internal/profilemanager/service.go +++ b/client/internal/profilemanager/service.go @@ -505,6 +505,8 @@ func (s *ServiceManager) loadAllProfiles(username string) ([]Profile, error) { Name: defaultName, Path: DefaultConfigPath, IsActive: activeIsDefault, + // TODO: determine how to seed default owners + Owners: []ipcauth.Identity{}, }} configDir, err := s.getConfigDir(username) @@ -545,11 +547,17 @@ func (s *ServiceManager) loadAllProfiles(username string) ([]Profile, error) { if name == "" { name = stem.String() } + + owners, err := readProfileOwners(path) + if err != nil { + return nil, err + } fileProfiles = append(fileProfiles, Profile{ ID: stem, Name: name, Path: path, IsActive: stem == ID(activeID), + Owners: owners, }) } @@ -577,29 +585,28 @@ func readProfileName(path string) string { return meta.Name } -// nolint: unused,unusedfunc -func ReadProfileOwner(path string) (ipcauth.Identity, error) { +func readProfileOwners(path string) ([]ipcauth.Identity, error) { data, err := os.ReadFile(path) if err != nil { - return ipcauth.Identity{}, err + return []ipcauth.Identity{}, err } var meta ownerMeta if err := json.Unmarshal(data, &meta); err != nil { - return ipcauth.Identity{}, err + return []ipcauth.Identity{}, err } if len(meta.Owners) < 1 { - return ipcauth.Identity{}, nil + return []ipcauth.Identity{}, nil } owner := meta.Owners[0] principal, ok := ipcauth.ParsePrincipal(owner) if !ok { - return ipcauth.Identity{}, fmt.Errorf("unexpected owner principal: %s", owner) + return []ipcauth.Identity{}, fmt.Errorf("unexpected owner principal: %s", owner) } id, err := ipcauth.IdentityFromPrincipal(principal) if err != nil { - return id, fmt.Errorf("parsing identity from principal failed: %w", err) + return []ipcauth.Identity{id}, fmt.Errorf("parsing identity from principal failed: %w", err) } - return id, nil + return []ipcauth.Identity{id}, nil } // nolint: unused,unusedfunc @@ -612,7 +619,7 @@ func StampOwner(path string, owner ipcauth.Identity) error { if err := json.Unmarshal(data, &cfg); err != nil { return err } - cfg.Owners = append([]string{}, ipcauth.OwnerPrincipalForIdentity(owner)) + cfg.Owners = []string{ipcauth.OwnerPrincipalForIdentity(owner)} if err := util.WriteJson(context.Background(), path, cfg); err != nil { return fmt.Errorf("failed to write profile owner: %w", err) diff --git a/client/proto/daemon.pb.go b/client/proto/daemon.pb.go index 7f3ce1bbf..f59a4c59b 100644 --- a/client/proto/daemon.pb.go +++ b/client/proto/daemon.pb.go @@ -5008,6 +5008,7 @@ type Profile struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` IsActive bool `protobuf:"varint,2,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` Id string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"` + Owners []string `protobuf:"bytes,4,rep,name=owners,proto3" json:"owners,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5063,6 +5064,13 @@ func (x *Profile) GetId() string { return "" } +func (x *Profile) GetOwners() []string { + if x != nil { + return x.Owners + } + return nil +} + type GetActiveProfileRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -7559,11 +7567,12 @@ const file_daemon_proto_rawDesc = "" + "\x13ListProfilesRequest\x12\x1a\n" + "\busername\x18\x01 \x01(\tR\busername\"C\n" + "\x14ListProfilesResponse\x12+\n" + - "\bprofiles\x18\x01 \x03(\v2\x0f.daemon.ProfileR\bprofiles\"J\n" + + "\bprofiles\x18\x01 \x03(\v2\x0f.daemon.ProfileR\bprofiles\"b\n" + "\aProfile\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1b\n" + "\tis_active\x18\x02 \x01(\bR\bisActive\x12\x0e\n" + - "\x02id\x18\x03 \x01(\tR\x02id\"\x19\n" + + "\x02id\x18\x03 \x01(\tR\x02id\x12\x16\n" + + "\x06owners\x18\x04 \x03(\tR\x06owners\"\x19\n" + "\x17GetActiveProfileRequest\"h\n" + "\x18GetActiveProfileResponse\x12 \n" + "\vprofileName\x18\x01 \x01(\tR\vprofileName\x12\x1a\n" + diff --git a/client/proto/daemon.proto b/client/proto/daemon.proto index 3953f9c15..9a9b58147 100644 --- a/client/proto/daemon.proto +++ b/client/proto/daemon.proto @@ -835,6 +835,7 @@ message Profile { string name = 1; bool is_active = 2; string id = 3; + repeated string owners = 4; } message GetActiveProfileRequest {}