Skip to content

Commit

Permalink
feat(config): support secureboot installer and ISO url
Browse files Browse the repository at this point in the history
This allows generating per node secureboot installer and ISO url.
You can have per node `machineSpec` like so:
```yaml
---
nodes:
  - machineSpec:
      secureboot: true
```

And the generated installer url will be something like:
`factory.talos.dev/installer-secureboot/<hash>:v1.6.0`
  • Loading branch information
budimanjojo committed Jan 22, 2024
1 parent 63622de commit 606f72f
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 23 deletions.
2 changes: 2 additions & 0 deletions cmd/genurl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var (
genurlExtensions []string
genurlKernelArgs []string
genurlOfflineMode bool
genurlSecureboot bool
)

var genurlCmd = &cobra.Command{
Expand All @@ -32,4 +33,5 @@ func init() {
genurlCmd.PersistentFlags().StringSliceVarP(&genurlExtensions, "extension", "e", []string{}, "Official extension image to be included in the image (ignored when talconfig.yaml is found)")
genurlCmd.PersistentFlags().StringSliceVarP(&genurlKernelArgs, "kernel-arg", "k", []string{}, "Kernel arguments to be passed to the image kernel (ignored when talconfig.yaml is found)")
genurlCmd.PersistentFlags().BoolVar(&genurlOfflineMode, "offline-mode", false, "Generate schematic ID without doing POST request to image-factory")
genurlCmd.PersistentFlags().BoolVar(&genurlSecureboot, "secure-boot", false, "Whether to generate Secure Boot enabled URL")
}
11 changes: 8 additions & 3 deletions cmd/genurl_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ var genurlInstallerCmd = &cobra.Command{
}

if node.IPAddress == genurlNode || node.Hostname == genurlNode {
url, err := talos.GetInstallerURL(schema, cfg.GetImageFactory(), cfg.GetTalosVersion(), genurlOfflineMode)
url, err := talos.GetInstallerURL(schema, cfg.GetImageFactory(), node.GetMachineSpec(), cfg.GetTalosVersion(), genurlOfflineMode)
if err != nil {
log.Fatalf("Failed to generate installer url for %s, %v", node.Hostname, err)
}
urls = append(urls, fmt.Sprintf(node.Hostname+": "+url))
break
}

url, err := talos.GetInstallerURL(schema, cfg.GetImageFactory(), cfg.GetTalosVersion(), genurlOfflineMode)
url, err := talos.GetInstallerURL(schema, cfg.GetImageFactory(), node.GetMachineSpec(), cfg.GetTalosVersion(), genurlOfflineMode)
if err != nil {
log.Fatalf("Failed to generate installer url for %s, %v", node.Hostname, err)
}
Expand All @@ -70,10 +70,15 @@ var genurlInstallerCmd = &cobra.Command{
},
},
}

tconfig := &config.TalhelperConfig{}
tconfig.ImageFactory.RegistryURL = genurlRegistryURL

url, err := talos.GetInstallerURL(cfg, tconfig.GetImageFactory(), genurlVersion, genurlOfflineMode)
spec := &config.MachineSpec{
Secureboot: genurlSecureboot,
}

url, err := talos.GetInstallerURL(cfg, tconfig.GetImageFactory(), spec, genurlVersion, genurlOfflineMode)
if err != nil {
log.Fatalf("Failed to generate installer url, %v", err)
}
Expand Down
8 changes: 6 additions & 2 deletions cmd/genurl_iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
var (
genurlISOTalosMode string
genurlISOArch string
genurlISOUseUKI bool
)

