LUKS support + other things
This commit is contained in:
parent
cbc12f1690
commit
4369fb82dd
8 changed files with 201 additions and 22 deletions
|
|
@ -2,36 +2,50 @@ package vm
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/AlexSSD7/vldisk/utils"
|
||||
"github.com/alessio/shellescape"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/multierr"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
type FileManager struct {
|
||||
logger *slog.Logger
|
||||
|
||||
vi *Instance
|
||||
}
|
||||
|
||||
func NewFileManager(vi *Instance) *FileManager {
|
||||
func NewFileManager(logger *slog.Logger, vi *Instance) *FileManager {
|
||||
return &FileManager{
|
||||
logger: logger,
|
||||
|
||||
vi: vi,
|
||||
}
|
||||
}
|
||||
|
||||
func (fm *FileManager) Init() error {
|
||||
c, err := fm.vi.DialSSH()
|
||||
sc, err := fm.vi.DialSSH()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "dial vm ssh")
|
||||
}
|
||||
|
||||
_, err = runSSHCmd(c, "apk add util-linux lvm2")
|
||||
defer func() { _ = sc.Close() }()
|
||||
|
||||
_, err = runSSHCmd(sc, "apk add util-linux lvm2")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "install utilities")
|
||||
}
|
||||
|
||||
_, err = runSSHCmd(c, "vgchange -ay")
|
||||
_, err = runSSHCmd(sc, "vgchange -ay")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "run vgchange cmd")
|
||||
}
|
||||
|
|
@ -45,11 +59,15 @@ func (fm *FileManager) Lsblk() ([]byte, error) {
|
|||
return nil, errors.Wrap(err, "dial vm ssh")
|
||||
}
|
||||
|
||||
defer func() { _ = sc.Close() }()
|
||||
|
||||
sess, err := sc.NewSession()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create new vm ssh session")
|
||||
}
|
||||
|
||||
defer func() { _ = sess.Close() }()
|
||||
|
||||
ret := new(bytes.Buffer)
|
||||
|
||||
sess.Stdout = ret
|
||||
|
|
@ -64,6 +82,84 @@ func (fm *FileManager) Lsblk() ([]byte, error) {
|
|||
|
||||
type MountOptions struct {
|
||||
FSType string
|
||||
LUKS bool
|
||||
}
|
||||
|
||||
const luksDMName = "cryptmnt"
|
||||
|
||||
func (fm *FileManager) luksOpen(sc *ssh.Client, fullDevPath string) error {
|
||||
lg := fm.logger.With("vm-path", fullDevPath)
|
||||
|
||||
sess, err := sc.NewSession()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create new vm ssh session")
|
||||
}
|
||||
|
||||
defer func() { sess.Close() }()
|
||||
|
||||
stdinPipe, err := sess.StdinPipe()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create vm ssh session stdin pipe")
|
||||
}
|
||||
|
||||
stderrBuf := bytes.NewBuffer(nil)
|
||||
sess.Stderr = stderrBuf
|
||||
|
||||
err = sess.Start("cryptsetup luksOpen " + shellescape.Quote(fullDevPath) + " " + luksDMName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "start cryptsetup luksopen cmd")
|
||||
}
|
||||
|
||||
lg.Info("Attempting to open LUKS device")
|
||||
|
||||
_, err = os.Stderr.Write([]byte("Enter Password: "))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "write prompt to stderr")
|
||||
}
|
||||
|
||||
pwd, err := term.ReadPassword(int(syscall.Stdin))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "read luks password")
|
||||
}
|
||||
|
||||
fmt.Print("\n")
|
||||
|
||||
var wErr error
|
||||
var wWG sync.WaitGroup
|
||||
|
||||
wWG.Add(1)
|
||||
go func() {
|
||||
defer wWG.Done()
|
||||
|
||||
_, err := stdinPipe.Write(pwd)
|
||||
_, err2 := stdinPipe.Write([]byte("\n"))
|
||||
wErr = errors.Wrap(multierr.Combine(err, err2), "write password to stdin")
|
||||
}()
|
||||
|
||||
// TODO: Timeout for this command
|
||||
|
||||
err = sess.Wait()
|
||||
if err != nil {
|
||||
return wrapErrWithLog(err, "wait for cryptsetup luksopen cmd to finish", stderrBuf.String())
|
||||
}
|
||||
|
||||
lg.Info("LUKS device opened successfully")
|
||||
|
||||
// Clear the memory up
|
||||
{
|
||||
for i := 0; i < len(pwd); i++ {
|
||||
pwd[i] = 0
|
||||
}
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
_, _ = rand.Read(pwd)
|
||||
}
|
||||
}
|
||||
|
||||
_ = stdinPipe.Close()
|
||||
wWG.Wait()
|
||||
|
||||
return wErr
|
||||
}
|
||||
|
||||
func (fm *FileManager) Mount(devName string, mo MountOptions) error {
|
||||
|
|
@ -88,12 +184,18 @@ func (fm *FileManager) Mount(devName string, mo MountOptions) error {
|
|||
return errors.Wrap(err, "dial vm ssh")
|
||||
}
|
||||
|
||||
sess, err := sc.NewSession()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create new vm ssh session")
|
||||
defer func() { _ = sc.Close() }()
|
||||
|
||||
if mo.LUKS {
|
||||
err = fm.luksOpen(sc, fullDevPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "luks open")
|
||||
}
|
||||
|
||||
fullDevPath = "/dev/mapper/" + luksDMName
|
||||
}
|
||||
|
||||
err = sess.Run("mount -t " + shellescape.Quote(mo.FSType) + " " + shellescape.Quote(fullDevPath) + " /mnt")
|
||||
_, err = runSSHCmd(sc, "mount -t "+shellescape.Quote(mo.FSType)+" "+shellescape.Quote(fullDevPath)+" /mnt")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "run mount cmd")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue