move to clean crypt handling

This commit is contained in:
Mikaël Cluseau
2023-02-02 00:28:36 +01:00
parent 3c7d56ae48
commit 69cc01db9b
5 changed files with 172 additions and 125 deletions

154
lvm.go
View File

@ -7,18 +7,32 @@ import (
"os"
"os/exec"
"path/filepath"
"sort"
"strconv"
"novit.nc/direktil/initrd/lvm"
config "novit.tech/direktil/pkg/bootstrapconfig"
)
func sortedKeys[T any](m map[string]T) (keys []string) {
keys = make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return
}
func setupLVM(cfg *config.Config) {
if len(cfg.LVM) == 0 {
log.Print("no LVM VG configured.")
return
}
// [dev] = filesystem
// eg: [/dev/sda1] = ext4
createdDevs := map[string]string{}
run("pvscan")
run("vgscan", "--mknodes")
@ -27,17 +41,21 @@ func setupLVM(cfg *config.Config) {
}
for _, vg := range cfg.LVM {
setupLVs(vg)
setupLVs(vg, createdDevs)
}
run("vgchange", "--sysinit", "-a", "ly")
for _, vg := range cfg.LVM {
setupCrypt(vg)
}
setupCrypt(cfg.Crypt, createdDevs)
for _, vg := range cfg.LVM {
setupFS(vg)
devs := make([]string, 0, len(createdDevs))
for k := range createdDevs {
devs = append(devs, k)
}
sort.Strings(devs)
for _, dev := range devs {
setupFS(dev, createdDevs[dev])
}
}
@ -113,7 +131,7 @@ func setupVG(vg config.LvmVG) {
}
}
func setupLVs(vg config.LvmVG) {
func setupLVs(vg config.LvmVG, createdDevs map[string]string) {
lvsRep := lvm.LVSReport{}
err := runJSON(&lvsRep, "lvs", "--reportformat", "json")
if err != nil {
@ -171,6 +189,12 @@ func setupLVs(vg config.LvmVG) {
dev := "/dev/" + vg.VG + "/" + lv.Name
zeroDevStart(dev)
fs := lv.FS
if fs == "" {
fs = vg.Defaults.FS
}
createdDevs[dev] = fs
}
}
@ -188,21 +212,52 @@ func zeroDevStart(dev string) {
}
}
func setupCrypt(vg config.LvmVG) {
cryptDevs := map[string]bool{}
func setupCrypt(devSpecs []config.CryptDev, createdDevs map[string]string) {
var password []byte
passwordVerified := false
for _, lv := range vg.LVs {
if lv.Crypt == "" {
// flat, expanded devices to open
devNames := make([]config.CryptDev, 0, len(devSpecs))
for _, devSpec := range devSpecs {
if devSpec.Dev == "" && devSpec.Prefix == "" {
fatalf("crypt: name %q: no dev or match set", devSpec.Name)
}
if devSpec.Dev != "" && devSpec.Prefix != "" {
fatalf("crypt: name %q: both dev (%q) and match (%q) are set", devSpec.Name, devSpec.Dev, devSpec.Prefix)
}
if devSpec.Dev != "" {
// already flat
devNames = append(devNames, devSpec)
continue
}
if cryptDevs[lv.Crypt] {
fatalf("duplicate crypt device name: %s", lv.Crypt)
matches, err := filepath.Glob(devSpec.Prefix + "*")
if err != nil {
fatalf("failed to search for device matches: %v", err)
}
cryptDevs[lv.Crypt] = true
for _, m := range matches {
suffix := m[len(devSpec.Prefix):]
devNames = append(devNames, config.CryptDev{Dev: m, Name: devSpec.Name + suffix})
}
}
cryptDevs := map[string]bool{}
for _, devName := range devNames {
name, dev := devName.Name, devName.Dev
if name == "" {
name = filepath.Base(dev)
}
if cryptDevs[name] {
fatalf("duplicate crypt device name: %s", name)
}
cryptDevs[name] = true
retryOpen:
if len(password) == 0 {
@ -213,7 +268,10 @@ func setupCrypt(vg config.LvmVG) {
}
}
dev := "/dev/" + vg.VG + "/" + lv.Name
fs := createdDevs[dev]
delete(createdDevs, dev)
tgtDev := "/dev/mapper/" + name
needFormat := !devInitialized(dev)
if needFormat {
@ -242,10 +300,20 @@ func setupCrypt(vg config.LvmVG) {
if err != nil {
fatalf("failed luksFormat: %v", err)
}
createdDevs[tgtDev] = fs
}
log.Print("openning encrypted device ", lv.Crypt, " from ", dev)
cmd := exec.Command("cryptsetup", "open", dev, lv.Crypt, "--key-file=-")
if len(password) == 0 {
password = askSecret("crypt password")
if len(password) == 0 {
fatalf("empty password given")
}
}
log.Print("openning encrypted device ", name, " from ", dev)
cmd := exec.Command("cryptsetup", "open", dev, name, "--key-file=-")
cmd.Stdin = bytes.NewBuffer(password)
cmd.Stdout = stdout
cmd.Stderr = stderr
@ -261,7 +329,7 @@ func setupCrypt(vg config.LvmVG) {
}
if needFormat {
zeroDevStart("/dev/mapper/" + lv.Crypt)
zeroDevStart(tgtDev)
}
passwordVerified = true
@ -294,33 +362,25 @@ func devInitialized(dev string) bool {
return false
}
func setupFS(vg config.LvmVG) {
for _, lv := range vg.LVs {
dev := "/dev/" + vg.VG + "/" + lv.Name
if lv.Crypt != "" {
dev = "/dev/mapper/" + lv.Crypt
}
if devInitialized(dev) {
log.Print("device ", dev, " already formatted")
continue
}
if lv.FS == "" {
lv.FS = vg.Defaults.FS
}
log.Print("formatting ", dev, " (", lv.FS, ")")
args := make([]string, 0)
switch lv.FS {
case "btrfs":
args = append(args, "-f")
case "ext4":
args = append(args, "-F")
}
run("mkfs."+lv.FS, append(args, dev)...)
func setupFS(dev, fs string) {
if devInitialized(dev) {
log.Print("device ", dev, " already formatted")
return
}
if fs == "" {
fs = "ext4"
}
log.Print("formatting ", dev, " (", fs, ")")
args := make([]string, 0)
switch fs {
case "btrfs":
args = append(args, "-f")
case "ext4":
args = append(args, "-F")
}
run("mkfs."+fs, append(args, dev)...)
}