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

Commit

Permalink
Merge pull request #173 from kairos-io/sysext_command
Browse files Browse the repository at this point in the history
  • Loading branch information
Itxaka authored Sep 16, 2024
2 parents 4b07f67 + 089dc0d commit 225c936
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/secscan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Checkout Source
uses: actions/checkout@v4
- name: Run Gosec Security Scanner
uses: securego/gosec@master
uses: securego/gosec@v2.21.0
with:
# we let the report trigger content trigger a failure using the GitHub Security features.
args: '-no-fail -fmt sarif -out results.sarif ./...'
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ARG LUET_VERSION=0.35.5
ARG GO_VERSION=1.23.0-alpine
ARG GO_VERSION=1.23-alpine

FROM quay.io/luet/base:$LUET_VERSION AS luet
FROM golang:$GO_VERSION AS builder
Expand Down
2 changes: 1 addition & 1 deletion Earthfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VERSION 0.7

# renovate: datasource=docker depName=golang versioning=docker
ARG --global GO_VERSION=1.23.0-bookworm
ARG --global GO_VERSION=1.23-bookworm
# renovate: datasource=github-releases depName=kairos-io/kairos
ARG IMAGE_VERSION=v3.1.2
ARG --global BASE_IMAGE=quay.io/kairos/ubuntu:24.04-core-amd64-generic-${IMAGE_VERSION}-uki
Expand Down
141 changes: 141 additions & 0 deletions cmd/sysext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package cmd

import (
"fmt"
"github.com/gofrs/uuid"
"github.com/kairos-io/enki/pkg/config"
"github.com/kairos-io/kairos-sdk/sysext"
"github.com/kairos-io/kairos-sdk/utils"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
)

func NewSysextCmd() *cobra.Command {
c := &cobra.Command{
Use: "sysext NAME CONTAINER",
Short: "Generate a sysextension from the last layer of the given CONTAINER",
Args: cobra.ExactArgs(2),
PreRunE: func(cmd *cobra.Command, args []string) error {
arch := viper.GetString("arch")
if arch != "amd64" && arch != "arm64" {
return fmt.Errorf("unsupported architecture: %s", arch)
}
return nil
},
RunE: func(cobraCmd *cobra.Command, args []string) error {
// Set this after parsing of the flags, so it fails on parsing and prints usage properly
cobraCmd.SilenceUsage = true
// we log the errors with our nice logger so stop cobra from logging them, just let it return the exit codes
cobraCmd.SilenceErrors = true

cfg, err := config.ReadConfigBuild(viper.GetString("config-dir"), cobraCmd.Flags())
if err != nil {
return err
}

name := args[0]
_, err = os.Stat(fmt.Sprintf("%s.sysext.raw", name))
if err == nil {
_ = os.Remove(fmt.Sprintf("%s.sysext.raw", name))
}
cfg.Logger.Logger.Info().Msg("🚀 Start sysext creation")

dir, _ := os.MkdirTemp("", "")
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
cfg.Logger.Logger.Error().Str("dir", dir).Err(err).Msg("⛔ removing dir")
}
}(dir)
cfg.Logger.Logger.Debug().Str("dir", dir).Msg("creating directory")
// Get the image struct
cfg.Logger.Logger.Info().Msg("💿 Getting image info")

platform := fmt.Sprintf("linux/%s", viper.Get("arch"))
image, err := utils.GetImage(args[1], platform, nil, nil)
if err != nil {
cfg.Logger.Logger.Error().Str("image", args[1]).Err(err).Msg("⛔ getting image")
return err
}
// Only for sysext, confext not supported yet
AllowList := regexp.MustCompile(`^usr/*|^/usr/*`)
// extract the files into the temp dir
cfg.Logger.Logger.Info().Msg("📤 Extracting archives from image layer")
err = sysext.ExtractFilesFromLastLayer(image, dir, cfg.Logger, AllowList)
if err != nil {
cfg.Logger.Logger.Error().Str("image", args[1]).Err(err).Msg("⛔ extracting layer")
}

// Now create the file that tells systemd that this is a sysext!
err = os.MkdirAll(filepath.Join(dir, "/usr/lib/extension-release.d/"), os.ModeDir|os.ModePerm)
if err != nil {
cfg.Logger.Logger.Error().Str("dir", filepath.Join(dir, "/usr/lib/extension-release.d/")).Err(err).Msg("⛔ creating dir")
}

arch := "x86-64"

if viper.Get("arch") == "arm64" {
arch = "arm64"
}

extensionData := fmt.Sprintf("ID=_any\nARCHITECTURE=%s", arch)

// If the extension ships any service files, we want this so systemd is reloaded and the service available immediately
if viper.GetBool("service-reload") {
extensionData = fmt.Sprintf("%s\nEXTENSION_RELOAD_MANAGER=1", extensionData)
}
err = os.WriteFile(filepath.Join(dir, "/usr/lib/extension-release.d/", fmt.Sprintf("extension-release.%s", name)), []byte(extensionData), os.ModePerm)
if err != nil {
cfg.Logger.Logger.Error().Str("file", fmt.Sprintf("extension-release.%s", name)).Err(err).Msg("⛔ creating releasefile")
}

cfg.Logger.Logger.Info().Msg("📦 Packing sysext into raw image")
// Call systemd-repart to create the sysext based off the files
command := exec.Command(
"systemd-repart",
"--make-ddi=sysext",
"--image-policy=root=verity+signed+absent:usr=verity+signed+absent",
fmt.Sprintf("--architecture=%s", arch),
// Having a fixed predictable seed makes the Image UUID be always the same if the inputs are the same,
// so its a reproducible image. So getting the same files and same cert/key should produce a reproducible image always
// Another layer to verify images, even if its a manual check, we make it easier
fmt.Sprintf("--seed=%s", uuid.NewV5(uuid.NamespaceDNS, "kairos-sysext")),
fmt.Sprintf("--copy-source=%s", dir),
fmt.Sprintf("%s.sysext.raw", name), // output sysext image
fmt.Sprintf("--private-key=%s", viper.Get("private-key")),
fmt.Sprintf("--certificate=%s", viper.Get("certificate")),
)
out, err := command.CombinedOutput()
cfg.Logger.Logger.Debug().Str("output", string(out)).Msg("building sysext")
if err != nil {
cfg.Logger.Logger.Error().Err(err).Str("command", strings.Join(command.Args, " ")).Msg("⛔ building sysext")
return err
}

cfg.Logger.Logger.Info().Str("output", fmt.Sprintf("%s.sysext.raw", name)).Msg("🎉 Done sysext creation")
return nil
},
}
c.Flags().String("private-key", "", "Private key to sign the sysext with")
c.Flags().String("certificate", "", "Certificate to sign the sysext with")
c.Flags().Bool("service-reload", false, "Make systemctl reload the service when loading the sysext. This is useful for sysext that provide systemd service files.")
c.Flags().String("arch", "amd64", "Arch to get the image from and build the sysext for. Accepts amd64 and arm64 values.")
_ = c.MarkFlagRequired("private-key")
_ = c.MarkFlagRequired("certificate")