var genurlISOCmd = &cobra.Command{
Expand Down Expand Up @@ -77,8 +78,10 @@ var genurlISOCmd = &cobra.Command{
}
tcfg := &config.TalhelperConfig{}
spec := &config.MachineSpec{
Mode: genurlISOTalosMode,
Arch: genurlISOArch,
Mode: genurlISOTalosMode,
Arch: genurlISOArch,
Secureboot: genurlSecureboot,
UseUKI: genurlISOUseUKI,
}
url, err := talos.GetISOURL(cfg, tcfg.GetImageFactory(), spec, genurlVersion, genurlOfflineMode)
if err != nil {
Expand All @@ -97,4 +100,5 @@ func init() {

genurlISOCmd.Flags().StringVarP(&genurlISOTalosMode, "talos-mode", "m", "metal", "Talos runtime mode to generate URL")
genurlISOCmd.Flags().StringVarP(&genurlISOArch, "arch", "a", "amd64", "CPU architecture support of the image")
genurlISOCmd.Flags().BoolVar(&genurlISOUseUKI, "use-uki", false, "Whether to generate UKI image url if Secure Boot is enabled")
}
34 changes: 29 additions & 5 deletions docs/docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -651,24 +651,24 @@ schematicEndpoint: /schematics
<tr markdown="1">
<td markdown="1">`installerURLTmpl`</td>
<td markdown="1">string</td>
<td markdown="1"><details><summary>Go template to parse the full installer URL.</summary>Available placeholders: `RegistryURL`,`ID`,`Version`</details><details><summary>*Show example*</summary>
<td markdown="1"><details><summary>Go template to parse the full installer URL.</summary>Available placeholders: `RegistryURL`,`ID`,`Version`, `Secureboot`</details><details><summary>*Show example*</summary>
```yaml
installerURLTmpl: "{{.RegistryURL}}/installer/{{.ID}}:{{.Version}}"
```
</summary></td>
<td markdown="1" align="center">`{{.RegistryURL}}/installer/{{.ID}}:{{.Version}}`</td>
<td markdown="1" align="center">`{{.RegistryURL}}/installer{{if .Secureboot}}-secureboot{{end}}/{{.ID}}:{{.Version}}`</td>
<td markdown="1" align="center">:negative_squared_cross_mark:</td>
</tr>

<tr markdown="1">
<td markdown="1">`ISOURLTmpl`</td>
<td markdown="1">string</td>
<td markdown="1"><details><summary>Go template to parse the full ISO image URL.</summary>Available placeholders: `Protocol`,`RegistryURL`,`ID`,`Version`,`Mode`,`Arch`</details><details><summary>*Show example*</summary>
<td markdown="1"><details><summary>Go template to parse the full ISO image URL.</summary>Available placeholders: `Protocol`,`RegistryURL`,`ID`,`Version`,`Mode`,`Arch`, `Secureboot`, `UseUKI`</details><details><summary>*Show example*</summary>
```yaml
installerURLTmpl: "{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}.iso"
ISOURLTmpl: "{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}.iso"
```
</summary></td>
<td markdown="1" align="center">`{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}.iso`</td>
<td markdown="1" align="center">`{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}{{if .Secureboot}}-secureboot{{end}}{{if and .Secureboot .UseUKI}}-uki.efi{{else}}.iso{{end}}`</td>
<td markdown="1" align="center">:negative_squared_cross_mark:</td>
</tr>

Expand Down Expand Up @@ -707,6 +707,30 @@ arch: arm64
<td markdown="1" align="center">:negative_squared_cross_mark:</td>
</tr>

<tr markdown="1">
<td markdown="1">`secureboot`</td>
<td markdown="1">bool</td>
<td markdown="1">Whether to enable Secure Boot.<details><summary>*Show example*</summary>
```yaml
secureboot: true
```
</summary></td>
<td markdown="1" align="center">`false`</td>
<td markdown="1" align="center">:negative_squared_cross_mark:</td>
</tr>

<tr markdown="1">
<td markdown="1">`useUKI`</td>
<td markdown="1">bool</td>
<td markdown="1">Whether to use UKI if Secure Boot is enabled.<details><summary>*Show example*</summary>
```yaml
useUKI: true
```
</summary></td>
<td markdown="1" align="center">`false`</td>
<td markdown="1" align="center">:negative_squared_cross_mark:</td>
</tr>

</table>

## IngressFirewall
Expand Down
5 changes: 5 additions & 0 deletions example/talconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ nodes:
except: 172.20.0.1/32
ipAddress: 192.168.200.11
controlPlane: true
machineSpec:
mode: metal
arch: amd64
useUKI: true
secureboot: true
schematic:
customization:
extraKernelArgs:
Expand Down
10 changes: 6 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,15 @@ type ImageFactory struct {
RegistryURL string `yaml:"registryURL,omitempty" jsonschema:"default=factory.talos.dev,description=Registry url or the image"`
SchematicEndpoint string `yaml:"schematicEndpoint,omitempty" jsonschema:"default=/schematics,description:Endpoint to get schematic ID from the registry"`
Protocol string `yaml:"protocol,omitempty" jsonschema:"default=https,description=Protocol of the registry(https or http)"`
InstallerURLTmpl string `yaml:"installerURLTmpl,omitempty" jsonschema:"default={{.RegistryURL}}/installer/{{.ID}}:{{.Version}},description=Template for installer image URL"`
ISOURLTmpl string `yaml:"ISOURLTmpl,omitempty" jsonschema:"default={{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}.iso,description=Template for ISO image URL"`
InstallerURLTmpl string `yaml:"installerURLTmpl,omitempty" jsonschema:"default={{.RegistryURL}}/installer{{if .Secureboot}}-secureboot{{end}}/{{.ID}}:{{.Version}},description=Template for installer image URL"`
ISOURLTmpl string `yaml:"ISOURLTmpl,omitempty" jsonschema:"default={{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}{{if .Secureboot}}-secureboot{{end}}{{if and .Secureboot .UseUKI}}-uki.efi{{else}}.iso{{end}},description=Template for ISO image URL"`
}

type MachineSpec struct {
Mode string `yaml:"mode,omitempty" jsonschema:"default=metal,description=Machine mode (e.g: metal)"`
Arch string `yaml:"arch,omitempty" jsonschema:"default=amd64,description=Machine architecture (e.g: amd64, arm64)"`
Mode string `yaml:"mode,omitempty" jsonschema:"default=metal,description=Machine mode (e.g: metal)"`
Arch string `yaml:"arch,omitempty" jsonschema:"default=amd64,description=Machine architecture (e.g: amd64, arm64)"`
Secureboot bool `yaml:"secureboot,omitempty" jsonschema:"default=false,description=Whether to enable Secure Boot"`
UseUKI bool `yaml:"useUKI,omitempty" jsonschema:"default=false,description=Whether to use UKI if Secure Boot is enabled"`
}

type IngressFirewall struct {
Expand Down
6 changes: 4 additions & 2 deletions pkg/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ func (c *TalhelperConfig) GetImageFactory() *ImageFactory {
RegistryURL: "factory.talos.dev",
SchematicEndpoint: "/schematics",
Protocol: "https",
InstallerURLTmpl: "{{.RegistryURL}}/installer/{{.ID}}:{{.Version}}",
ISOURLTmpl: "{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}.iso",
InstallerURLTmpl: "{{.RegistryURL}}/installer{{if .Secureboot}}-secureboot{{end}}/{{.ID}}:{{.Version}}",
ISOURLTmpl: "{{.Protocol}}://{{.RegistryURL}}/image/{{.ID}}/{{.Version}}/{{.Mode}}-{{.Arch}}{{if .Secureboot}}-secureboot{{end}}{{if and .Secureboot .UseUKI}}-uki.efi{{else}}.iso{{end}}",
}
if c.ImageFactory.RegistryURL != "" {
result.RegistryURL = c.ImageFactory.RegistryURL
Expand Down Expand Up @@ -107,6 +107,8 @@ func (n *Node) GetMachineSpec() *MachineSpec {
if n.MachineSpec.Arch != "" {
result.Arch = n.MachineSpec.Arch
}
result.Secureboot = n.MachineSpec.Secureboot
result.UseUKI = n.MachineSpec.UseUKI
return result
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/generate/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ func GenerateUpgradeCommand(cfg *config.TalhelperConfig, outDir string, node str
url = n.TalosImageURL + ":" + cfg.GetTalosVersion()
} else if n.Schematic != nil {
var err error
url, err = talos.GetInstallerURL(n.Schematic, cfg.GetImageFactory(), cfg.GetTalosVersion(), true)
url, err = talos.GetInstallerURL(n.Schematic, cfg.GetImageFactory(), n.GetMachineSpec(), cfg.GetTalosVersion(), true)
if err != nil {
return fmt.Errorf("Failed to generate installer url for %s, %v", n.Hostname, err)
}
} else {
url, _ = talos.GetInstallerURL(&schematic.Schematic{}, cfg.GetImageFactory(), cfg.GetTalosVersion(), true)
url, _ = talos.GetInstallerURL(&schematic.Schematic{}, cfg.GetImageFactory(), n.GetMachineSpec(), cfg.GetTalosVersion(), true)
}

upgradeFlags := []string{
Expand Down
4 changes: 2 additions & 2 deletions pkg/talos/nodeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func installerURL(node *config.Node, cfg taloscfg.Provider, iFactory *config.Ima
version := strings.Split(cfg.Machine().Install().Image(), ":")

if node.Schematic != nil && node.TalosImageURL == "" {
url, err := GetInstallerURL(node.Schematic, iFactory, version[1], offlineMode)
url, err := GetInstallerURL(node.Schematic, iFactory, node.GetMachineSpec(), version[1], offlineMode)
if err != nil {
return "", err
}
Expand All @@ -118,5 +118,5 @@ func installerURL(node *config.Node, cfg taloscfg.Provider, iFactory *config.Ima
return node.TalosImageURL + ":" + version[1], nil
}

return GetInstallerURL(&schematic.Schematic{}, iFactory, version[1], offlineMode)
return GetInstallerURL(&schematic.Schematic{}, iFactory, node.GetMachineSpec(), version[1], offlineMode)
}
8 changes: 7 additions & 1 deletion pkg/talos/schematic.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type installerTmpl struct {
RegistryURL string
ID string
Version string
Secureboot bool
}

type isoTmpl struct {
Expand All @@ -31,12 +32,15 @@ type isoTmpl struct {
Version string
Mode string
Arch string
Secureboot bool
UseUKI bool
}

func GetInstallerURL(cfg *schematic.Schematic, factory *config.ImageFactory, version string, offlineMode bool) (string, error) {
func GetInstallerURL(cfg *schematic.Schematic, factory *config.ImageFactory, spec *config.MachineSpec, version string, offlineMode bool) (string, error) {
tmplData := installerTmpl{
RegistryURL: factory.RegistryURL,
Version: version,
Secureboot: spec.Secureboot,
}

id, err := getSchematicID(cfg, factory, offlineMode)
Expand Down Expand Up @@ -65,6 +69,8 @@ func GetISOURL(cfg *schematic.Schematic, factory *config.ImageFactory, spec *con
Version: version,
Mode: spec.Mode,
Arch: spec.Arch,
Secureboot: spec.Secureboot,
UseUKI: spec.UseUKI,
}

id, err := getSchematicID(cfg, factory, offlineMode)
Expand Down
11 changes: 9 additions & 2 deletions pkg/talos/schematic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func TestGetInstallerURL(t *testing.T) {
name string
cfg *schematic.Schematic
iFactory *config.ImageFactory
machineSpec *config.MachineSpec
version string
expectedURL string
}
Expand All @@ -54,6 +55,7 @@ func TestGetInstallerURL(t *testing.T) {
iFactory: &config.ImageFactory{
RegistryURL: "factory.talos.dev",
},
machineSpec: &config.MachineSpec{},
version: "v1.5.4",
expectedURL: "factory.talos.dev/installer/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba:v1.5.4",
},
Expand All @@ -70,6 +72,7 @@ func TestGetInstallerURL(t *testing.T) {
iFactory: &config.ImageFactory{
RegistryURL: "",
},
machineSpec: &config.MachineSpec{},
version: "v1.5.4",
expectedURL: "factory.talos.dev/installer/98442b5bb4e8d050f30978ce3e6ec22e7bf534d57cafcd51313235128057e612:v1.5.4",
},
Expand All @@ -82,6 +85,7 @@ func TestGetInstallerURL(t *testing.T) {
},
},
iFactory: &config.ImageFactory{},
machineSpec: &config.MachineSpec{},
expectedURL: "factory.talos.dev/installer/ff5083b14ccb03821ea738d712ac08a82b44d2693013622059edaae286665239:",
},

Expand All @@ -98,14 +102,17 @@ func TestGetInstallerURL(t *testing.T) {
iFactory: &config.ImageFactory{
RegistryURL: "test.registry/",
},
machineSpec: &config.MachineSpec{
Secureboot: true,
},
version: "1.5.4",
expectedURL: "test.registry//installer/104c23dfe7c5bfeff6a4cc7e166d8b3bba0f371760592c7677c90c822bb1d109:1.5.4",
expectedURL: "test.registry//installer-secureboot/104c23dfe7c5bfeff6a4cc7e166d8b3bba0f371760592c7677c90c822bb1d109:1.5.4",
},
} {
t.Run(test.name, func(t *testing.T) {
cfg := &config.TalhelperConfig{}
cfg.ImageFactory = *test.iFactory
url, err := GetInstallerURL(test.cfg, cfg.GetImageFactory(), test.version, true)
url, err := GetInstallerURL(test.cfg, cfg.GetImageFactory(), test.machineSpec, test.version, true)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 606f72f

Please sign in to comment.