Merge pull request 'Add possibility for priviledge drop' (#13) from priv1 into main

Reviewed-on: https://codeberg.org/grisu48/weblug/pulls/13
This commit is contained in:
Felix Niederwanger 2023-06-06 08:50:57 +00:00
commit cec58caffe
6 changed files with 49 additions and 2 deletions

View file

@ -14,6 +14,8 @@ type Config struct {
type ConfigSettings struct {
BindAddress string `yaml:"bind"` // Bind address for the webserver
UID int `yaml:"uid"` // Custom user ID or 0, if not being used
GID int `yaml:"gid"` // Custom group ID or 0, if not being used
}
func (cf *Config) SetDefaults() {

View file

@ -38,7 +38,11 @@ func awaitTerminationSignal() {
// Perform sanity check on hooks
func sanityCheckHooks(hooks []Hook) error {
uid := os.Getuid()
// Check UID and GID settings. When hooks have their own UID and GID settings, we need the main program to run as root (required for setgid/setuid)
uid := cf.Settings.UID
if uid == 0 {
uid = os.Getuid()
}
for _, hook := range hooks {
// If a hook sets a custom uid or gid, ensure we're running as root, otherwise print a warning
if hook.UID != 0 && uid != 0 {
@ -81,6 +85,20 @@ func main() {
os.Exit(3)
}
// Drop privileges?
if cf.Settings.GID != 0 {
if err := syscall.Setgid(cf.Settings.GID); err != nil {
fmt.Fprintf(os.Stderr, "setgid failed: %s\n", err)
os.Exit(1)
}
}
if cf.Settings.UID != 0 {
if err := syscall.Setuid(cf.Settings.UID); err != nil {
fmt.Fprintf(os.Stderr, "setuid failed: %s\n", err)
os.Exit(1)
}
}
// Create default handlers
http.HandleFunc("/health", createHealthHandler())
http.HandleFunc("/health.json", createHealthHandler())

View file

@ -46,6 +46,10 @@ See the following example configuration file:
.br
.B " bind: ":2088" # bind to all addresses
.br
.B " uid: 0 # run under specified user id
.br
.B " gid: 0 # run under specified group id
.br
.B "# hook definitions. A hook needs to define the HTTP endpoint ("route") and the command
.br
.B "# See the following examples for more possible options.

View file

@ -19,6 +19,7 @@ export SECRET1="top5ecret"
rm -f testfile
../weblug test.yaml &
../weblug test_uid.yaml &
sleep 1
## Check touch webhook, which creates "testfile"
@ -60,7 +61,14 @@ fi
## Check environment variables
timeout 10 curl --fail 'http://127.0.0.1:2088/env'
## Check UID/GID handling
# Ensure weblug is running with UID=65534
pgrep -u 65534 weblug
# Ensure weblug2 (test_uid) is actually running
timeout 10 curl --fail 'http://127.0.0.1:2089/uid'
echo -e "\n\nall good"

11
test/test_uid.yaml Normal file
View file

@ -0,0 +1,11 @@
---
settings:
bind: "127.0.0.1:2089" # bind address for webserver
uid: 65534
gid: 65534
hooks:
- name: 'uid hook'
route: "/uid"
command: "id -u"
output: True

View file

@ -4,6 +4,10 @@
settings:
#bind: "127.0.0.1:2088" # bind address for webserver
bind: ":2088" # bind to all addresses
# Note: Due to current limitations, weblug needs to run as root when you use custom uid,gid settings per webhook
# This is a known issue, see https://codeberg.org/grisu48/weblug/issues/9
uid: 0 # run under specified user id
gid: 0 # run under specified group id
# hook definitions. A hook needs to define the HTTP endpoint ("route") and the command
# See the following examples for more possible options.