Skip to content
This repository has been archived by the owner on Aug 12, 2021. It is now read-only.

Commit

Permalink
Move privileged subcommands to individual files under cmd/priv/
Browse files Browse the repository at this point in the history
Also adds cmd.Abort() for standardized command failure.

Signed-off-by: Jan Dubois <jan.dubois@suse.com>
  • Loading branch information
jandubois committed Apr 27, 2021
1 parent 237a70d commit 88d14fc
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 64 deletions.
40 changes: 40 additions & 0 deletions cmd/priv/hyperkit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package priv

import (
"encoding/json"
"fmt"
"os"

hyperkit "github.com/moby/hyperkit/go"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd"
)

func Hyperkit() {
if len(os.Args) != 5 {
cmd.Abort("usage: hyperkit CONFIG DISKS CMDLINE")
}

var h hyperkit.HyperKit
err := json.Unmarshal([]byte(os.Args[2]), &h)
if err != nil {
cmd.Abort("Unmarshalling hyperkit structure failed: %v", err)
}

var disks []hyperkit.RawDisk
err = json.Unmarshal([]byte(os.Args[3]), &disks)
if err != nil {
cmd.Abort("Unmarshalling hyperkit disks structure failed: %v", err)
}

// Type conversion from hyperkit.RawDisk to hyperkit.Disk
for _, disk := range disks {
h.Disks = append(h.Disks, &disk)
}

_, err = h.Start(os.Args[4])
if err != nil {
cmd.Abort("Failed to start hyperkit: %v", err)
}
_, _ = fmt.Fprintln(os.Stderr, "Hyperkit started successfully")
os.Exit(0)
}
29 changes: 29 additions & 0 deletions cmd/priv/nfs-exports.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package priv

import (
"fmt"
"os"

"github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit"
)

func NFSExports() {
if len(os.Args) < 4 {
cmd.Abort("usage: nfs-exports [add|remove] arguments")
}

var err error
switch os.Args[2] {
case "add":
err = hyperkit.AddNFSExports(os.Args[3:]...)
case "remove":
err = hyperkit.RemoveNFSExports(os.Args[3:]...)
default:
err = fmt.Errorf("Unknown nfs-export subcommand: %s", os.Args[2])
}
if err != nil {
cmd.Abort("nfs-export %s failed: %v", os.Args[2], err)
}
os.Exit(0)
}
21 changes: 21 additions & 0 deletions cmd/priv/uuid-to-mac-addr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package priv

import (
"fmt"
"os"

"github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit"
)

func UUIDtoMacAddr() {
if len(os.Args) != 3 {
cmd.Abort("usage: uuid-to-mac-addr UUID")
}
mac, err := hyperkit.GetMACAddressFromUUID(os.Args[2])
if err != nil {
cmd.Abort("Getting MAC address from UUID failed: %v", err)
}
fmt.Println(mac)
os.Exit(0)
}
11 changes: 11 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cmd

import (
"fmt"
"os"
"strings"

"github.com/docker/machine/libmachine/log"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit"
Expand Down Expand Up @@ -41,6 +43,15 @@ func onInit() {
}
}

func Abort(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
_, _ = os.Stderr.WriteString(msg)
if !strings.HasSuffix(msg, "\n") {
_, _ = os.Stderr.WriteString("\n")
}
os.Exit(1)
}

func Execute() error {
return rootCmd.Execute()
}
87 changes: 23 additions & 64 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,92 +17,47 @@ limitations under the License.
package main

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"syscall"

"github.com/docker/machine/libmachine/drivers/plugin"
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
mobyhyperkit "github.com/moby/hyperkit/go"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/cmd/priv"
"github.com/rancher-sandbox/docker-machine-driver-hyperkit/pkg/hyperkit"
)

