Migrated wrench command
This commit is contained in:
parent
17a816e360
commit
6f876b2a17
230
cmd/wrench/main.go
Normal file
230
cmd/wrench/main.go
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
import "fmt"
|
||||||
|
import "flag"
|
||||||
|
import "strconv"
|
||||||
|
import "os/exec"
|
||||||
|
import "os/user"
|
||||||
|
import "path/filepath"
|
||||||
|
import "golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
func printErr (format string, values ...any) {
|
||||||
|
fmt.Fprintf(os.Stderr, os.Args[0] + ": " + format, values...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serviceUser (service string) string {
|
||||||
|
return "hn-" + service
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryCommand (cmd *exec.Cmd, failReason string) {
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
printErr("%s: %s", failReason, string(output))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ownOne (path string, uid, gid int) {
|
||||||
|
file, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not stat %s: %v", path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chown(path, uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not change ownership of %s: %v", path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if file.IsDir() {
|
||||||
|
err = os.Chmod(path, 0770)
|
||||||
|
} else {
|
||||||
|
err = os.Chmod(path, 0660)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not change mode of %s: %v", path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main () {
|
||||||
|
user, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not get username %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// define commands
|
||||||
|
hashCommand := flag.NewFlagSet("hash", flag.ExitOnError)
|
||||||
|
hashCost := hashCommand.Uint("cost", uint(bcrypt.DefaultCost), "Cost of the hash")
|
||||||
|
hashText := hashCommand.String("k", "", "Text content of the key")
|
||||||
|
|
||||||
|
addUserCommand := flag.NewFlagSet("adduser", flag.ExitOnError)
|
||||||
|
addUserService := addUserCommand.String ("s", "router",
|
||||||
|
"Service to add a user for")
|
||||||
|
|
||||||
|
delUserCommand := flag.NewFlagSet("deluser", flag.ExitOnError)
|
||||||
|
delUserService := delUserCommand.String ("s", "router",
|
||||||
|
"Service to delete the user for")
|
||||||
|
|
||||||
|
authCommand := flag.NewFlagSet("auth", flag.ExitOnError)
|
||||||
|
authService := authCommand.String ("s", "router",
|
||||||
|
"Service to authorize the user to access")
|
||||||
|
authUser := authCommand.String ("u", user.Username,
|
||||||
|
"User to be given access")
|
||||||
|
|
||||||
|
ownCommand := flag.NewFlagSet("own", flag.ExitOnError)
|
||||||
|
ownService := ownCommand.String ("s", "router",
|
||||||
|
"Service to give ownership of the file to")
|
||||||
|
ownFile := ownCommand.String ("f", ".",
|
||||||
|
"File to take ownership of")
|
||||||
|
ownRecursive := ownCommand.Bool ("r", false,
|
||||||
|
"Whether or not to recurse into sub-directories")
|
||||||
|
|
||||||
|
// execute correct command
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "hash":
|
||||||
|
execHash(int(*hashCost), *hashText)
|
||||||
|
case "adduser":
|
||||||
|
execAdduser(*addUserService)
|
||||||
|
case "deluser":
|
||||||
|
execDeluser(*delUserService)
|
||||||
|
case "auth":
|
||||||
|
execAuth(*authService, *authUser)
|
||||||
|
case "own":
|
||||||
|
execOwn(*ownService, *ownFile, *ownRecursive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func execHash (cost int, key string) {
|
||||||
|
if cost < bcrypt.MinCost {
|
||||||
|
printErr("cost is too low, must be at least %v", bcrypt.MinCost)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if cost > bcrypt.MaxCost {
|
||||||
|
printErr("cost is too hight, can be at most %v", bcrypt.MaxCost)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(key), cost)
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not hash key: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
func execAdduser (service string) {
|
||||||
|
fullName := serviceUser(service)
|
||||||
|
|
||||||
|
// BUSYBOX
|
||||||
|
adduser, err := exec.LookPath("adduser")
|
||||||
|
if err == nil {
|
||||||
|
addgroup, _ := exec.LookPath("addgroup")
|
||||||
|
tryCommand (exec.Command(addgroup, fullName, "-S"),
|
||||||
|
"could not add group")
|
||||||
|
tryCommand (exec.Command(adduser, fullName, "-SHDG", fullName),
|
||||||
|
"could not add user")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GNU
|
||||||
|
useradd, err := exec.LookPath("useradd")
|
||||||
|
if err == nil {
|
||||||
|
tryCommand (exec.Command (
|
||||||
|
useradd, fullName, "-rUM",
|
||||||
|
"--shell", "/sbin/nologin"), "could not add user")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printErr("could not add user: no command adduser or useradd")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func execDeluser (service string) {
|
||||||
|
fullName := serviceUser(service)
|
||||||
|
|
||||||
|
// BUSYBOX
|
||||||
|
deluser, err := exec.LookPath("deluser")
|
||||||
|
if err == nil {
|
||||||
|
tryCommand (exec.Command(deluser, fullName, "--remove-home"),
|
||||||
|
"could not delete user")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GNU
|
||||||
|
userdel, err := exec.LookPath("userdel")
|
||||||
|
if err == nil {
|
||||||
|
tryCommand (exec.Command(userdel, fullName, "-r"),
|
||||||
|
"could not delete user")
|
||||||
|
groupdel, _ := exec.LookPath("groupdel")
|
||||||
|
tryCommand (exec.Command(groupdel, fullName),
|
||||||
|
"could not delete group")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printErr("could not delete user: no command deluser or userdel")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func execAuth (service, user string) {
|
||||||
|
fullName := serviceUser(service)
|
||||||
|
|
||||||
|
adduser, err := exec.LookPath("adduser")
|
||||||
|
if err == nil {
|
||||||
|
tryCommand (exec.Command(adduser, user, fullName),
|
||||||
|
"could not add user to group " + fullName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GNU
|
||||||
|
useradd, err := exec.LookPath("usermod")
|
||||||
|
if err == nil {
|
||||||
|
tryCommand (exec.Command(useradd, "-a", "-g", fullName, user),
|
||||||
|
"could not add user to group " + fullName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printErr("could not auth user: no command adduser or usermod")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func execOwn (service, file string, recurse bool) {
|
||||||
|
fullName := serviceUser(service)
|
||||||
|
|
||||||
|
userInfo, err := user.Lookup(fullName)
|
||||||
|
uid, _ := strconv.Atoi(userInfo.Uid)
|
||||||
|
gid, _ := strconv.Atoi(userInfo.Gid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not get user info: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !recurse {
|
||||||
|
ownOne(file, uid, gid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = filepath.Walk(file, func(
|
||||||
|
filePath string,
|
||||||
|
file os.FileInfo,
|
||||||
|
err error,
|
||||||
|
) error {
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not traverse filesystem: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ownOne(filePath, uid, gid)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
printErr("could not traverse filesystem: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user