Add possibility for priviledge drop
Adds the `uid` and `gid` settings in the main configuration file, which allows weblug to run under a unprivileged user account. This comes with the limitation, that unless the program runs as root, custom webhook `uid/gid` settings are not possible.
This commit is contained in:
parent
1bdcbd7904
commit
121ab40b02
|
@ -14,6 +14,8 @@ type Config struct {
|
||||||
|
|
||||||
type ConfigSettings struct {
|
type ConfigSettings struct {
|
||||||
BindAddress string `yaml:"bind"` // Bind address for the webserver
|
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() {
|
func (cf *Config) SetDefaults() {
|
||||||
|
|
|
@ -38,7 +38,11 @@ func awaitTerminationSignal() {
|
||||||
|
|
||||||
// Perform sanity check on hooks
|
// Perform sanity check on hooks
|
||||||
func sanityCheckHooks(hooks []Hook) error {
|
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 {
|
for _, hook := range hooks {
|
||||||
// If a hook sets a custom uid or gid, ensure we're running as root, otherwise print a warning
|
// 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 {
|
if hook.UID != 0 && uid != 0 {
|
||||||
|
@ -81,6 +85,20 @@ func main() {
|
||||||
os.Exit(3)
|
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
|
// Create default handlers
|
||||||
http.HandleFunc("/health", createHealthHandler())
|
http.HandleFunc("/health", createHealthHandler())
|
||||||
http.HandleFunc("/health.json", createHealthHandler())
|
http.HandleFunc("/health.json", createHealthHandler())
|
||||||
|
|
|
@ -46,6 +46,10 @@ See the following example configuration file:
|
||||||
.br
|
.br
|
||||||
.B " bind: ":2088" # bind to all addresses
|
.B " bind: ":2088" # bind to all addresses
|
||||||
.br
|
.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
|
.B "# hook definitions. A hook needs to define the HTTP endpoint ("route") and the command
|
||||||
.br
|
.br
|
||||||
.B "# See the following examples for more possible options.
|
.B "# See the following examples for more possible options.
|
||||||
|
|
|
@ -19,6 +19,7 @@ export SECRET1="top5ecret"
|
||||||
|
|
||||||
rm -f testfile
|
rm -f testfile
|
||||||
../weblug test.yaml &
|
../weblug test.yaml &
|
||||||
|
../weblug test_uid.yaml &
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
## Check touch webhook, which creates "testfile"
|
## Check touch webhook, which creates "testfile"
|
||||||
|
@ -60,7 +61,14 @@ fi
|
||||||
|
|
||||||
## Check environment variables
|
## Check environment variables
|
||||||
|
|
||||||
|
|
||||||
timeout 10 curl --fail 'http://127.0.0.1:2088/env'
|
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"
|
echo -e "\n\nall good"
|
||||||
|
|
11
test/test_uid.yaml
Normal file
11
test/test_uid.yaml
Normal 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
|
|
@ -4,6 +4,10 @@
|
||||||
settings:
|
settings:
|
||||||
#bind: "127.0.0.1:2088" # bind address for webserver
|
#bind: "127.0.0.1:2088" # bind address for webserver
|
||||||
bind: ":2088" # bind to all addresses
|
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
|
# hook definitions. A hook needs to define the HTTP endpoint ("route") and the command
|
||||||
# See the following examples for more possible options.
|
# See the following examples for more possible options.
|
||||||
|
|
Loading…
Reference in a new issue