func main() {
if syscall.Geteuid() != 0 {
executable, err := os.Executable()
if err != nil {
fmt.Fprintf(os.Stderr, "cannot determina name of executable: %v", err)
os.Exit(1)
cmd.Abort("Cannot determine name of executable: %v", err)
}

permErr := "%s needs to run with elevated permissions. " +
"Please run the following command, then try again: " +
"sudo chown root:wheel %s && sudo chmod u+s %s"

fmt.Fprintf(os.Stderr, permErr, filepath.Base(executable), executable, executable)
os.Exit(1)
cmd.Abort(permErr, filepath.Base(executable), executable, executable)
}

if len(os.Args) == 3 && os.Args[1] == "uuid-to-mac-addr" {
mac, err := hyperkit.GetMACAddressFromUUID(os.Args[2])
if err != nil {
fmt.Fprintf(os.Stderr, "getting MAC address from UUID: %v", err)
os.Exit(1)
}
fmt.Println(mac)
return
}

if len(os.Args) > 3 && os.Args[1] == "nfs-exports" {
var err error
if os.Args[2] == "add" {
err = hyperkit.AddNFSExports(os.Args[3:]...)
} else if os.Args[2] == "remove" {
err = hyperkit.RemoveNFSExports(os.Args[3:]...)
} else {
err = fmt.Errorf("unknown nfs-export subcommand: %s", os.Args[2])
}
if err != nil {
fmt.Fprintf(os.Stderr, "nfs-export %s failed: %v", os.Args[2], err)
os.Exit(1)
if len(os.Args) > 1 {
// All of the privileged commands will call os.Exit() and never return

This comment has been minimized.

Copy link
@mook-as

mook-as Apr 27, 2021

It might be good to do a panic("Should not be reached") anyway?

This comment has been minimized.

Copy link
@jandubois

jandubois Apr 27, 2021

Author Member

It should be fine. The next thing that happens if execution falls through it that we drop privileges and then cobra will display usage information. This is the last chance to execute something while EUID is still 0.

switch os.Args[1] {
case "hyperkit":
priv.Hyperkit()
case "nfs-exports":
priv.NFSExports()
case "uuid-to-mac-addr":
priv.UUIDtoMacAddr()
}
return
}

if len(os.Args) == 5 && os.Args[1] == "hyperkit" {
var h mobyhyperkit.HyperKit
err := json.Unmarshal([]byte(os.Args[2]), &h)
if err != nil {
fmt.Fprintf(os.Stderr, "unmarshaling hyperkit structure failed: %v", err)
os.Exit(1)
}

var disks []mobyhyperkit.RawDisk
err = json.Unmarshal([]byte(os.Args[3]), &disks)
if err != nil {
fmt.Fprintf(os.Stderr, "unmarshaling hyperkit disks structure failed: %v", err)
os.Exit(1)
}
for _, disk := range disks {
h.Disks = append(h.Disks, &disk)
}

_, err = h.Start(os.Args[4])
if err != nil {
fmt.Fprintf(os.Stderr, "failed to start hyperkit: %v", err)
os.Exit(1)
}
fmt.Fprintln(os.Stderr, "Hyperkit started successfully")
os.Exit(0)
}

// Drop root privileges before running driver mode, or commands via cobra
if err := syscall.Setuid(syscall.Getuid()); err != nil {
fmt.Fprintf(os.Stderr, "cannot drop privileges: %v", err)
os.Exit(1)
cmd.Abort("Cannot drop privileges: %v", err)
}

if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal {
Expand All @@ -115,15 +70,19 @@ func main() {
// driver, living in a different directory).
executable, err := os.Executable()
if err != nil {
fmt.Fprintf(os.Stderr, "cannot determine absolute path to current executable: %v", err)
os.Exit(1)
cmd.Abort("Cannot determine absolute path to current executable: %v", err)
}
executable, err = filepath.EvalSymlinks(executable)
if err != nil {
fmt.Fprintf(os.Stderr, "cannot evaluate symlinks in path to current executable: %v", err)
os.Exit(1)
cmd.Abort("Cannot evaluate symlinks in path to current executable: %v", err)
}
err = os.Setenv("PATH", os.ExpandEnv(fmt.Sprintf("%s:$PATH", filepath.Dir(executable))))
if err != nil {
cmd.Abort("Cannot update PATH: %v", err)
}
os.Setenv("PATH", os.ExpandEnv(fmt.Sprintf("%s:$PATH", filepath.Dir(executable))))

cmd.Execute()
err = cmd.Execute()
if err != nil {
cmd.Abort("Command failed: %v", err)
}
}

0 comments on commit 88d14fc

Please sign in to comment.