-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsetup-playbook.yml
More file actions
290 lines (263 loc) · 14.4 KB
/
setup-playbook.yml
File metadata and controls
290 lines (263 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
---
#
# Linux Server Management - Main Setup Playbook
#
# This playbook performs comprehensive server setup and hardening by:
# 1. Creating user accounts with SSH key management
# 2. Applying CIS-based security hardening via konstruktoid.hardening
# 3. Configuring system security policies and access controls
#
# Requirements:
# - Target systems: Ubuntu 20.04+, Debian 10+
# - Ansible 2.9+
# - Internet connectivity (for downloading hardening role)
# - SSH key access to target hosts
# - Variables defined in group_vars or host_vars
#
# Required Variables:
# - SSH_USERLIST: List of users to create (see group_vars examples)
# - AUDITD_ACTION_MAIL_ACCT: Email address for audit alerts
# - MANAGE_UFW: Enable/disable UFW firewall management (true/false)
# - UFW_OUTGOING_TRAFFIC: List of allowed outbound traffic rules
# - REBOOT_UBUNTU: Allow automatic reboots for updates (true/false)
# - SSHD_ADMIN_NET: List of networks allowed for SSH admin access
#
# Optional Variables:
# - MANAGE_USERS: Enable/disable user management (default: true)
# - Various other hardening options (see variable definitions below)
#
# Usage:
# ansible-playbook -i inventory setup-playbook.yml
# ansible-playbook -i inventory setup-playbook.yml --tags users
# ansible-playbook -i inventory setup-playbook.yml --skip-tags hardening
#
# Based on: https://github.com/konstruktoid/ansible-role-hardening
# Licensed under: Apache License 2.0
#
- name: Linux Server Setup and Hardening
hosts: all
any_errors_fatal: true
# Pre-flight checks to ensure required variables are defined
pre_tasks:
- name: Validate required variables are defined
ansible.builtin.assert:
that:
- SSH_USERLIST is defined
- SSH_USERLIST | length > 0
- AUDITD_ACTION_MAIL_ACCT is defined
- AUDITD_ACTION_MAIL_ACCT | length > 0
- MANAGE_UFW is defined
- MANAGE_UFW | type_debug == "bool"
- UFW_OUTGOING_TRAFFIC is defined
- UFW_OUTGOING_TRAFFIC | length > 0
- AUTO_UPDATES_OPTIONS.reboot is defined
- AUTO_UPDATES_OPTIONS.reboot | type_debug == "bool"
- SSHD_ADMIN_NET is defined
- SSHD_ADMIN_NET | length > 0
- ENABLE_2FA is defined
- ENABLE_2FA | type_debug == "bool"
fail_msg: |
Missing required variables. Please ensure all mandatory variables are defined:
- SSH_USERLIST: List of users to create
- AUDITD_ACTION_MAIL_ACCT: Email address for audit alerts
- MANAGE_UFW: Enable/disable UFW firewall management (true/false)
- UFW_OUTGOING_TRAFFIC: List of allowed outbound traffic rules
- AUTO_UPDATES_OPTIONS.reboot: Allow automatic reboots for updates (true/false)
- SSHD_ADMIN_NET: List of networks allowed for SSH admin access
- ENABLE_2FA: Enable/disable 2FA globally (true/false)
success_msg: "All required variables validation passed"
tags: [validation, always]
- name: Display playbook execution information
ansible.builtin.debug:
msg:
- "Target host: {{ inventory_hostname }}"
- "Environment: {{ environment | default('undefined') }}"
- "User management: {{ MANAGE_USERS | default(true) }}"
- "2FA enabled globally: {{ ENABLE_2FA }}"
- "Number of users to create: {{ SSH_USERLIST | length }}"
tags: [info, always]
tasks:
# ===================================================================
# USER MANAGEMENT SECTION
# Create user accounts with SSH keys and sudo permissions
# ===================================================================
- name: Create user accounts with SSH key management
ansible.builtin.include_role:
name: users_add
apply:
become: true
vars:
users_add_userlist: "{{ SSH_USERLIST }}"
# users_add uses enable_2fa (role var), keep as-is.
# noqa: var-naming[no-role-prefix]
enable_2fa: "{{ ENABLE_2FA }}"
when: MANAGE_USERS is not defined or MANAGE_USERS | bool
tags: [users, user-management]
- name: Execute pending handlers after user creation
ansible.builtin.meta: flush_handlers
tags: [users, user-management, handlers]
# ===================================================================
# HARDENING ROLE PREPARATION SECTION
# Download and prepare the konstruktoid.hardening role
# ===================================================================
- name: Clean existing hardening role directory
ansible.builtin.file:
path: "{{ lookup('env', 'HOME') }}/.ansible/roles/konstruktoid.hardening"
state: absent
delegate_to: localhost
run_once: true
tags: [hardening, setup, role-download]
- name: Create fresh directory for hardening role
ansible.builtin.file:
path: "{{ lookup('env', 'HOME') }}/.ansible/roles/konstruktoid.hardening"
state: directory
mode: '0755'
delegate_to: localhost
run_once: true
tags: [hardening, setup, role-download]
- name: Download konstruktoid.hardening role from GitHub
ansible.builtin.git:
repo: https://github.com/konstruktoid/ansible-role-hardening.git
dest: "{{ lookup('env', 'HOME') }}/.ansible/roles/konstruktoid.hardening"
version: '4da78c8723d7792dbce73ce5aea47d8144f4596f' # v4.3.0
delegate_to: localhost
run_once: true
tags: [hardening, setup, role-download]
# ===================================================================
# SYSTEM HARDENING SECTION
# Apply CIS-based security hardening configurations
# ===================================================================
- name: Apply CIS-based system hardening via konstruktoid.hardening
ansible.builtin.include_role:
name: konstruktoid.hardening
vars:
# Suppress ansible-lint var-naming warning for third-party role variables
# noqa: var-naming[no-role-prefix]
# === SYSTEM UPDATE CONFIGURATION ===
# Modern automatic updates configuration (replaces old reboot_ubuntu)
automatic_updates:
enabled: "{{ AUTO_UPDATES_OPTIONS.enabled | default(true) }}"
only_security: "{{ AUTO_UPDATES_OPTIONS.only_security | default(true) }}"
reboot: "{{ AUTO_UPDATES_OPTIONS.reboot | default(true) }}"
reboot_from_time: "{{ AUTO_UPDATES_OPTIONS.reboot_from_time | default('2:00') }}"
reboot_time_margin_mins: "{{ AUTO_UPDATES_OPTIONS.reboot_time_margin_mins | default(20) }}"
custom_origins: "{{ AUTO_UPDATES_OPTIONS.custom_origins | default('') }}"
# === LOGIN AND SESSION MANAGEMENT ===
logind: "{{ LOGIND_HARDENING }}" # Configure systemd-logind settings
session_timeout: "{{ SESSION_TIMEOUT | default(900) }}" # Session timeout in seconds (15 min default)
# === AUDIT AND LOGGING ===
auditd_action_mail_acct: "{{ AUDITD_ACTION_MAIL_ACCT }}" # Email for audit alerts
# === NETWORK AND FIREWALL ===
ufw_outgoing_traffic: "{{ UFW_OUTGOING_TRAFFIC }}" # UFW outbound traffic policy
manage_ufw: "{{ MANAGE_UFW }}" # Enable/disable UFW management
disable_wireless: "{{ DISABLE_WIRELESS | default(true) }}" # Disable wireless interfaces
# === SSH CONFIGURATION ===
manage_ssh: "{{ MANAGE_SSH | default(true) }}" # Enable SSH hardening
sshd_admin_net: "{{ SSHD_ADMIN_NET }}" # Networks allowed for SSH admin access
sshd_allow_users: "{{ SSH_USERLIST | map(attribute='username') | list }}" # Users allowed SSH access
sshd_allow_groups: "{{ SSH_USERLIST | map(attribute='username') | list }}" # Groups allowed SSH access
sshd_login_grace_time: "{{ SSHD_LOGIN_GRACE_TIME | default(60) }}" # SSH login grace period
sshd_max_auth_tries: "{{ SSHD_MAX_AUTH_TRIES | default(3) }}" # Maximum SSH auth attempts
sshd_allow_tcp_forwarding: "{{ SSHD_ALLOW_TCP_FORWARDING | default(false) }}" # Allow SSH port forwarding
sshd_client_alive_interval: "{{ SSHD_TIMEOUT_SECS | default(300) }}" # SSH client timeout (5 min default)
sshd_use_pam: "{{ ENABLE_2FA | bool or SSHD_USE_PAM | default(true) }}"
sshd_kbd_interactive_authentication: "{{ ENABLE_2FA | bool or SSHD_KBD_INTERACTIVE_AUTHENTICATION | default(true) }}"
sshd_password_authentication: "{{ SSHD_PASSWORD_AUTHENTICATION | default(false) }}"
sshd_authentication_methods: "{{ 'publickey,keyboard-interactive:pam' if (ENABLE_2FA | default(false) | bool) else 'publickey' }}"
# === SYSTEM SECURITY ===
disable_apport: true # Disable Ubuntu crash reporting
disable_root_account: "{{ DISABLE_ROOT_ACCOUNT | default(true) }}" # Disable root login
manage_users: "{{ MANAGE_USERS }}" # Enable user account management
manage_packages: true # Enable package management (removal/installation)
delete_users: ["games", "gnats", "irc", "list", "news", "sync", "uucp", "ubuntu", "debian"]
# === SYSTEM COMPONENT MANAGEMENT ===
# Each option controls whether the hardening role manages specific system components
manage_motdnews: "{{ MANAGE_MOTDNEWS | default(true) }}" # Message of the day
manage_kernel: "{{ MANAGE_KERNEL | default(true) }}" # Kernel parameters
manage_kernel_modules: "{{ MANAGE_KERNEL_MODULES | default(true) }}" # Kernel module blacklisting
manage_systemd: "{{ MANAGE_SYSTEMD | default(true) }}" # Systemd service hardening
manage_faillock: "{{ MANAGE_FAILLOCK | default(true) }}" # Account lockout policies
manage_fstab: "{{ MANAGE_FSTAB | default(true) }}" # Filesystem mount options
manage_mounts: "{{ MANAGE_MOUNTS | default(true) }}" # Mount point security
manage_pam: "{{ MANAGE_PAM | default(true) }}" # PAM configuration
manage_pwquality: "{{ MANAGE_PWQUALITY | default(true) }}" # Password quality rules
manage_postfix: "{{ MANAGE_POSTFIX | default(true) }}" # Mail server configuration
manage_netplan: "{{ MANAGE_NETPLAN | default(true) }}" # Network configuration
manage_resolved: "{{ MANAGE_RESOLVED | default(true) }}" # DNS resolver configuration
manage_hosts: "{{ MANAGE_HOSTS | default(true) }}" # Hosts file management
manage_issue: "{{ MANAGE_ISSUE | default(true) }}" # Login banner configuration
manage_logind: "{{ MANAGE_LOGIND | default(true) }}" # Login manager configuration
manage_suid_sgid_permissions: "{{ SUID_SGID_PERMISSIONS | default(true) }}" # SUID/SGID file permissions
manage_path: "{{ MANAGE_PATH | default(true) }}" # PATH environment variable security
# === PACKAGE MANAGEMENT ===
# Dynamically generate packages blocklist excluding mandatory packages
packages_blocklist: "{{
(lookup('ansible.builtin.file', lookup('env', 'HOME') + '/.ansible/roles/konstruktoid.hardening/defaults/main.yml')
| from_yaml)['packages_blocklist']
| difference((MANDATORY_PACKAGES | default([])))
}}"
# temp: coming upstream renaming. Change the name permanently once
# https://github.com/konstruktoid/ansible-role-hardening/pull/981 is merged
blocked_installed_packages: "{{ packages_blocklist }}"
tags: [hardening, security, cis-hardening]
# ===================================================================
# POST-CONFIGURATION SECTION
# Run any additional custom commands if specified
# ===================================================================
- name: Execute custom post-configuration commands
ansible.builtin.shell: |
{{ POST_RUN_EXTRA_COMMANDS }}
args:
executable: /bin/bash
become: true
when: POST_RUN_EXTRA_COMMANDS is defined and POST_RUN_EXTRA_COMMANDS | trim != ""
changed_when: false # Prevent task from always reporting "changed"
tags: [post-config, custom-commands]
- name: Create PAM MOTD configuration for Debian-family (erased by hardening manage_pam config template)
ansible.builtin.lineinfile:
path: /etc/pam.d/sshd
line: "session optional pam_motd.so motd=/var/cache/motd-security-status"
insertafter: "# Print the message of the day upon successful login"
state: present
become: true
when: ansible_facts["os_family"] == "Debian"
# Post-execution validation and reporting
post_tasks:
- name: Verify SSH service is running and enabled
ansible.builtin.systemd:
name: ssh
state: started
enabled: true
check_mode: true
register: ssh_status
failed_when: false
tags: [validation, post-check]
- name: Verify UFW firewall status (if managed)
ansible.builtin.command: ufw status
register: ufw_status
when: MANAGE_UFW | default(false)
changed_when: false
failed_when: false
become: true
tags: [validation, post-check]
- name: Display setup completion summary
ansible.builtin.debug:
msg:
- "===== SETUP COMPLETION SUMMARY ====="
- "Host: {{ inventory_hostname }}"
- "Users validated via this playbook: {{ SSH_USERLIST | length }}"
- "Hardening applied: {{ 'Yes' if (MANAGE_UFW | default(false)) else 'Partial' }}"
- "SSH service status: {{ 'Running' if ssh_status.status.ActiveState == 'active' else 'Check required' }}"
- "UFW status: {{ ufw_status.stdout.split('\n')[0] if (MANAGE_UFW | default(false) and ufw_status is defined) else 'Not managed' }}"
- "====================================="
tags: [info, summary]
- name: Reminder about next steps
ansible.builtin.debug:
msg:
- "IMPORTANT NEXT STEPS:"
- "1. Test SSH connectivity with new user accounts"
- "2. Verify sudo access for admin users"
- "3. Review firewall rules if UFW was configured"
- "4. Check system logs for any errors: journalctl -xe"
- "5. Consider rebooting to ensure all changes take effect"
tags: [info, reminder]