Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
Copy rootfs efi files into the iso generation
Browse files Browse the repository at this point in the history
To support secureboot, efi artifacts need to come from the rootfs so
they match their signatures with the shim+grub+kernel

This change does several things:

 - Drops uneeded constants
 - Drops unused efi files copying
 - No longer copies the /efi dir from the rootfs(osbuilder image) into
   the livecd
 - No longer uses the generic efi artifacts to generate the image
 - Searches for know paths where the efi artifacts are per distro and
   uses them to generate the efi boot image

Signed-off-by: Itxaka <itxaka@kairos.io>
  • Loading branch information
Itxaka committed Dec 30, 2023
1 parent f8a2119 commit 1dfa982
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 204 deletions.
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.20

require (
github.com/kairos-io/kairos-agent/v2 v2.1.11-0.20230713071318-9a16b94e2af6
github.com/kairos-io/kairos-sdk v0.0.14
github.com/kairos-io/kairos-sdk v0.0.22-0.20231230114601-eaa9d3ce040b
github.com/mitchellh/mapstructure v1.5.0
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.10
Expand All @@ -26,7 +26,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.10.0-rc.8 // indirect
github.com/Microsoft/hcsshim v0.11.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230117203413-a47887b8f098 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
Expand All @@ -36,8 +36,8 @@ require (
github.com/cloudflare/circl v1.3.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/containerd v1.7.1 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/containerd/containerd v1.7.7 // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/denisbrodbeck/machineid v1.0.1 // indirect
github.com/diskfs/go-diskfs v1.3.0 // indirect
Expand Down Expand Up @@ -72,7 +72,7 @@ require (
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/itchyny/gojq v0.12.12 // indirect
github.com/itchyny/gojq v0.12.13 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/jaypipes/ghw v0.10.0 // indirect
github.com/jaypipes/pcidb v1.0.0 // indirect
Expand Down Expand Up @@ -130,7 +130,7 @@ require (
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/term v0.10.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek=
github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20230117203413-a47887b8f098 h1:gQT1cLGP56jqbm0ioh/80TgknBT2EyZ5XwnnJsiQQKo=
Expand Down Expand Up @@ -113,8 +114,10 @@ github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARu
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.7.1 h1:k8DbDkSOwt5rgxQ3uCI4WMKIJxIndSCBUaGm5oRn+Go=
github.com/containerd/containerd v1.7.1/go.mod h1:gA+nJUADRBm98QS5j5RPROnt0POQSMK+r7P7EGMC/Qc=
github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
Expand Down Expand Up @@ -307,6 +310,7 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA=
github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE=
github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4=
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
github.com/jaypipes/ghw v0.10.0 h1:UHu9UX08Py315iPojADFPOkmjTsNzHj4g4adsNKKteY=
Expand All @@ -330,6 +334,10 @@ github.com/kairos-io/kairos-sdk v0.0.9-0.20230719194412-fe26d1de9166 h1:xAsvPm5a
github.com/kairos-io/kairos-sdk v0.0.9-0.20230719194412-fe26d1de9166/go.mod h1:AK9poWisuhnzri04diXnTG8L7EkOSUArSeeDn2LYFU0=
github.com/kairos-io/kairos-sdk v0.0.14 h1:yVKaay70cjmAUY6m4uLoV9UguBv3Dx3JxAh2faRlUZo=
github.com/kairos-io/kairos-sdk v0.0.14/go.mod h1:+fhVoCEA2hD7OFTmhDmy4pP3uC9q84OYhDa7irkEVWQ=
github.com/kairos-io/kairos-sdk v0.0.21 h1:iF1Wq+j4xTsR4TSNd/xkuOTTQDvf+yPB2E3IsmYsbOA=
github.com/kairos-io/kairos-sdk v0.0.21/go.mod h1:17dpFG2d3Q/TcT86DlLK5nNXEjlSrkYl7bsvO2cpYGE=
github.com/kairos-io/kairos-sdk v0.0.22-0.20231230114601-eaa9d3ce040b h1:Exytc6SC8OiGYJfRPBLJ3QVqkonR7A21Ra5zSZ2M178=
github.com/kairos-io/kairos-sdk v0.0.22-0.20231230114601-eaa9d3ce040b/go.mod h1:17dpFG2d3Q/TcT86DlLK5nNXEjlSrkYl7bsvO2cpYGE=
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c/go.mod h1:VOfm8h1NySetVlpHDSnbpCMsvCgYaU+YDn4XezUy2+4=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand Down Expand Up @@ -530,6 +538,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
Expand Down Expand Up @@ -686,6 +695,7 @@ golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down
219 changes: 89 additions & 130 deletions pkg/action/build-iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package action
import (
"fmt"
"path/filepath"
"strings"
"time"

"github.com/kairos-io/enki/pkg/constants"
Expand Down Expand Up @@ -82,13 +81,6 @@ func (b *BuildISOAction) ISORun() (err error) {
return err
}

b.cfg.Logger.Infof("Preparing EFI image...")
err = b.applySources(uefiDir, b.spec.UEFI...)
if err != nil {
b.cfg.Logger.Errorf("Failed installing EFI packages: %v", err)
return err
}

b.cfg.Logger.Infof("Preparing ISO image root tree...")
err = b.applySources(isoDir, b.spec.Image...)
if err != nil {
Expand Down Expand Up @@ -142,19 +134,99 @@ func (b BuildISOAction) prepareISORoot(isoDir string, rootDir string, uefiDir st
}

b.cfg.Logger.Info("Creating EFI image...")
err = b.createEFI(uefiDir, filepath.Join(isoDir, constants.IsoEFIPath))
err = b.createEFI(rootDir, isoDir)
if err != nil {
return err
}
return nil
}

func (b BuildISOAction) createEFI(root string, img string) error {
efiSize, err := utils.DirSize(b.cfg.Fs, root)
func (b BuildISOAction) createEFI(rootdir string, isoDir string) error {
var err error
img := filepath.Join(isoDir, constants.IsoEFIPath)
temp, _ := utils.TempDir(b.cfg.Fs, "", "enki-iso")
utils.MkdirAll(b.cfg.Fs, filepath.Join(temp, constants.EfiBootPath), constants.DirPerm)
utils.MkdirAll(b.cfg.Fs, filepath.Join(isoDir, constants.EfiBootPath), constants.DirPerm)
// Get possible shim file paths
shimFiles := sdk.GetEfiShimFiles(b.cfg.Arch)
// Get possible grub file paths
grubFiles := sdk.GetEfiGrubFiles(b.cfg.Arch)

// Calculate shim path based on arch
var shimDest string
switch b.cfg.Arch {
case constants.ArchAmd64, constants.Archx86:
shimDest = filepath.Join(temp, constants.ShimEfiDest)
case constants.ArchArm64:
shimDest = filepath.Join(temp, constants.ShimEfiArmDest)
default:
err = fmt.Errorf("not supported architecture: %v", b.cfg.Arch)
}

shimDone := false
for _, f := range shimFiles {
_, err := b.cfg.Fs.Stat(filepath.Join(rootdir, f))
if err != nil {
b.cfg.Logger.Warnf("skip copying %s: %s", filepath.Join(rootdir, f), err)
continue
}
b.cfg.Logger.Debugf("Copying %s to %s", filepath.Join(rootdir, f), shimDest)
err = utils.CopyFile(
b.cfg.Fs,
filepath.Join(rootdir, f),
shimDest,
)
if err != nil {
b.cfg.Logger.Warnf("error reading %s: %s", filepath.Join(rootdir, f), err)
continue
}
shimDone = true
break
}
if !shimDone {
b.cfg.Logger.Debugf("List of shim files searched for in %s: %s", rootdir, shimFiles)
return fmt.Errorf("could not find any shim file to copy")
}

grubDone := false
for _, f := range grubFiles {
stat, err := b.cfg.Fs.Stat(filepath.Join(rootdir, f))
if err != nil {
b.cfg.Logger.Warnf("skip copying %s: %s", filepath.Join(rootdir, f), err)
continue
}
// Same name as the source, shim looks for that name.
nameDest := filepath.Join(temp, "EFI/BOOT", stat.Name())
b.cfg.Logger.Debugf("Copying %s to %s", filepath.Join(rootdir, f), nameDest)

err = utils.CopyFile(
b.cfg.Fs,
filepath.Join(rootdir, f),
nameDest,
)
if err != nil {
b.cfg.Logger.Warnf("error reading %s: %s", filepath.Join(rootdir, f), err)
continue
}
grubDone = true
break
}
if !grubDone {
b.cfg.Logger.Debugf("List of grub files searched for: %s", grubFiles)
return fmt.Errorf("could not find any grub efi file to copy")
}

// Generate grub cfg that chainloads into the default livecd grub under /boot/grub2/grub.cfg
// Its read from the root of the livecd, so we need to copy it into /EFI/BOOT/grub.cfg
// This is due to the hybrid bios/efi boot mode of the livecd
// the uefi.img is loaded into memory and run, but grub only sees the livecd root
b.cfg.Fs.WriteFile(filepath.Join(isoDir, constants.EfiBootPath, constants.GrubCfg), []byte(constants.GrubEfiCfg), constants.FilePerm)

// Calculate EFI image size based on artifacts
efiSize, err := utils.DirSize(b.cfg.Fs, temp)
if err != nil {
return err
}

// align efiSize to the next 4MB slot
align := int64(4 * 1024 * 1024)
efiSizeMB := (efiSize/align*align + align) / (1024 * 1024)
Expand All @@ -168,14 +240,17 @@ func (b BuildISOAction) createEFI(root string, img string) error {
if err != nil {
return err
}
b.cfg.Logger.Debugf("EFI image created at %s", img)

files, err := b.cfg.Fs.ReadDir(root)
files, err := b.cfg.Fs.ReadDir(temp)
if err != nil {
return err
}

for _, f := range files {
_, err = b.cfg.Runner.Run("mcopy", "-s", "-i", img, filepath.Join(root, f.Name()), "::")
// This copies the efi files into the efi img used for the boot
b.cfg.Logger.Debugf("Copying %s to %s", filepath.Join(temp, f.Name()), img)
_, err = b.cfg.Runner.Run("mcopy", "-s", "-i", img, filepath.Join(temp, f.Name()), "::")
if err != nil {
return err
}
Expand Down Expand Up @@ -242,119 +317,3 @@ func (b BuildISOAction) applySources(target string, sources ...*v1.ImageSource)
}
return nil
}

func (g *BuildISOAction) PrepareEFI(rootDir, uefiDir string) error {
err := utils.MkdirAll(g.cfg.Fs, filepath.Join(uefiDir, constants.EfiBootPath), constants.DirPerm)
if err != nil {
return err
}

switch g.cfg.Arch {
case constants.ArchAmd64, constants.Archx86:
err = utils.CopyFile(
g.cfg.Fs,
filepath.Join(rootDir, constants.GrubEfiImagex86),
filepath.Join(uefiDir, constants.GrubEfiImagex86Dest),
)
case constants.ArchArm64:
err = utils.CopyFile(
g.cfg.Fs,
filepath.Join(rootDir, constants.GrubEfiImageArm64),
filepath.Join(uefiDir, constants.GrubEfiImageArm64Dest),
)
default:
err = fmt.Errorf("Not supported architecture: %v", g.cfg.Arch)
}
if err != nil {
return err
}

return g.cfg.Fs.WriteFile(filepath.Join(uefiDir, constants.EfiBootPath, constants.GrubCfg), []byte(constants.GrubEfiCfg), constants.FilePerm)
}

func (g *BuildISOAction) PrepareISO(rootDir, imageDir string) error {

err := utils.MkdirAll(g.cfg.Fs, filepath.Join(imageDir, constants.GrubPrefixDir), constants.DirPerm)
if err != nil {
return err
}

switch g.cfg.Arch {
case constants.ArchAmd64, constants.Archx86:
// Create eltorito image
eltorito, err := g.BuildEltoritoImg(rootDir)
if err != nil {
return err
}

// Inlude loaders in expected paths
loaderDir := filepath.Join(imageDir, constants.IsoLoaderPath)
err = utils.MkdirAll(g.cfg.Fs, loaderDir, constants.DirPerm)
if err != nil {
return err
}
loaderFiles := []string{eltorito, constants.GrubBootHybridImg}
loaderFiles = append(loaderFiles, strings.Split(constants.SyslinuxFiles, " ")...)
for _, f := range loaderFiles {
err = utils.CopyFile(g.cfg.Fs, filepath.Join(rootDir, f), loaderDir)
if err != nil {
return err
}
}
fontsDir := filepath.Join(loaderDir, "/grub2/fonts")
err = utils.MkdirAll(g.cfg.Fs, fontsDir, constants.DirPerm)
if err != nil {
return err
}
err = utils.CopyFile(g.cfg.Fs, filepath.Join(rootDir, constants.GrubFont), fontsDir)
if err != nil {
return err
}
case constants.ArchArm64:
// TBC
default:
return fmt.Errorf("Not supported architecture: %v", g.cfg.Arch)
}

// Write grub.cfg file
err = g.cfg.Fs.WriteFile(
filepath.Join(imageDir, constants.GrubPrefixDir, constants.GrubCfg),
[]byte(fmt.Sprintf(constants.GrubCfgTemplate, g.spec.GrubEntry, g.spec.Label)),
constants.FilePerm,
)
if err != nil {
return err
}

// Include EFI contents in iso root too
return g.PrepareEFI(rootDir, imageDir)
}

func (g *BuildISOAction) BuildEltoritoImg(rootDir string) (string, error) {
var args []string
args = append(args, "-O", constants.GrubBiosTarget)
args = append(args, "-o", constants.GrubBiosImg)
args = append(args, "-p", constants.GrubPrefixDir)
args = append(args, "-d", constants.GrubI386BinDir)
args = append(args, strings.Split(constants.GrubModules, " ")...)

chRoot := utils.NewChroot(rootDir, &g.cfg.Config)
out, err := chRoot.Run("grub2-mkimage", args...)
if err != nil {
g.cfg.Logger.Errorf("grub2-mkimage failed: %s", string(out))
g.cfg.Logger.Errorf("Error: %v", err)
return "", err
}

concatFiles := func() error {
return utils.ConcatFiles(
g.cfg.Fs, []string{constants.GrubBiosCDBoot, constants.GrubBiosImg},
constants.GrubEltoritoImg,
)
}
err = chRoot.RunCallback(concatFiles)
if err != nil {
return "", err
}
return constants.GrubEltoritoImg, nil
}
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func NewConfig(opts ...GenericOptions) *v1.Config {
if c.Mounter == nil {
c.Mounter = mount.New(constants.MountBinary)
}
litter.Config.HidePrivateFields = false

return c
}
Expand Down
Loading

0 comments on commit 1dfa982

Please sign in to comment.