mirror of
https://github.com/MengMengCode/CLICD.git
synced 2026-08-08 14:34:49 +08:00
修复预设密码以及KEY问题
This commit is contained in:
+19
-10
@@ -407,6 +407,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
|||||||
mac := randomMAC()
|
mac := randomMAC()
|
||||||
sshPassword := generateRandomString(16)
|
sshPassword := generateRandomString(16)
|
||||||
sshPublicKey := ""
|
sshPublicKey := ""
|
||||||
|
sshAuthMode := ""
|
||||||
if !IsWindowsImage(image.ID) {
|
if !IsWindowsImage(image.ID) {
|
||||||
sshAccess, err := lxc.ResolveCreateSSHAccess(cfg)
|
sshAccess, err := lxc.ResolveCreateSSHAccess(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -414,6 +415,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
|||||||
}
|
}
|
||||||
sshPassword = sshAccess.Password
|
sshPassword = sshAccess.Password
|
||||||
sshPublicKey = sshAccess.PublicKey
|
sshPublicKey = sshAccess.PublicKey
|
||||||
|
sshAuthMode = sshAccess.Mode
|
||||||
}
|
}
|
||||||
publicIPv4s, err := lxc.AllocatePublicIPv4Assignments(id, cfg.PublicIPv4s, cfg.IPv4Count, cfg.AssignIPv4)
|
publicIPv4s, err := lxc.AllocatePublicIPv4Assignments(id, cfg.PublicIPv4s, cfg.IPv4Count, cfg.AssignIPv4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -465,7 +467,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
|||||||
if err := createOverlayDisk(ImagePath(image.ID), diskPath, cfg.DiskGB); err != nil {
|
if err := createOverlayDisk(ImagePath(image.ID), diskPath, cfg.DiskGB); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := createSeedISO(seedPath, vmName, cfg.Name, sshPassword, sshPublicKey, mac, ipv6List, ipv4List, *image); err != nil {
|
if err := createSeedISO(seedPath, vmName, cfg.Name, sshPassword, sshPublicKey, mac, ipv6List, ipv4List, *image, sshAuthMode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
xml = domainXML(vmName, int(cfg.VCPU), cfg.RAMMB, diskPath, seedPath, mac, cfg.IOSpeedMBps, cfg.NetworkBWMbps, image.Desktop != "")
|
xml = domainXML(vmName, int(cfg.VCPU), cfg.RAMMB, diskPath, seedPath, mac, cfg.IOSpeedMBps, cfg.NetworkBWMbps, image.Desktop != "")
|
||||||
@@ -1853,8 +1855,9 @@ func shellQuoteWindows(value string) string {
|
|||||||
return `"` + strings.ReplaceAll(value, `"`, `\"`) + `"`
|
return `"` + strings.ReplaceAll(value, `"`, `\"`) + `"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSeedISO(seedPath, instanceID, hostname, password, publicKey, mac string, ipv6s []string, ipv4s []string, image Image) error {
|
func createSeedISO(seedPath, instanceID, hostname, password, publicKey, mac string, ipv6s []string, ipv4s []string, image Image, sshAuthMode string) error {
|
||||||
guestSetup := kvmSSHSetupScript(password, publicKey)
|
disablePubkey := sshAuthMode == "password" || sshAuthMode == "auto_password"
|
||||||
|
guestSetup := kvmSSHSetupScript(password, disablePubkey, publicKey)
|
||||||
if desktopSetup := kvmDesktopSetupScript(image); desktopSetup != "" {
|
if desktopSetup := kvmDesktopSetupScript(image); desktopSetup != "" {
|
||||||
guestSetup += "\n" + desktopSetup
|
guestSetup += "\n" + desktopSetup
|
||||||
}
|
}
|
||||||
@@ -2432,11 +2435,11 @@ func runKVMGuestAgentSSHSetup(name string, password string) error {
|
|||||||
if err := qemuGuestPing(name); err != nil {
|
if err := qemuGuestPing(name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return qemuGuestExec(name, kvmSSHSetupScript(password), 180*time.Second)
|
return qemuGuestExec(name, kvmSSHSetupScript(password, false), 180*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKVMSSHSetup(client *ssh.Client, password string) error {
|
func runKVMSSHSetup(client *ssh.Client, password string) error {
|
||||||
return runKVMSSHScript(client, kvmSSHSetupScript(password), "KVM SSH", 150*time.Second)
|
return runKVMSSHScript(client, kvmSSHSetupScript(password, false), "KVM SSH", 150*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKVMSSHScript(client *ssh.Client, script string, description string, timeout time.Duration) error {
|
func runKVMSSHScript(client *ssh.Client, script string, description string, timeout time.Duration) error {
|
||||||
@@ -2465,12 +2468,16 @@ func runKVMSSHScript(client *ssh.Client, script string, description string, time
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func kvmSSHSetupScript(password string, publicKeys ...string) string {
|
func kvmSSHSetupScript(password string, disablePubkeyAuth bool, publicKeys ...string) string {
|
||||||
publicKey := ""
|
publicKey := ""
|
||||||
if len(publicKeys) > 0 {
|
if len(publicKeys) > 0 {
|
||||||
publicKey = strings.TrimSpace(publicKeys[0])
|
publicKey = strings.TrimSpace(publicKeys[0])
|
||||||
}
|
}
|
||||||
return `set -u
|
pubkeyValue := "yes"
|
||||||
|
if disablePubkeyAuth {
|
||||||
|
pubkeyValue = "no"
|
||||||
|
}
|
||||||
|
script := `set -u
|
||||||
ROOT_PASSWORD=` + shellQuote(password) + `
|
ROOT_PASSWORD=` + shellQuote(password) + `
|
||||||
SSH_PUBLIC_KEY=` + shellQuote(publicKey) + `
|
SSH_PUBLIC_KEY=` + shellQuote(publicKey) + `
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
@@ -2499,7 +2506,7 @@ fi
|
|||||||
mkdir -p /etc/ssh/sshd_config.d
|
mkdir -p /etc/ssh/sshd_config.d
|
||||||
cat > /etc/ssh/sshd_config.d/99-clicd-root.conf <<'EOF'
|
cat > /etc/ssh/sshd_config.d/99-clicd-root.conf <<'EOF'
|
||||||
PermitRootLogin yes
|
PermitRootLogin yes
|
||||||
PubkeyAuthentication yes
|
PubkeyAuthentication __CLICD_PUBKEY_AUTH__
|
||||||
PasswordAuthentication yes
|
PasswordAuthentication yes
|
||||||
KbdInteractiveAuthentication yes
|
KbdInteractiveAuthentication yes
|
||||||
ChallengeResponseAuthentication yes
|
ChallengeResponseAuthentication yes
|
||||||
@@ -2507,8 +2514,8 @@ EOF
|
|||||||
if [ -f /etc/ssh/sshd_config ]; then
|
if [ -f /etc/ssh/sshd_config ]; then
|
||||||
grep -q '^PermitRootLogin ' /etc/ssh/sshd_config && sed -i 's/^PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config || printf '\nPermitRootLogin yes\n' >> /etc/ssh/sshd_config
|
grep -q '^PermitRootLogin ' /etc/ssh/sshd_config && sed -i 's/^PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config || printf '\nPermitRootLogin yes\n' >> /etc/ssh/sshd_config
|
||||||
grep -q '^#PermitRootLogin ' /etc/ssh/sshd_config && sed -i 's/^#PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config || true
|
grep -q '^#PermitRootLogin ' /etc/ssh/sshd_config && sed -i 's/^#PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config || true
|
||||||
grep -q '^PubkeyAuthentication ' /etc/ssh/sshd_config && sed -i 's/^PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config || printf '\nPubkeyAuthentication yes\n' >> /etc/ssh/sshd_config
|
grep -q '^PubkeyAuthentication ' /etc/ssh/sshd_config && sed -i 's/^PubkeyAuthentication .*/PubkeyAuthentication __CLICD_PUBKEY_AUTH__/' /etc/ssh/sshd_config || printf '\nPubkeyAuthentication __CLICD_PUBKEY_AUTH__\n' >> /etc/ssh/sshd_config
|
||||||
grep -q '^#PubkeyAuthentication ' /etc/ssh/sshd_config && sed -i 's/^#PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config || true
|
grep -q '^#PubkeyAuthentication ' /etc/ssh/sshd_config && sed -i 's/^#PubkeyAuthentication .*/PubkeyAuthentication __CLICD_PUBKEY_AUTH__/' /etc/ssh/sshd_config || true
|
||||||
grep -q '^PasswordAuthentication ' /etc/ssh/sshd_config && sed -i 's/^PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config || printf '\nPasswordAuthentication yes\n' >> /etc/ssh/sshd_config
|
grep -q '^PasswordAuthentication ' /etc/ssh/sshd_config && sed -i 's/^PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config || printf '\nPasswordAuthentication yes\n' >> /etc/ssh/sshd_config
|
||||||
grep -q '^#PasswordAuthentication ' /etc/ssh/sshd_config && sed -i 's/^#PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config || true
|
grep -q '^#PasswordAuthentication ' /etc/ssh/sshd_config && sed -i 's/^#PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config || true
|
||||||
grep -q '^KbdInteractiveAuthentication ' /etc/ssh/sshd_config && sed -i 's/^KbdInteractiveAuthentication .*/KbdInteractiveAuthentication yes/' /etc/ssh/sshd_config || printf '\nKbdInteractiveAuthentication yes\n' >> /etc/ssh/sshd_config
|
grep -q '^KbdInteractiveAuthentication ' /etc/ssh/sshd_config && sed -i 's/^KbdInteractiveAuthentication .*/KbdInteractiveAuthentication yes/' /etc/ssh/sshd_config || printf '\nKbdInteractiveAuthentication yes\n' >> /etc/ssh/sshd_config
|
||||||
@@ -2549,6 +2556,8 @@ if [ -w /dev/tty1 ]; then
|
|||||||
printf '\nCLICD VNC console is ready. Press Enter for login prompt.\n' >/dev/tty1 || true
|
printf '\nCLICD VNC console is ready. Press Enter for login prompt.\n' >/dev/tty1 || true
|
||||||
fi
|
fi
|
||||||
`
|
`
|
||||||
|
script = strings.ReplaceAll(script, "__CLICD_PUBKEY_AUTH__", pubkeyValue)
|
||||||
|
return script
|
||||||
}
|
}
|
||||||
|
|
||||||
func kvmDesktopSetupScript(image Image) string {
|
func kvmDesktopSetupScript(image Image) string {
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ func (m *Manager) CreateContainer(cfg ContainerConfig) error {
|
|||||||
fmt.Printf("Warning: failed to install IPv6 init in %s: %v\n", lxcName, err)
|
fmt.Printf("Warning: failed to install IPv6 init in %s: %v\n", lxcName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := m.preconfigureSSH(rootfsPath, cfg.TemplateID); err != nil {
|
if err := m.preconfigureSSH(rootfsPath, cfg.TemplateID, sshAccess.Mode); err != nil {
|
||||||
fmt.Printf("Warning: failed to pre-configure SSH in %s: %v\n", lxcName, err)
|
fmt.Printf("Warning: failed to pre-configure SSH in %s: %v\n", lxcName, err)
|
||||||
}
|
}
|
||||||
if sshAccess.PublicKey != "" {
|
if sshAccess.PublicKey != "" {
|
||||||
@@ -512,11 +512,13 @@ IPv6AcceptRA=no
|
|||||||
}
|
}
|
||||||
|
|
||||||
// preconfigureSSH installs and configures SSH directly in the rootfs before first boot.
|
// preconfigureSSH installs and configures SSH directly in the rootfs before first boot.
|
||||||
func (m *Manager) preconfigureSSH(rootfsPath, templateID string) error {
|
func (m *Manager) preconfigureSSH(rootfsPath, templateID string, sshAuthMode string) error {
|
||||||
_ = templateID
|
_ = templateID
|
||||||
|
// Disable pubkey auth when user chose password-only mode (password or auto_password)
|
||||||
|
disablePubkey := sshAuthMode == SSHAuthPassword || sshAuthMode == SSHAuthAutoPassword
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cmd, err := m.rootfsCommand(rootfsPath, "sh", "-c", sshSetupScript(false))
|
cmd, err := m.rootfsCommand(rootfsPath, "sh", "-c", sshSetupScript(false, disablePubkey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1758,7 +1760,7 @@ func (m *Manager) EnsureSSH(id int) error {
|
|||||||
config.SaveConfig()
|
config.SaveConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
script := sshSetupScript(true)
|
script := sshSetupScript(true, false) // keep pubkey enabled for runtime ensure
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -1826,7 +1828,11 @@ func (m *Manager) containerPortListening(lxcName string, port int) bool {
|
|||||||
return exec.CommandContext(ctx, "lxc-attach", "-n", lxcName, "--", "sh", "-c", check).Run() == nil
|
return exec.CommandContext(ctx, "lxc-attach", "-n", lxcName, "--", "sh", "-c", check).Run() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshSetupScript(startService bool) string {
|
func sshSetupScript(startService bool, disablePubkeyAuth bool) string {
|
||||||
|
pubkeyValue := "yes"
|
||||||
|
if disablePubkeyAuth {
|
||||||
|
pubkeyValue = "no"
|
||||||
|
}
|
||||||
script := `set -u
|
script := `set -u
|
||||||
|
|
||||||
# DNS setup: handle both traditional /etc/resolv.conf and systemd-resolved (Ubuntu 24.04).
|
# DNS setup: handle both traditional /etc/resolv.conf and systemd-resolved (Ubuntu 24.04).
|
||||||
@@ -1945,7 +1951,7 @@ ssh-keygen -A >/dev/null 2>&1 || true
|
|||||||
|
|
||||||
cat >/etc/ssh/sshd_config.d/99-clicd.conf <<'EOF'
|
cat >/etc/ssh/sshd_config.d/99-clicd.conf <<'EOF'
|
||||||
PermitRootLogin yes
|
PermitRootLogin yes
|
||||||
PubkeyAuthentication yes
|
PubkeyAuthentication __CLICD_PUBKEY_AUTH__
|
||||||
PasswordAuthentication yes
|
PasswordAuthentication yes
|
||||||
KbdInteractiveAuthentication no
|
KbdInteractiveAuthentication no
|
||||||
ChallengeResponseAuthentication no
|
ChallengeResponseAuthentication no
|
||||||
@@ -1953,7 +1959,7 @@ UsePAM no
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
set_sshd_option PermitRootLogin yes
|
set_sshd_option PermitRootLogin yes
|
||||||
set_sshd_option PubkeyAuthentication yes
|
set_sshd_option PubkeyAuthentication __CLICD_PUBKEY_AUTH__
|
||||||
set_sshd_option PasswordAuthentication yes
|
set_sshd_option PasswordAuthentication yes
|
||||||
set_sshd_option KbdInteractiveAuthentication no
|
set_sshd_option KbdInteractiveAuthentication no
|
||||||
set_sshd_option ChallengeResponseAuthentication no
|
set_sshd_option ChallengeResponseAuthentication no
|
||||||
@@ -1981,6 +1987,7 @@ ensure_sshd_runtime_dir
|
|||||||
exit 32
|
exit 32
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
script = strings.ReplaceAll(script, "__CLICD_PUBKEY_AUTH__", pubkeyValue)
|
||||||
if !startService {
|
if !startService {
|
||||||
return script
|
return script
|
||||||
}
|
}
|
||||||
@@ -2054,7 +2061,7 @@ func (m *Manager) ResetSSHPassword(id int, password string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
rootfsPath := filepath.Join(m.LxcPath, lxcName, "rootfs")
|
rootfsPath := filepath.Join(m.LxcPath, lxcName, "rootfs")
|
||||||
if err := m.preconfigureSSH(rootfsPath, c.Template); err != nil {
|
if err := m.preconfigureSSH(rootfsPath, c.Template, ""); err != nil {
|
||||||
return "", fmt.Errorf("failed to configure SSH: %v", err)
|
return "", fmt.Errorf("failed to configure SSH: %v", err)
|
||||||
}
|
}
|
||||||
if err := m.setRootfsPassword(rootfsPath, newPassword); err != nil {
|
if err := m.setRootfsPassword(rootfsPath, newPassword); err != nil {
|
||||||
@@ -2626,7 +2633,7 @@ func (m *Manager) ReinstallContainer(id int, templateID string, authConfig ...Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.SSHPassword = sshAccess.Password
|
c.SSHPassword = sshAccess.Password
|
||||||
if err := m.preconfigureSSH(rootfsPath, templateID); err != nil {
|
if err := m.preconfigureSSH(rootfsPath, templateID, sshAccess.Mode); err != nil {
|
||||||
fmt.Printf("Warning: failed to pre-configure SSH in %s after reinstall: %v\n", lxcName, err)
|
fmt.Printf("Warning: failed to pre-configure SSH in %s after reinstall: %v\n", lxcName, err)
|
||||||
}
|
}
|
||||||
if sshAccess.PublicKey != "" {
|
if sshAccess.PublicKey != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user