Skip to content

Commit

Permalink
Fix permissions checks on windows
Browse files Browse the repository at this point in the history
Signed-off-by: Brad Davidson <[email protected]>
  • Loading branch information
brandond committed Feb 7, 2025
1 parent b2418ba commit 838d687
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 8 deletions.
9 changes: 6 additions & 3 deletions pkg/cli/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"

"github.com/gorilla/mux"
"github.com/k3s-io/k3s/pkg/agent"
Expand All @@ -19,8 +18,10 @@ import (
"github.com/k3s-io/k3s/pkg/profile"
"github.com/k3s-io/k3s/pkg/spegel"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/util/permissions"
"github.com/k3s-io/k3s/pkg/version"
"github.com/k3s-io/k3s/pkg/vpn"
"github.com/pkg/errors"
"github.com/rancher/wrangler/v3/pkg/signals"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
Expand All @@ -45,8 +46,10 @@ func Run(ctx *cli.Context) error {
return err
}

if runtime.GOOS != "windows" && os.Getuid() != 0 && !cmds.AgentConfig.Rootless {
return fmt.Errorf("agent must be run as root, or with --rootless")
if !cmds.AgentConfig.Rootless {
if err := permissions.IsPrivileged(); err != nil {
return errors.Wrap(err, "agent requires additional privilege if not run with --rootless")
}
}

if cmds.AgentConfig.TokenFile != "" {
Expand Down
7 changes: 5 additions & 2 deletions pkg/cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/k3s-io/k3s/pkg/server"
"github.com/k3s-io/k3s/pkg/spegel"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/util/permissions"
"github.com/k3s-io/k3s/pkg/version"
"github.com/k3s-io/k3s/pkg/vpn"
"github.com/pkg/errors"
Expand Down Expand Up @@ -72,8 +73,10 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
return err
}

if !cfg.DisableAgent && os.Getuid() != 0 && !cfg.Rootless {
return fmt.Errorf("server must run as root, or with --rootless and/or --disable-agent")
if !cfg.DisableAgent && !cfg.Rootless {
if err := permissions.IsPrivileged(); err != nil {
return errors.Wrap(err, "server requires additional privilege when not run with --rootless and/or --disable-agent")
}
}

if cfg.Rootless {
Expand Down
4 changes: 2 additions & 2 deletions pkg/datadir/datadir.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package datadir

import (
"os"
"path/filepath"

"github.com/k3s-io/k3s/pkg/util/permissions"
"github.com/k3s-io/k3s/pkg/version"
"github.com/pkg/errors"
"github.com/rancher/wrangler/v3/pkg/resolvehome"
Expand All @@ -22,7 +22,7 @@ func Resolve(dataDir string) (string, error) {

func LocalHome(dataDir string, forceLocal bool) (string, error) {
if dataDir == "" {
if os.Getuid() == 0 && !forceLocal {
if permissions.IsPrivileged() == nil && !forceLocal {
dataDir = DefaultDataDir
} else {
dataDir = DefaultHomeDataDir
Expand Down
3 changes: 2 additions & 1 deletion pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/k3s-io/k3s/pkg/server/handlers"
"github.com/k3s-io/k3s/pkg/static"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/util/permissions"
"github.com/k3s-io/k3s/pkg/version"
"github.com/pkg/errors"
"github.com/rancher/wrangler/v3/pkg/apply"
Expand Down Expand Up @@ -330,7 +331,7 @@ func addrTypesPrioTemplate(flannelExternal bool) string {

func HomeKubeConfig(write, rootless bool) (string, error) {
if write {
if os.Getuid() == 0 && !rootless {
if permissions.IsPrivileged() == nil && !rootless {
return datadir.GlobalConfig, nil
}
return resolvehome.Resolve(datadir.HomeConfig)
Expand Down
18 changes: 18 additions & 0 deletions pkg/util/permissions/permissions_others.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !windows
// +build !windows

package permissions

import (
"fmt"
"os"
)

// IsPrivileged returns an error if the process is not running as root.
// Ref: https://github.com/kubernetes/kubernetes/pull/96616
func IsPrivileged() error {
if os.Getuid() != 0 {
return fmt.Errorf("not running as root")
}
return nil
}
47 changes: 47 additions & 0 deletions pkg/util/permissions/permissions_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//go:build windows
// +build windows

package permissions

import (
"fmt"

"github.com/pkg/errors"
"golang.org/x/sys/windows"
)

// IsPrivileged returns an error if the the process is not running as a member of the BUILTIN\Administrators group.
// Ref: https://github.com/kubernetes/kubernetes/pull/96616
func IsPrivileged() error {
var sid *windows.SID

// Although this looks scary, it is directly copied from the
// official windows documentation. The Go API for this is a
// direct wrap around the official C++ API.
// Ref: https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-checktokenmembership
err := windows.AllocateAndInitializeSid(
&windows.SECURITY_NT_AUTHORITY,
2,
windows.SECURITY_BUILTIN_DOMAIN_RID,
windows.DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&sid)
if err != nil {
return errors.Wrap(err, "failed to create Windows SID")
}
defer windows.FreeSid(sid)

// Ref: https://github.com/golang/go/issues/28804#issuecomment-438838144
token := windows.Token(0)

member, err := token.IsMember(sid)
if err != nil {
return errors.Wrap(err, "failed to check group membership")
}

if !member {
return fmt.Errorf("not running as member of BUILTIN\\Administrators group")
}

return nil
}

0 comments on commit 838d687

Please sign in to comment.