Skip to content

Commit

Permalink
avoid sudo when user is root
Browse files Browse the repository at this point in the history
  • Loading branch information
femnad committed Dec 9, 2023
1 parent 22041d3 commit f727f6d
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 36 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Provision
run: |
~/go/bin/fup -f tests/config/test.yml -l 0 -n
~/go/bin/fup -f tests/config/test.yml -l 0 -n -b
- name: Verify
run: |
Expand All @@ -67,8 +67,8 @@ jobs:
- name: Provision
run: |
~/go/bin/fup -f https://raw.githubusercontent.com/femnad/fup/main/tests/config/test-remote.yml -l 0 -n
~/go/bin/fup -f https://raw.githubusercontent.com/femnad/fup/${{ github.ref_name }}/tests/config/test-remote.yml -l 0 -n
- name: Verify
run: |
~/go/bin/fup-verify -c https://raw.githubusercontent.com/femnad/fup/main/tests/config/test-remote.yml -f tests/config/verify-test-remote.yml
~/go/bin/fup-verify -c https://raw.githubusercontent.com/femnad/fup/${{ github.ref_name }}/tests/config/test-remote.yml -f tests/config/verify-test-remote.yml
94 changes: 75 additions & 19 deletions common/filecontent.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,43 @@ type ManagedFile struct {
ValidateCmd string
}

