Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -272,5 +272,5 @@
}
]
},
"generated_at": "2025-07-09T20:27:15Z"
"generated_at": "2025-07-31T17:26:46Z"
}
1 change: 1 addition & 0 deletions changes/20250731182237.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:bug: `[platform]` make sure command with privileges are run when passwords are not needed
1 change: 1 addition & 0 deletions changes/20250731182404.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:bug: `[filesystem]` make sure to unlink files when removal is called so that sockets are correctly closed
13 changes: 13 additions & 0 deletions utils/filesystem/extendedosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ package filesystem
import (
"context"
"os"
"syscall"

"github.com/spf13/afero"

"github.com/ARM-software/golang-utils/utils/commonerrors"
"github.com/ARM-software/golang-utils/utils/platform"
)

Expand All @@ -19,6 +21,17 @@ type ExtendedOsFs struct {
afero.OsFs
}

func (c *ExtendedOsFs) Remove(name string) (err error) {
err = commonerrors.Ignore(ConvertFileSystemError(c.OsFs.Remove(name)), commonerrors.ErrNotFound)
if err != nil {
return
}
// The following is to ensure sockets are correctly removed
// https://stackoverflow.com/questions/16681944/how-to-reliably-unlink-a-unix-domain-socket-in-go-programming-language
err = commonerrors.Ignore(ConvertFileSystemError(syscall.Unlink(name)), commonerrors.ErrNotFound)
return
}

func (c *ExtendedOsFs) ChownIfPossible(name string, uid int, gid int) error {
return ConvertFileSystemError(c.OsFs.Chown(name, uid, gid))
}
Expand Down
2 changes: 1 addition & 1 deletion utils/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func ConvertFileSystemError(err error) error {
return commonerrors.WrapError(commonerrors.ErrConflict, err, "")
case commonerrors.CorrespondTo(err, "required privilege is not held") || commonerrors.CorrespondTo(err, "operation not permitted"):
return commonerrors.WrapError(commonerrors.ErrForbidden, err, "")
case os.IsNotExist(err) || commonerrors.Any(err, os.ErrNotExist, afero.ErrFileNotFound):
case os.IsNotExist(err) || commonerrors.Any(err, os.ErrNotExist, afero.ErrFileNotFound) || IsPathNotExist(err) || commonerrors.CorrespondTo(err, "No such file or directory"):
return commonerrors.WrapError(commonerrors.ErrNotFound, err, "")
case commonerrors.Any(err, os.ErrNoDeadline):
return commonerrors.WrapError(commonerrors.ErrUnsupported, err, "file type does not support deadline")
Expand Down
2 changes: 1 addition & 1 deletion utils/platform/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func WithPrivileges(cmd *command.CommandAsDifferentUser) (cmdWithPrivileges *com
if err != nil {
return
}
if !hasPrivileges {
if !hasPrivileges && hasPasswordlessPrivileges() {
cmdWithPrivileges.Prepend(getRunCommandWithPrivileges())
}
return
Expand Down
11 changes: 10 additions & 1 deletion utils/platform/cmd_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

package platform

import "github.com/ARM-software/golang-utils/utils/subprocess/command"
import (
"os/exec"

"github.com/ARM-software/golang-utils/utils/subprocess/command"
)

var (
// sudoCommand describes the command to use to execute command as root
Expand All @@ -22,3 +26,8 @@ func DefineSudoCommand(args ...string) {
func getRunCommandWithPrivileges() *command.CommandAsDifferentUser {
return sudoCommand
}

func hasPasswordlessPrivileges() bool {
// See https://www.baeldung.com/linux/sudo-passwordless-check
return exec.Command("sh", "-c", "sudo -n true 2>/dev/null || exit 1").Run() == nil
}
8 changes: 7 additions & 1 deletion utils/platform/cmd_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

package platform

import "github.com/ARM-software/golang-utils/utils/subprocess/command"
import (
"github.com/ARM-software/golang-utils/utils/subprocess/command"
)

var (
// runAsAdmin describes the command to use to run command as Administrator
Expand All @@ -23,3 +25,7 @@ func DefineRunAsAdmin(args ...string) {
func getRunCommandWithPrivileges() *command.CommandAsDifferentUser {
return runAsAdmin
}

func hasPasswordlessPrivileges() bool {
return true
}
4 changes: 2 additions & 2 deletions utils/subprocess/command/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"sync"
)

// CommandAsDifferentUser helps redefining commands so that they are run as a different user or with more privileges.
// CommandAsDifferentUser helps to redefine commands so that they are run as a different user or with more privileges.
type CommandAsDifferentUser struct {
mu sync.RWMutex
// changeUserCmd describes the command to use to execute any command as a different user
Expand Down Expand Up @@ -65,7 +65,7 @@ func (c *CommandAsDifferentUser) Prepend(cmd *CommandAsDifferentUser) *CommandAs
return c
}

// NewCommandAsDifferentUser defines a command wrapper which helps redefining commands so that they are run as a different user.
// NewCommandAsDifferentUser defines a command wrapper which helps to redefine commands so that they are run as a different user.
// e.g.
// - switchUserCmd="sudo" to run commands as `root`
// - switchUserCmd="su", "tom" if `tom` has enough privileges to run the command
Expand Down
Loading