err := viper.BindPFlags(c.Flags())
if err != nil {
return nil
}

return c
}

func init() {
rootCmd.AddCommand(NewSysextCmd())
}
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
module github.com/kairos-io/enki

go 1.22.5
go 1.23.1

require (
github.com/containerd/containerd v1.7.21
github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca
github.com/foxboron/sbctl v0.0.0-20240526163235-64e649b31c8e
github.com/gofrs/uuid v4.4.0+incompatible
github.com/google/go-containerregistry v0.20.2
github.com/google/uuid v1.6.0
github.com/kairos-io/go-ukify v0.2.2
github.com/kairos-io/kairos-agent/v2 v2.13.5
github.com/kairos-io/kairos-sdk v0.4.1
github.com/kairos-io/kairos-sdk v0.4.3
github.com/klauspost/compress v1.17.9
github.com/mitchellh/mapstructure v1.5.0
github.com/mudler/go-processmanager v0.0.0-20240820160718-8b802d3ecf82
Expand Down Expand Up @@ -59,7 +60,7 @@ require (
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/cli v27.1.1+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v27.1.2+incompatible // indirect
github.com/docker/docker v27.2.0+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
Expand Down
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m3
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY=
github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
Expand Down Expand Up @@ -402,6 +404,8 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
Expand Down Expand Up @@ -661,6 +665,16 @@ github.com/kairos-io/kairos-agent/v2 v2.13.5 h1:WEEU6efzWlsbT6KQNir6h3WmrdVgwGq7
github.com/kairos-io/kairos-agent/v2 v2.13.5/go.mod h1:yE4N0jbBUV6maQScBl8KLnmFbbkD+xEUNAzfWF7uGZw=
github.com/kairos-io/kairos-sdk v0.4.1 h1:WF+X30URojMxV7AlzVj0uejvPWG4zq1WNga0swAX4dY=
github.com/kairos-io/kairos-sdk v0.4.1/go.mod h1:lgQAYkh0aWIZg4/CQcC+OPQp95ONs2PzkMIcAq8w6OY=
github.com/kairos-io/kairos-sdk v0.4.2-0.20240903105642-a509f9388eb6 h1:auCG/aP/esvKCq1aeeoyqieTMbRO7WHKs4fY05WWXc0=
github.com/kairos-io/kairos-sdk v0.4.2-0.20240903105642-a509f9388eb6/go.mod h1:0ltpn7BODc+ztbee+2y/GfJMW125H1OFqHxSNqgWObE=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905081210-705fa3ebfa2a h1:zBGCh/ZPeOHdcbZdATg+LPCypdwx+3WzfD4a1TVwCYs=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905081210-705fa3ebfa2a/go.mod h1:0ltpn7BODc+ztbee+2y/GfJMW125H1OFqHxSNqgWObE=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905082603-42cf473c006c h1:jJ1KRqVEHN8QodFaA4maYlbygDwCdvSGbROFDDMk4lo=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905082603-42cf473c006c/go.mod h1:0ltpn7BODc+ztbee+2y/GfJMW125H1OFqHxSNqgWObE=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905131825-2d092e9edd4d h1:l2YccCeCefd9AnhO8JxgoqWiI/9aqo/knIV+zsBF/ms=
github.com/kairos-io/kairos-sdk v0.4.3-0.20240905131825-2d092e9edd4d/go.mod h1:0ltpn7BODc+ztbee+2y/GfJMW125H1OFqHxSNqgWObE=
github.com/kairos-io/kairos-sdk v0.4.3 h1:gIC/PsWjv9/Z+6RIHRG9IS5MB9gACw1ZjPAi7VydSSo=
github.com/kairos-io/kairos-sdk v0.4.3/go.mod h1:bxUPzirl8vNtqB48FJ2835QKio3d3PrHbkAejkibV8I=
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-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand Down

0 comments on commit 225c936

Please sign in to comment.