Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os/exec: windows: support simple way of launching process with username/password #42773

Open
rgl opened this issue Nov 22, 2020 · 9 comments
Open

Comments

@rgl
Copy link

@rgl rgl commented Nov 22, 2020

Currently os.exec allow us to use a Token to create a process under a different user, but its not clear how to do that; so please provide an proper example :-)

Please note that #35653 or #21105 are somewhat related to this, but they were closed by using the more complex CreateProcessWithLogon function and didn't provide an example of starting a process under a different user.

Also, I think it would also be useful to add support for setting the user domain/username/password in syscall.SysProcAttr and internally use CreateProcessWithLogonW/CreateProcessWithLogon function instead of CreateProcessAsUserW/CreateProcessAsUser (as done in Go).

If that makes sense, I can try to create a PR that adds the following properties to syscall.SysProcAttr:

  • Domain
  • Username
  • Password

And use CreateProcessWithLogonW to launch the process when Username is set.

BTW, dotnet also uses the CreateProcessWithLogon function.

What do you think?

@ianlancetaylor ianlancetaylor changed the title os/exec windows: support simple way of launching process with username/password os/exec: windows: support simple way of launching process with username/password Nov 23, 2020
@ianlancetaylor ianlancetaylor added this to the Backlog milestone Nov 23, 2020
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Nov 23, 2020

CC @alexbrainman @mattn @zx2c4

Can you suggest exactly what fields would be added to syscall.SysProcAttr, and how they would be documented? Thanks.

Loading

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Nov 23, 2020

I'm pretty familiar with these APIs and can probably do that but... what are you actually trying to accomplish? Most folks should probably not be passing password strings and such around. Do you have a use case in mind?

Loading

@rgl
Copy link
Author

@rgl rgl commented Nov 23, 2020

I'm playing with the idea of improving the nomad raw_exec driver to somehow use non-administrator/system accounts. One of that ways is to use CreateProcessWithLogon; others are to somehow use Group Managed Service Accounts and/or Local Service Accounts (these do not have a user managed password, as such, are more convenient to use; but these seem to require the application to run (or be wrapped) as a Windows service).

Loading

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Nov 23, 2020

I don't know too much about that, so I might be guessing incorrectly at some of the details. It sounds like you have a system service running highly privileged, and you'd like it to create processes running as less privileged users, as specified through a configuration file? And this should be done non-interactively? So sort of like the equivalent of the unix idiom:

if (!fork()) {
    setuid(1001);
    setgid(1001);
    execve(....);
}

Is that what you're after?

Loading

@rgl
Copy link
Author

@rgl rgl commented Nov 23, 2020

Its exactly that :-)

Nomad is running as a windows service (under the SYSTEM account) and acting as a init/service manager (akin to systemd) for the processes its starts as child processes; that is, it launches the process as a child process, captures their output as logs, re-launches then when they die, etc.

Loading

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Nov 23, 2020

Gotcha, okay. So in that case, if you're already running as Local System, you don't want to use these APIs that require a password. Rather, mint a token using something like NtCreateToken, and then pass that to the Token field:

attrs := &os.ProcAttr{
                Sys: &syscall.SysProcAttr{
                        Token: syscall.Token(theTokenThatYouJustMade),
                },
}

And then attrs is passed to os.StartProcess like usual.


Given that os.StartProcess already takes a token to support this use case, I'm not sure there's anything required of the actual Go runtime here, so maybe this can be closed?

Loading

@rgl
Copy link
Author

@rgl rgl commented Nov 23, 2020

Interesting! So we can mint any user token, load its profile, and start the process?

If so, I think that the only thing missing is an example of this in the documentation 🙂

Loading

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Nov 23, 2020

Interesting! So we can mint any user token, load its profile, and start the process?

If you're running as Local System, then yep, pretty much.

If so, I think that the only thing missing is an example of this in the documentation

I don't think it's the job of Go's documentation to provide walkthroughs of how to use rarely used NT APIs, especially ones involving manual token creation.

Loading

@rgl
Copy link
Author

@rgl rgl commented Nov 23, 2020

Thank you! I will try to get it working.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants