diff --git a/dracut/modules.d/90wwinit/load-wwinit.sh b/dracut/modules.d/90wwinit/load-wwinit.sh index a06c33b8..e15d1ef2 100644 --- a/dracut/modules.d/90wwinit/load-wwinit.sh +++ b/dracut/modules.d/90wwinit/load-wwinit.sh @@ -43,7 +43,7 @@ info "warewulf: mounting ${wwinit_root_device} at ${NEWROOT}" fi ) || die "warewulf: failed to mount ${wwinit_root_device} at ${NEWROOT}" -for stage in "image" "system" "runtime"; do +for stage in "image" "system" ; do get_stage "${stage}" done diff --git a/etc/grub/grub.cfg.ww b/etc/grub/grub.cfg.ww index 7b88eaf8..03d44f85 100644 --- a/etc/grub/grub.cfg.ww +++ b/etc/grub/grub.cfg.ww @@ -66,7 +66,9 @@ menuentry "Single-stage boot" --id single-stage { echo "Downloading images..." image="${uri}&stage=image&compress=gz" system="${uri}&stage=system&compress=gz" + {{- if not (eq .Https true) }} runtime="${uri}&stage=runtime&compress=gz" + {{- end }} initrd $image $system $runtime if [ $? != 0 ] then @@ -113,7 +115,9 @@ menuentry "Single-stage boot (no compression)" --id single-stage-nocompress { echo "Downloading images..." image="${uri}&stage=image" system="${uri}&stage=system" + {{- if not (eq .Https true) }} runtime="${uri}&stage=runtime" + {{- end }} initrd $image $system $runtime if [ $? != 0 ] then diff --git a/etc/ipxe/default.ipxe b/etc/ipxe/default.ipxe index 872bdd24..4718322a 100644 --- a/etc/ipxe/default.ipxe +++ b/etc/ipxe/default.ipxe @@ -46,8 +46,10 @@ echo Downloading compressed image with imgextract... imgextract --name image ${uri}&stage=image&compress=gz || goto error_use_initrd echo Downloading compressed system overlay image with imgextract... imgextract --name system ${uri}&stage=system&compress=gz || goto error_reboot +{{- if not (eq .Https true) }} echo Downloading compressed runtime overlay image with imgextract... imgextract --name runtime ${uri}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) +{{- end }} goto boot_single_stage :error_use_initrd @@ -63,8 +65,10 @@ echo Downloading compressed image with initrd... initrd --name image ${uri}&stage=image&compress=gz || goto error_reboot echo Downloading compressed system overlay with initrd... initrd --name system ${uri}&stage=system&compress=gz || goto error_reboot +{{- if not (eq .Https true) }} echo Downloading compressed runtime overlay with initrd... initrd --name runtime ${uri}&stage=runtime&compress=gz && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) +{{- end }} goto boot_single_stage :initrd_nocompress @@ -76,8 +80,10 @@ echo Downloading uncompressed image with initrd... initrd --name image ${uri}&stage=image || goto error_reboot echo Downloading uncompressed system overlay with initrd... initrd --name system ${uri}&stage=system || goto error_reboot +{{- if not (eq .Https true) }} echo Downloading uncompressed runtime overlay with initrd... initrd --name runtime ${uri}&stage=runtime && set runtime_initrd initrd=runtime || echo Unable to download runtime overlay. (ignored) +{{- end }} goto boot_single_stage :dracut diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index 29c9a97d..791de899 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -1,6 +1,10 @@ package wwclient import ( + "crypto/tls" + "crypto/x509" + "encoding/pem" + "errors" "fmt" "io" "net" @@ -112,9 +116,31 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { wwlog.Info("running from trusted port: %d", localTCPAddr.Port) } + tlsConfig := &tls.Config{} + if conf.Warewulf.EnableHttps() { + caCert, err := os.ReadFile("/warewulf/keys/warewulf.crt") + if err != nil { + wwlog.Error("failed to read ca cert: %s", err) + return err + } + block, _ := pem.Decode(caCert) + if block == nil { + wwlog.Warn("failed to parse certificate PEM") + } else if cert, err := x509.ParseCertificate(block.Bytes); err == nil { + wwlog.Info("using cert: %s", cert.SerialNumber) + } else { + wwlog.Warn("parsing cert failed: %s", err) + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + tlsConfig.RootCAs = caCertPool + } + Webclient = &http.Client{ Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, + TLSClientConfig: tlsConfig, + Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ LocalAddr: &localTCPAddr, Timeout: 30 * time.Second, @@ -232,8 +258,15 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { } } + port := conf.Warewulf.Port + scheme := "http" + if conf.Warewulf.EnableHttps() { + port = conf.Warewulf.SecurePort + scheme = "https" + } + for { - updateSystem(target, ipaddr, conf.Warewulf.Port, wwid, tag, localUUID) + updateSystem(target, ipaddr, port, wwid, tag, localUUID, scheme) if !finishedInitialSync { // Notify systemd that the service has started successfully. // @@ -274,7 +307,7 @@ func parseWWIDFromCmdline(cmdline string) (string, error) { return "", fmt.Errorf("wwid parameter not found in kernel command line") } -func updateSystem(target string, ipaddr string, port int, wwid string, tag string, localUUID uuid.UUID) { +func updateSystem(target string, ipaddr string, port int, wwid string, tag string, localUUID uuid.UUID, scheme string) { var resp *http.Response counter := 0 for { @@ -285,7 +318,7 @@ func updateSystem(target string, ipaddr string, port int, wwid string, tag strin values.Set("stage", "runtime") values.Set("compress", "gz") getURL := &url.URL{ - Scheme: "http", + Scheme: scheme, Host: fmt.Sprintf("%s:%d", ipaddr, port), Path: fmt.Sprintf("provision/%s", wwid), RawQuery: values.Encode(), @@ -296,6 +329,15 @@ func updateSystem(target string, ipaddr string, port int, wwid string, tag strin defer resp.Body.Close() break } else { + var certificateInvalidError x509.CertificateInvalidError + var unknownAuthorityError x509.UnknownAuthorityError + var hostnameError x509.HostnameError + if errors.As(err, &certificateInvalidError) || + errors.As(err, &unknownAuthorityError) || + errors.As(err, &hostnameError) { + wwlog.Error("TLS connection failed: %v", err) + os.Exit(1) + } if counter > 60 { counter = 0 }