feat: terminal as a chosen OS user, create users from the panel (0.0.2)
- agent reports the OS user it runs as (enroll + poll header) - per-machine terminal user on the edit page; defaults to the agent's own user (root on Linux) - create a new user from the panel: name, password, optional sudo group - show the reason in the terminal when a shell fails to start - bump version to 0.0.2
This commit is contained in:
1 parent
be7fbabd9e
commit
3dde07f403
18 files changed
+530
-45
No files matched your search
+30
-11
@@ -59,6 +59,8 @@ CREATE TABLE IF NOT EXISTS agents (
|
||||
arch TEXT NOT NULL,
|
||||
token_hash TEXT NOT NULL,
|
||||
version TEXT NOT NULL DEFAULT '',
|
||||
run_user TEXT NOT NULL DEFAULT '',
|
||||
login_user TEXT NOT NULL DEFAULT '',
|
||||
enrolled_at INTEGER NOT NULL,
|
||||
last_seen INTEGER NOT NULL
|
||||
);
|
||||
@@ -101,6 +103,8 @@ CREATE TABLE IF NOT EXISTS forward_rules (
|
||||
`ALTER TABLE forward_rules ADD COLUMN proto TEXT NOT NULL DEFAULT 'http'`,
|
||||
`ALTER TABLE agents ADD COLUMN version TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE ufw_rules ADD COLUMN rule_id INTEGER NOT NULL DEFAULT 0`,
|
||||
`ALTER TABLE agents ADD COLUMN run_user TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE agents ADD COLUMN login_user TEXT NOT NULL DEFAULT ''`,
|
||||
} {
|
||||
if _, err := db.sql.Exec(alter); err != nil && !strings.Contains(err.Error(), "duplicate column") {
|
||||
return err
|
||||
@@ -222,9 +226,18 @@ type Agent struct {
|
||||
Arch string
|
||||
TokenHash string
|
||||
Version string
|
||||
RunUser string // OS user the agent process runs as (reported by the agent)
|
||||
LoginUser string // OS user terminals are opened as; "" = RunUser
|
||||
LastSeen time.Time
|
||||
}
|
||||
|
||||
// TerminalUser is the OS user a terminal on this agent runs as. Agents are
|
||||
// installed as a root systemd service, so that is the fallback for agents too
|
||||
// old to report their user.
|
||||
func (a Agent) TerminalUser() string {
|
||||
return firstNonEmpty(a.LoginUser, a.RunUser, "root")
|
||||
}
|
||||
|
||||
// Online reports whether the agent polled recently enough to be considered up.
|
||||
func (a Agent) Online() bool {
|
||||
return time.Since(a.LastSeen) < 45*time.Second
|
||||
@@ -233,9 +246,9 @@ func (a Agent) Online() bool {
|
||||
func (db *DB) CreateAgent(a Agent) error {
|
||||
now := time.Now().Unix()
|
||||
_, err := db.sql.Exec(
|
||||
`INSERT INTO agents(id, name, hostname, os, arch, token_hash, version, enrolled_at, last_seen)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
a.ID, a.Name, a.Hostname, a.OS, a.Arch, a.TokenHash, a.Version, now, now)
|
||||
`INSERT INTO agents(id, name, hostname, os, arch, token_hash, version, run_user, enrolled_at, last_seen)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
a.ID, a.Name, a.Hostname, a.OS, a.Arch, a.TokenHash, a.Version, a.RunUser, now, now)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -243,8 +256,8 @@ func (db *DB) GetAgent(id string) (*Agent, error) {
|
||||
a := &Agent{}
|
||||
var last int64
|
||||
err := db.sql.QueryRow(
|
||||
`SELECT id, name, hostname, os, arch, token_hash, version, last_seen FROM agents WHERE id = ?`, id).
|
||||
Scan(&a.ID, &a.Name, &a.Hostname, &a.OS, &a.Arch, &a.TokenHash, &a.Version, &last)
|
||||
`SELECT id, name, hostname, os, arch, token_hash, version, run_user, login_user, last_seen FROM agents WHERE id = ?`, id).
|
||||
Scan(&a.ID, &a.Name, &a.Hostname, &a.OS, &a.Arch, &a.TokenHash, &a.Version, &a.RunUser, &a.LoginUser, &last)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -257,7 +270,7 @@ func (db *DB) GetAgent(id string) (*Agent, error) {
|
||||
|
||||
func (db *DB) ListAgents() ([]Agent, error) {
|
||||
rows, err := db.sql.Query(
|
||||
`SELECT id, name, hostname, os, arch, version, last_seen FROM agents ORDER BY name`)
|
||||
`SELECT id, name, hostname, os, arch, version, run_user, login_user, last_seen FROM agents ORDER BY name`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -266,7 +279,7 @@ func (db *DB) ListAgents() ([]Agent, error) {
|
||||
for rows.Next() {
|
||||
var a Agent
|
||||
var last int64
|
||||
if err := rows.Scan(&a.ID, &a.Name, &a.Hostname, &a.OS, &a.Arch, &a.Version, &last); err != nil {
|
||||
if err := rows.Scan(&a.ID, &a.Name, &a.Hostname, &a.OS, &a.Arch, &a.Version, &a.RunUser, &a.LoginUser, &last); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.LastSeen = time.Unix(last, 0)
|
||||
@@ -280,10 +293,16 @@ func (db *DB) TouchAgent(id string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TouchAgentVersion updates last_seen and the reported version together.
|
||||
func (db *DB) TouchAgentVersion(id, version string) error {
|
||||
_, err := db.sql.Exec(`UPDATE agents SET last_seen = ?, version = ? WHERE id = ?`,
|
||||
time.Now().Unix(), version, id)
|
||||
// TouchAgentInfo updates last_seen together with the reported version and OS user.
|
||||
func (db *DB) TouchAgentInfo(id, version, runUser string) error {
|
||||
_, err := db.sql.Exec(`UPDATE agents SET last_seen = ?, version = ?, run_user = ? WHERE id = ?`,
|
||||
time.Now().Unix(), version, runUser, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetAgentLoginUser sets the OS user terminals are opened as ("" = the agent's own).
|
||||
func (db *DB) SetAgentLoginUser(id, user string) error {
|
||||
_, err := db.sql.Exec(`UPDATE agents SET login_user = ? WHERE id = ?`, user, id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user