underpost 2.99.5 → 2.99.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,294 @@
1
+ #!/bin/bash
2
+ # Rocky Linux 9 - Anaconda %pre Ephemeral Commissioning Script
3
+ # Variables ROOT_PASS, AUTHORIZED_KEYS, ADMIN_USER must be set before this script runs.
4
+
5
+ set +e
6
+
7
+ # 1. Set root password
8
+ if [ -n "$ROOT_PASS" ]; then
9
+ echo "root:$ROOT_PASS" | chpasswd 2>/dev/null || \
10
+ echo "$ROOT_PASS" | passwd --stdin root 2>/dev/null || {
11
+ HASH=$(python3 -c "import crypt; print(crypt.crypt('$ROOT_PASS', crypt.mksalt(crypt.METHOD_SHA512)))" 2>/dev/null || \
12
+ openssl passwd -6 "$ROOT_PASS" 2>/dev/null)
13
+ [ -n "$HASH" ] && sed -i "s|^root:[^:]*:|root:$HASH:|" /etc/shadow 2>/dev/null
14
+ }
15
+ fi
16
+
17
+ # 2. SSH authorized_keys for root
18
+ if [ -n "$AUTHORIZED_KEYS" ]; then
19
+ mkdir -p /root/.ssh && chmod 700 /root/.ssh
20
+ echo "$AUTHORIZED_KEYS" > /root/.ssh/authorized_keys
21
+ chmod 600 /root/.ssh/authorized_keys
22
+ fi
23
+
24
+ # 3. Create admin user
25
+ if command -v useradd >/dev/null 2>&1; then
26
+ useradd -m -G wheel "$ADMIN_USER" 2>/dev/null || true
27
+ else
28
+ NEXT_UID=$(awk -F: 'BEGIN{max=999} $3>max && $3<60000{max=$3} END{print max+1}' /etc/passwd 2>/dev/null || echo 1001)
29
+ if ! grep -q "^$ADMIN_USER:" /etc/passwd 2>/dev/null; then
30
+ echo "$ADMIN_USER:x:$NEXT_UID:$NEXT_UID:$ADMIN_USER:/home/$ADMIN_USER:/bin/bash" >> /etc/passwd
31
+ echo "$ADMIN_USER:x:$NEXT_UID:" >> /etc/group 2>/dev/null
32
+ echo "$ADMIN_USER:!:19000:0:99999:7:::" >> /etc/shadow 2>/dev/null
33
+ mkdir -p /home/$ADMIN_USER
34
+ fi
35
+ fi
36
+
37
+ if [ -n "$ROOT_PASS" ]; then
38
+ echo "$ADMIN_USER:$ROOT_PASS" | chpasswd 2>/dev/null || \
39
+ echo "$ROOT_PASS" | passwd --stdin "$ADMIN_USER" 2>/dev/null || {
40
+ HASH=$(python3 -c "import crypt; print(crypt.crypt('$ROOT_PASS', crypt.mksalt(crypt.METHOD_SHA512)))" 2>/dev/null || \
41
+ openssl passwd -6 "$ROOT_PASS" 2>/dev/null)
42
+ [ -n "$HASH" ] && sed -i "s|^$ADMIN_USER:[^:]*:|$ADMIN_USER:$HASH:|" /etc/shadow 2>/dev/null
43
+ }
44
+ fi
45
+
46
+ if [ -n "$AUTHORIZED_KEYS" ]; then
47
+ mkdir -p /home/$ADMIN_USER/.ssh && chmod 700 /home/$ADMIN_USER/.ssh
48
+ echo "$AUTHORIZED_KEYS" > /home/$ADMIN_USER/.ssh/authorized_keys
49
+ chmod 600 /home/$ADMIN_USER/.ssh/authorized_keys
50
+ chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.ssh 2>/dev/null || true
51
+ fi
52
+
53
+ if [ -d /etc/sudoers.d ]; then
54
+ echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$ADMIN_USER
55
+ chmod 0440 /etc/sudoers.d/$ADMIN_USER
56
+ elif [ -f /etc/sudoers ]; then
57
+ echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
58
+ fi
59
+
60
+ # 4. Configure sshd
61
+ if [ -f /etc/ssh/sshd_config ]; then
62
+ sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
63
+ sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
64
+ sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
65
+ sed -i 's/^#*ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
66
+ sed -i 's/^#*UsePAM.*/UsePAM yes/' /etc/ssh/sshd_config
67
+ sed -i 's/^#*KbdInteractiveAuthentication.*/KbdInteractiveAuthentication yes/' /etc/ssh/sshd_config
68
+ grep -q "^PasswordAuthentication" /etc/ssh/sshd_config || echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
69
+ grep -q "^PermitRootLogin" /etc/ssh/sshd_config || echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
70
+ grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config || echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
71
+ else
72
+ mkdir -p /etc/ssh
73
+ cat > /etc/ssh/sshd_config << 'SSHEOF'
74
+ Port 22
75
+ PermitRootLogin yes
76
+ PubkeyAuthentication yes
77
+ AuthorizedKeysFile .ssh/authorized_keys
78
+ PasswordAuthentication yes
79
+ ChallengeResponseAuthentication yes
80
+ KbdInteractiveAuthentication yes
81
+ UsePAM yes
82
+ Subsystem sftp /usr/libexec/openssh/sftp-server
83
+ SSHEOF
84
+ fi
85
+
86
+ if [ -d /etc/ssh/sshd_config.d ]; then
87
+ cat > /etc/ssh/sshd_config.d/00-underpost.conf << 'SSHCONF'
88
+ PermitRootLogin yes
89
+ PasswordAuthentication yes
90
+ PubkeyAuthentication yes
91
+ KbdInteractiveAuthentication yes
92
+ SSHCONF
93
+ fi
94
+
95
+ if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
96
+ ssh-keygen -A 2>/dev/null || {
97
+ ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" 2>/dev/null
98
+ ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" 2>/dev/null
99
+ ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" 2>/dev/null
100
+ }
101
+ fi
102
+
103
+ # 5. Initialize rpmdb and dnf repos
104
+ mkdir -p /var/lib/rpm /var/cache/dnf /var/log/dnf /etc/yum.repos.d /etc/pki/rpm-gpg /etc/dnf/vars
105
+ echo "9" > /etc/dnf/vars/releasever
106
+
107
+ if ! grep -q "^VERSION_ID=" /etc/os-release 2>/dev/null; then
108
+ cat > /etc/os-release << 'OSREL'
109
+ NAME="Rocky Linux"
110
+ VERSION="9"
111
+ ID="rocky"
112
+ ID_LIKE="rhel centos fedora"
113
+ VERSION_ID="9"
114
+ PLATFORM_ID="platform:el9"
115
+ PRETTY_NAME="Rocky Linux 9 (Ephemeral Anaconda)"
116
+ ANSI_COLOR="0;32"
117
+ HOME_URL="https://rockylinux.org/"
118
+ OSREL
119
+ fi
120
+
121
+ [ ! -f /etc/system-release ] && echo "Rocky Linux release 9 (Ephemeral)" > /etc/system-release
122
+
123
+ rpm --initdb 2>/dev/null || rpmdb --initdb 2>/dev/null || {
124
+ if command -v python3 >/dev/null 2>&1; then
125
+ python3 -c "
126
+ import sqlite3, os
127
+ db_path = '/var/lib/rpm/rpmdb.sqlite'
128
+ if not os.path.exists(db_path):
129
+ conn = sqlite3.connect(db_path)
130
+ conn.execute('CREATE TABLE IF NOT EXISTS Packages (key BLOB NOT NULL, data BLOB NOT NULL)')
131
+ conn.execute('CREATE TABLE IF NOT EXISTS Name (key BLOB NOT NULL, data BLOB NOT NULL)')
132
+ conn.execute('CREATE TABLE IF NOT EXISTS Basenames (key BLOB NOT NULL, data BLOB NOT NULL)')
133
+ conn.execute('CREATE TABLE IF NOT EXISTS Installtid (key BLOB NOT NULL, data BLOB NOT NULL)')
134
+ conn.execute('CREATE TABLE IF NOT EXISTS Providename (key BLOB NOT NULL, data BLOB NOT NULL)')
135
+ conn.execute('CREATE TABLE IF NOT EXISTS Requirename (key BLOB NOT NULL, data BLOB NOT NULL)')
136
+ conn.execute('CREATE TABLE IF NOT EXISTS Dirnames (key BLOB NOT NULL, data BLOB NOT NULL)')
137
+ conn.execute('CREATE TABLE IF NOT EXISTS Sha1header (key BLOB NOT NULL, data BLOB NOT NULL)')
138
+ conn.execute('CREATE TABLE IF NOT EXISTS Sigmd5 (key BLOB NOT NULL, data BLOB NOT NULL)')
139
+ conn.commit()
140
+ conn.close()
141
+ " 2>/dev/null
142
+ fi
143
+ }
144
+ chmod -R 755 /var/lib/rpm 2>/dev/null
145
+
146
+ REPO_ARCH=$(uname -m)
147
+
148
+ rpm --import https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9 2>/dev/null || \
149
+ curl -fsSL https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9 2>/dev/null || true
150
+
151
+ cat > /etc/dnf/dnf.conf << 'DNFCONF'
152
+ [main]
153
+ gpgcheck=1
154
+ installonly_limit=3
155
+ clean_requirements_on_remove=True
156
+ best=True
157
+ skip_if_unavailable=True
158
+ install_weak_deps=False
159
+ tsflags=nodocs
160
+ DNFCONF
161
+
162
+ cat > /etc/yum.repos.d/rocky-baseos.repo << REPOEOF
163
+ [baseos]
164
+ name=Rocky Linux 9 - BaseOS
165
+ baseurl=http://dl.rockylinux.org/pub/rocky/9/BaseOS/$REPO_ARCH/os/
166
+ gpgcheck=1
167
+ enabled=1
168
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
169
+ https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
170
+ skip_if_unavailable=1
171
+ REPOEOF
172
+
173
+ cat > /etc/yum.repos.d/rocky-appstream.repo << REPOEOF2
174
+ [appstream]
175
+ name=Rocky Linux 9 - AppStream
176
+ baseurl=http://dl.rockylinux.org/pub/rocky/9/AppStream/$REPO_ARCH/os/
177
+ gpgcheck=1
178
+ enabled=1
179
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
180
+ https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
181
+ skip_if_unavailable=1
182
+ REPOEOF2
183
+
184
+ cat > /etc/yum.repos.d/rocky-extras.repo << REPOEOF3
185
+ [extras]
186
+ name=Rocky Linux 9 - Extras
187
+ baseurl=http://dl.rockylinux.org/pub/rocky/9/extras/$REPO_ARCH/os/
188
+ gpgcheck=1
189
+ enabled=1
190
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
191
+ https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
192
+ skip_if_unavailable=1
193
+ REPOEOF3
194
+
195
+ cat > /etc/yum.repos.d/rocky-crb.repo << REPOEOF4
196
+ [crb]
197
+ name=Rocky Linux 9 - CRB
198
+ baseurl=http://dl.rockylinux.org/pub/rocky/9/CRB/$REPO_ARCH/os/
199
+ gpgcheck=1
200
+ enabled=0
201
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
202
+ https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
203
+ skip_if_unavailable=1
204
+ REPOEOF4
205
+
206
+ cat > /etc/yum.repos.d/epel.repo << REPOEOF5
207
+ [epel]
208
+ name=Extra Packages for Enterprise Linux 9
209
+ metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-9&arch=$REPO_ARCH
210
+ gpgcheck=1
211
+ enabled=1
212
+ gpgkey=https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
213
+ skip_if_unavailable=1
214
+ REPOEOF5
215
+
216
+ rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 2>/dev/null || \
217
+ curl -fsSL https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9 2>/dev/null || true
218
+
219
+ dnf makecache --releasever=9 --quiet 2>/dev/null || dnf makecache --releasever=9 2>/dev/null || true
220
+
221
+ # Install sudo
222
+ if ! command -v sudo >/dev/null 2>&1; then
223
+ dnf install -y --releasever=9 --nogpgcheck sudo 2>/dev/null || \
224
+ dnf install -y --releasever=9 --nogpgcheck --disableplugin='*' sudo 2>/dev/null || true
225
+ fi
226
+
227
+ if command -v sudo >/dev/null 2>&1; then
228
+ mkdir -p /etc/sudoers.d
229
+ echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$ADMIN_USER
230
+ chmod 0440 /etc/sudoers.d/$ADMIN_USER
231
+ fi
232
+
233
+ cat > /home/$ADMIN_USER/.bash_profile 2>/dev/null << PROFILEEOF
234
+ if ! command -v sudo >/dev/null 2>&1; then
235
+ echo ""
236
+ echo "NOTE: sudo is not available. Use 'su -' to switch to root."
237
+ echo ""
238
+ fi
239
+ PROFILEEOF
240
+ chown $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.bash_profile 2>/dev/null || true
241
+
242
+ # Restart sshd
243
+ if command -v systemctl >/dev/null 2>&1; then
244
+ systemctl restart sshd 2>/dev/null || systemctl restart sshd.service 2>/dev/null
245
+ fi
246
+ SSHD_PID=$(cat /var/run/sshd.pid 2>/dev/null || pidof sshd 2>/dev/null | awk '{print $1}')
247
+ [ -n "$SSHD_PID" ] && kill -HUP "$SSHD_PID" 2>/dev/null
248
+ if ! pidof sshd >/dev/null 2>&1; then
249
+ /usr/sbin/sshd 2>/dev/null || sshd 2>/dev/null
250
+ fi
251
+
252
+ # 6. Status report
253
+ DETECTED_IP=$(ip -4 addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1 | head -1)
254
+
255
+ echo ""
256
+ echo "=============================================="
257
+ echo "Underpost: Ephemeral SSHD Setup Complete"
258
+ echo "=============================================="
259
+ echo "Root login: root / (password set: $([ -n "$ROOT_PASS" ] && echo 'yes' || echo 'no'))"
260
+ echo "Admin user: $ADMIN_USER / (password set: $([ -n "$ROOT_PASS" ] && echo 'yes' || echo 'no'))"
261
+ echo "SSH keys: $([ -n "$AUTHORIZED_KEYS" ] && echo 'configured' || echo 'NOT configured')"
262
+ echo "sshd status: $(pidof sshd >/dev/null 2>&1 && echo "running (pid $(pidof sshd))" || echo 'NOT running')"
263
+ echo "sudo: $(command -v sudo >/dev/null 2>&1 && echo 'installed' || echo 'NOT available (use su -)')"
264
+ echo "IP address: $DETECTED_IP"
265
+ echo "=============================================="
266
+
267
+ # Physical console display (printf with \r\n for proper line breaks on serial/physical consoles)
268
+ {
269
+ printf "\r\n"
270
+ printf "██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░██████╗░░█████╗░░██████╗████████╗\r\n"
271
+ printf "██║░░░██║████╗░██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝\r\n"
272
+ printf "██║░░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██████╔╝██║░░██║╚█████╗░░░░██║░░░\r\n"
273
+ printf "██║░░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██╔═══╝░██║░░██║░╚═══██╗░░░██║░░░\r\n"
274
+ printf "╚██████╔╝██║░╚███║██████╔╝███████╗██║░░██║██║░░░░░╚█████╔╝██████╔╝░░░██║░░░\r\n"
275
+ printf "░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚═╝░░░░░░╚════╝░╚═════╝░░░░╚═╝░░░\r\n"
276
+ printf "==============================================\r\n"
277
+ printf " Underpost Ephemeral Commissioning Active\r\n"
278
+ printf "==============================================\r\n"
279
+ printf " SSH as: root@%s\r\n" "$DETECTED_IP"
280
+ printf " or: %s@%s\r\n" "$ADMIN_USER" "$DETECTED_IP"
281
+ printf " Key: %s\r\n" "$([ -n "$AUTHORIZED_KEYS" ] && echo 'pubkey auth enabled' || echo 'password only')"
282
+ printf " dnf: ready (BaseOS, AppStream, Extras, EPEL)\r\n"
283
+ printf "==============================================\r\n"
284
+ printf "\r\n"
285
+ } > /dev/console 2>/dev/null || true
286
+
287
+ # 7. Infinite wait loop - keep Anaconda live environment active
288
+ while true; do
289
+ sleep 60
290
+ if ! pidof sshd >/dev/null 2>&1; then
291
+ echo "$(date): sshd not running, restarting..." >> /tmp/ks-pre.log
292
+ /usr/sbin/sshd 2>/dev/null || sshd 2>/dev/null
293
+ fi
294
+ done