Upgrade kcrypt partitions on boot (#122)

Co-authored-by: Dimitris Karakasilis <jimmykarily@gmail.com>
This commit is contained in:
Itxaka 2023-05-08 09:44:43 +02:00 committed by GitHub
parent 2e9e5de03e
commit 14426d39b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 3 deletions

View File

@ -36,6 +36,7 @@ const (
OpWaitForSysroot = "wait-for-sysroot"
OpLvmActivate = "lvm-activation"
OpKcryptUnlock = "unlock-all"
OpKcryptUpgrade = "upgrade-kcrypt"
PersistentStateTarget = "/usr/local/.state"
LogDir = "/run/immucore"
LinuxFs = "ext4"

View File

@ -0,0 +1,61 @@
package utils
import (
"fmt"
"path/filepath"
"strings"
"github.com/gofrs/uuid"
"github.com/jaypipes/ghw"
"github.com/kairos-io/kairos-sdk/utils"
)
// UpgradeKcryptPartitions will try check for the uuid of the persistent partition and upgrade its uuid.
func UpgradeKcryptPartitions() error {
// Generate the predictable UUID
persistentUUID := uuid.NewV5(uuid.NamespaceURL, "COS_PERSISTENT")
// Check if there are any LUKS partitions, otherwise ignore
blk, err := ghw.Block()
if err != nil {
return err
}
for _, disk := range blk.Disks {
for _, p := range disk.Partitions {
if p.Type == "crypto_LUKS" {
// Check against known partition label on persistent
Log.Debug().Str("label", p.Label).Str("dev", p.Name).Msg("found luks partition")
if p.Label == "persistent" {
// Get current UUID
volumeUUID, err := utils.SH(fmt.Sprintf("cryptsetup luksUUID %s", filepath.Join("/dev", p.Name)))
if err != nil {
Log.Err(err).Send()
return err
}
volumeUUID = strings.TrimSpace(volumeUUID)
volumeUUIDParsed, err := uuid.FromString(volumeUUID)
Log.Debug().Interface("volumeUUID", volumeUUIDParsed).Send()
Log.Debug().Interface("persistentUUID", persistentUUID).Send()
if err != nil {
Log.Err(err).Send()
return err
}
// Check to see if it's the same already to not do anything
if volumeUUIDParsed.String() != persistentUUID.String() {
Log.Debug().Str("old", volumeUUIDParsed.String()).Str("new", persistentUUID.String()).Msg("Uuid is different, updating")
out, err := utils.SH(fmt.Sprintf("cryptsetup luksUUID -q --uuid %s %s", persistentUUID, filepath.Join("/dev", p.Name)))
if err != nil {
Log.Err(err).Str("out", out).Msg("Updating uuid failed")
return err
}
} else {
Log.Debug().Msg("UUIDs are the same, not updating")
}
}
}
}
}
return nil
}

View File

@ -24,11 +24,17 @@ func (s *State) RegisterNormalBoot(g *herd.Graph) error {
// Mount Root (COS_STATE or COS_RECOVERY and then the image active/passive/recovery under s.Rootdir)
s.LogIfError(s.MountRootDagStep(g), "running mount root stage")
// Run unlock. Depends on mount root because it needs the kcrypt-discovery-challenger available under /sysroot
s.LogIfError(s.RunKcrypt(g, herd.WithDeps(cnst.OpMountRoot)), "kcrypt unlock")
// Upgrade kcrypt partitions to kcrypt 0.6.0 if any
// Depend on LVM in case the LVM is encrypted somehow? Not sure if possible.
s.LogIfError(s.RunKcryptUpgrade(g, herd.WithDeps(cnst.OpLvmActivate)), "upgrade kcrypt partitions")
// Run unlock.
// Depends on mount root because it needs the kcrypt-discovery-challenger available under /sysroot
// Depends on OpKcryptUpgrade until we don't support upgrading from 1.X to the current version
s.LogIfError(s.RunKcrypt(g, herd.WithDeps(cnst.OpMountRoot, cnst.OpKcryptUpgrade)), "kcrypt unlock")
// Mount COS_OEM (After root as it mounts under s.Rootdir/oem)
s.LogIfError(s.MountOemDagStep(g, cnst.OpMountRoot, cnst.OpLvmActivate, cnst.OpKcryptUnlock), "oem mount")
s.LogIfError(s.MountOemDagStep(g, cnst.OpMountRoot, cnst.OpLvmActivate), "oem mount")
// Run yip stage rootfs. Requires root+oem+sentinel to be mounted
s.LogIfError(s.RootfsStageDagStep(g, herd.WithDeps(cnst.OpMountRoot, cnst.OpMountOEM, cnst.OpSentinel)), "running rootfs stage")

View File

@ -598,3 +598,12 @@ func (s *State) LVMActivation(g *herd.Graph) error {
func (s *State) RunKcrypt(g *herd.Graph, opts ...herd.OpOption) error {
return g.Add(cnst.OpKcryptUnlock, append(opts, herd.WithCallback(func(ctx context.Context) error { return kcrypt.UnlockAll() }))...)
}
// RunKcryptUpgrade will upgrade encrypted partitions created with 1.x to the new 2.x format, where
// we inspect the uuid of the partition directly to know which label to use for the key
// As those old installs have an old agent the only way to do it is during the first boot after the upgrade to the newest immucore.
func (s *State) RunKcryptUpgrade(g *herd.Graph, opts ...herd.OpOption) error {
return g.Add(cnst.OpKcryptUpgrade, append(opts, herd.WithCallback(func(ctx context.Context) error {
return internalUtils.UpgradeKcryptPartitions()
}))...)
}