mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
raw_exec windows: add support for setting the task user (#25496)
This commit is contained in:
3
.changelog/25496.txt
Normal file
3
.changelog/25496.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:improvement
|
||||
rawexec: add support for setting the task user on windows platform
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build !linux
|
||||
//go:build !linux && !windows
|
||||
|
||||
package executor
|
||||
|
||||
|
||||
@@ -6,14 +6,108 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-set/v3"
|
||||
"github.com/hashicorp/nomad/client/lib/cpustats"
|
||||
"github.com/hashicorp/nomad/drivers/shared/executor/procstats"
|
||||
"github.com/hashicorp/nomad/plugins/drivers"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func NewExecutorWithIsolation(logger hclog.Logger, compute cpustats.Compute) Executor {
|
||||
logger = logger.Named("executor")
|
||||
logger.Error("isolation executor is not supported on this platform, using default")
|
||||
return NewExecutor(logger, compute)
|
||||
}
|
||||
|
||||
func (e *UniversalExecutor) configureResourceContainer(_ *ExecCommand, _ int) (func() error, func(), error) {
|
||||
cleanup := func() {}
|
||||
running := func() error { return nil }
|
||||
return running, cleanup, nil
|
||||
}
|
||||
|
||||
func (e *UniversalExecutor) start(command *ExecCommand) error {
|
||||
return e.childCmd.Start()
|
||||
}
|
||||
|
||||
func withNetworkIsolation(f func() error, _ *drivers.NetworkIsolationSpec) error {
|
||||
return f()
|
||||
}
|
||||
|
||||
func setCmdUser(cmd *exec.Cmd, user string) error {
|
||||
nameParts := strings.Split(user, "\\")
|
||||
if len(nameParts) != 2 {
|
||||
return errors.New("user name must contain domain")
|
||||
}
|
||||
token, err := createUserToken(nameParts[0], nameParts[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create user token: %w", err)
|
||||
}
|
||||
|
||||
if cmd.SysProcAttr == nil {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
cmd.SysProcAttr.Token = *token
|
||||
|
||||
runtime.AddCleanup(cmd, func(attr *syscall.SysProcAttr) {
|
||||
_ = attr.Token.Close()
|
||||
}, cmd.SysProcAttr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
advapiDll = windows.NewLazySystemDLL("advapi32.dll")
|
||||
procLogonUserW = advapiDll.NewProc("LogonUserW")
|
||||
)
|
||||
|
||||
const (
|
||||
_LOGON_SERVICE uint32 = 5
|
||||
_PROVIDER_DEFAULT uint32 = 0
|
||||
)
|
||||
|
||||
func createUserToken(domain, username string) (*syscall.Token, error) {
|
||||
userw, err := syscall.UTF16PtrFromString(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert username to UTF-16: %w", err)
|
||||
}
|
||||
domainw, err := syscall.UTF16PtrFromString(domain)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert user domain to UTF-16: %w", err)
|
||||
}
|
||||
var token syscall.Token
|
||||
ret, _, e := procLogonUserW.Call(
|
||||
uintptr(unsafe.Pointer(userw)),
|
||||
uintptr(unsafe.Pointer(domainw)),
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
uintptr(_LOGON_SERVICE),
|
||||
uintptr(_PROVIDER_DEFAULT),
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
if ret == 0 {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func (e *UniversalExecutor) ListProcesses() set.Collection[int] {
|
||||
return procstats.ListByPid(e.childCmd.Process.Pid)
|
||||
}
|
||||
|
||||
func (e *UniversalExecutor) setSubCmdCgroup(*exec.Cmd, string) (func(), error) {
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
// configure new process group for child process and creates a JobObject for the
|
||||
// executor. Children of the executor will be created in the same JobObject
|
||||
// Ref: https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects
|
||||
|
||||
@@ -47,8 +47,11 @@ The `raw_exec` driver supports the following configuration in the job spec:
|
||||
conflict with other Nomad driver's cgroups and have unintended side
|
||||
effects.
|
||||
|
||||
~> The `task.user` field cannot be set on a Task using the `raw_exec` driver if
|
||||
the Nomad client has been hardened according to the [production][hardening] guide.
|
||||
~> On Linux, you cannot set the `task.user` field on a task using the `raw_exec`
|
||||
driver if you have hardened the Nomad client according to the
|
||||
[production][hardening] guide. On Windows, when Nomad is running as a [system
|
||||
service][service], you may specify a less-privileged service user. For example,
|
||||
`NT AUTHORITY\LocalService`, `NT AUTHORITY\NetworkService`.
|
||||
|
||||
- `oom_score_adj` - (Optional) A positive integer to indicate the likelihood of
|
||||
the task being OOM killed (valid only for Linux). Defaults to 0.
|
||||
@@ -208,5 +211,6 @@ resources {
|
||||
```
|
||||
|
||||
[hardening]: /nomad/docs/install/production/requirements#user-permissions
|
||||
[service]: /nomad/docs/install/windows-service
|
||||
[plugin-options]: #plugin-options
|
||||
[plugin-block]: /nomad/docs/configuration/plugin
|
||||
|
||||
@@ -110,6 +110,9 @@ job "docs" {
|
||||
[Docker][] images specify their own default users. This can only be set
|
||||
on Linux platforms, and clients can restrict [which drivers][user_drivers]
|
||||
are allowed to run tasks as [certain users][user_denylist].
|
||||
On Windows, when Nomad is running as a [system service][service] for the
|
||||
[`raw_exec`][raw_exec] driver, you may specify a less-privileged service user.
|
||||
For example, `NT AUTHORITY\LocalService`, `NT AUTHORITY\NetworkService`.
|
||||
|
||||
- `template` <code>([Template][]: nil)</code> - Specifies the set of templates
|
||||
to render for the task. Templates can be used to inject both static and
|
||||
@@ -222,6 +225,7 @@ task "server" {
|
||||
[vault]: /nomad/docs/job-specification/vault 'Nomad vault Job Specification'
|
||||
[volumemount]: /nomad/docs/job-specification/volume_mount 'Nomad volume_mount Job Specification'
|
||||
[exec]: /nomad/docs/drivers/exec 'Nomad exec Driver'
|
||||
[raw_exec]: /nomad/docs/drivers/raw_exec 'Nomad raw_exec Driver'
|
||||
[java]: /nomad/docs/drivers/java 'Nomad Java Driver'
|
||||
[docker]: /nomad/docs/drivers/docker 'Nomad Docker Driver'
|
||||
[rkt]: /nomad/plugins/drivers/community/rkt 'Nomad rkt Driver'
|
||||
@@ -232,3 +236,4 @@ task "server" {
|
||||
[max_kill]: /nomad/docs/configuration/client#max_kill_timeout
|
||||
[kill_signal]: /nomad/docs/job-specification/task#kill_signal
|
||||
[Workload Identity]: /nomad/docs/concepts/workload-identity 'Nomad Workload Identity'
|
||||
[service]: /nomad/docs/install/windows-service
|
||||
|
||||
Reference in New Issue
Block a user