diff --git a/pkgs/sops-install-secrets/darwin.go b/pkgs/sops-install-secrets/darwin.go index 6e1c2de..ba3f943 100644 --- a/pkgs/sops-install-secrets/darwin.go +++ b/pkgs/sops-install-secrets/darwin.go @@ -4,8 +4,12 @@ package main import ( + "errors" "fmt" + "log" "os" + "os/exec" + "strings" "golang.org/x/sys/unix" ) @@ -33,30 +37,64 @@ func SecureSymlinkChown(symlinkToCheck string, expectedTarget string, owner, gro return nil } +// Does: +// mkdir /tmp/mymount // NUMSECTORS=128000 # a sector is 512 bytes // mydev=`hdiutil attach -nomount ram://$NUMSECTORS` // newfs_hfs $mydev -// mkdir /tmp/mymount // mount -t hfs $mydev /tmp/mymount - func MountSecretFs(mountpoint string, keysGid int, userMode bool) error { - //if err := os.MkdirAll(mountpoint, 0751); err != nil { - // return fmt.Errorf("Cannot create directory '%s': %w", mountpoint, err) - //} + if err := os.MkdirAll(mountpoint, 0751); 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 + log.Printf("%q\n", string(out)) + diskpath := strings.TrimRight(string(out[:]), " \t\n") + log.Printf("%q\n", diskpath) + log.Printf("hdiutil attach ret %v. out: %s", err, diskpath) + + // format as hfs + out, err = exec.Command("newfs_hfs", diskpath).Output() + log.Printf("newfs_hfs ret %v. out: %s", err, out) + + // "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: + out, err = exec.Command("mount", "-t", "hfs", diskpath, mountpoint).Output() + log.Printf("mount ret %v. out: %s", err, out) + + // There is no documented way to check for memfs mountpoint. Thus we place a file. + _, err = os.Create(mountpoint + "/sops-nix-secretfs") + + // 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 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) - //} + 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 }