mirror of
https://github.com/Mic92/sops-nix.git
synced 2025-12-26 14:14:58 +08:00
gosec only found int to uint downcasts which are unavoidable as sadly the go API usually uses int instead of uint in places.
94 lines
3.3 KiB
Go
94 lines
3.3 KiB
Go
//go:build darwin
|
|
// +build darwin
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
func RuntimeDir() (string, error) {
|
|
// TODO this could be garbage collected on a 3d basis
|
|
out, err := exec.Command("getconf", "DARWIN_USER_TEMP_DIR").Output()
|
|
rundir := strings.TrimRight(string(out[:]), " \t\n")
|
|
if err != nil {
|
|
return "", fmt.Errorf("cannot get DARWIN_USER_TEMP_DIR: %v", err)
|
|
}
|
|
return strings.TrimSuffix(rundir, "/"), nil
|
|
}
|
|
|
|
// Does:
|
|
// mkdir /tmp/mymount
|
|
// NUMSECTORS=128000 # a sector is 512 bytes
|
|
// mydev=`hdiutil attach -nomount ram://$NUMSECTORS`
|
|
// newfs_hfs $mydev
|
|
// mount -t hfs $mydev /tmp/mymount
|
|
func MountSecretFs(mountpoint string, keysGID int, _useTmpfs bool, userMode bool) error {
|
|
if err := os.MkdirAll(mountpoint, 0o751); err != nil {
|
|
return fmt.Errorf("cannot create directory '%s': %w", mountpoint, err)
|
|
}
|
|
if _, err := os.Stat(mountpoint + "/sops-nix-secretfs"); !errors.Is(err, os.ErrNotExist) {
|
|
return nil // secret fs already exists
|
|
}
|
|
|
|
// MacOS/darwin options for temporary files:
|
|
// - /tmp or NSTemporaryDirectory is persistent, and regularly wiped from files not touched >3d
|
|
// https://wiki.lazarus.freepascal.org/Locating_the_macOS_tmp_directory
|
|
// - there is no ramfs, also `man statfs` doesn't have flags for memfs things
|
|
// - we can allocate and mount statically allocated memory (ram://), however most
|
|
// functions for that are not publicly exposed to userspace.
|
|
mb := 64 // size in MB
|
|
size := mb * 1024 * 1024 / 512 // size in sectors a 512 bytes
|
|
cmd := exec.Command("hdiutil", "attach", "-nomount", fmt.Sprintf("ram://%d", int(size)))
|
|
out, err := cmd.Output() // /dev/diskN
|
|
if err != nil {
|
|
return fmt.Errorf("cannot execute hdiutil: %w", err)
|
|
}
|
|
diskpath := strings.TrimRight(string(out[:]), " \t\n")
|
|
|
|
// format as hfs
|
|
_, err = exec.Command("newfs_hfs", "-s", diskpath).Output()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot create hfs filesystem at '%s': %w", diskpath, err)
|
|
}
|
|
|
|
// "posix" mount takes `struct hfs_mount_args` which we dont have bindings for at hand.
|
|
// See https://stackoverflow.com/a/49048846/4108673
|
|
// err = unix.Mount("hfs", mountpoint, unix.MNT_NOEXEC|unix.MNT_NODEV, mount_args)
|
|
// Instead we call:
|
|
_, err = exec.Command("mount", "-t", "hfs", "-o", "nobrowse,nodev,nosuid,-m=0751", diskpath, mountpoint).Output()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot mount '%s' to '%s': %w", diskpath, mountpoint, err)
|
|
}
|
|
|
|
// There is no documented way to check for memfs mountpoint. Thus we place a file.
|
|
path := mountpoint + "/sops-nix-secretfs"
|
|
_, err = os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot create file '%s': %w", path, err)
|
|
}
|
|
|
|
// This would be the way to check on unix.
|
|
//buf := unix.Statfs_t{}
|
|
//if err := unix.Statfs(mountpoint, &buf); err != nil {
|
|
// return fmt.Errorf("Cannot get statfs for directory '%s': %w", mountpoint, err)
|
|
//}
|
|
//
|
|
//if int32(buf.Type) != RAMFS_MAGIC {
|
|
// if err := unix.Mount("none", mountpoint, "ramfs", unix.MS_NODEV|unix.MS_NOSUID, "mode=0751"); err != nil {
|
|
// return fmt.Errorf("Cannot mount: %s", err)
|
|
// }
|
|
//}
|
|
|
|
if !userMode {
|
|
if err := os.Chown(mountpoint, 0, int(keysGID)); err != nil {
|
|
return fmt.Errorf("cannot change owner/group of '%s' to 0/%d: %w", mountpoint, keysGID, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|