-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Stéphane Graber <[email protected]>
- Loading branch information
Showing
8 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,5 @@ mkosi.crt | |
mkosi.key | ||
|
||
mkosi.images/base/mkosi.extra/boot/EFI/ | ||
|
||
incus-osd/incus-osd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package main | ||
|
||
import ( | ||
"compress/gzip" | ||
"context" | ||
"fmt" | ||
"io" | ||
"log/slog" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
"slices" | ||
"strings" | ||
|
||
"github.com/google/go-github/v68/github" | ||
|
||
"github.com/lxc/incus-os/incus-osd/internal/keyring" | ||
"github.com/lxc/incus-os/incus-osd/internal/systemd" | ||
) | ||
|
||
var ( | ||
ghOrganization = "lxc" | ||
ghRepository = "incus-os" | ||
osExtensions = []string{"debug.raw.gz", "incus.raw.gz"} | ||
osExtensionsPath = "/var/lib/extensions" | ||
) | ||
|
||
func main() { | ||
err := run() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error: %v\n", err) | ||
} | ||
} | ||
|
||
func run() error { | ||
ctx := context.TODO() | ||
|
||
// Prepare a logger. | ||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) | ||
slog.SetDefault(logger) | ||
|
||
// Check kernel keyring. | ||
slog.Info("Getting trusted system keys") | ||
keys, err := keyring.GetKeys(ctx, keyring.PlatformKeyring) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Determine runtime mode. | ||
mode := "unsafe" | ||
|
||
for _, key := range keys { | ||
if key.Fingerprint == "7d4dc2ac7ad1ef27365ff599612e07e2312adf79" { | ||
mode = "release" | ||
} | ||
|
||
if mode == "unsafe" && strings.HasPrefix(key.Description, "mkosi of ") { | ||
mode = "dev" | ||
} | ||
|
||
slog.Info("Platform keyring entry", "name", key.Description, "key", key.Fingerprint) | ||
} | ||
|
||
slog.Info("Starting up", "mode", mode, "app", "incus") | ||
|
||
// Fetch the system extensions. | ||
gh := github.NewClient(nil) | ||
|
||
release, _, err := gh.Repositories.GetLatestRelease(ctx, ghOrganization, ghRepository) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
slog.Info(fmt.Sprintf("Found latest %s/%s release", ghOrganization, ghRepository), "tag", release.GetTagName()) | ||
|
||
assets, _, err := gh.Repositories.ListReleaseAssets(ctx, ghOrganization, ghRepository, release.GetID(), nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = os.MkdirAll(osExtensionsPath, 0700) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, asset := range assets { | ||
if !slices.Contains(osExtensions, asset.GetName()) { | ||
continue | ||
} | ||
|
||
slog.Info("Downloading OS extension", "file", asset.GetName(), "url", asset.GetBrowserDownloadURL()) | ||
|
||
rc, _, err := gh.Repositories.DownloadReleaseAsset(ctx, ghOrganization, ghRepository, asset.GetID(), http.DefaultClient) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer rc.Close() | ||
|
||
body, err := gzip.NewReader(rc) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer body.Close() | ||
|
||
fd, err := os.Create(filepath.Join(osExtensionsPath, strings.TrimSuffix(asset.GetName(), ".gz"))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer fd.Close() | ||
|
||
_, err = io.Copy(fd, body) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// Apply the system extensions. | ||
slog.Info("Refreshing system extensions") | ||
err = systemd.RefreshExtensions(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Apply the system users. | ||
slog.Info("Refreshing users") | ||
err = systemd.RefreshUsers(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Enable and start Incus. | ||
slog.Info("Starting Incus") | ||
err = systemd.EnableUnit(ctx, true, "incus.socket", "incus-lxcfs.service", "incus-startup.service", "incus.service") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
module github.com/lxc/incus-os/incus-osd | ||
|
||
go 1.23.4 | ||
|
||
require ( | ||
github.com/google/go-github/v68 v68.0.0 | ||
github.com/lxc/incus/v6 v6.8.0 | ||
) | ||
|
||
require ( | ||
github.com/google/go-querystring v1.1.0 // indirect | ||
golang.org/x/sys v0.28.0 // indirect | ||
gopkg.in/yaml.v2 v2.4.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= | ||
github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= | ||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= | ||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= | ||
github.com/lxc/incus/v6 v6.8.0 h1:SgAvmsRfzRYuwTsJbaLeX9xsJfAb6nckGOu1nXI8dcQ= | ||
github.com/lxc/incus/v6 v6.8.0/go.mod h1:dVwGmKWdDJvFK4MzJsZGqFKUKalAKwPwc5q126VyMIQ= | ||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= | ||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | ||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package keyring | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"os" | ||
"strings" | ||
) | ||
|
||
// PlatformKeyring is the SecureBoot platform keyring. | ||
var PlatformKeyring = "1f010000" | ||
|
||
// Key represents a key in the Linux kernel keyring. | ||
type Key struct { | ||
Description string | ||
Fingerprint string | ||
Type string | ||
} | ||
|
||
// GetKeys returns a list of keys in the requested keyring. | ||
func GetKeys(ctx context.Context, keyring string) ([]Key, error) { | ||
keys := []Key{} | ||
|
||
// Read the key list. | ||
fd, err := os.Open("/proc/keys") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
defer fd.Close() | ||
|
||
// Iterate over the entries.. | ||
fdScan := bufio.NewScanner(fd) | ||
for fdScan.Scan() { | ||
fields := strings.Fields(fdScan.Text()) | ||
|
||
if len(fields) < 10 { | ||
// Skipping invalid entries. | ||
continue | ||
} | ||
|
||
if fields[4] != keyring { | ||
// Skipping entries outside of the platform (SecureBoot) keyring. | ||
continue | ||
} | ||
|
||
keyFields := strings.Split(strings.Join(fields[8:], " "), ": ") | ||
|
||
keys = append(keys, Key{ | ||
Description: strings.Join(keyFields[0:len(keyFields)-2], ": "), | ||
Fingerprint: keyFields[len(keyFields)-2], | ||
Type: strings.Fields(keyFields[len(keyFields)-1])[0], | ||
}) | ||
} | ||
|
||
return keys, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package systemd | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/lxc/incus/v6/shared/subprocess" | ||
) | ||
|
||
func RefreshExtensions(ctx context.Context) error { | ||
_, err := subprocess.RunCommandContext(ctx, "systemd-sysext", "refresh") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package systemd | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/lxc/incus/v6/shared/subprocess" | ||
) | ||
|
||
func EnableUnit(ctx context.Context, now bool, units ...string) error { | ||
args := []string{"enable"} | ||
|
||
if now { | ||
args = append(args, "--now") | ||
} | ||
|
||
args = append(args, units...) | ||
|
||
_, err := subprocess.RunCommandContext(ctx, "systemctl", args...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package systemd | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/lxc/incus/v6/shared/subprocess" | ||
) | ||
|
||
func RefreshUsers(ctx context.Context) error { | ||
_, err := subprocess.RunCommandContext(ctx, "systemd-sysusers") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |