cleanup code after review

Signed-off-by: Christian Goll <cgoll@suse.com>
This commit is contained in:
Christian Goll
2023-10-25 09:11:05 +02:00
committed by Jonathon Anderson
parent 4379c4c18d
commit 725176cfed
13 changed files with 118 additions and 140 deletions

View File

@@ -133,6 +133,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
the host running warewulf. If node has container it will get these binaries from the
container image.
- Added support for booting nodes with grub. Enable this behavior using
warewulf.grubboot: true in warewulf.conf. For unknown nodes, grub.efi
and shim.efi are extracted from the Warewulf host. If the booted node
has a container these binaries are extracted from the container image.
## [4.4.0] 2023-01-18
### Added

View File

@@ -24,13 +24,6 @@ func ProfileSet(set *wwapiv1.ProfileSetParameter) (err error) {
if err != nil {
return errors.Wrap(err, "Could not open database")
}
var pConf node.NodeConf
err = yaml.Unmarshal([]byte(set.NodeConfYaml), &pConf)
if err != nil {
wwlog.Error(fmt.Sprintf("%v", err.Error()))
return
}
dbError := apinode.DbSave(&nodeDB)
return dbError
}

View File

@@ -1,58 +0,0 @@
package container
import (
"os"
"path"
"path/filepath"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
func grubDirs() []string {
return []string{
`/usr/share/grub2/x86_64-efi`,
`/usr/share/efi/x86_64/`,
`/boot/efi/EFI/*/`,
}
}
func grubNames() []string {
return []string{
`grub-tpm.efi`,
`grub.efi`,
`grubx64.efi`,
`grubia32.efi`,
`grubaa64.efi`,
`grubarm.efi`,
}
}
/*
find a grub.efi in the used container
*/
func GrubFind(container string) string {
container_path := RootFsDir(container)
wwlog.Debug("Finding grub under paths: %s", container_path)
if container_path == "" {
return ""
}
return GrubFindPath(container_path)
}
func GrubFindPath(grub_path string) string {
for _, grubdir := range grubDirs() {
wwlog.Debug("Checking grub directory: %s", grubdir)
for _, grubname := range grubNames() {
wwlog.Debug("Checking for grub name: %s", grubname)
grubPaths, _ := filepath.Glob(path.Join(grub_path, grubdir, grubname))
for _, grubpath := range grubPaths {
wwlog.Debug("Checking for grub path: %s", grubpath)
// Only succeeds if grubpath exists and, if a
// symlink, links to a path that also exists
if _, err := os.Stat(grubpath); err == nil {
return grubpath
}
}
}
}
return ""
}

View File

@@ -1,59 +0,0 @@
package container
import (
"os"
"path"
"path/filepath"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
func shimDirs() []string {
return []string{
`/usr/share/efi/x86_64/`,
`/usr/lib64/efi`,
`/boot/efi/EFI/*/`,
}
}
func shimNames() []string {
return []string{
`shim.efi`,
`shim-sles.efi`,
`shimx64.efi`,
`shim-susesigned.efi`,
}
}
/*
find the path of the shim binary in container
*/
func ShimFind(container string) string {
container_path := RootFsDir(container)
wwlog.Debug("Finding shim under path: %s", container_path)
if container_path == "" {
return ""
}
return ShimFindPath(container_path)
}
/*
find the path of the shim binary in container
*/
func ShimFindPath(shimpath string) string {
for _, shimdir := range shimDirs() {
wwlog.Debug("Checking shim directory: %s", shimdir)
for _, shimname := range shimNames() {
wwlog.Debug("Checking for shim name: %s", shimname)
shimPaths, _ := filepath.Glob(path.Join(shimpath, shimdir, shimname))
for _, shimPath := range shimPaths {
wwlog.Debug("Checking for shim path: %s", shimPath)
// Only succeeds if shimPath exists and, if a
// symlink, links to a path that also exists
if _, err := os.Stat(shimPath); err == nil {
return shimPath
}
}
}
}
return ""
}

View File

@@ -0,0 +1,94 @@
package container
import (
"os"
"path"
"path/filepath"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
)
func shimDirs() []string {
return []string{
`/usr/share/efi/x86_64/`,
`/usr/lib64/efi/`,
`/boot/efi/EFI/*/`,
}
}
func shimNames() []string {
return []string{
`shim.efi`,
`shim-sles.efi`,
`shimx64.efi`,
`shim-susesigned.efi`,
}
}
func grubDirs() []string {
return []string{
`/usr/lib64/efi/`,
`/usr/share/grub2/*-efi/`,
`/usr/share/efi/*/`,
`/boot/efi/EFI/*/`,
}
}
func grubNames() []string {
return []string{
`grub-tpm.efi`,
`grub.efi`,
`grubx64.efi`,
`grubia32.efi`,
`grubaa64.efi`,
`grubarm.efi`,
}
}
/*
find the path of the shim binary in container
*/
func ShimFind(container string) string {
var container_path string
if container != "" {
container_path = RootFsDir(container)
} else {
container_path = "/"
}
wwlog.Debug("Finding grub under paths: %s", container_path)
return BootLoaderFindPath(container_path, shimNames, shimDirs)
}
/*
find a grub.efi in the used container
*/
func GrubFind(container string) string {
var container_path string
if container != "" {
container_path = RootFsDir(container)
} else {
container_path = "/"
}
wwlog.Debug("Finding grub under paths: %s", container_path)
return BootLoaderFindPath(container_path, grubNames, grubDirs)
}
/*
find the path of the shim binary in container
*/
func BootLoaderFindPath(cpath string, names func() []string, paths func() []string) string {
for _, bdir := range paths() {
wwlog.Debug("Checking shim directory: %s", bdir)
for _, bname := range names() {
wwlog.Debug("Checking for bootloader name: %s", bname)
shimPaths, _ := filepath.Glob(path.Join(cpath, bdir, bname))
for _, shimPath := range shimPaths {
wwlog.Debug("Checking for bootloader path: %s", shimPath)
// Only succeeds if shimPath exists and, if a
// symlink, links to a path that also exists
if _, err := os.Stat(shimPath); err == nil {
return shimPath
}
}
}
}
return ""
}

View File

@@ -34,7 +34,6 @@ type TemplateStruct struct {
Tftp warewulfconf.TFTPConf
Paths warewulfconf.BuildConfig
AllNodes []node.NodeInfo
ProfileMap map[string]*node.NodeInfo
node.NodeConf
// backward compatiblity
Container string
@@ -56,10 +55,6 @@ func InitStruct(nodeInfo *node.NodeInfo) TemplateStruct {
if err != nil {
wwlog.Warn("couldn't get all nodes: %s", err)
}
tstruct.ProfileMap, err = nodeDB.MapAllProfiles()
if err != nil {
wwlog.Warn("couldn't get all profiles: %s", err)
}
// init some convenience vars
tstruct.Id = nodeInfo.Id.Get()
tstruct.Hostname = nodeInfo.Id.Get()

View File

@@ -20,7 +20,7 @@ to the tftp directory
func CopyShimGrub() (err error) {
conf := warewulfconf.Get()
wwlog.Debug("copy shim and grub binaries from host")
shimPath := container.ShimFindPath("/")
shimPath := container.ShimFind("")
if shimPath == "" {
return fmt.Errorf("no shim found on the host os")
}
@@ -29,7 +29,7 @@ func CopyShimGrub() (err error) {
return err
}
_ = os.Chmod(path.Join(conf.Paths.Tftpdir, "warewulf", "shim.efi"), 0o755)
grubPath := container.GrubFindPath("/")
grubPath := container.GrubFind("")
if grubPath == "" {
return fmt.Errorf("no grub found on host os")
}

View File

@@ -16,8 +16,10 @@ import (
// TODO: https://github.com/danderson/netboot/blob/master/pixiecore/dhcp.go
// TODO: https://github.com/pin/tftp
/*
wrapper type for the server mux as him requests http://efiboot//grub.efi which is filtered out by http to `301 Moved Permanently` which
which shim.fi can't handle. So filter out `//` before they hit http
wrapper type for the server mux as shim requests http://efiboot//grub.efi
which is filtered out by http to `301 Moved Permanently` what
shim.efi can't handle. So filter out `//` before they hit go/http.
Makes go/http more to behave like apache
*/
type slashFix struct {
mux http.Handler

View File

@@ -27,7 +27,13 @@ option architecture-type code 93 = unsigned integer 16;
{{- if $.Warewulf.GrubBoot }}
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
next-server {{ $.Ipaddr }};
filename "warewulf/shim.efi";
if substring (option vendor-class-identifier, 15, 5) = "00000" {
# pure BIOS clients will get iPXE configuration
filename "http://{{$.Ipaddr}}:{{$.Warewulf.Port}}/ipxe/${mac:hexhyp}";
} else {
# EFI clients will get shim and grub instead
filename "warewulf/shim.efi";
}
} elsif substring (option vendor-class-identifier, 0, 10) = "HTTPClient" {
filename "http://{{$.Ipaddr}}:{{$.Warewulf.Port}}/efiboot/shim.efi";
}

View File

@@ -1,13 +1,13 @@
===========
Use of Grub
===========
===============
Boot Management
===============
Instead of the iPXE starter a combination of `shim and GRUB <https://www.suse.com/c/uefi-secure-boot-details/>`_
can be used with the advantage that secure boot can be used. That means
that only the signed kernel of a distribution can be booted. This can
be a huge security benefit for some scenarios.
In order to enable the grub boot method it has to ne enabled in `warewulf.conf`.
In order to enable the grub boot method it has to be enabled in `warewulf.conf`.
Nodes which are not known to warewulf will then booted with the shim/grub from
the host on which warewulf is installed.

View File

@@ -55,7 +55,7 @@ when a user lands on a compute node, there is generally nothing
stopping them from spoofing a provision request and downloading the
provisioned raw materials for inspection.
In Warewulf there are ways to secure the provisioning process:
In Warewulf there are ways multiple to secure the provisioning process:
#. The provisioning connections and transfers are not secure due to
not being able to manage a secure root of trust through a PXE

View File

@@ -18,7 +18,7 @@ Welcome to the Warewulf User Guide!
Warewulf Initialization <contents/initialization>
Container Management <contents/containers>
Kernel Management <contents/kernel>
Boot Management <contents/grub>
Boot Management <contents/boot-management>
Node Configuration <contents/nodeconfig>
Node Profiles <contents/profiles>
Warewulf Overlays <contents/overlays>

View File

@@ -139,6 +139,7 @@ yq e '
%config(noreplace) %{_sysconfdir}/warewulf/wwapi*.conf
%config(noreplace) %{_sysconfdir}/warewulf/examples
%config(noreplace) %{_sysconfdir}/warewulf/ipxe
%config(noreplace) %{_sysconfdir}/warewulf/grub
%config(noreplace) %attr(0640,-,-) %{_sysconfdir}/warewulf/nodes.conf
%{_sysconfdir}/bash_completion.d/wwctl