func GetMvCmd(src, dst string) marecmd.Input {
func needsSudoForPath(dst string) (bool, error) {
isRoot, err := IsUserRoot()
if err != nil {
return false, err
}

var sudo bool
if isRoot {
sudo = false
} else {
sudo = !IsHomePath(dst)
}

return sudo, nil
}

func GetMvCmd(src, dst string) (marecmd.Input, error) {
cmd := fmt.Sprintf("mv %s %s", src, dst)
sudo := !IsHomePath(dst)

return marecmd.Input{Command: cmd, Sudo: sudo}
sudo, err := needsSudoForPath(dst)
if err != nil {
return marecmd.Input{}, err
}

return marecmd.Input{Command: cmd, Sudo: sudo}, nil
}

func getChmodCmd(target string, mode int) marecmd.Input {
func getChmodCmd(target string, mode int) (marecmd.Input, error) {
octal := strconv.FormatInt(int64(mode), 8)
cmd := fmt.Sprintf("chmod %s %s", octal, target)
sudo := !IsHomePath(target)

return marecmd.Input{Command: cmd, Sudo: sudo}
sudo, err := needsSudoForPath(target)
if err != nil {
return marecmd.Input{}, err
}

return marecmd.Input{Command: cmd, Sudo: sudo}, nil
}

func Checksum(f string) (string, error) {
Expand All @@ -79,28 +103,34 @@ func Checksum(f string) (string, error) {
}

func getStatSum(f string) (statSum, error) {
var s statSum
isRoot, err := IsUserRoot()
if err != nil {
return s, err
}

cmd := fmt.Sprintf("stat -c %%a %s", f)
out, err := marecmd.RunFormatError(marecmd.Input{Command: cmd, Sudo: true})
out, err := marecmd.RunFormatError(marecmd.Input{Command: cmd, Sudo: !isRoot})
if err != nil {
if strings.HasSuffix(strings.TrimSpace(out.Stderr), statNoExistsError) {
return statSum{}, os.ErrNotExist
return s, os.ErrNotExist
}
return statSum{}, err
return s, err
}

mode, err := strconv.ParseUint(strings.TrimSpace(out.Stdout), 10, 32)
if err != nil {
return statSum{}, err
return s, err
}

out, err = marecmd.RunFormatError(marecmd.Input{Command: fmt.Sprintf("sha256sum %s", f), Sudo: true})
out, err = marecmd.RunFormatError(marecmd.Input{Command: fmt.Sprintf("sha256sum %s", f), Sudo: !isRoot})
if err != nil {
return statSum{}, err
return s, err
}

sumFields := strings.Split(out.Stdout, " ")
if len(sumFields) != 2 {
return statSum{}, fmt.Errorf("unexpected sha256sum output: %s", out.Stdout)
return s, fmt.Errorf("unexpected sha256sum output: %s", out.Stdout)
}
sum := sumFields[0]

Expand Down Expand Up @@ -165,7 +195,12 @@ func chown(file, user, group string) error {
}
chownCmd += " " + file

return marecmd.RunNoOutput(marecmd.Input{Command: chownCmd, Sudo: true})
isRoot, err := IsUserRoot()
if err != nil {
return err
}

return marecmd.RunNoOutput(marecmd.Input{Command: chownCmd, Sudo: !isRoot})
}

func ensureDir(dir string) error {
Expand All @@ -180,7 +215,12 @@ func ensureDir(dir string) error {

internal.Log.Warningf("escalating privileges to create directory %s", dir)
mkdirCmd := fmt.Sprintf("mkdir -p %s", dir)
return marecmd.RunNoOutput(marecmd.Input{Command: mkdirCmd, Sudo: true})

isRoot, err := IsUserRoot()
if err != nil {
return err
}
return marecmd.RunNoOutput(marecmd.Input{Command: mkdirCmd, Sudo: !isRoot})
}

func WriteContent(file ManagedFile) (bool, error) {
Expand Down Expand Up @@ -252,10 +292,14 @@ func WriteContent(file ManagedFile) (bool, error) {
dir, _ := path.Split(target)
err = ensureDir(dir)
if err != nil {
return false, err
return changed, err
}

mv, err := GetMvCmd(srcPath, target)
if err != nil {
return changed, err
}

mv := GetMvCmd(srcPath, target)
err = marecmd.RunNoOutput(mv)
if err != nil {
return changed, err
Expand All @@ -277,15 +321,27 @@ func WriteContent(file ManagedFile) (bool, error) {
}

if currentMode != mode || !dstExists {
chmodCmd := getChmodCmd(target, mode)
chmodCmd, err := getChmodCmd(target, mode)
if err != nil {
return changed, err
}

chmodErr := marecmd.RunNoOutput(chmodCmd)
if chmodErr != nil {
return changed, chmodErr
}
}

if noPermission || !IsHomePath(target) {
_, err = marecmd.RunFormatError(marecmd.Input{Command: fmt.Sprintf("chown %s:%s %s", rootUser, rootUser, target), Sudo: true})
isRoot, err := IsUserRoot()
if err != nil {
return false, err
}

_, err = marecmd.RunFormatError(marecmd.Input{
Command: fmt.Sprintf("chown %s:%s %s", rootUser, rootUser, target),
Sudo: !isRoot,
})
if err != nil {
return changed, err
}
Expand Down
16 changes: 16 additions & 0 deletions common/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package common

import "github.com/femnad/fup/internal"

const (
rootUid = 0
)

func IsUserRoot() (bool, error) {
userId, err := internal.GetCurrentUserId()
if err != nil {
return false, err
}

return userId == rootUid, nil
}
5 changes: 3 additions & 2 deletions packages/apt.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

marecmd "github.com/femnad/mare/cmd"

"github.com/femnad/fup/common"
"github.com/femnad/fup/remote"
)

Expand Down Expand Up @@ -54,7 +55,7 @@ func (Apt) remoteInstall(url string) error {
return err
}

sudo, err := isUserRoot()
sudo, err := common.IsUserRoot()
if err != nil {
return err
}
Expand All @@ -81,7 +82,7 @@ func (Apt) RemoteInstall(urls []string) error {
targets = append(targets, target)
}

sudo, err := isUserRoot()
sudo, err := common.IsUserRoot()
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion packages/dnf.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

"github.com/femnad/fup/common"
marecmd "github.com/femnad/mare/cmd"
)

Expand Down Expand Up @@ -35,7 +36,7 @@ func (Dnf) RemoveCmd() string {
}

func (Dnf) RemoteInstall(urls []string) error {
sudo, err := isUserRoot()
sudo, err := common.IsUserRoot()
if err != nil {
return err
}
Expand Down
11 changes: 1 addition & 10 deletions packages/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,6 @@ type PkgManager interface {
RemoteInstall(urls []string) error
}

func isUserRoot() (bool, error) {
userId, err := internal.GetCurrentUserId()
if err != nil {
return false, err
}

return userId != rootUid, nil
}

type Installer struct {
Pkg PkgManager
Installed mapset.Set[string]
Expand All @@ -54,7 +45,7 @@ func setToSlice[T comparable](set mapset.Set[T]) []T {
}

func (i Installer) maybeRunWithSudo(cmds ...string) error {
sudo, err := isUserRoot()
sudo, err := common.IsUserRoot()
if err != nil {
return err
}
Expand Down
6 changes: 5 additions & 1 deletion provision/ensurelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ func ensureLine(line base.LineInFile) error {
return nil
}

mv := common.GetMvCmd(tmpPath, line.File)
mv, err := common.GetMvCmd(tmpPath, line.File)
if err != nil {
return err
}

out, err := marecmd.RunFormatError(mv)
if err != nil {
return fmt.Errorf("error renaming %s to %s: %v, output %s", tmpPath, line.File, err, out.Stderr)
Expand Down

0 comments on commit f727f6d

Please sign in to comment.