@@ -35,10 +35,135 @@ set +u
3535CLOUDINIT_DEFAULT_USER=" ${CLOUDINIT_DEFAULT_USER:- root} "
3636CLOUDINIT_DNS_SERVERS=" ${CLOUDINIT_DNS_SERVERS:- 1.1.1.1 8.8.8.8} "
3737CLOUDINIT_SEARCH_DOMAIN=" ${CLOUDINIT_SEARCH_DOMAIN:- local} "
38- CLOUDINIT_SSH_KEYS=" ${CLOUDINIT_SSH_KEYS:-/ root / .ssh / authorized_keys} "
38+ CLOUDINIT_SSH_KEYS=" ${CLOUDINIT_SSH_KEYS:- } " # Empty by default - user must explicitly provide keys
3939
4040# ==============================================================================
41- # SECTION 2: HELPER FUNCTIONS
41+ # SECTION 2: SSH KEY DISCOVERY AND SELECTION
42+ # ==============================================================================
43+
44+ # ------------------------------------------------------------------------------
45+ # _ci_ssh_extract_keys_from_file - Extracts valid SSH public keys from a file
46+ # ------------------------------------------------------------------------------
47+ function _ci_ssh_extract_keys_from_file() {
48+ local file=" $1 "
49+ [[ -f " $file " && -r " $file " ]] || return 0
50+ grep -E ' ^(ssh-(rsa|ed25519|dss|ecdsa)|ecdsa-sha2-)' " $file " 2> /dev/null || true
51+ }
52+
53+ # ------------------------------------------------------------------------------
54+ # _ci_ssh_discover_files - Scans standard paths for SSH keys
55+ # ------------------------------------------------------------------------------
56+ function _ci_ssh_discover_files() {
57+ local -a cand=()
58+ shopt -s nullglob
59+ cand+=(/root/.ssh/authorized_keys /root/.ssh/authorized_keys2)
60+ cand+=(/root/.ssh/* .pub)
61+ cand+=(/etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/* )
62+ shopt -u nullglob
63+ printf ' %s\n' " ${cand[@]} "
64+ }
65+
66+ # ------------------------------------------------------------------------------
67+ # _ci_ssh_count_keys - Counts available SSH keys on the system
68+ # ------------------------------------------------------------------------------
69+ function _ci_ssh_count_keys() {
70+ local count=0
71+ while IFS= read -r file; do
72+ [[ -f " $file " && -r " $file " ]] || continue
73+ local keys=$( _ci_ssh_extract_keys_from_file " $file " | wc -l)
74+ count=$(( count + keys))
75+ done < <( _ci_ssh_discover_files)
76+ echo " $count "
77+ }
78+
79+ # ------------------------------------------------------------------------------
80+ # configure_cloudinit_ssh_keys - Interactive SSH key selection for Cloud-Init
81+ #
82+ # Usage: configure_cloudinit_ssh_keys
83+ # Sets: CLOUDINIT_SSH_KEYS (path to temporary file with selected keys)
84+ # ------------------------------------------------------------------------------
85+ function configure_cloudinit_ssh_keys() {
86+ local backtitle=" Proxmox VE Helper Scripts"
87+ local default_key_count=$( _ci_ssh_count_keys)
88+ local ssh_key_mode
89+
90+ # Create temp file for selected keys
91+ CLOUDINIT_SSH_KEYS_TEMP=" $( mktemp) "
92+
93+ if [[ " $default_key_count " -gt 0 ]]; then
94+ ssh_key_mode=$( whiptail --backtitle " $backtitle " --title " SSH KEY SOURCE" --menu \
95+ " Provision SSH keys for Cloud-Init VM:" 14 72 4 \
96+ " host" " Import all keys from host ($default_key_count found)" \
97+ " manual" " Paste a single public key" \
98+ " file" " Specify path to authorized_keys file" \
99+ " none" " No SSH keys (password auth only)" 3>&1 1>&2 2>&3 ) || return 1
100+ else
101+ ssh_key_mode=$( whiptail --backtitle " $backtitle " --title " SSH KEY SOURCE" --menu \
102+ " No host keys detected. Choose:" 12 72 3 \
103+ " manual" " Paste a single public key" \
104+ " file" " Specify path to authorized_keys file" \
105+ " none" " No SSH keys (password auth only)" 3>&1 1>&2 2>&3 ) || return 1
106+ fi
107+
108+ case " $ssh_key_mode " in
109+ host)
110+ # Import all keys from host
111+ while IFS= read -r file; do
112+ _ci_ssh_extract_keys_from_file " $file " >> " $CLOUDINIT_SSH_KEYS_TEMP "
113+ done < <( _ci_ssh_discover_files)
114+ local imported=$( wc -l < " $CLOUDINIT_SSH_KEYS_TEMP " )
115+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${DGN} SSH Keys: ${BGN}${imported} keys imported from host${CL} "
116+ ;;
117+ manual)
118+ local pubkey
119+ pubkey=$( whiptail --backtitle " $backtitle " --title " PASTE SSH PUBLIC KEY" \
120+ --inputbox " Paste your SSH public key (ssh-rsa, ssh-ed25519, etc.):" 10 76 3>&1 1>&2 2>&3 ) || return 1
121+ if [[ -n " $pubkey " ]]; then
122+ echo " $pubkey " > " $CLOUDINIT_SSH_KEYS_TEMP "
123+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${DGN} SSH Keys: ${BGN} 1 key added manually${CL} "
124+ else
125+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${DGN} SSH Keys: ${BGN} none (empty input)${CL} "
126+ CLOUDINIT_SSH_KEYS=" "
127+ rm -f " $CLOUDINIT_SSH_KEYS_TEMP "
128+ return 0
129+ fi
130+ ;;
131+ file)
132+ local keyfile
133+ keyfile=$( whiptail --backtitle " $backtitle " --title " SSH KEY FILE" \
134+ --inputbox " Enter path to authorized_keys file:" 10 60 " /root/.ssh/authorized_keys" 3>&1 1>&2 2>&3 ) || return 1
135+ if [[ -f " $keyfile " ]]; then
136+ _ci_ssh_extract_keys_from_file " $keyfile " > " $CLOUDINIT_SSH_KEYS_TEMP "
137+ local imported=$( wc -l < " $CLOUDINIT_SSH_KEYS_TEMP " )
138+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${DGN} SSH Keys: ${BGN}${imported} keys from ${keyfile}${CL} "
139+ else
140+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${RD} File not found: ${keyfile}${CL} "
141+ CLOUDINIT_SSH_KEYS=" "
142+ rm -f " $CLOUDINIT_SSH_KEYS_TEMP "
143+ return 1
144+ fi
145+ ;;
146+ none | * )
147+ echo -e " ${ROOTSSH:- 🔑 }${BOLD}${DGN} SSH Keys: ${BGN} none (password auth only)${CL} "
148+ CLOUDINIT_SSH_KEYS=" "
149+ rm -f " $CLOUDINIT_SSH_KEYS_TEMP "
150+ return 0
151+ ;;
152+ esac
153+
154+ # Set the variable for setup_cloud_init to use
155+ if [[ -s " $CLOUDINIT_SSH_KEYS_TEMP " ]]; then
156+ CLOUDINIT_SSH_KEYS=" $CLOUDINIT_SSH_KEYS_TEMP "
157+ else
158+ CLOUDINIT_SSH_KEYS=" "
159+ rm -f " $CLOUDINIT_SSH_KEYS_TEMP "
160+ fi
161+
162+ return 0
163+ }
164+
165+ # ==============================================================================
166+ # SECTION 3: HELPER FUNCTIONS
42167# ==============================================================================
43168
44169# ------------------------------------------------------------------------------
@@ -148,9 +273,10 @@ function setup_cloud_init() {
148273 local cipassword=$( openssl rand -base64 16)
149274 qm set " $vmid " --cipassword " $cipassword " > /dev/null
150275
151- # Add SSH keys if available
152- if [ -f " $CLOUDINIT_SSH_KEYS " ]; then
276+ # Add SSH keys only if explicitly provided (not auto-imported from host)
277+ if [ -n " ${CLOUDINIT_SSH_KEYS :- } " ] && [ - f " $CLOUDINIT_SSH_KEYS " ]; then
153278 qm set " $vmid " --sshkeys " $CLOUDINIT_SSH_KEYS " > /dev/null 2>&1 || true
279+ _ci_msg_info " SSH keys imported from: $CLOUDINIT_SSH_KEYS "
154280 fi
155281
156282 # Configure network
0 commit comments