How to execute a command using root?

2 099 vues
Accéder directement au premier message non lu

Benjamin

non lue,
30 août 2019, 02:49:0430/08/2019
à golang-nuts
Hi,
    I need to execute a couple of commands in golang, the code is roughly as below,

   cmd := exec.Command(executable, newArgs...)

   if env != nil && len(env) > 0 {

       cmd.Env = env

   }

   outMsg, err := cmd.CombinedOutput()

   if err != nil {
       
......

   }


   Executing the commands need root privileges, so it works when I start the golang program using "sudo ./gobinary".  But the golang program is supposed to run inside a container, so it isn't good to run the container using root. Then I tried to use "sudo" to execute the command, but the environment variables can't be carried over into the command; In other words, once I use "sudo" to execute the commands, then the environment variables are lost.  

   Do anyone have any suggestions on this? Thanks.

Jan Mercl

non lue,
30 août 2019, 02:54:3430/08/2019
à Benjamin,golang-nuts
On Fri, Aug 30, 2019 at 8:49 AM Benjamin <wangchao...@gmail.com> wrote:

> Do anyone have any suggestions on this? Thanks.

IINM, what you want is not possible. Moreover, it should not be possible.

Jan Mercl

non lue,
30 août 2019, 02:56:4830/08/2019
à Benjamin,golang-nuts
On Fri, Aug 30, 2019 at 8:53 AM Jan Mercl <0xj...@gmail.com> wrote:

> Moreover, it should not be possible.

But whitelisting certain users to run certain programs using sudo, but
no password, is possible.

Jakob Borg

non lue,
30 août 2019, 02:56:5030/08/2019
à Benjamin,golang-nuts
On 30 Aug 2019, at 08:49, Benjamin <wangchao...@gmail.com> wrote:

Then I tried to use "sudo" to execute the command, but the environment variables can't be carried over into the command;

This is a sudo configuration issue. See sudo --preserve-env etc. 

Best regards,
Jakob

Benjamin

non lue,
30 août 2019, 03:43:3830/08/2019
à golang-nuts
Yes, it works. Thank you very much!

在 2019年8月30日星期五 UTC+8下午2:56:50,Jakob Borg写道:

Kevin Chadwick

non lue,
30 août 2019, 07:13:4030/08/2019
à golang-nuts
On 8/30/19 7:49 AM, Benjamin wrote:
> Do anyone have any suggestions on this? Thanks

Sudo is an option. I prefer to have a master root process that spawns workers
processes that drop privileges via setegid...seteuid... syscalls to dedicated
users for various tasks. Takes concurrency to the next level and organises your
code, but it is more work. Also allows flexibility on chrooting that requires
root (though I find OpenBSDs unveil more useful mostly but occasionally both).

If you don't want a process to be taken down by a process group fatal then fork
it separately via a startup shell script.

Chris Burkert

non lue,
31 août 2019, 04:07:5931/08/2019
à Kevin Chadwick,golang-nuts
Dear Kevin,
is there some code available to dig into that? I plan to do something similar that a regular user process starts up a kind of a root broker which starts several other processes as different users. Especially for the communication part I don’t have a good and secure idea so far.
thanks - Chris

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/8908b67e-d5d6-698b-bd54-f2c95fc2566f%40gmail.com.

Ronny Bangsund

non lue,
31 août 2019, 06:33:4131/08/2019
à golang-nuts
On Saturday, August 31, 2019 at 10:07:59 AM UTC+2, Chris Burkert wrote:
is there some code available to dig into that? I plan to do something similar that a regular user process starts up a kind of a root broker which starts several other processes as different users.
You would by necessity have to launch a root process, which then degrades to whichever user it should actually run as. It's a one-way operation, no backsies :)

Digging through my vast mess of code, I found this function which sets the real and effective user (Setreuid) of the calling process:
func DegradeToUser(uname string) error {
        uid := syscall.Geteuid()
        if uid == 0 {
                u, err := user.Lookup(uname)
                if err != nil {
                        return err
                }

                uid, err := strconv.Atoi(u.Uid)
                if err != nil {
                        return err
                }

                gid, err := strconv.Atoi(u.Gid)
                if err != nil {
                        return err
                }

                err = syscall.Setgid(gid)
                if err != nil {
                        return err
                }

                err = syscall.Setreuid(-1, uid)
                if err != nil {
                        return err
                }
        } else {
                return errors.New(ErrorNotRoot)
        }

        return nil
}

An error string is the only thing missing (ErrorNotRoot), otherwise it should be complete.

Especially for the communication part I don’t have a good and secure idea so far.
My hammer is gRPC if I need something with a little security. It's a bit convoluted initially, but allows authenticating via certificates. If you're running everything on one system there might be better ways,

Jakob Borg

non lue,
31 août 2019, 09:14:2831/08/2019
à golang-nuts,Ronny Bangsund
On 31 Aug 2019, at 12:33, Ronny Bangsund <ronny.b...@gmail.com> wrote:

Digging through my vast mess of code, I found this function which sets the real and effective user (Setreuid) of the calling process:
func DegradeToUser(uname string) error {

Doesn't this suffer from the issue of only affecting the current thread on Linux, and hence not being safe to use from Go?


Setting the uid/gid as part of starting a child process should be safe though (https://golang.org/pkg/syscall/#Credential).

//jb

Ronny Bangsund

non lue,
31 août 2019, 15:36:0031/08/2019
à golang-nuts


On Saturday, August 31, 2019 at 3:14:28 PM UTC+2, Jakob Borg wrote:
On 31 Aug 2019, at 12:33, Ronny Bangsund <ronny....@gmail.com> wrote:

Digging through my vast mess of code, I found this function which sets the real and effective user (Setreuid) of the calling process:
func DegradeToUser(uname string) error {

Doesn't this suffer from the issue of only affecting the current thread on Linux, and hence not being safe to use from Go?
No idea if Setreuid() works any differently than Setuid(), but I wouldn't rule it out. Paranoia should be the default state :)
 

Setting the uid/gid as part of starting a child process should be safe though (https://golang.org/pkg/syscall/#Credential).
Yeah, using that with StartProcess() might be a better idea.

Répondre à tous
Répondre à l'auteur
Transférer
0 nouveau message