-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathauthdaemon.go
More file actions
150 lines (130 loc) · 3.88 KB
/
authdaemon.go
File metadata and controls
150 lines (130 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
import (
"context"
"errors"
"fmt"
"os"
"runtime"
"github.com/fosrl/newt/authdaemon"
"github.com/fosrl/newt/logger"
)
const (
defaultPrincipalsPath = "/var/run/auth-daemon/principals"
defaultCACertPath = "/etc/ssh/ca.pem"
)
var (
errPresharedKeyRequired = errors.New("auth-daemon-key is required when --auth-daemon is enabled")
errRootRequired = errors.New("auth-daemon must be run as root (use sudo)")
authDaemonServer *authdaemon.Server // Global auth daemon server instance
)
// startAuthDaemon initializes and starts the auth daemon in the background.
// It validates requirements (Linux, root, preshared key) and starts the server
// in a goroutine so it runs alongside normal newt operation.
func startAuthDaemon(ctx context.Context) error {
// Validation
if runtime.GOOS != "linux" {
return fmt.Errorf("auth-daemon is only supported on Linux, not %s", runtime.GOOS)
}
if os.Geteuid() != 0 {
return errRootRequired
}
// Use defaults if not set
principalsFile := authDaemonPrincipalsFile
if principalsFile == "" {
principalsFile = defaultPrincipalsPath
}
caCertPath := authDaemonCACertPath
if caCertPath == "" {
caCertPath = defaultCACertPath
}
// Create auth daemon server
cfg := authdaemon.Config{
DisableHTTPS: true, // We run without HTTP server in newt
PresharedKey: "this-key-is-not-used", // Not used in embedded mode, but set to non-empty to satisfy validation
PrincipalsFilePath: principalsFile,
CACertPath: caCertPath,
Force: true,
GenerateRandomPassword: authDaemonGenerateRandomPassword,
}
srv, err := authdaemon.NewServer(cfg)
if err != nil {
return fmt.Errorf("create auth daemon server: %w", err)
}
authDaemonServer = srv
// Start the auth daemon in a goroutine so it runs alongside newt
go func() {
logger.Info("Auth daemon starting (native mode, no HTTP server)")
if err := srv.Run(ctx); err != nil {
logger.Error("Auth daemon error: %v", err)
}
logger.Info("Auth daemon stopped")
}()
return nil
}
// runPrincipalsCmd executes the principals subcommand logic
func runPrincipalsCmd(args []string) {
opts := struct {
PrincipalsFile string
Username string
}{
PrincipalsFile: defaultPrincipalsPath,
}
// Parse flags manually
for i := 0; i < len(args); i++ {
switch args[i] {
case "--principals-file":
if i+1 >= len(args) {
fmt.Fprintf(os.Stderr, "Error: --principals-file requires a value\n")
os.Exit(1)
}
opts.PrincipalsFile = args[i+1]
i++
case "--username":
if i+1 >= len(args) {
fmt.Fprintf(os.Stderr, "Error: --username requires a value\n")
os.Exit(1)
}
opts.Username = args[i+1]
i++
case "--help", "-h":
printPrincipalsHelp()
os.Exit(0)
default:
fmt.Fprintf(os.Stderr, "Error: unknown flag: %s\n", args[i])
printPrincipalsHelp()
os.Exit(1)
}
}
// Validation
if opts.Username == "" {
fmt.Fprintf(os.Stderr, "Error: username is required\n")
printPrincipalsHelp()
os.Exit(1)
}
// Get principals
list, err := authdaemon.GetPrincipals(opts.PrincipalsFile, opts.Username)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if len(list) == 0 {
fmt.Println("")
return
}
for _, principal := range list {
fmt.Println(principal)
}
}
func printPrincipalsHelp() {
fmt.Fprintf(os.Stderr, `Usage: newt principals [flags]
Output principals for a username (for AuthorizedPrincipalsCommand in sshd_config).
Read the principals file and print principals that match the given username, one per line.
Configure in sshd_config with AuthorizedPrincipalsCommand and %%u for the username.
Flags:
--principals-file string Path to the principals file (default "%s")
--username string Username to look up (required)
--help, -h Show this help message
Example:
newt principals --username alice
`, defaultPrincipalsPath)
}