Skip to content

Commit

Permalink
Fixed Generate Private Key Problems in Windows
Browse files Browse the repository at this point in the history
Found an issue when trying to get a private key when running my unit test locally on my windows machine. From investigating found that privs.go only worked with uid's and gid's which is only functional with mac and linux. I modified a few things to work with windows SID's as well by checking what os is being ran. I ran my tests after modifying on both my linux container and locally on windows and it seems to work now. I also had to change around a few lines in GeneratePrivateKey since it calls a "chown" which is not a windows command.
  • Loading branch information
joereuss12 committed Sep 27, 2023
1 parent a6fc00c commit 6970eda
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 24 deletions.
23 changes: 20 additions & 3 deletions config/init_server_creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import (
"fmt"
"math/big"
"os"
"os/exec"
"path/filepath"
"runtime"
"sync/atomic"
"time"

Expand Down Expand Up @@ -194,6 +196,10 @@ func GeneratePrivateKey(keyLocation string, curve elliptic.Curve) error {
if err != nil {
return err
}
user, err := GetDaemonUser()
if err != nil {
return err
}
groupname, err := GetDaemonGroup()
if err != nil {
return err
Expand All @@ -219,9 +225,20 @@ func GeneratePrivateKey(keyLocation string, curve elliptic.Curve) error {
if err != nil {
return err
}
if err = os.Chown(keyLocation, uid, gid); err != nil {
return errors.Wrapf(err, "Failed to chown generated key %v to daemon group %v",
keyLocation, groupname)
// Windows does not have "chown", has to work differently
currentOS := runtime.GOOS
if currentOS == "windows" {
cmd := exec.Command("icacls", keyLocation, "/grant", user+":F")
output, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrapf(err, "Failed to chown generated key %v to daemon group %v: %s",
keyLocation, groupname, string(output))
}
} else { // Else we are running on linux/mac
if err = os.Chown(keyLocation, uid, gid); err != nil {
return errors.Wrapf(err, "Failed to chown generated key %v to daemon group %v",
keyLocation, groupname)
}
}

bytes, err := x509.MarshalPKCS8PrivateKey(priv)
Expand Down
69 changes: 48 additions & 21 deletions config/privs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ package config

import (
"os/user"
"runtime"
"strconv"
"strings"

"github.com/pkg/errors"
)
Expand All @@ -30,11 +32,13 @@ var (

uidErr error
gidErr error
sidErr error
usernameErr error
groupErr error

uid int
gid int
sid string
username string
group string
)
Expand All @@ -45,9 +49,11 @@ func init() {

uid = -1
gid = -1
sid = ""
if err != nil {
uidErr = err
gidErr = err
sidErr = err
usernameErr = err
groupErr = err
return
Expand All @@ -66,29 +72,46 @@ func init() {
return
}
}
username = desiredUsername
uid, err = strconv.Atoi(userObj.Uid)
if err != nil {
uid = -1
uidErr = err
}
gid, err = strconv.Atoi(userObj.Gid)
if err != nil {
gid = -1
gidErr = err
}
groupObj, err := user.LookupGroupId(userObj.Gid)
if err == nil {
group = groupObj.Name
} else {
// Fall back to using the GID as the group name. This is done because,
// currently, the group name is just for logging strings. The group name
// lookup often fails because we've disabled CGO and only CGO will use the
// full glibc stack to resolve information via SSSD.
//
// This decision should be revisited if we ever enable CGO.
//Windows has userId's different from mac and linux, need to parse to get it
currentOS := runtime.GOOS
if currentOS == "windows" {
//Get the user ID from the SID
sidParts := strings.Split(userObj.Uid, "-")
uidString := sidParts[len(sidParts)-1]
uid, err = strconv.Atoi(uidString)
if err != nil {
uid = -1
uidErr = err
}
sid = userObj.Gid
//group is just the whole SID
group = userObj.Gid
} else { //Mac and linux have similar enough uid's so can group them here
uid, err = strconv.Atoi(userObj.Uid)
if err != nil {
uid = -1
uidErr = err
}
gid, err = strconv.Atoi(userObj.Gid)
if err != nil {
gid = -1
gidErr = err
}
groupObj, err := user.LookupGroupId(userObj.Gid)
if err == nil {
group = groupObj.Name
} else {
// Fall back to using the GID as the group name. This is done because,
// currently, the group name is just for logging strings. The group name
// lookup often fails because we've disabled CGO and only CGO will use the
// full glibc stack to resolve information via SSSD.
//
// This decision should be revisited if we ever enable CGO.
group = userObj.Gid
}
}
// username same for both windows, linux, and mac
username = desiredUsername
}

func IsRootExecution() bool {
Expand All @@ -107,6 +130,10 @@ func GetDaemonGID() (int, error) {
return gid, gidErr
}

func GetDaemonSID() (string, error) {
return sid, sidErr
}

func GetDaemonGroup() (string, error) {
return group, groupErr
}

0 comments on commit 6970eda

Please sign in to comment.