Skip to content

Commit

Permalink
Implement new configuration strategy for httpboot plugin (#243)
Browse files Browse the repository at this point in the history
* Implement new configuration strategy for HTTPBOOT plugin

* Fix complaince check

* Add test configs dynamically

* Update Readme.md

* Refactor tests

Fix some debugging output

---------

Co-authored-by: kkumar <[email protected]>
Co-authored-by: Damyan Yordanov <[email protected]>
  • Loading branch information
3 people authored Jan 16, 2025
1 parent a5867fb commit c2b755a
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 133 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ Implements HTTP boot from [Unifed Kernel Image](https://uapi-group.org/specifica
Delivers the HTTP boot image as a [BootFileURL](https://www.rfc-editor.org/rfc/rfc5970.html#section-3.2). Based on configuration it delivers either a client-specific UKIs dynamically or a default UKI for all clients. When client-specific UKIs are configured, IPv6 relays *must* be used, so the client can be identified based on its link-local address (which the relay always provides).
### Configuration
A single HTTP(s) URL shall be passed as a string. It must be either
A single HTTP(s) URL shall be passed as a string in `httpboot_config.yaml` as given below. It must be either
- a direct URL to an UKI (default UKI for all clients)
- magic identifier `bootservice:`+ a URL to a boot service delivering dynamically client-specific UKIs based on client identification
- `clientSpecific: false` deliver default UKI for all clients via a static address
- `clientSpecific: true` use a boot service delivering dynamically client-specific UKIs, based on client identification
````yaml
bootFile: http://[2001:db8::1]/default-image.uki
clientSpecific: false
````
### Notes
- not tested on IPv4
- IPv6 relays are supported
Expand Down
2 changes: 1 addition & 1 deletion config/default/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ data:
- onmetal:
- dns: 2001:4860:4860::6464 2001:4860:4860::64
- pxeboot: pxeboot_config.yaml
- httpboot: bootservice:http://example.com/boot-operator-endpoint:8083
- httpboot: httpboot_config.yaml
2 changes: 1 addition & 1 deletion example/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ server6:
# always provide the same IP address, no matter who's asking:
# - bluefield: bluefield_config.yaml
# implement HTTPBoot
- httpboot: http://[2001:db8::1]/image.uki
- httpboot: httpboot_config.yaml
# add leased IPs to ironcore's IPAM
- ipam: ipam_config.yaml
# lease IPs based on /127 subnets coming from relays running on the switches
Expand Down
2 changes: 2 additions & 0 deletions example/httpboot_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bootFile: http://[2001:db8::1]/default-image.uki
clientSpecific: false
9 changes: 9 additions & 0 deletions internal/api/httpboot_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: MIT

package api

type HttpBootConfig struct {
BootFile string `yaml:"bootFile"`
ClientSpecific bool `yaml:"clientSpecific"`
}
44 changes: 35 additions & 9 deletions plugins/httpboot/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import (
"io"
"net/http"
"net/url"
"os"
"strings"

"github.com/coredhcp/coredhcp/handler"
"github.com/coredhcp/coredhcp/logger"
"github.com/coredhcp/coredhcp/plugins"
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/ironcore-dev/fedhcp/internal/api"
"gopkg.in/yaml.v2"
)

var bootFile4 string
Expand All @@ -33,27 +36,50 @@ var Plugin = plugins.Plugin{

const httpClient = "HTTPClient"

func parseArgs(args ...string) (*url.URL, bool, error) {
func parseArgs(args ...string) (string, error) {
if len(args) != 1 {
return nil, false, fmt.Errorf("exactly one argument must be passed to the httpboot plugin, got %d", len(args))
return "", fmt.Errorf("exactly one argument must be passed to the plugin, got %d", len(args))
}
arg := args[0]
useBootService := strings.HasPrefix(arg, "bootservice:")
if useBootService {
arg = strings.TrimPrefix(arg, "bootservice:")
return args[0], nil
}

func loadConfig(args ...string) (*api.HttpBootConfig, error) {
path, err := parseArgs(args...)
if err != nil {
return nil, fmt.Errorf("invalid configuration: %v", err)
}

log.Debugf("Reading config file %s", path)
configData, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %v", err)
}

config := &api.HttpBootConfig{}
if err = yaml.Unmarshal(configData, config); err != nil {
return nil, fmt.Errorf("failed to parse config file: %v", err)
}
return config, nil
}

func parseConfig(args ...string) (*url.URL, bool, error) {
httpbootConfig, err := loadConfig(args...)
if err != nil {
return nil, false, fmt.Errorf("erorr loading plugin configuration: %v", err)
}
arg := httpbootConfig.BootFile
parsedURL, err := url.Parse(arg)
if err != nil {
return nil, false, fmt.Errorf("invalid URL: %v", err)
}
if (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") || parsedURL.Host == "" || parsedURL.Path == "" {
return nil, false, fmt.Errorf("malformed httpboot parameter, should be a valid HTTP(s) URL")
}
return parsedURL, useBootService, nil
return parsedURL, httpbootConfig.ClientSpecific, nil
}

func setup6(args ...string) (handler.Handler6, error) {
u, ubs, err := parseArgs(args...)
u, ubs, err := parseConfig(args...)
if err != nil {
return nil, fmt.Errorf("invalid configuration: %v", err)
}
Expand All @@ -64,7 +90,7 @@ func setup6(args ...string) (handler.Handler6, error) {
}

func setup4(args ...string) (handler.Handler4, error) {
u, ubs, err := parseArgs(args...)
u, ubs, err := parseConfig(args...)
if err != nil {
return nil, fmt.Errorf("invalid configuration: %v", err)
}
Expand Down
Loading

0 comments on commit c2b755a

Please sign in to comment.