9p: numeric uname principal, atomic UID counter
Session uname is now a numeric UID (>=10000) separate from the session name. Rename no longer affects identity — the mount keeps working with the same principal. - SessionStore uses atomic.Uint32 for UID generation - Session.Uname() returns the immutable principal - SessionByUname() lookup for attach-time group assignment - fileOwnerGroup uses principal, not session name - WithMount() passed from createSession
This commit is contained in:
parent
a25dab6ee5
commit
4cf8a666e3
11
server.go
11
server.go
|
|
@ -279,6 +279,8 @@ func New(sink *olog.Sink, opts ...ServerOption) *Server {
|
|||
return storeWrite(s.transcriptStore, name, data)
|
||||
},
|
||||
OnRename: func(oldID, newID string) {
|
||||
s.RemoveGroup("agent", oldID)
|
||||
s.AddGroup("agent", newID)
|
||||
oldPrefix := "/s/" + oldID
|
||||
newPrefix := "/s/" + newID
|
||||
for _, c := range s.conns {
|
||||
|
|
@ -326,15 +328,14 @@ func (s *Server) InGroup(group, user string) bool {
|
|||
}
|
||||
|
||||
// fileOwnerGroup returns the uid and gid for a given path.
|
||||
// Session files are owned by the session ID with group "agent".
|
||||
// Session files are owned by the session's principal with group "agent".
|
||||
// Everything else is owned by "ollie" with group "ollie".
|
||||
func (s *Server) fileOwnerGroup(path string) (uid, gid string) {
|
||||
if strings.HasPrefix(path, "/s/") {
|
||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 2)
|
||||
if len(parts) >= 1 && parts[0] != "new" {
|
||||
// Check if parts[0] is a session (not a script like sh, bfg, etc.)
|
||||
if sess := s.sessionStore.Session(parts[0]); sess != nil {
|
||||
return parts[0], "agent"
|
||||
return sess.Uname(), "agent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -771,9 +772,9 @@ func (s *Server) attach(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
|||
qid := plan9.Qid{Type: QTDir, Path: 0}
|
||||
cs.fids[fc.Fid] = &fid{path: "/", qid: qid}
|
||||
s.log.Debug("Tattach uname=%q", fc.Uname)
|
||||
// Assign group membership based on whether uname is a session ID.
|
||||
// Assign group membership based on whether uname is a session principal.
|
||||
if fc.Uname != "" {
|
||||
if sess := s.sessionStore.Session(fc.Uname); sess != nil {
|
||||
if s.sessionStore.SessionByUname(fc.Uname) != nil {
|
||||
s.AddGroup("agent", fc.Uname)
|
||||
} else {
|
||||
s.AddGroup("user", fc.Uname)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"ollie/pkg/agent"
|
||||
"ollie/pkg/backend"
|
||||
|
|
@ -21,6 +22,7 @@ import (
|
|||
type Session struct {
|
||||
mu sync.RWMutex
|
||||
id string
|
||||
uname string // immutable user principal (numeric UID), set at creation
|
||||
Core agent.Core
|
||||
Ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
|
@ -37,6 +39,7 @@ func NewSession(id string, core agent.Core, ctx context.Context, cancel context.
|
|||
}
|
||||
|
||||
func (sess *Session) RunnableID() string { return sess.id }
|
||||
func (sess *Session) Uname() string { return sess.uname }
|
||||
|
||||
func (sess *Session) Cancel() {
|
||||
sess.cancel()
|
||||
|
|
@ -120,9 +123,15 @@ type SessionStoreConfig struct {
|
|||
// SessionStore implements Store for session management.
|
||||
type SessionStore struct {
|
||||
*storeConfig
|
||||
cfg SessionStoreConfig
|
||||
mu sync.RWMutex
|
||||
sessions map[string]*Session
|
||||
cfg SessionStoreConfig
|
||||
mu sync.RWMutex
|
||||
sessions map[string]*Session
|
||||
nextUID atomic.Uint32 // incrementing principal counter
|
||||
}
|
||||
|
||||
// nextUname generates the next uname atomically.
|
||||
func (s *SessionStore) nextUname() string {
|
||||
return fmt.Sprintf("%d", s.nextUID.Add(1))
|
||||
}
|
||||
|
||||
func NewSessionStore(cfg SessionStoreConfig) *SessionStore {
|
||||
|
|
@ -136,6 +145,7 @@ func NewSessionStore(cfg SessionStoreConfig) *SessionStore {
|
|||
cfg: cfg,
|
||||
sessions: make(map[string]*Session),
|
||||
}
|
||||
ss.nextUID.Store(9999)
|
||||
ss.storeConfig = &storeConfig{
|
||||
StatFn: ss.stat,
|
||||
ListFn: ss.list,
|
||||
|
|
@ -236,6 +246,18 @@ func (s *SessionStore) Session(id string) *Session {
|
|||
return s.sessions[id]
|
||||
}
|
||||
|
||||
// SessionByUname returns the session with the given uname (principal), or nil.
|
||||
func (s *SessionStore) SessionByUname(uname string) *Session {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
for _, sess := range s.sessions {
|
||||
if sess.uname == uname {
|
||||
return sess
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenStore returns a RunnableStore for the given session ID.
|
||||
func (s *SessionStore) OpenStore(id string) (RunnableStore, error) {
|
||||
if sess := s.Session(id); sess != nil {
|
||||
|
|
@ -358,6 +380,7 @@ func (s *SessionStore) createSession(args []string) error {
|
|||
|
||||
var core agent.Core
|
||||
var allowTools []string
|
||||
uname := s.nextUname()
|
||||
if s.cfg.NewCore != nil {
|
||||
var err error
|
||||
core, err = s.cfg.NewCore(sessID, agentName, cwd)
|
||||
|
|
@ -393,6 +416,7 @@ func (s *SessionStore) createSession(args []string) error {
|
|||
}
|
||||
|
||||
var execOpts []execute.Option
|
||||
execOpts = append(execOpts, execute.WithMount())
|
||||
if s.cfg.Strict {
|
||||
execOpts = append(execOpts, execute.WithStrict())
|
||||
}
|
||||
|
|
@ -409,7 +433,7 @@ func (s *SessionStore) createSession(args []string) error {
|
|||
"execute": execute.Decl(cwd, execOpts...),
|
||||
})
|
||||
|
||||
env := agent.BuildAgentEnv(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID})
|
||||
env := agent.BuildAgentEnv(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID, "OLLIE_UNAME=" + uname})
|
||||
|
||||
core = agent.NewAgentCore(agent.AgentCoreConfig{
|
||||
Backend: be,
|
||||
|
|
@ -417,6 +441,7 @@ func (s *SessionStore) createSession(args []string) error {
|
|||
AgentsDir: s.cfg.AgentsDir,
|
||||
SessionsDir: s.cfg.SessionsDir,
|
||||
SessionID: sessID,
|
||||
Uname: uname,
|
||||
CWD: cwd,
|
||||
Env: env,
|
||||
NewDispatcher: newDisp,
|
||||
|
|
@ -429,6 +454,7 @@ func (s *SessionStore) createSession(args []string) error {
|
|||
sess.AllowTools = allowTools
|
||||
|
||||
s.mu.Lock()
|
||||
sess.uname = uname
|
||||
s.sessions[sessID] = sess
|
||||
s.mu.Unlock()
|
||||
|
||||
|
|
|
|||
Reference in New Issue