diff --git a/dracut/modules.d/90wwinit/load-wwinit.sh b/dracut/modules.d/90wwinit/load-wwinit.sh index a40ef978..d89867d2 100644 --- a/dracut/modules.d/90wwinit/load-wwinit.sh +++ b/dracut/modules.d/90wwinit/load-wwinit.sh @@ -61,7 +61,7 @@ if [ "${WWTLS}" = "true" ] && [ -f "$cert_file" ]; then # TLS enabled: build HTTPS URI using wwid from kernel cmdline # (mirrors wwclient URL construction in internal/app/wwclient/root.go) wwid=$(getarg wwid) - runtime_uri="https://${WWIPADDR}:${WWSECUREPORT}/provision/${wwid}" + runtime_uri="https://${WWIPADDR}:${WWTLSPORT}/provision/${wwid}" get_stage "runtime" "${runtime_uri}" "${cert_file}" || warn "warewulf: unable to load runtime overlay over HTTPS (ignored)" else # No TLS: fetch runtime over HTTP diff --git a/etc/nodes.conf b/etc/nodes.conf index b7017f85..d5147c2f 100644 --- a/etc/nodes.conf +++ b/etc/nodes.conf @@ -7,6 +7,7 @@ nodeprofiles: system overlay: - wwinit - wwclient + - hosts - fstab - hostname - ssh.host_keys diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index f296eff2..e25d7144 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -261,7 +261,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { port := conf.Warewulf.Port scheme := "http" if conf.Warewulf.EnableTLS() { - port = conf.Warewulf.SecurePort + port = conf.Warewulf.TlsPort scheme = "https" } diff --git a/internal/app/wwctl/configure/main.go b/internal/app/wwctl/configure/main.go index 5532a197..5f63dc9a 100644 --- a/internal/app/wwctl/configure/main.go +++ b/internal/app/wwctl/configure/main.go @@ -1,14 +1,11 @@ package configure import ( - "fmt" "os" - "path" "github.com/spf13/cobra" warewulfconf "github.com/warewulf/warewulf/internal/pkg/config" "github.com/warewulf/warewulf/internal/pkg/configure" - "github.com/warewulf/warewulf/internal/pkg/util" "github.com/warewulf/warewulf/internal/pkg/wwlog" ) @@ -23,17 +20,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } if allFunctions { - keystore := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls") - keyFile := path.Join(keystore, "warewulf.key") - certFile := path.Join(keystore, "warewulf.crt") - - if !util.IsFile(keyFile) || !util.IsFile(certFile) { - err = configure.GenTLSKeys() - if err != nil { - return err - } - } else { - fmt.Printf("Keys already exist in %s\n", keystore) + if _, err = configure.TLS(false); err != nil { + return err } err = configure.WAREWULFD() diff --git a/internal/app/wwctl/configure/tls/main.go b/internal/app/wwctl/configure/tls/main.go index b84fe8a7..af99bc37 100644 --- a/internal/app/wwctl/configure/tls/main.go +++ b/internal/app/wwctl/configure/tls/main.go @@ -19,10 +19,6 @@ func CobraRunE(cmd *cobra.Command, args []string) error { conf := config.Get() keystore := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls") - if err := os.MkdirAll(keystore, 0755); err != nil { - return fmt.Errorf("could not create keystore directory: %w", err) - } - keyFile := path.Join(keystore, "warewulf.key") certFile := path.Join(keystore, "warewulf.crt") @@ -75,21 +71,21 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return nil } - if util.IsFile(keyFile) && util.IsFile(certFile) && !force { - if create { - fmt.Fprintf(cmd.OutOrStdout(), "Keys already exist in %s\n", keystore) + if !conf.Warewulf.EnableTLS() { + fmt.Fprintf(cmd.OutOrStdout(), "TLS is not enabled in warewulf.conf\n") + return nil + } + + created, err := configure.TLS(force) + if err != nil { + return err + } + if created { + if err := configure.WAREWULFD(); err != nil { + return fmt.Errorf("failed to restart warewulfd: %w", err) } } else { - if create { - if err := configure.GenTLSKeys(); err != nil { - return err - } - if err := configure.WAREWULFD(); err != nil { - return fmt.Errorf("failed to restart warewulfd: %w", err) - } - } else { - return fmt.Errorf("keys not found in: %s", keystore) - } + fmt.Fprintf(cmd.OutOrStdout(), "Keys already exist in %s\n", keystore) } w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 2, ' ', 0) diff --git a/internal/app/wwctl/configure/tls/main_test.go b/internal/app/wwctl/configure/tls/main_test.go index 7759dc91..8251b994 100644 --- a/internal/app/wwctl/configure/tls/main_test.go +++ b/internal/app/wwctl/configure/tls/main_test.go @@ -14,6 +14,9 @@ func Test_Keys(t *testing.T) { env := testenv.New(t) defer env.RemoveAll() + // Enable TLS in the test config + env.WriteFile("etc/warewulf/warewulf.conf", "warewulf:\n tls: true\n") + // Define a keystore path within the test environment keystoreRelPath := "etc/warewulf/tls" keystorePath := env.GetPath(keystoreRelPath) @@ -24,11 +27,10 @@ func Test_Keys(t *testing.T) { t.Run("keys create", func(t *testing.T) { baseCmd := GetCommand() // Reset flags - create = true importPath = "" exportPath = "" - baseCmd.SetArgs([]string{"--create"}) + baseCmd.SetArgs([]string{}) buf := new(bytes.Buffer) baseCmd.SetOut(buf) baseCmd.SetErr(buf) @@ -43,11 +45,10 @@ func Test_Keys(t *testing.T) { t.Run("keys exist check", func(t *testing.T) { baseCmd := GetCommand() // Reset flags - create = true // Even with create, it should say they exist importPath = "" exportPath = "" - baseCmd.SetArgs([]string{"--create"}) + baseCmd.SetArgs([]string{}) buf := new(bytes.Buffer) baseCmd.SetOut(buf) baseCmd.SetErr(buf) @@ -61,7 +62,6 @@ func Test_Keys(t *testing.T) { t.Run("keys display", func(t *testing.T) { baseCmd := GetCommand() // Reset flags - create = false importPath = "" exportPath = "" @@ -88,7 +88,6 @@ func Test_Keys(t *testing.T) { baseCmd := GetCommand() // Reset flags - create = false importPath = "" exportPath = exportFullPath diff --git a/internal/app/wwctl/configure/tls/root.go b/internal/app/wwctl/configure/tls/root.go index 0fa24abc..9f90db93 100644 --- a/internal/app/wwctl/configure/tls/root.go +++ b/internal/app/wwctl/configure/tls/root.go @@ -18,14 +18,12 @@ var ( } importPath string exportPath string - create bool force bool ) func init() { baseCmd.PersistentFlags().StringVar(&importPath, "import", "", "Import keys from directory") baseCmd.PersistentFlags().StringVar(&exportPath, "export", "", "Export keys to directory") - baseCmd.PersistentFlags().BoolVar(&create, "create", false, "Create keys if they do not exist") baseCmd.PersistentFlags().BoolVarP(&force, "force", "f", false, "Enforce creation of keys even if they exist") } diff --git a/internal/pkg/config/buildconfig.go.in b/internal/pkg/config/buildconfig.go.in index d562f5cb..18909050 100644 --- a/internal/pkg/config/buildconfig.go.in +++ b/internal/pkg/config/buildconfig.go.in @@ -42,7 +42,7 @@ func (conf TFTPConf) Enabled() bool { // BaseConf. type WarewulfConf struct { Port int `yaml:"port,omitempty" default:"9873"` - SecurePort int `yaml:"secure port,omitempty" default:"9874"` + TlsPort int `yaml:"tls port,omitempty" default:"9874"` SecureP *bool `yaml:"secure,omitempty" default:"true"` EnableTLSP *bool `yaml:"tls,omitempty" default:"false"` UpdateInterval int `yaml:"update interval,omitempty" default:"60"` diff --git a/internal/pkg/config/root_test.go b/internal/pkg/config/root_test.go index fe5a6f41..26de357c 100644 --- a/internal/pkg/config/root_test.go +++ b/internal/pkg/config/root_test.go @@ -22,7 +22,7 @@ warewulf: host overlay: true port: 9873 secure: true - secure port: 9874 + tls port: 9874 update interval: 60 nfs: enabled: true @@ -70,7 +70,7 @@ warewulf: host overlay: true port: 9873 secure: true - secure port: 9874 + tls port: 9874 update interval: 60 nfs: enabled: true @@ -120,7 +120,7 @@ warewulf: host overlay: true port: 9873 secure: true - secure port: 9874 + tls port: 9874 update interval: 60 nfs: enabled: true @@ -167,7 +167,7 @@ warewulf: host overlay: true port: 9873 secure: true - secure port: 9874 + tls port: 9874 update interval: 60 nfs: enabled: true @@ -243,7 +243,7 @@ warewulf: host overlay: true port: 9873 secure: false - secure port: 9874 + tls port: 9874 update interval: 60 nfs: enabled: true diff --git a/internal/pkg/configure/tls.go b/internal/pkg/configure/tls.go index 4a65f72c..c6695a66 100644 --- a/internal/pkg/configure/tls.go +++ b/internal/pkg/configure/tls.go @@ -14,16 +14,44 @@ import ( "time" warewulfconf "github.com/warewulf/warewulf/internal/pkg/config" + "github.com/warewulf/warewulf/internal/pkg/util" "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -/* -GenTLSKeys checks for existence of x509 keys and creates them if they don't exist. -*/ +// TLS ensures TLS keys exist if TLS is enabled. +// If force is true, regenerates even if keys already exist. +// Returns true if new keys were generated. +func TLS(force bool) (bool, error) { + conf := warewulfconf.Get() + if !conf.Warewulf.EnableTLS() { + return false, nil + } + + keystore := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls") + keyFile := path.Join(keystore, "warewulf.key") + certFile := path.Join(keystore, "warewulf.crt") + + if !force && util.IsFile(keyFile) && util.IsFile(certFile) { + wwlog.Info("TLS keys already exist in %s", keystore) + return false, nil + } + + if err := GenTLSKeys(); err != nil { + return false, err + } + wwlog.Info("TLS keys generated in %s", keystore) + return true, nil +} + +// GenTLSKeys generates new TLS keys and certificate unconditionally. func GenTLSKeys() error { conf := warewulfconf.Get() keystore := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls") + if err := os.MkdirAll(keystore, 0755); err != nil { + return fmt.Errorf("could not create keystore directory: %w", err) + } + keyFile := path.Join(keystore, "warewulf.key") certFile := path.Join(keystore, "warewulf.crt") wwlog.Verbose("Generating new x509 keys in %s", keystore) diff --git a/internal/pkg/warewulfd/server/server.go b/internal/pkg/warewulfd/server/server.go index 87dd9429..4523b15b 100644 --- a/internal/pkg/warewulfd/server/server.go +++ b/internal/pkg/warewulfd/server/server.go @@ -94,12 +94,12 @@ func RunServer() error { crt := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls", "warewulf.crt") if !util.IsFile(key) || !util.IsFile(crt) { - return fmt.Errorf("TLS enabled but keys not found in %s, run 'wwctl configure tls --create' to generate keys", path.Join(conf.Paths.Sysconfdir, "warewulf", "tls")) + return fmt.Errorf("TLS enabled but keys not found in %s, run 'wwctl configure tls' to generate keys", path.Join(conf.Paths.Sysconfdir, "warewulf", "tls")) } httpsHandler := configureRootHandler(apiHandler) go func() { - wwlog.Info("Starting HTTPS service on port %d", conf.Warewulf.SecurePort) - if err := http.ListenAndServeTLS(":"+strconv.Itoa(conf.Warewulf.SecurePort), crt, key, httpsHandler); err != nil { + wwlog.Info("Starting HTTPS service on port %d", conf.Warewulf.TlsPort) + if err := http.ListenAndServeTLS(":"+strconv.Itoa(conf.Warewulf.TlsPort), crt, key, httpsHandler); err != nil { errChan <- fmt.Errorf("could not start HTTPS service: %w", err) } }() diff --git a/overlays/wwinit/internal/wwinit_test.go b/overlays/wwinit/internal/wwinit_test.go index 368ed72b..c1149179 100644 --- a/overlays/wwinit/internal/wwinit_test.go +++ b/overlays/wwinit/internal/wwinit_test.go @@ -103,7 +103,7 @@ WWIPMI_USER="user" WWIPMI_PASSWORD="password" WWIPMI_WRITE="true" WWTLS=false -WWSECUREPORT=9874 +WWTLSPORT=9874 WWIPADDR=192.168.0.1 ` diff --git a/overlays/wwinit/rootfs/warewulf/config.ww b/overlays/wwinit/rootfs/warewulf/config.ww index 36e19fca..3b19adfb 100644 --- a/overlays/wwinit/rootfs/warewulf/config.ww +++ b/overlays/wwinit/rootfs/warewulf/config.ww @@ -12,5 +12,5 @@ WWIPMI_WRITE="{{$.Ipmi.Write.Bool}}" WWIPMI_VLAN="{{$.Ipmi.Tags.vlan}}" {{- end }} WWTLS={{$.Warewulf.EnableTLS}} -WWSECUREPORT={{$.Warewulf.SecurePort}} +WWTLSPORT={{$.Warewulf.TlsPort}} WWIPADDR={{$.Ipaddr}}