@ebowwa/hetzner 0.1.0
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.
- package/actions.js +802 -0
- package/actions.ts +1053 -0
- package/auth.js +35 -0
- package/auth.ts +37 -0
- package/bootstrap/FIREWALL.md +326 -0
- package/bootstrap/KERNEL-HARDENING.md +258 -0
- package/bootstrap/SECURITY-INTEGRATION.md +281 -0
- package/bootstrap/TESTING.md +301 -0
- package/bootstrap/cloud-init.js +279 -0
- package/bootstrap/cloud-init.ts +394 -0
- package/bootstrap/firewall.js +279 -0
- package/bootstrap/firewall.ts +342 -0
- package/bootstrap/genesis.js +406 -0
- package/bootstrap/genesis.ts +518 -0
- package/bootstrap/index.js +35 -0
- package/bootstrap/index.ts +71 -0
- package/bootstrap/kernel-hardening.js +266 -0
- package/bootstrap/kernel-hardening.test.ts +230 -0
- package/bootstrap/kernel-hardening.ts +272 -0
- package/bootstrap/security-audit.js +118 -0
- package/bootstrap/security-audit.ts +124 -0
- package/bootstrap/ssh-hardening.js +182 -0
- package/bootstrap/ssh-hardening.ts +192 -0
- package/client.js +137 -0
- package/client.ts +177 -0
- package/config.js +5 -0
- package/config.ts +5 -0
- package/errors.js +270 -0
- package/errors.ts +371 -0
- package/index.js +28 -0
- package/index.ts +55 -0
- package/package.json +56 -0
- package/pricing.js +284 -0
- package/pricing.ts +422 -0
- package/schemas.js +660 -0
- package/schemas.ts +765 -0
- package/server-status.ts +81 -0
- package/servers.js +424 -0
- package/servers.ts +568 -0
- package/ssh-keys.js +90 -0
- package/ssh-keys.ts +122 -0
- package/ssh-setup.ts +218 -0
- package/types.js +96 -0
- package/types.ts +389 -0
- package/volumes.js +172 -0
- package/volumes.ts +229 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kernel Hardening Cloud-Init Components
|
|
3
|
+
*
|
|
4
|
+
* Composable cloud-init blocks for securing the Linux kernel on new servers.
|
|
5
|
+
* Implements 2026 best practices for network stack hardening, IP spoofing
|
|
6
|
+
* protection, SYN flood mitigation, and secure core dump policies.
|
|
7
|
+
*
|
|
8
|
+
* Background: Public-facing VPS servers are constantly probed and attacked.
|
|
9
|
+
* Default Linux kernel settings prioritize compatibility over security. This
|
|
10
|
+
* module applies CIS Benchmark-aligned hardening via /etc/sysctl.d/ which
|
|
11
|
+
* persists across reboots and overrides defaults.
|
|
12
|
+
*
|
|
13
|
+
* Three composable functions return cloud-init line arrays for splicing into
|
|
14
|
+
* the appropriate YAML sections:
|
|
15
|
+
* - kernelHardeningPackages() → packages: section (currently empty, reserved)
|
|
16
|
+
* - kernelHardeningWriteFiles() → write_files: section (drops sysctl config)
|
|
17
|
+
* - kernelHardeningRunCmd() → runcmd: section (applies settings immediately)
|
|
18
|
+
*
|
|
19
|
+
* Security Measures Implemented:
|
|
20
|
+
* 1. Network Stack Hardening: SYN cookies, ICMP rate limits, martian packet logging
|
|
21
|
+
* 2. IP Spoofing Protection: Reverse path filtering, source address verification
|
|
22
|
+
* 3. SYN Flood Protection: TCP SYN cookies, reuse time_wait connections
|
|
23
|
+
* 4. Core Dump Restrictions: Disable setuid dumps, limit core dump size to 0
|
|
24
|
+
* 5. File Permissions: Hard links, symlinks, FIFO protection
|
|
25
|
+
* 6. Memory Protection: ASLR, randomize_va_space
|
|
26
|
+
*
|
|
27
|
+
* References:
|
|
28
|
+
* - CIS Benchmark for Ubuntu Linux 24.04
|
|
29
|
+
* - NIST SP 800-53 Revision 5
|
|
30
|
+
* - https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Packages required for kernel hardening.
|
|
35
|
+
* Returns cloud-init YAML lines for the `packages:` section.
|
|
36
|
+
*
|
|
37
|
+
* Note: All kernel hardening is done via sysctl configuration, which uses
|
|
38
|
+
* built-in kernel functionality. No additional packages are required.
|
|
39
|
+
* This function is reserved for future expansion (e.g., auditd, kexec-tools).
|
|
40
|
+
*/
|
|
41
|
+
export function kernelHardeningPackages(): string[] {
|
|
42
|
+
return [
|
|
43
|
+
// Reserved for future packages (auditd, kexec-tools, etc.)
|
|
44
|
+
// Currently empty - all hardening via sysctl
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Kernel sysctl configuration file for comprehensive hardening.
|
|
50
|
+
* Returns cloud-init YAML lines for the `write_files:` section.
|
|
51
|
+
*
|
|
52
|
+
* Drops /etc/sysctl.d/99-security-hardening.conf which:
|
|
53
|
+
* - Takes precedence over /etc/sysctl.conf (99- prefix ensures last load)
|
|
54
|
+
* - Persists across reboots (sysctl.d files are applied on boot)
|
|
55
|
+
* - Can be applied immediately via `sysctl --system` (see runcmd)
|
|
56
|
+
*
|
|
57
|
+
* Settings organized by category:
|
|
58
|
+
* 1. IP Spoofing Protection: rp_filter, secure redirects
|
|
59
|
+
* 2. SYN Flood Protection: syncookies, tcp_tw_reuse
|
|
60
|
+
* 3. Network Stack: ICMP rate limits, martian logging, ignore broadcasts
|
|
61
|
+
* 4. Core Dumps: Disabled for setuid programs, limited for all processes
|
|
62
|
+
* 5. Memory Protection: ASLR, randomize_va_space
|
|
63
|
+
* 6. Filesystem: Hard link/symlink protection
|
|
64
|
+
*/
|
|
65
|
+
export function kernelHardeningWriteFiles(): string[] {
|
|
66
|
+
const lines: string[] = [];
|
|
67
|
+
|
|
68
|
+
lines.push(" # Kernel hardening: sysctl.d configuration for 2026 best practices");
|
|
69
|
+
lines.push(" # This file persists across reboots and overrides /etc/sysctl.conf");
|
|
70
|
+
lines.push(" - path: /etc/sysctl.d/99-security-hardening.conf");
|
|
71
|
+
lines.push(" owner: root:root");
|
|
72
|
+
lines.push(" permissions: '0644'");
|
|
73
|
+
lines.push(" content: |");
|
|
74
|
+
lines.push(" # =================================================================");
|
|
75
|
+
lines.push(" # Kernel Security Hardening Configuration");
|
|
76
|
+
lines.push(" # =================================================================");
|
|
77
|
+
lines.push(" # Applied via cloud-init for com.hetzner.codespaces");
|
|
78
|
+
lines.push(" # Version: 1.0.0 (2026 best practices)");
|
|
79
|
+
lines.push(" #");
|
|
80
|
+
lines.push(" # This configuration follows CIS Benchmark and NIST guidelines");
|
|
81
|
+
lines.push(" # See: /usr/share/doc/linux-doc/sysctl/ for parameter documentation");
|
|
82
|
+
lines.push("");
|
|
83
|
+
lines.push(" # =================================================================");
|
|
84
|
+
lines.push(" # 1. IP SPOOFING PROTECTION");
|
|
85
|
+
lines.push(" # =================================================================");
|
|
86
|
+
lines.push(" # Enable reverse path filtering (validates source addresses)");
|
|
87
|
+
lines.push(" # Prevents IP spoofing attacks by dropping packets with invalid sources");
|
|
88
|
+
lines.push(" net.ipv4.conf.all.rp_filter = 1");
|
|
89
|
+
lines.push(" net.ipv4.conf.default.rp_filter = 1");
|
|
90
|
+
lines.push("");
|
|
91
|
+
lines.push(" # Log martian packets (packets with impossible addresses)");
|
|
92
|
+
lines.push(" # Helps detect spoofing attempts and network misconfigurations");
|
|
93
|
+
lines.push(" net.ipv4.conf.all.log_martians = 1");
|
|
94
|
+
lines.push("");
|
|
95
|
+
lines.push(" # Disable ICMP redirect acceptance (prevent MITM attacks)");
|
|
96
|
+
lines.push(" net.ipv4.conf.all.accept_redirects = 0");
|
|
97
|
+
lines.push(" net.ipv4.conf.default.accept_redirects = 0");
|
|
98
|
+
lines.push(" net.ipv4.conf.all.secure_redirects = 0");
|
|
99
|
+
lines.push(" net.ipv4.conf.default.secure_redirects = 0");
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push(" # Disable sending ICMP redirects");
|
|
102
|
+
lines.push(" net.ipv4.conf.all.send_redirects = 0");
|
|
103
|
+
lines.push(" net.ipv4.conf.default.send_redirects = 0");
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push(" # =================================================================");
|
|
106
|
+
lines.push(" # 2. SYN FLOOD PROTECTION");
|
|
107
|
+
lines.push(" # =================================================================");
|
|
108
|
+
lines.push(" # Enable SYN cookies (protects against SYN flood attacks)");
|
|
109
|
+
lines.push(" # Allows server to continue accepting connections under SYN flood");
|
|
110
|
+
lines.push(" net.ipv4.tcp_syncookies = 1");
|
|
111
|
+
lines.push("");
|
|
112
|
+
lines.push(" # Reuse TIME_WAIT sockets for new connections (safer, faster)");
|
|
113
|
+
lines.push(" # Reduces connection table exhaustion under high load");
|
|
114
|
+
lines.push(" net.ipv4.tcp_tw_reuse = 1");
|
|
115
|
+
lines.push("");
|
|
116
|
+
lines.push(" # Reduce SYN backlog and timeouts for faster detection");
|
|
117
|
+
lines.push(" net.ipv4.tcp_max_syn_backlog = 2048");
|
|
118
|
+
lines.push(" net.ipv4.tcp_synack_retries = 2");
|
|
119
|
+
lines.push(" net.ipv4.tcp_syn_retries = 5");
|
|
120
|
+
lines.push("");
|
|
121
|
+
lines.push(" # =================================================================");
|
|
122
|
+
lines.push(" # 3. NETWORK STACK HARDENING");
|
|
123
|
+
lines.push(" # =================================================================");
|
|
124
|
+
lines.push(" # Disable ICMP redirect acceptance (IPv6)");
|
|
125
|
+
lines.push(" net.ipv6.conf.all.accept_redirects = 0");
|
|
126
|
+
lines.push(" net.ipv6.conf.default.accept_redirects = 0");
|
|
127
|
+
lines.push("");
|
|
128
|
+
lines.push(" # Ignore ICMP broadcasts (prevent smurf attacks)");
|
|
129
|
+
lines.push(" net.ipv4.icmp_echo_ignore_broadcasts = 1");
|
|
130
|
+
lines.push("");
|
|
131
|
+
lines.push(" # Ignore bogus ICMP error responses (prevent ICMP attacks)");
|
|
132
|
+
lines.push(" net.ipv4.icmp_ignore_bogus_error_responses = 1");
|
|
133
|
+
lines.push("");
|
|
134
|
+
lines.push(" # Enable TCP timestamps (RFC 1323) for better sequence handling");
|
|
135
|
+
lines.push(" # Also protects against wrapped sequence number attacks");
|
|
136
|
+
lines.push(" net.ipv4.tcp_timestamps = 1");
|
|
137
|
+
lines.push("");
|
|
138
|
+
lines.push(" # Enable TCP selective acknowledgments (better performance)");
|
|
139
|
+
lines.push(" net.ipv4.tcp_sack = 1");
|
|
140
|
+
lines.push("");
|
|
141
|
+
lines.push(" # =================================================================");
|
|
142
|
+
lines.push(" # 4. CORE DUMP RESTRICTIONS");
|
|
143
|
+
lines.push(" # =================================================================");
|
|
144
|
+
lines.push(" # Disable core dumps for setuid programs (prevent privilege escalation)");
|
|
145
|
+
lines.push(" fs.suid_dumpable = 0");
|
|
146
|
+
lines.push("");
|
|
147
|
+
lines.push(" # Limit core dump size to 0 (disable core dumps)");
|
|
148
|
+
lines.push(" # Override in /etc/security/limits.conf if needed for debugging");
|
|
149
|
+
lines.push(" kernel.core_pattern = |/bin/false");
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(" # =================================================================");
|
|
152
|
+
lines.push(" # 5. MEMORY PROTECTION (ASLR)");
|
|
153
|
+
lines.push(" # =================================================================");
|
|
154
|
+
lines.push(" # Enable Address Space Layout Randomization (full)");
|
|
155
|
+
lines.push(" # Makes exploitation of memory corruption vulnerabilities harder");
|
|
156
|
+
lines.push(" # 0: Disabled, 1: Conservative, 2: Full (default)");
|
|
157
|
+
lines.push(" kernel.randomize_va_space = 2");
|
|
158
|
+
lines.push("");
|
|
159
|
+
lines.push(" # =================================================================");
|
|
160
|
+
lines.push(" # 6. FILESYSTEM PROTECTION");
|
|
161
|
+
lines.push(" # =================================================================");
|
|
162
|
+
lines.push(" # Hard link/symlink protection (prevent time-of-check time-of-use)");
|
|
163
|
+
lines.push(" fs.protected_hardlinks = 1");
|
|
164
|
+
lines.push(" fs.protected_symlinks = 1");
|
|
165
|
+
lines.push("");
|
|
166
|
+
lines.push(" # FIFO protection (prevent FIFO attacks on world-writable directories)");
|
|
167
|
+
lines.push(" fs.protected_fifos = 2");
|
|
168
|
+
lines.push("");
|
|
169
|
+
lines.push(" # Regular file protection (prevent file overwrite attacks)");
|
|
170
|
+
lines.push(" fs.protected_regular = 2");
|
|
171
|
+
lines.push("");
|
|
172
|
+
lines.push(" # =================================================================");
|
|
173
|
+
lines.push(" # 7. NETWORK BEHAVIOR TUNING");
|
|
174
|
+
lines.push(" # =================================================================");
|
|
175
|
+
lines.push(" # Enable TCP Fast Open (TFO) for reduced latency");
|
|
176
|
+
lines.push(" net.ipv4.tcp_fastopen = 3");
|
|
177
|
+
lines.push("");
|
|
178
|
+
lines.push(" # Disable source routing (prevent packet routing manipulation)");
|
|
179
|
+
lines.push(" net.ipv4.conf.all.accept_source_route = 0");
|
|
180
|
+
lines.push(" net.ipv4.conf.default.accept_source_route = 0");
|
|
181
|
+
lines.push(" net.ipv6.conf.all.accept_source_route = 0");
|
|
182
|
+
lines.push(" net.ipv6.conf.default.accept_source_route = 0");
|
|
183
|
+
lines.push("");
|
|
184
|
+
lines.push(" # Enable TCP window scaling (RFC 7323) for high-bandwidth links");
|
|
185
|
+
lines.push(" net.ipv4.tcp_window_scaling = 1");
|
|
186
|
+
lines.push("");
|
|
187
|
+
lines.push(" # =================================================================");
|
|
188
|
+
lines.push(" # 8. SECURITY-RELATED KERNEL PARAMETERS");
|
|
189
|
+
lines.push(" # =================================================================");
|
|
190
|
+
lines.push(" # Disable magic sysrq key (prevent console-based attacks)");
|
|
191
|
+
lines.push(" # 0: Disabled, 1: Enable (for debugging only)");
|
|
192
|
+
lines.push(" kernel.sysrq = 0");
|
|
193
|
+
lines.push("");
|
|
194
|
+
lines.push(" # Disable kexec system call (prevent kernel replacement)");
|
|
195
|
+
lines.push(" # 0: Disabled, 1: Enabled");
|
|
196
|
+
lines.push(" kernel.kexec_load = 0");
|
|
197
|
+
lines.push("");
|
|
198
|
+
lines.push(" # Disable user namespaces (prevent container breakouts)");
|
|
199
|
+
lines.push(" # 0: Disabled, 1: Enabled");
|
|
200
|
+
lines.push(" user.max_user_namespaces = 0");
|
|
201
|
+
lines.push("");
|
|
202
|
+
lines.push(" # Enable unprivileged bpf disabled (prevent eBPF-based exploits)");
|
|
203
|
+
lines.push(" # 0: Disabled, 1: Enabled");
|
|
204
|
+
lines.push(" kernel.unprivileged_bpf_disabled = 1");
|
|
205
|
+
lines.push("");
|
|
206
|
+
lines.push(" # =================================================================");
|
|
207
|
+
lines.push(" # 9. ADDITIONAL HARDENING (2026)");
|
|
208
|
+
lines.push(" # =================================================================");
|
|
209
|
+
lines.push(" # Disable IPv6 if not needed (uncomment if IPv6 is disabled)");
|
|
210
|
+
lines.push(" # net.ipv6.conf.all.disable_ipv6 = 1");
|
|
211
|
+
lines.push(" # net.ipv6.conf.default.disable_ipv6 = 1");
|
|
212
|
+
lines.push("");
|
|
213
|
+
lines.push(" # Enable dmesg restriction (prevent kernel info leaks)");
|
|
214
|
+
lines.push(" kernel.dmesg_restrict = 1");
|
|
215
|
+
lines.push("");
|
|
216
|
+
lines.push(" # Restrict ptrace scope (prevent process tracing by non-parent)");
|
|
217
|
+
lines.push(" # 0: Traditional, 1: Restricted, 2: Admin-only, 3: No attach");
|
|
218
|
+
lines.push(" kernel.yama.ptrace_scope = 2");
|
|
219
|
+
lines.push("");
|
|
220
|
+
lines.push(" # =================================================================");
|
|
221
|
+
lines.push(" # 10. PERFORMANCE TUNING (safe defaults)");
|
|
222
|
+
lines.push(" # =================================================================");
|
|
223
|
+
lines.push(" # Increase connection tracking table size (for stateful firewalls)");
|
|
224
|
+
lines.push(" net.netfilter.nf_conntrack_max = 262144");
|
|
225
|
+
lines.push("");
|
|
226
|
+
lines.push(" # Reduce TCP keepalive timeouts for faster dead peer detection");
|
|
227
|
+
lines.push(" net.ipv4.tcp_keepalive_time = 600");
|
|
228
|
+
lines.push(" net.ipv4.tcp_keepalive_intvl = 30");
|
|
229
|
+
lines.push(" net.ipv4.tcp_keepalive_probes = 3");
|
|
230
|
+
lines.push("");
|
|
231
|
+
|
|
232
|
+
return lines;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Commands to apply kernel hardening settings immediately at first boot.
|
|
237
|
+
* Returns cloud-init YAML lines for the `runcmd:` section.
|
|
238
|
+
*
|
|
239
|
+
* Order matters:
|
|
240
|
+
* 1. Load all sysctl settings from /etc/sysctl.d/*.conf
|
|
241
|
+
* 2. Apply settings immediately (don't wait for reboot)
|
|
242
|
+
* 3. Log applied settings for audit trail
|
|
243
|
+
* 4. Display summary for cloud-init output verification
|
|
244
|
+
*/
|
|
245
|
+
export function kernelHardeningRunCmd(): string[] {
|
|
246
|
+
const lines: string[] = [];
|
|
247
|
+
|
|
248
|
+
lines.push(" # Kernel hardening: apply sysctl settings immediately");
|
|
249
|
+
lines.push(" # Settings are already in /etc/sysctl.d/99-security-hardening.conf");
|
|
250
|
+
lines.push("");
|
|
251
|
+
lines.push(" # Apply all sysctl settings (overrides defaults immediately)");
|
|
252
|
+
lines.push(" - sysctl --system");
|
|
253
|
+
lines.push("");
|
|
254
|
+
lines.push(" # Log applied settings for audit trail");
|
|
255
|
+
lines.push(" - sysctl -a | grep -E '(rp_filter|syncookies|randomize_va|suid_dump)' > /var/log/kernel-hardening.log 2>&1 || true");
|
|
256
|
+
lines.push("");
|
|
257
|
+
lines.push(" # Display summary of critical hardening settings");
|
|
258
|
+
lines.push(" - |");
|
|
259
|
+
lines.push(" echo '========================================'");
|
|
260
|
+
lines.push(" echo 'Kernel Hardening Applied (2026)'");
|
|
261
|
+
lines.push(" echo '========================================'");
|
|
262
|
+
lines.push(" echo 'IP Spoof Protection: '$(sysctl -n net.ipv4.conf.all.rp_filter)");
|
|
263
|
+
lines.push(" echo 'SYN Cookies: '$(sysctl -n net.ipv4.tcp_syncookies)");
|
|
264
|
+
lines.push(" echo 'ASLR Level: '$(sysctl -n kernel.randomize_va_space)");
|
|
265
|
+
lines.push(" echo 'SUID Core Dumps: '$(sysctl -n fs.suid_dumpable)");
|
|
266
|
+
lines.push(" echo 'Hard Links Protected: '$(sysctl -n fs.protected_hardlinks)");
|
|
267
|
+
lines.push(" echo 'Ptrace Scope: '$(sysctl -n kernel.yama.ptrace_scope)");
|
|
268
|
+
lines.push(" echo '========================================'");
|
|
269
|
+
lines.push("");
|
|
270
|
+
|
|
271
|
+
return lines;
|
|
272
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Audit Cloud-Init Components
|
|
3
|
+
*
|
|
4
|
+
* Composable cloud-init blocks for running post-bootstrap security audits.
|
|
5
|
+
* Generates comprehensive security reports for verification and compliance.
|
|
6
|
+
*
|
|
7
|
+
* This module runs LAST in the bootstrap sequence, after all other security
|
|
8
|
+
* hardening is applied. It captures the state of the system for verification.
|
|
9
|
+
*
|
|
10
|
+
* Three composable functions return cloud-init line arrays for splicing into
|
|
11
|
+
* the appropriate YAML sections:
|
|
12
|
+
* - securityAuditPackages() → packages: section
|
|
13
|
+
* - securityAuditWriteFiles() → write_files: section
|
|
14
|
+
* - securityAuditRunCmd() → runcmd: section
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Packages required for security auditing.
|
|
18
|
+
* Returns cloud-init YAML lines for the `packages:` section.
|
|
19
|
+
*
|
|
20
|
+
* - lynis: Comprehensive security auditing tool
|
|
21
|
+
*/
|
|
22
|
+
export function securityAuditPackages() {
|
|
23
|
+
return [
|
|
24
|
+
" - lynis",
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Files to write at first boot for security auditing.
|
|
29
|
+
* Returns cloud-init YAML lines for the `write_files:` section.
|
|
30
|
+
*
|
|
31
|
+
* Drops 1 file onto the server:
|
|
32
|
+
*
|
|
33
|
+
* 1. /opt/monitoring/security-audit.sh
|
|
34
|
+
* - Collects security metrics (UFW, fail2ban, sshd, sysctl)
|
|
35
|
+
* - Runs Lynis audit with warnings-only output
|
|
36
|
+
* - Generates JSON report at /var/log/security-audit.json
|
|
37
|
+
* - Logs summary to /var/log/security-audit.log
|
|
38
|
+
*/
|
|
39
|
+
export function securityAuditWriteFiles() {
|
|
40
|
+
const lines = [];
|
|
41
|
+
// 1. Security audit script - comprehensive security check
|
|
42
|
+
lines.push(" # Security audit script - runs after all hardening");
|
|
43
|
+
lines.push(" - path: /opt/monitoring/security-audit.sh");
|
|
44
|
+
lines.push(" owner: root:root");
|
|
45
|
+
lines.push(" permissions: '0755'");
|
|
46
|
+
lines.push(" content: |");
|
|
47
|
+
lines.push(" #!/bin/bash");
|
|
48
|
+
lines.push(" set -euo pipefail");
|
|
49
|
+
lines.push(" LOGFILE=\"/var/log/security-audit.log\"");
|
|
50
|
+
lines.push(" REPORTFILE=\"/var/log/security-audit.json\"");
|
|
51
|
+
lines.push(" echo \"Security Audit started at $(date -Iseconds)\" | tee \"$LOGFILE\"");
|
|
52
|
+
lines.push("");
|
|
53
|
+
lines.push(" # Firewall status");
|
|
54
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
55
|
+
lines.push(" echo \"=== UFW Firewall Status ===\" | tee -a \"$LOGFILE\"");
|
|
56
|
+
lines.push(" ufw status verbose | tee -a \"$LOGFILE\" || true");
|
|
57
|
+
lines.push("");
|
|
58
|
+
lines.push(" # Fail2ban status");
|
|
59
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
60
|
+
lines.push(" echo \"=== Fail2ban Status ===\" | tee -a \"$LOGFILE\"");
|
|
61
|
+
lines.push(" systemctl status fail2ban --no-pager | tee -a \"$LOGFILE\" || true");
|
|
62
|
+
lines.push(" fail2ban-client status sshd | tee -a \"$LOGFILE\" || true");
|
|
63
|
+
lines.push("");
|
|
64
|
+
lines.push(" # SSHd status");
|
|
65
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
66
|
+
lines.push(" echo \"=== SSHd Status ===\" | tee -a \"$LOGFILE\"");
|
|
67
|
+
lines.push(" systemctl status ssh --no-pager | tee -a \"$LOGFILE\" || true");
|
|
68
|
+
lines.push(" sshd -T | grep -E '(PasswordAuthentication|PermitRootLogin|MaxStartups)' | tee -a \"$LOGFILE\" || true");
|
|
69
|
+
lines.push("");
|
|
70
|
+
lines.push(" # Kernel hardening status");
|
|
71
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
72
|
+
lines.push(" echo \"=== Kernel Hardening Status ===\" | tee -a \"$LOGFILE\"");
|
|
73
|
+
lines.push(" sysctl randomize_va_space kptr_restrict tcp_syncookies | tee -a \"$LOGFILE\" || true");
|
|
74
|
+
lines.push("");
|
|
75
|
+
lines.push(" # Lynis audit (warnings only, non-interactive)");
|
|
76
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
77
|
+
lines.push(" echo \"=== Lynis Security Audit ===\" | tee -a \"$LOGFILE\"");
|
|
78
|
+
lines.push(" lynis audit system --warnings-only --quiet 2>&1 | tee -a \"$LOGFILE\" || true");
|
|
79
|
+
lines.push("");
|
|
80
|
+
lines.push(" # Generate JSON report");
|
|
81
|
+
lines.push(" timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)");
|
|
82
|
+
lines.push(" ufw_active=$(ufw status | grep -c \"Status: active\" || echo \"0\")");
|
|
83
|
+
lines.push(" fail2ban_active=$(systemctl is-active fail2ban 2>/dev/null || echo \"inactive\")");
|
|
84
|
+
lines.push(" sshd_active=$(systemctl is-active ssh 2>/dev/null || echo \"inactive\")");
|
|
85
|
+
lines.push(" aslr_enabled=$(cat /proc/sys/kernel/randomize_va_space 2>/dev/null || echo \"0\")");
|
|
86
|
+
lines.push(" cat > \"$REPORTFILE\" <<AUDEOF");
|
|
87
|
+
lines.push(" {");
|
|
88
|
+
lines.push(" \"timestamp\": \"$timestamp\",");
|
|
89
|
+
lines.push(" \"firewall\": { \"active\": $ufw_active },");
|
|
90
|
+
lines.push(" \"fail2ban\": { \"active\": \"$fail2ban_active\" },");
|
|
91
|
+
lines.push(" \"sshd\": { \"active\": \"$sshd_active\" },");
|
|
92
|
+
lines.push(" \"kernel_hardening\": { \"aslr_enabled\": $aslr_enabled }");
|
|
93
|
+
lines.push(" }");
|
|
94
|
+
lines.push(" AUDEOF");
|
|
95
|
+
lines.push(" echo \"Security Audit completed at $(date -Iseconds)\" | tee -a \"$LOGFILE\"");
|
|
96
|
+
lines.push(" echo \"Report saved to $REPORTFILE\" | tee -a \"$LOGFILE\"");
|
|
97
|
+
lines.push("");
|
|
98
|
+
return lines;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Commands to run security audit at first boot.
|
|
102
|
+
* Returns cloud-init YAML lines for the `runcmd:` section.
|
|
103
|
+
*
|
|
104
|
+
* Order matters:
|
|
105
|
+
* 1. Create /opt/monitoring directory (audit script target)
|
|
106
|
+
* 2. Run security audit script (captures state after all hardening)
|
|
107
|
+
* 3. Log audit completion for verification
|
|
108
|
+
*/
|
|
109
|
+
export function securityAuditRunCmd() {
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push(" # Security audit: run comprehensive security check");
|
|
112
|
+
lines.push(" - mkdir -p /opt/monitoring");
|
|
113
|
+
lines.push(" - /opt/monitoring/security-audit.sh");
|
|
114
|
+
lines.push(" - echo \"Security audit completed at $(date -Iseconds)\" | tee -a /root/.bootstrap-status");
|
|
115
|
+
lines.push("");
|
|
116
|
+
return lines;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=security-audit.js.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Audit Cloud-Init Components
|
|
3
|
+
*
|
|
4
|
+
* Composable cloud-init blocks for running post-bootstrap security audits.
|
|
5
|
+
* Generates comprehensive security reports for verification and compliance.
|
|
6
|
+
*
|
|
7
|
+
* This module runs LAST in the bootstrap sequence, after all other security
|
|
8
|
+
* hardening is applied. It captures the state of the system for verification.
|
|
9
|
+
*
|
|
10
|
+
* Three composable functions return cloud-init line arrays for splicing into
|
|
11
|
+
* the appropriate YAML sections:
|
|
12
|
+
* - securityAuditPackages() → packages: section
|
|
13
|
+
* - securityAuditWriteFiles() → write_files: section
|
|
14
|
+
* - securityAuditRunCmd() → runcmd: section
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Packages required for security auditing.
|
|
19
|
+
* Returns cloud-init YAML lines for the `packages:` section.
|
|
20
|
+
*
|
|
21
|
+
* - lynis: Comprehensive security auditing tool
|
|
22
|
+
*/
|
|
23
|
+
export function securityAuditPackages(): string[] {
|
|
24
|
+
return [
|
|
25
|
+
" - lynis",
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Files to write at first boot for security auditing.
|
|
31
|
+
* Returns cloud-init YAML lines for the `write_files:` section.
|
|
32
|
+
*
|
|
33
|
+
* Drops 1 file onto the server:
|
|
34
|
+
*
|
|
35
|
+
* 1. /opt/monitoring/security-audit.sh
|
|
36
|
+
* - Collects security metrics (UFW, fail2ban, sshd, sysctl)
|
|
37
|
+
* - Runs Lynis audit with warnings-only output
|
|
38
|
+
* - Generates JSON report at /var/log/security-audit.json
|
|
39
|
+
* - Logs summary to /var/log/security-audit.log
|
|
40
|
+
*/
|
|
41
|
+
export function securityAuditWriteFiles(): string[] {
|
|
42
|
+
const lines: string[] = [];
|
|
43
|
+
|
|
44
|
+
// 1. Security audit script - comprehensive security check
|
|
45
|
+
lines.push(" # Security audit script - runs after all hardening");
|
|
46
|
+
lines.push(" - path: /opt/monitoring/security-audit.sh");
|
|
47
|
+
lines.push(" owner: root:root");
|
|
48
|
+
lines.push(" permissions: '0755'");
|
|
49
|
+
lines.push(" content: |");
|
|
50
|
+
lines.push(" #!/bin/bash");
|
|
51
|
+
lines.push(" set -euo pipefail");
|
|
52
|
+
lines.push(" LOGFILE=\"/var/log/security-audit.log\"");
|
|
53
|
+
lines.push(" REPORTFILE=\"/var/log/security-audit.json\"");
|
|
54
|
+
lines.push(" echo \"Security Audit started at $(date -Iseconds)\" | tee \"$LOGFILE\"");
|
|
55
|
+
lines.push("");
|
|
56
|
+
lines.push(" # Firewall status");
|
|
57
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
58
|
+
lines.push(" echo \"=== UFW Firewall Status ===\" | tee -a \"$LOGFILE\"");
|
|
59
|
+
lines.push(" ufw status verbose | tee -a \"$LOGFILE\" || true");
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push(" # Fail2ban status");
|
|
62
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
63
|
+
lines.push(" echo \"=== Fail2ban Status ===\" | tee -a \"$LOGFILE\"");
|
|
64
|
+
lines.push(" systemctl status fail2ban --no-pager | tee -a \"$LOGFILE\" || true");
|
|
65
|
+
lines.push(" fail2ban-client status sshd | tee -a \"$LOGFILE\" || true");
|
|
66
|
+
lines.push("");
|
|
67
|
+
lines.push(" # SSHd status");
|
|
68
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
69
|
+
lines.push(" echo \"=== SSHd Status ===\" | tee -a \"$LOGFILE\"");
|
|
70
|
+
lines.push(" systemctl status ssh --no-pager | tee -a \"$LOGFILE\" || true");
|
|
71
|
+
lines.push(" sshd -T | grep -E '(PasswordAuthentication|PermitRootLogin|MaxStartups)' | tee -a \"$LOGFILE\" || true");
|
|
72
|
+
lines.push("");
|
|
73
|
+
lines.push(" # Kernel hardening status");
|
|
74
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
75
|
+
lines.push(" echo \"=== Kernel Hardening Status ===\" | tee -a \"$LOGFILE\"");
|
|
76
|
+
lines.push(" sysctl randomize_va_space kptr_restrict tcp_syncookies | tee -a \"$LOGFILE\" || true");
|
|
77
|
+
lines.push("");
|
|
78
|
+
lines.push(" # Lynis audit (warnings only, non-interactive)");
|
|
79
|
+
lines.push(" echo \"\" | tee -a \"$LOGFILE\"");
|
|
80
|
+
lines.push(" echo \"=== Lynis Security Audit ===\" | tee -a \"$LOGFILE\"");
|
|
81
|
+
lines.push(" lynis audit system --warnings-only --quiet 2>&1 | tee -a \"$LOGFILE\" || true");
|
|
82
|
+
lines.push("");
|
|
83
|
+
lines.push(" # Generate JSON report");
|
|
84
|
+
lines.push(" timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)");
|
|
85
|
+
lines.push(" ufw_active=$(ufw status | grep -c \"Status: active\" || echo \"0\")");
|
|
86
|
+
lines.push(" fail2ban_active=$(systemctl is-active fail2ban 2>/dev/null || echo \"inactive\")");
|
|
87
|
+
lines.push(" sshd_active=$(systemctl is-active ssh 2>/dev/null || echo \"inactive\")");
|
|
88
|
+
lines.push(" aslr_enabled=$(cat /proc/sys/kernel/randomize_va_space 2>/dev/null || echo \"0\")");
|
|
89
|
+
lines.push(" cat > \"$REPORTFILE\" <<AUDEOF");
|
|
90
|
+
lines.push(" {");
|
|
91
|
+
lines.push(" \"timestamp\": \"$timestamp\",");
|
|
92
|
+
lines.push(" \"firewall\": { \"active\": $ufw_active },");
|
|
93
|
+
lines.push(" \"fail2ban\": { \"active\": \"$fail2ban_active\" },");
|
|
94
|
+
lines.push(" \"sshd\": { \"active\": \"$sshd_active\" },");
|
|
95
|
+
lines.push(" \"kernel_hardening\": { \"aslr_enabled\": $aslr_enabled }");
|
|
96
|
+
lines.push(" }");
|
|
97
|
+
lines.push(" AUDEOF");
|
|
98
|
+
lines.push(" echo \"Security Audit completed at $(date -Iseconds)\" | tee -a \"$LOGFILE\"");
|
|
99
|
+
lines.push(" echo \"Report saved to $REPORTFILE\" | tee -a \"$LOGFILE\"");
|
|
100
|
+
lines.push("");
|
|
101
|
+
|
|
102
|
+
return lines;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Commands to run security audit at first boot.
|
|
107
|
+
* Returns cloud-init YAML lines for the `runcmd:` section.
|
|
108
|
+
*
|
|
109
|
+
* Order matters:
|
|
110
|
+
* 1. Create /opt/monitoring directory (audit script target)
|
|
111
|
+
* 2. Run security audit script (captures state after all hardening)
|
|
112
|
+
* 3. Log audit completion for verification
|
|
113
|
+
*/
|
|
114
|
+
export function securityAuditRunCmd(): string[] {
|
|
115
|
+
const lines: string[] = [];
|
|
116
|
+
|
|
117
|
+
lines.push(" # Security audit: run comprehensive security check");
|
|
118
|
+
lines.push(" - mkdir -p /opt/monitoring");
|
|
119
|
+
lines.push(" - /opt/monitoring/security-audit.sh");
|
|
120
|
+
lines.push(" - echo \"Security audit completed at $(date -Iseconds)\" | tee -a /root/.bootstrap-status");
|
|
121
|
+
lines.push("");
|
|
122
|
+
|
|
123
|
+
return lines;
|
|
124
|
+
}
|