mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 22:37:28 +00:00
feat(pods/admin): root admin alias, default-caps cleanup, pod rebuild script
- auth: add `root` as an admin-console route alias (alongside admin/sysop); still gated by $AGENTBBS_ADMINS — the name confers nothing on its own. - pods: drop the now-redundant tuneApt apt-sandbox hack. Rootless podman keeps its default capability set, so apt/chown/su work without disabling the download sandbox. - scripts/rebuild-pods.sh: recreate all member pods (keeps home volumes) so they pick up the current container profile on next `ssh pod@`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
06bc5631d8
commit
a8cb7e3182
5 changed files with 69 additions and 24 deletions
|
|
@ -43,8 +43,9 @@ var DomainNames = map[string]bool{"domain": true, "domains": true}
|
|||
|
||||
// AdminNames are usernames that route to the privileged admin console (PRD §6).
|
||||
// The route only opens for accounts whose name is in the operator allowlist
|
||||
// (see IsAdmin); the name itself confers nothing.
|
||||
var AdminNames = map[string]bool{"admin": true, "sysop": true}
|
||||
// (see IsAdmin); the name itself confers nothing — so "root" is just a familiar
|
||||
// alias here, not a backdoor.
|
||||
var AdminNames = map[string]bool{"admin": true, "sysop": true, "root": true}
|
||||
|
||||
// TorURLNames route to the one-shot "fetch a URL over Tor" command (premium).
|
||||
var TorURLNames = map[string]bool{"tor-url": true}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package auth
|
|||
import "testing"
|
||||
|
||||
func TestIsAdminName(t *testing.T) {
|
||||
for _, name := range []string{"admin", "ADMIN", "sysop"} {
|
||||
for _, name := range []string{"admin", "ADMIN", "sysop", "root"} {
|
||||
if !IsAdminName(name) {
|
||||
t.Errorf("IsAdminName(%q) = false, want true", name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,6 @@ func (m *Manager) ensure(user string) (string, error) {
|
|||
// Already exists?
|
||||
if err := exec.Command(m.engine, "container", "inspect", name).Run(); err == nil {
|
||||
_ = exec.Command(m.engine, "start", name).Run() // no-op if running
|
||||
m.tuneApt(name)
|
||||
return name, nil
|
||||
}
|
||||
args := []string{
|
||||
|
|
@ -149,28 +148,9 @@ func (m *Manager) ensure(user string) (string, error) {
|
|||
if err != nil {
|
||||
return "", fmt.Errorf("pods: create failed: %v: %s", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
m.tuneApt(name)
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// tuneApt makes apt usable inside the hardened pod. apt drops privileges to
|
||||
// the _apt user for downloads (setgroups/setegid/seteuid), which needs
|
||||
// CAP_SETUID/CAP_SETGID/CAP_CHOWN — caps we intentionally drop (cap-drop ALL).
|
||||
// Rather than re-grant those to the whole container, disable apt's download
|
||||
// sandbox so package management runs as the pod's (rootless-mapped) root.
|
||||
//
|
||||
// Only applies to the podman/container-root path; under docker the pod runs as
|
||||
// uid 1000 and can't write /etc/apt (apt isn't usable there by design). Failure
|
||||
// is non-fatal: a missing config just means the user sees the old apt errors.
|
||||
func (m *Manager) tuneApt(name string) {
|
||||
if m.engine == "docker" {
|
||||
return
|
||||
}
|
||||
_ = exec.Command(m.engine, "exec", "--user", "root", name,
|
||||
"sh", "-c", `printf 'APT::Sandbox::User "root";\n' > /etc/apt/apt.conf.d/00no-sandbox`,
|
||||
).Run()
|
||||
}
|
||||
|
||||
// Attach provisions the pod and wires the SSH session to a shell inside it.
|
||||
// Blocks until the shell exits or the session closes.
|
||||
func (m *Manager) Attach(s ssh.Session, user string) error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue