Merge pull request #5052 from dokku/5020-sudo-crontab
Run crontab under sudo to support rhel systems
This commit is contained in:
@@ -1 +1 @@
|
||||
dokku ALL=NOPASSWD:SETENV:/usr/bin/docker,/usr/bin/docker-image-labeler,/usr/bin/pack
|
||||
dokku ALL=NOPASSWD:SETENV:/usr/bin/docker,/usr/bin/docker-image-labeler,/usr/bin/pack,/usr/bin/crontab
|
||||
|
||||
@@ -183,6 +183,10 @@ func SetPermissions(path string, fileMode os.FileMode) error {
|
||||
|
||||
systemGroup := GetenvWithDefault("DOKKU_SYSTEM_GROUP", "dokku")
|
||||
systemUser := GetenvWithDefault("DOKKU_SYSTEM_USER", "dokku")
|
||||
if strings.HasPrefix(path, "/etc/sudoers.d/") {
|
||||
systemGroup = "root"
|
||||
systemUser = "root"
|
||||
}
|
||||
|
||||
group, err := user.LookupGroup(systemGroup)
|
||||
if err != nil {
|
||||
@@ -207,7 +211,20 @@ func SetPermissions(path string, fileMode os.FileMode) error {
|
||||
|
||||
// WriteSliceToFile writes a slice of strings to a file
|
||||
func WriteSliceToFile(filename string, lines []string) error {
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
mode := os.FileMode(0600)
|
||||
if strings.HasPrefix(filename, "/etc/sudoers.d/") {
|
||||
// sudoers files should be either 0600 (rhel) or 0440 (debian)
|
||||
defaultMode := map[string]bool{
|
||||
"centos": true,
|
||||
"fedora": true,
|
||||
"rhel": true,
|
||||
}
|
||||
if !defaultMode[os.Getenv("DOKKU_DISTRO")] {
|
||||
mode = os.FileMode(0440)
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -220,8 +237,8 @@ func WriteSliceToFile(filename string, lines []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
file.Chmod(0600)
|
||||
SetPermissions(filename, 0600)
|
||||
file.Chmod(mode)
|
||||
SetPermissions(filename, mode)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
1
plugins/cron/.gitignore
vendored
1
plugins/cron/.gitignore
vendored
@@ -3,5 +3,6 @@
|
||||
/triggers/*
|
||||
/triggers
|
||||
/cron-*
|
||||
/install
|
||||
/post-*
|
||||
/report
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SUBCOMMANDS = subcommands/list subcommands/report
|
||||
TRIGGERS = triggers/cron-write triggers/post-delete triggers/post-deploy triggers/report
|
||||
TRIGGERS = triggers/cron-write triggers/install triggers/post-delete triggers/post-deploy triggers/report
|
||||
BUILD = commands subcommands triggers
|
||||
PLUGIN_NAME = cron
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ func fetchCronEntries(appName string) ([]templateCommand, error) {
|
||||
}
|
||||
|
||||
func deleteCrontab() error {
|
||||
command := common.NewShellCmd("crontab -l -u dokku")
|
||||
command := common.NewShellCmd("sudo /usr/bin/crontab -l -u dokku")
|
||||
command.ShowOutput = false
|
||||
if !command.Execute() {
|
||||
return nil
|
||||
}
|
||||
|
||||
command = common.NewShellCmd("crontab -r -u dokku")
|
||||
command = common.NewShellCmd("sudo /usr/bin/crontab -r -u dokku")
|
||||
command.ShowOutput = false
|
||||
out, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
@@ -163,7 +163,7 @@ func writeCronEntries() error {
|
||||
return fmt.Errorf("Unable to template out schedule file: %v", err)
|
||||
}
|
||||
|
||||
command := common.NewShellCmd(fmt.Sprintf("crontab -u dokku %s", tmpFile.Name()))
|
||||
command := common.NewShellCmd(fmt.Sprintf("sudo /usr/bin/crontab -u dokku %s", tmpFile.Name()))
|
||||
command.ShowOutput = false
|
||||
out, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
|
||||
@@ -20,6 +20,8 @@ func main() {
|
||||
switch trigger {
|
||||
case "cron-write":
|
||||
err = cron.TriggerCronWrite()
|
||||
case "install":
|
||||
err = cron.TriggerInstall()
|
||||
case "post-delete":
|
||||
err = cron.TriggerPostDelete()
|
||||
case "post-deploy":
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// TriggerInstall installs a sudoers file so we can execute crontab via sudo
|
||||
func TriggerInstall() error {
|
||||
lines := []string{"%dokku ALL=(ALL) NOPASSWD:/usr/bin/crontab"}
|
||||
notty := map[string]bool{
|
||||
"centos": true,
|
||||
"fedora": true,
|
||||
"rhel": true,
|
||||
}
|
||||
if notty[os.Getenv("DOKKU_DISTRO")] {
|
||||
lines = append(lines, "Defaults:dokku !requiretty")
|
||||
}
|
||||
|
||||
return common.WriteSliceToFile("/etc/sudoers.d/dokku-cron", lines)
|
||||
}
|
||||
|
||||
// TriggerPostDelete updates the cron entries for all apps
|
||||
func TriggerPostDelete() error {
|
||||
return writeCronEntries()
|
||||
|
||||
@@ -24,6 +24,7 @@ trigger-nginx-vhosts-install() {
|
||||
NGINX_SUDOERS_FILE="/etc/sudoers.d/dokku-openresty"
|
||||
fi
|
||||
|
||||
local mode="0440"
|
||||
case "$DOKKU_DISTRO" in
|
||||
debian | raspbian)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/sbin/invoke-rc.d $NGINX_INIT_NAME reload, $NGINX_BIN -t, ${NGINX_BIN} -t -c *" >"$NGINX_SUDOERS_FILE"
|
||||
@@ -48,10 +49,11 @@ trigger-nginx-vhosts-install() {
|
||||
centos | fedora | rhel)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:/usr/bin/systemctl reload $NGINX_INIT_NAME, $NGINX_BIN -t, $NGINX_BIN -t -c *" >"$NGINX_SUDOERS_FILE"
|
||||
echo "Defaults:dokku !requiretty" >>"$NGINX_SUDOERS_FILE"
|
||||
mode="0600"
|
||||
;;
|
||||
esac
|
||||
|
||||
chmod 0440 "$NGINX_SUDOERS_FILE"
|
||||
chmod "$mode" "$NGINX_SUDOERS_FILE"
|
||||
|
||||
# if dhparam.pem has not been created, create it the first time
|
||||
if [[ ! -f "$NGINX_ROOT/dhparam.pem" ]]; then
|
||||
|
||||
@@ -10,7 +10,7 @@ trigger-storage-install() {
|
||||
chown dokku:dokku "${storage_directory}"
|
||||
|
||||
STORAGE_SUDOERS_FILE="/etc/sudoers.d/dokku-storage"
|
||||
|
||||
local mode="0440"
|
||||
case "$DOKKU_DISTRO" in
|
||||
arch | debian | opensuse | raspbian | ubuntu)
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:$PLUGIN_AVAILABLE_PATH/storage/bin/chown-storage-dir *" >"$STORAGE_SUDOERS_FILE"
|
||||
@@ -21,9 +21,11 @@ trigger-storage-install() {
|
||||
echo "%dokku ALL=(ALL) NOPASSWD:$PLUGIN_AVAILABLE_PATH/storage/bin/chown-storage-dir *" >"$STORAGE_SUDOERS_FILE"
|
||||
echo "Defaults:dokku !requiretty" >>"$STORAGE_SUDOERS_FILE"
|
||||
echo "Defaults env_keep += \"DOKKU_LIB_ROOT\"" >>"$STORAGE_SUDOERS_FILE"
|
||||
|
||||
mode="0600"
|
||||
;;
|
||||
esac
|
||||
|
||||
chmod "$mode" "$STORAGE_SUDOERS_FILE"
|
||||
}
|
||||
|
||||
trigger-storage-install "$@"
|
||||
|
||||
@@ -37,6 +37,13 @@ teardown() {
|
||||
assert_output "$help_output"
|
||||
}
|
||||
|
||||
@test "(cron) installed" {
|
||||
run /bin/bash -c "test -f /etc/sudoers.d/dokku-cron"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
}
|
||||
|
||||
@test "(cron) invalid [missing-keys]" {
|
||||
run deploy_app python dokku@dokku.me:$TEST_APP template_cron_file_invalid
|
||||
echo "output: $output"
|
||||
|
||||
Reference in New Issue
Block a user