From ad6699c110407aa2a4ae07c40eef9583129e918d Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 12 Apr 2024 08:08:42 +0200 Subject: [PATCH 1/4] allow the user to specify ssh key types Signed-off-by: Christian Goll --- CHANGELOG.md | 4 ++++ internal/app/wwctl/configure/ssh/main.go | 2 +- internal/app/wwctl/configure/ssh/root.go | 2 ++ internal/pkg/configure/ssh.go | 8 ++++++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c4dcfa5..19869eb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## v4.5.2, unreleased +### Added + +- Allow specification of the ssh-keys to be to be created. #1185 + ### Fixed - Fix nightly release build failure issue. #1195 diff --git a/internal/app/wwctl/configure/ssh/main.go b/internal/app/wwctl/configure/ssh/main.go index b88e925e..e2db9aba 100644 --- a/internal/app/wwctl/configure/ssh/main.go +++ b/internal/app/wwctl/configure/ssh/main.go @@ -6,5 +6,5 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - return configure.SSH() + return configure.SSH(keyTypes...) } diff --git a/internal/app/wwctl/configure/ssh/root.go b/internal/app/wwctl/configure/ssh/root.go index 6c41d68a..cd08db39 100644 --- a/internal/app/wwctl/configure/ssh/root.go +++ b/internal/app/wwctl/configure/ssh/root.go @@ -12,6 +12,7 @@ var ( "keys.", RunE: CobraRunE, } + keyTypes []string ) func init() { @@ -19,5 +20,6 @@ func init() { // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { + baseCmd.PersistentFlags().StringArrayVarP(&keyTypes, "keytypes", "t", []string{"rsa", "dsa", "ecdsa", "ed25519"}, "ssh key types to be created") return baseCmd } diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go index 81e04449..16b3c2d5 100644 --- a/internal/pkg/configure/ssh.go +++ b/internal/pkg/configure/ssh.go @@ -11,7 +11,11 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func SSH() error { +/* +Create password less ssh keys in the home of the user who its +calling this function. (root in our case) +*/ +func SSH(keyTypes ...string) error { if os.Getuid() == 0 { fmt.Printf("Updating system keys\n") conf := warewulfconf.Get() @@ -23,7 +27,7 @@ func SSH() error { os.Exit(1) } - for _, k := range [4]string{"rsa", "dsa", "ecdsa", "ed25519"} { + for _, k := range keyTypes { keytype := "ssh_host_" + k + "_key" if !util.IsFile(path.Join(wwkeydir, keytype)) { fmt.Printf("Setting up key: %s\n", keytype) From 21150d29753ab9e506e946da31f54fbd997a100d Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 15 Apr 2024 12:06:43 +0200 Subject: [PATCH 2/4] make created ssh keys configureable Signed-off-by: Christian Goll --- etc/warewulf.conf | 6 ++++++ internal/app/wwctl/configure/root.go | 2 +- internal/app/wwctl/configure/ssh/main.go | 4 ++++ internal/app/wwctl/configure/ssh/root.go | 6 ++++-- internal/pkg/config/root.go | 2 ++ internal/pkg/config/ssh.go | 5 +++++ 6 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 internal/pkg/config/ssh.go diff --git a/etc/warewulf.conf b/etc/warewulf.conf index 1c998b3d..a9afbccb 100644 --- a/etc/warewulf.conf +++ b/etc/warewulf.conf @@ -38,3 +38,9 @@ container mounts: - source: /etc/resolv.conf dest: /etc/resolv.conf readonly: true +ssh: + key types: + - rsa + - dsa + - ecdsa + - ed25519 diff --git a/internal/app/wwctl/configure/root.go b/internal/app/wwctl/configure/root.go index dd78e436..40a84e02 100644 --- a/internal/app/wwctl/configure/root.go +++ b/internal/app/wwctl/configure/root.go @@ -28,7 +28,7 @@ func init() { baseCmd.AddCommand(nfs.GetCommand()) baseCmd.AddCommand(hostfile.GetCommand()) - baseCmd.PersistentFlags().BoolVarP(&allFunctions, "all", "a", false, "Configure all services") + baseCmd.Flags().BoolVarP(&allFunctions, "all", "a", false, "Configure all services") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/configure/ssh/main.go b/internal/app/wwctl/configure/ssh/main.go index e2db9aba..e73e13f4 100644 --- a/internal/app/wwctl/configure/ssh/main.go +++ b/internal/app/wwctl/configure/ssh/main.go @@ -2,9 +2,13 @@ package ssh import ( "github.com/spf13/cobra" + warewulfconf "github.com/warewulf/warewulf/internal/pkg/config" "github.com/warewulf/warewulf/internal/pkg/configure" ) func CobraRunE(cmd *cobra.Command, args []string) error { + if len(keyTypes) == 0 { + keyTypes = append(keyTypes, warewulfconf.Get().SSH.KeyTypes...) + } return configure.SSH(keyTypes...) } diff --git a/internal/app/wwctl/configure/ssh/root.go b/internal/app/wwctl/configure/ssh/root.go index cd08db39..9e56b6ae 100644 --- a/internal/app/wwctl/configure/ssh/root.go +++ b/internal/app/wwctl/configure/ssh/root.go @@ -1,6 +1,8 @@ package ssh -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" +) var ( baseCmd = &cobra.Command{ @@ -20,6 +22,6 @@ func init() { // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { - baseCmd.PersistentFlags().StringArrayVarP(&keyTypes, "keytypes", "t", []string{"rsa", "dsa", "ecdsa", "ed25519"}, "ssh key types to be created") + baseCmd.PersistentFlags().StringArrayVarP(&keyTypes, "keytypes", "t", []string{}, "ssh key types to be created") return baseCmd } diff --git a/internal/pkg/config/root.go b/internal/pkg/config/root.go index e8369f14..97f26b98 100644 --- a/internal/pkg/config/root.go +++ b/internal/pkg/config/root.go @@ -38,6 +38,7 @@ type RootConf struct { DHCP *DHCPConf `yaml:"dhcp"` TFTP *TFTPConf `yaml:"tftp"` NFS *NFSConf `yaml:"nfs"` + SSH *SSHConf `yaml:"ssh,omitempty"` MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` Paths *BuildConfig `yaml:"paths"` @@ -53,6 +54,7 @@ func New() *RootConf { cachedConf.DHCP = new(DHCPConf) cachedConf.TFTP = new(TFTPConf) cachedConf.NFS = new(NFSConf) + cachedConf.SSH = new(SSHConf) cachedConf.Paths = new(BuildConfig) if err := defaults.Set(&cachedConf); err != nil { panic(err) diff --git a/internal/pkg/config/ssh.go b/internal/pkg/config/ssh.go new file mode 100644 index 00000000..a9abe4dc --- /dev/null +++ b/internal/pkg/config/ssh.go @@ -0,0 +1,5 @@ +package config + +type SSHConf struct { + KeyTypes []string `yaml:"key types" default:"[\"rsa\",\"dsa\",\"ecdsa\",\"ed25519\"]"` +} From 7046c6dc8c8a0c0b001ff9878edf71fef6698a2c Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Fri, 19 Apr 2024 17:26:18 -0600 Subject: [PATCH 3/4] Use the first configured ssh key type for authn Previously, the authentication key was always generated using rsa. Now it uses the first configured ssh key type. Signed-off-by: Jonathon Anderson --- internal/pkg/configure/ssh.go | 27 +++++++++++-------- internal/pkg/overlay/datastructure.go | 2 ++ .../{ssh_setup.csh => ssh_setup.csh.ww} | 8 ++++-- .../{ssh_setup.sh => ssh_setup.sh.ww} | 8 ++++-- 4 files changed, 30 insertions(+), 15 deletions(-) rename overlays/host/rootfs/etc/profile.d/{ssh_setup.csh => ssh_setup.csh.ww} (77%) rename overlays/host/rootfs/etc/profile.d/{ssh_setup.sh => ssh_setup.sh.ww} (81%) diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go index 16b3c2d5..4d12c1db 100644 --- a/internal/pkg/configure/ssh.go +++ b/internal/pkg/configure/ssh.go @@ -52,21 +52,26 @@ func SSH(keyTypes ...string) error { } authorizedKeys := path.Join(homeDir, "/.ssh/authorized_keys") - rsaPriv := path.Join(homeDir, "/.ssh/id_rsa") - rsaPub := path.Join(homeDir, "/.ssh/id_rsa.pub") if !util.IsFile(authorizedKeys) { - fmt.Printf("Setting up: %s\n", authorizedKeys) - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", rsaPriv, "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - err := util.CopyFile(rsaPub, authorizedKeys) - if err != nil { - return errors.Wrap(err, "failed to copy keys") + if len(keyTypes) > 0 { + keyType := keyTypes[0] + fmt.Printf("Setting up: %s\n", authorizedKeys) + privKey := path.Join(homeDir, "/.ssh/id_"+keyType) + pubKey := privKey + ".pub" + err = util.ExecInteractive("ssh-keygen", "-q", "-t", keyType, "-f", privKey, "-C", "", "-N", "") + if err != nil { + return errors.Wrap(err, "Failed to exec ssh-keygen command") + } + err := util.CopyFile(pubKey, authorizedKeys) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("Failed to copy %s to authorized_keys", pubKey)) + } + } else { + fmt.Printf("Skipping authorized_keys: no key types configured\n") } } else { - fmt.Printf("Skipping, authorized_keys already exists: %s\n", authorizedKeys) + fmt.Printf("Skipping authorized_keys: already exists: %s\n", authorizedKeys) } return nil diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 43f018a9..947bf4ff 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -31,6 +31,7 @@ type TemplateStruct struct { Ipv6 bool Dhcp warewulfconf.DHCPConf Nfs warewulfconf.NFSConf + Ssh warewulfconf.SSHConf Warewulf warewulfconf.WarewulfConf Tftp warewulfconf.TFTPConf Paths warewulfconf.BuildConfig @@ -60,6 +61,7 @@ func InitStruct(nodeInfo *node.NodeInfo) TemplateStruct { tstruct.Id = nodeInfo.Id.Get() tstruct.Hostname = nodeInfo.Id.Get() tstruct.Nfs = *controller.NFS + tstruct.Ssh = *controller.SSH tstruct.Dhcp = *controller.DHCP tstruct.Tftp = *controller.TFTP tstruct.Paths = *controller.Paths diff --git a/overlays/host/rootfs/etc/profile.d/ssh_setup.csh b/overlays/host/rootfs/etc/profile.d/ssh_setup.csh.ww similarity index 77% rename from overlays/host/rootfs/etc/profile.d/ssh_setup.csh rename to overlays/host/rootfs/etc/profile.d/ssh_setup.csh.ww index 8befc753..0f3f023b 100644 --- a/overlays/host/rootfs/etc/profile.d/ssh_setup.csh +++ b/overlays/host/rootfs/etc/profile.d/ssh_setup.csh.ww @@ -3,12 +3,13 @@ ## Automatically configure SSH keys for a user on C SHell login ## Copy this file to /etc/profile.d along with ssh_setup.sh +{{- if gt (len .Ssh.KeyTypes) 0 }} +{{ $keyType := index .Ssh.KeyTypes 0 }} set _UID=`id -u` - if ( ( $_UID > 500 || $_UID == 0 ) && ( ! -f "$HOME/.ssh/config" && ! -f "$HOME/.ssh/cluster" ) ) then echo "Configuring SSH for cluster access" install -d -m 700 $HOME/.ssh - ssh-keygen -t rsa -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" >& /dev/null + ssh-keygen -t {{ $keyType }} -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" >& /dev/null cat $HOME/.ssh/cluster.pub >>! $HOME/.ssh/authorized_keys chmod 0600 $HOME/.ssh/authorized_keys @@ -20,3 +21,6 @@ if ( ( $_UID > 500 || $_UID == 0 ) && ( ! -f "$HOME/.ssh/config" && ! -f "$HOME/ echo " StrictHostKeyChecking=no" >> $HOME/.ssh/config chmod 0600 $HOME/.ssh/config endif +{{- else }} +# No ssh key types configured +{{- end }} diff --git a/overlays/host/rootfs/etc/profile.d/ssh_setup.sh b/overlays/host/rootfs/etc/profile.d/ssh_setup.sh.ww similarity index 81% rename from overlays/host/rootfs/etc/profile.d/ssh_setup.sh rename to overlays/host/rootfs/etc/profile.d/ssh_setup.sh.ww index daa1dfb8..3ab1fffc 100644 --- a/overlays/host/rootfs/etc/profile.d/ssh_setup.sh +++ b/overlays/host/rootfs/etc/profile.d/ssh_setup.sh.ww @@ -11,12 +11,13 @@ ## Automatically configure SSH keys for a user on login ## Copy this file to /etc/profile.d +{{- if gt (len .Ssh.KeyTypes) 0 }} +{{ $keyType := index .Ssh.KeyTypes 0 }} _UID=`id -u` - if [ $_UID -ge 500 -o $_UID -eq 0 ] && [ ! -f "$HOME/.ssh/config" -a ! -f "$HOME/.ssh/cluster" ]; then echo "Configuring SSH for cluster access" install -d -m 700 $HOME/.ssh - ssh-keygen -t rsa -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" > /dev/null 2>&1 + ssh-keygen -t {{ $keyType }} -f $HOME/.ssh/cluster -N '' -C "Warewulf Cluster key" > /dev/null 2>&1 cat $HOME/.ssh/cluster.pub >> $HOME/.ssh/authorized_keys chmod 0600 $HOME/.ssh/authorized_keys @@ -26,3 +27,6 @@ if [ $_UID -ge 500 -o $_UID -eq 0 ] && [ ! -f "$HOME/.ssh/config" -a ! -f "$HOME echo " StrictHostKeyChecking=no" >> $HOME/.ssh/config chmod 0600 $HOME/.ssh/config fi +{{- else }} +# No ssh key types configured +{{- end }} From a164498aa55bd94ef05293356f01cfbd54787d23 Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Fri, 19 Apr 2024 19:17:42 -0600 Subject: [PATCH 4/4] Documentation for SSH key type configuration Signed-off-by: Jonathon Anderson --- .../rootfs/warewulf/template-variables.md.ww | 9 +++++++ userdocs/contents/configuration.rst | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/overlays/debug/rootfs/warewulf/template-variables.md.ww b/overlays/debug/rootfs/warewulf/template-variables.md.ww index 1a2940eb..8b2e96cd 100644 --- a/overlays/debug/rootfs/warewulf/template-variables.md.ww +++ b/overlays/debug/rootfs/warewulf/template-variables.md.ww @@ -108,6 +108,15 @@ data from other structures. - Mount: {{ $export.Mount }} {{- end }} +### SSH + +{{- if gt (len .Ssh.KeyTypes) 0 }} +- Key types: +{{- range $index, $keyType := .Ssh.KeyTypes }} + - {{ $keyType }} +{{- end }} +- First key type: {{ index .Ssh.KeyTypes 0 }} +{{- end }} ### Warewulf diff --git a/userdocs/contents/configuration.rst b/userdocs/contents/configuration.rst index a16edefc..e16549fa 100644 --- a/userdocs/contents/configuration.rst +++ b/userdocs/contents/configuration.rst @@ -49,6 +49,12 @@ Warewulf (4.5.1): - source: /etc/resolv.conf dest: /etc/resolv.conf readonly: true + ssh: + key types: + - rsa + - dsa + - ecdsa + - ed25519 Generally you can leave this file as is, as long as you set the appropriate networking information. Specifically the following @@ -151,6 +157,25 @@ may be overridden using ``warewulf.conf:paths``. * ``wwclientdir``: Where the Warewulf client looks for its configuration on a provisioned node. +SSH key types +------------- + +*New in Warewulf v4.5.1* + +SSH key types to generate during ``wwctl configure ssh`` may be overridden using ``warewulf.conf:ssh:key types``. + +.. code-block:: yaml + + ssh: + key types: + - rsa + - dsa + - ecdsa + - ed25519 + +Warewulf will generate host keys for each listed key type. +The first listed key type is used to generate authentication ssh keys. + nodes.conf ==========