move to recommended file and directory structure
This commit is contained in:
parent
8af8eafaf7
commit
7c2c5e06b2
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,3 +22,6 @@ bookstack-db.container
|
|||||||
bookstack-srv.container
|
bookstack-srv.container
|
||||||
sgnarva-srv.container
|
sgnarva-srv.container
|
||||||
sgnarva-db.container
|
sgnarva-db.container
|
||||||
|
|
||||||
|
ansible/inventories/production/host_vars/*/vars.yml
|
||||||
|
ansible/inventories/production/host_vars/*/vault.yml
|
||||||
|
|||||||
@ -1,31 +1,34 @@
|
|||||||
# Ansible MicroOS VM setup
|
# Ansible MicroOS VM setup
|
||||||
|
|
||||||
<!--
|
## Description
|
||||||
Unfortunately, the devsec hardening role does not play well with MicroOS.
|
|
||||||
|
|
||||||
1. Install devsec hardening collection
|
(Vaulted) Variables for accessing the host with specific credentials are stored in the host_vars,
|
||||||
```shell
|
they are handled as specific for how each user accesses a specific host.
|
||||||
ansible-galaxy collection install devsec.hardening
|
|
||||||
|
(Vaulted) Variables for the services are stored in the group_vars,
|
||||||
|
they are shared between all administrators of the host.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Create vars and vault file for accessing the host following this structure.
|
||||||
|
Adjust the username, become method and password.
|
||||||
|
|
||||||
|
`inventories/production/host_vars/io/vars.yml`:
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
ansible_user: tobias
|
||||||
|
ansible_become_method: sudo
|
||||||
```
|
```
|
||||||
2. Create the inventory.txt file for the server
|
|
||||||
3. Run the hardening playbook. Does not run completely through because of MicroOS immutability. At some point, a PR properly supporting MicroOS could be opened to https://github.com/dev-sec/ansible-os-hardening
|
`inventories/production/host_vars/io/vault.yml`:
|
||||||
```shell
|
(create through `ansible-vault create vault.yml` with a strong password)
|
||||||
ansible-playbook -i inventory.txt hardening.yml
|
```yaml
|
||||||
|
---
|
||||||
|
ansible_become_pass: EXAMPLE
|
||||||
```
|
```
|
||||||
-->
|
|
||||||
4. Run the custom_hardening playbook. This mostly sets SSH parameters to best practice values.
|
## Usage
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ansible-playbook -i inventory.txt custom_hardening.yml
|
ansible-playbook main.yml
|
||||||
```
|
|
||||||
5. Run the allow_privileged_ports_rootless playbook. This allows a rootless traefik container to use ports 80 and 443.
|
|
||||||
```shell
|
|
||||||
ansible-playbook -i inventory.txt allow_privileged_ports_rootless.yml
|
|
||||||
```
|
|
||||||
6. Run the deploy_services playbook. This creates groups and users for each service, creates a btrfs subvolume for data and copies the quadlet files to the correct location, then activates the service.
|
|
||||||
```shell
|
|
||||||
ansible-playbook -i inventory.txt deploy_services.yml
|
|
||||||
```
|
|
||||||
7. Run the deploy_traefik_config playbool. This copies the traefik configuration to the correct location.
|
|
||||||
```shell
|
|
||||||
ansible-playbook -i inventory.txt deploy_traefik_config.yml
|
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Allow normal users to bind to port 80
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Set sysctl to allow normal users to bind to ports starting from 80
|
|
||||||
sysctl:
|
|
||||||
name: net.ipv4.ip_unprivileged_port_start
|
|
||||||
value: 80
|
|
||||||
state: present
|
|
||||||
reload: yes
|
|
||||||
|
|
||||||
- name: Verify the sysctl setting
|
|
||||||
command: sysctl net.ipv4.ip_unprivileged_port_start
|
|
||||||
register: sysctl_result
|
|
||||||
|
|
||||||
- debug:
|
|
||||||
msg: "net.ipv4.ip_unprivileged_port_start: {{ sysctl_result.stdout }}"
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Automate borg backup
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Check if Borg backup script exist
|
|
||||||
stat:
|
|
||||||
path: /usr/local/sbin/backup.bash
|
|
||||||
register: backup_status
|
|
||||||
- name: Check if Borg check script exists
|
|
||||||
stat:
|
|
||||||
path: /usr/local/sbin/check_backup.bash
|
|
||||||
register: check_status
|
|
||||||
- name: Synchronize Borg scripts
|
|
||||||
when: backup_status.stat.exists == False or check_status.stat.exists == False
|
|
||||||
synchronize:
|
|
||||||
src: ./borg_scripts/
|
|
||||||
dest: /usr/local/sbin/
|
|
||||||
rsync_opts:
|
|
||||||
- "--chown=root:root"
|
|
||||||
- "--chmod=0700"
|
|
||||||
- name: Create borg backup systemd service
|
|
||||||
copy:
|
|
||||||
content: |
|
|
||||||
[Unit]
|
|
||||||
Description=Borg backup
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/usr/local/sbin/borg_backup.sh
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
dest: /etc/systemd/system/borg_backup.service
|
|
||||||
- name: Create borg backup systemd timer
|
|
||||||
copy:
|
|
||||||
content: |
|
|
||||||
[Unit]
|
|
||||||
Description=Borg backup timer
|
|
||||||
|
|
||||||
[Timer]
|
|
||||||
OnCalendar=*-*-* 05:00:00
|
|
||||||
Persistent=true
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=timers.target
|
|
||||||
dest: /etc/systemd/system/borg_backup.timer
|
|
||||||
- name: Start and enable borg backup timer
|
|
||||||
systemd:
|
|
||||||
name: borg_backup.timer
|
|
||||||
enabled: yes
|
|
||||||
state: started
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
- name: install commonly used programs
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: install common programs with zypper and transactional-update
|
|
||||||
community.general.zypper:
|
|
||||||
pkg:
|
|
||||||
- borgbackup
|
|
||||||
- tmux
|
|
||||||
- lynis
|
|
||||||
- toolbox
|
|
||||||
state: present
|
|
||||||
register: zypper_result
|
|
||||||
- name: reboot if software needed to be installed
|
|
||||||
ansible.builtin.reboot:
|
|
||||||
when: zypper_result.changed
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Apply SSH best practices configuration
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Ensure the sshd_config.d directory exists
|
|
||||||
file:
|
|
||||||
path: /etc/ssh/sshd_config.d
|
|
||||||
state: directory
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0755'
|
|
||||||
|
|
||||||
- name: Create a configuration file to apply SSH best practices
|
|
||||||
copy:
|
|
||||||
content: |
|
|
||||||
# Disable password authentication
|
|
||||||
PasswordAuthentication no
|
|
||||||
|
|
||||||
# Disable challenge-response authentication
|
|
||||||
ChallengeResponseAuthentication no
|
|
||||||
|
|
||||||
# Allow root login
|
|
||||||
PermitRootLogin yes
|
|
||||||
|
|
||||||
# Disable empty passwords
|
|
||||||
PermitEmptyPasswords no
|
|
||||||
|
|
||||||
# Disable X11 forwarding
|
|
||||||
X11Forwarding no
|
|
||||||
|
|
||||||
# Use only protocol 2
|
|
||||||
Protocol 2
|
|
||||||
|
|
||||||
# Log more verbosely
|
|
||||||
LogLevel VERBOSE
|
|
||||||
|
|
||||||
# Keep-alive packets to ensure connection stability
|
|
||||||
TCPKeepAlive yes
|
|
||||||
ClientAliveInterval 60
|
|
||||||
ClientAliveCountMax 10
|
|
||||||
dest: /etc/ssh/sshd_config.d/best_practices.conf
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0644'
|
|
||||||
|
|
||||||
- name: Restart SSH service to apply changes
|
|
||||||
service:
|
|
||||||
name: sshd
|
|
||||||
state: restarted
|
|
||||||
|
|
||||||
- name: Verify SSH configuration settings
|
|
||||||
shell: "sshd -T"
|
|
||||||
register: ssh_config_result
|
|
||||||
|
|
||||||
- name: Check specific SSH settings
|
|
||||||
debug:
|
|
||||||
msg: "{{ ssh_config_result.stdout_lines | select('search', 'passwordauthentication no') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'challengeresponseauthentication no') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'permitrootlogin yes') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'permitemptypasswords no') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'x11forwarding no') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'protocol 2') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'loglevel verbose') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'clientaliveinterval 60') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'clientalivecountmax 3') | list }}\n
|
|
||||||
{{ ssh_config_result.stdout_lines | select('search', 'tcpkeepalive yes') | list }}"
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Copy Traefik configuration files to the server
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
tasks:
|
|
||||||
- name: Synchronize Traefik configuration files
|
|
||||||
synchronize:
|
|
||||||
src: ./traefik_config/
|
|
||||||
dest: /var/vol/traefik/
|
|
||||||
rsync_opts:
|
|
||||||
- "--chown=traefik:traefik"
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
- name: Apply DevSec hardening
|
|
||||||
hosts: all
|
|
||||||
become: yes
|
|
||||||
vars:
|
|
||||||
sysctl_overwrite:
|
|
||||||
# Enable IPv4 traffic forwarding. Needed for containers.
|
|
||||||
net.ipv4.ip_forward: 1
|
|
||||||
os_security_users_allow:
|
|
||||||
- "change_user" # Ensure this user is allowed to avoid modifying /bin/su (does not work on read-only filesystems)
|
|
||||||
os_family: "Suse"
|
|
||||||
os_release: "Tumbleweed" # Treat MicroOS as Tumbleweed
|
|
||||||
os_version: "{{ ansible_distribution_version }}"
|
|
||||||
os_vars:
|
|
||||||
packages:
|
|
||||||
- sudo
|
|
||||||
- openssh
|
|
||||||
ignore_fs_types:
|
|
||||||
- squashfs
|
|
||||||
- iso9660
|
|
||||||
- vfat
|
|
||||||
auth_pam:
|
|
||||||
- common-password
|
|
||||||
- common-auth
|
|
||||||
- common-account
|
|
||||||
- common-session
|
|
||||||
pam_passwords:
|
|
||||||
- password requisite pam_pwquality.so retry=3
|
|
||||||
- password required pam_unix.so use_authtok remember=5 sha512 shadow
|
|
||||||
securetty: [console, tty1, tty2, tty3, tty4, tty5, tty6]
|
|
||||||
sshd:
|
|
||||||
package: openssh
|
|
||||||
service: sshd
|
|
||||||
config: /etc/ssh/sshd_config
|
|
||||||
kernel_modules_disabled:
|
|
||||||
- cramfs
|
|
||||||
- freevxfs
|
|
||||||
- jffs2
|
|
||||||
- hfs
|
|
||||||
- hfsplus
|
|
||||||
- squashfs
|
|
||||||
- udf
|
|
||||||
- vfat
|
|
||||||
auditd_package: audit # This is the correct package name for auditd in openSUSE
|
|
||||||
os_env_umask: "027" # Setting a default umask value
|
|
||||||
os_auth_uid_min: "1000" # Setting the minimum user ID for non-system users
|
|
||||||
os_auth_uid_max: "60000" # Setting the maximum user ID for non-system users
|
|
||||||
os_auth_gid_min: 1000
|
|
||||||
os_auth_gid_max: 60000
|
|
||||||
os_auth_sys_uid_min: "100" # Setting the minimum user ID for system users
|
|
||||||
os_auth_sys_uid_max: "499" # Setting the maximum user ID for system users
|
|
||||||
os_auth_sys_gid_min: 100
|
|
||||||
os_auth_sys_gid_max: 499
|
|
||||||
os_auth_sub_uid_min: 100000
|
|
||||||
os_auth_sub_uid_max: 600100000
|
|
||||||
os_auth_sub_uid_count: 65536
|
|
||||||
os_auth_sub_gid_min: 100000
|
|
||||||
os_auth_sub_gid_max: 600100000
|
|
||||||
os_auth_sub_gid_count: 65536
|
|
||||||
os_shadow_perms:
|
|
||||||
owner: root
|
|
||||||
group: shadow
|
|
||||||
mode: "0640"
|
|
||||||
os_passwd_perms:
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
hidepid_option: "2" # allowed values: 0, 1, 2
|
|
||||||
os_mnt_boot_group: 'root'
|
|
||||||
os_mnt_boot_owner: 'root'
|
|
||||||
os_mnt_dev_group: 'root'
|
|
||||||
os_mnt_dev_owner: 'root'
|
|
||||||
os_mnt_dev_shm_group: 'root'
|
|
||||||
os_mnt_dev_shm_owner: 'root'
|
|
||||||
os_mnt_home_group: 'root'
|
|
||||||
os_mnt_home_owner: 'root'
|
|
||||||
os_mnt_run_group: 'root'
|
|
||||||
os_mnt_run_owner: 'root'
|
|
||||||
os_mnt_tmp_group: 'root'
|
|
||||||
os_mnt_tmp_owner: 'root'
|
|
||||||
os_mnt_var_group: 'root'
|
|
||||||
os_mnt_var_owner: 'root'
|
|
||||||
os_mnt_var_log_group: 'root'
|
|
||||||
os_mnt_var_log_owner: 'root'
|
|
||||||
os_mnt_var_log_audit_group: 'root'
|
|
||||||
os_mnt_var_log_audit_owner: 'root'
|
|
||||||
os_mnt_var_tmp_group: 'root'
|
|
||||||
os_mnt_var_tmp_owner: 'root'
|
|
||||||
roles:
|
|
||||||
- devsec.hardening.os_hardening
|
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
$ANSIBLE_VAULT;1.1;AES256;podman_hosts
|
||||||
|
34396465333337346339653661356338373861326337663939616531623866336233653963353739
|
||||||
|
6264653732373635336563333732303735653532393865350a313135343361633034623239643339
|
||||||
|
31326238316333326166366638623963653635623533623833333862646462333363353066663434
|
||||||
|
6536343138643462320a393638643763633433363861326139326536663439633566386664393964
|
||||||
|
37366533323633376436396431383231346438643136326138643565343239393734643662386232
|
||||||
|
31373630376164623663333361323531626165646236393732353031313636623434323931633434
|
||||||
|
33343834356237376264383064393135663435323134373561306166306561356431656434633834
|
||||||
|
66653039633833643930303331323236633532343731613137383835643338373364633834653264
|
||||||
|
34643861366665336638656261373531343233353735353435643431303835376635356331373437
|
||||||
|
38306537643730646131666665396466366161303165303539663438666461623335366532376666
|
||||||
|
34356161383031353939343531333062623064353865636437633436613334663866346163316664
|
||||||
|
32383134333464663133
|
||||||
4
ansible/inventories/production/hosts.yml
Normal file
4
ansible/inventories/production/hosts.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
podman_hosts:
|
||||||
|
hosts:
|
||||||
|
io:
|
||||||
|
ansible_host: io.rohrschacht.de
|
||||||
@ -1,13 +1,12 @@
|
|||||||
---
|
---
|
||||||
- name: apply custom hardening for ssh
|
- name: podman host setup
|
||||||
import_playbook: custom_hardening.yml
|
hosts: podman_hosts
|
||||||
- name: install commonly used programs
|
roles:
|
||||||
import_playbook: common_programs.yml
|
- common
|
||||||
- name: allow privileged ports for rootless containers
|
- hardening
|
||||||
import_playbook: allow_privileged_ports_rootless.yml
|
- rootless_host
|
||||||
- name: deploy services
|
- traefik
|
||||||
import_playbook: deploy_services.yml
|
- backup
|
||||||
- name: deploy traefik configuration
|
|
||||||
import_playbook: deploy_traefik_config.yml
|
#- name: deploy services
|
||||||
- name: automate backup
|
# import_playbook: deploy_services.yml
|
||||||
import_playbook: automate_backup.yml
|
|
||||||
|
|||||||
48
ansible/roles/backup/tasks/main.yml
Normal file
48
ansible/roles/backup/tasks/main.yml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy backup.bash script
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: backup.bash.j2
|
||||||
|
dest: /usr/local/sbin/backup.bash
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Deploy check_backup.bash script
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: check_backup.bash.j2
|
||||||
|
dest: /usr/local/sbin/check_backup.bash
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Create borg backup systemd service
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Borg backup
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/local/sbin/borg_backup.sh
|
||||||
|
User=root
|
||||||
|
Group=root
|
||||||
|
dest: /etc/systemd/system/borg_backup.service
|
||||||
|
- name: Create borg backup systemd timer
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Borg backup timer
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 05:00:00
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
dest: /etc/systemd/system/borg_backup.timer
|
||||||
|
- name: Start and enable borg backup timer
|
||||||
|
systemd:
|
||||||
|
name: borg_backup.timer
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
BACKUP_USER="your_remote_user" # Remote SSH username
|
BACKUP_USER="{{ backup.user }}" # Remote SSH username
|
||||||
BACKUP_HOST="your_remote_host" # Remote SSH server
|
BACKUP_HOST="{{ backup.host }}" # Remote SSH server
|
||||||
BACKUP_PATH="/path/to/remote/backup/folder" # Remote backup folder
|
BACKUP_PATH="{{ backup.path }}" # Remote backup folder
|
||||||
BORG_PASSPHRASE="your_encryption_password" # Encryption password (in plain text)
|
BORG_PASSPHRASE="{{ backup.passphrase }}" # Encryption password (in plain text)
|
||||||
BACKUP_NAME="backup-$(date +'%Y-%m-%d')" # Name of the backup archive
|
BACKUP_NAME="backup-$(date +'%Y-%m-%d')" # Name of the backup archive
|
||||||
BACKUP_REPO="ssh://$BACKUP_USER@$BACKUP_HOST/$BACKUP_PATH" # Borg repository location
|
BACKUP_REPO="ssh://$BACKUP_USER@$BACKUP_HOST/$BACKUP_PATH" # Borg repository location
|
||||||
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
BACKUP_USER="your_remote_user" # Remote SSH username
|
BACKUP_USER="{{ backup.user }}" # Remote SSH username
|
||||||
BACKUP_HOST="your_remote_host" # Remote SSH server
|
BACKUP_HOST="{{ backup.host }}" # Remote SSH server
|
||||||
BACKUP_PATH="/path/ro/remote/backup/folder" # Remote backup folder
|
BACKUP_PATH="{{ backup.path }}" # Remote backup folder
|
||||||
BORG_PASSPHRASE="your_encryption_password" # Encryption password (in plain text)
|
BORG_PASSPHRASE="{{ backup.passphrase }}" # Encryption password (in plain text)
|
||||||
BACKUP_NAME="backup-$(date +'%Y-%m-%d')" # Name of the backup archive
|
BACKUP_NAME="backup-$(date +'%Y-%m-%d')" # Name of the backup archive
|
||||||
BACKUP_REPO="ssh://$BACKUP_USER@$BACKUP_HOST/$BACKUP_PATH" # Borg repository location
|
BACKUP_REPO="ssh://$BACKUP_USER@$BACKUP_HOST/$BACKUP_PATH" # Borg repository location
|
||||||
|
|
||||||
3
ansible/roles/common/tasks/main.yml
Normal file
3
ansible/roles/common/tasks/main.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
- name: Install common programs
|
||||||
|
include_tasks: programs.yml
|
||||||
13
ansible/roles/common/tasks/programs.yml
Normal file
13
ansible/roles/common/tasks/programs.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
- name: install common programs with zypper and transactional-update
|
||||||
|
community.general.zypper:
|
||||||
|
pkg:
|
||||||
|
- borgbackup
|
||||||
|
- tmux
|
||||||
|
- lynis
|
||||||
|
- toolbox
|
||||||
|
state: present
|
||||||
|
register: zypper_result
|
||||||
|
- name: reboot if software needed to be installed
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
when: zypper_result.changed
|
||||||
6
ansible/roles/hardening/handlers/main.yml
Normal file
6
ansible/roles/hardening/handlers/main.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Restart sshd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: sshd
|
||||||
|
state: restarted
|
||||||
3
ansible/roles/hardening/tasks/main.yml
Normal file
3
ansible/roles/hardening/tasks/main.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
- name: SSH hardening
|
||||||
|
include_tasks: ssh.yml
|
||||||
59
ansible/roles/hardening/tasks/ssh.yml
Normal file
59
ansible/roles/hardening/tasks/ssh.yml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure the sshd_config.d directory exists
|
||||||
|
file:
|
||||||
|
path: /etc/ssh/sshd_config.d
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Create a configuration file to apply SSH best practices
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
# Disable password authentication
|
||||||
|
PasswordAuthentication no
|
||||||
|
|
||||||
|
# Disable challenge-response authentication
|
||||||
|
ChallengeResponseAuthentication no
|
||||||
|
|
||||||
|
# Allow root login
|
||||||
|
PermitRootLogin yes
|
||||||
|
|
||||||
|
# Disable empty passwords
|
||||||
|
PermitEmptyPasswords no
|
||||||
|
|
||||||
|
# Disable X11 forwarding
|
||||||
|
X11Forwarding no
|
||||||
|
|
||||||
|
# Use only protocol 2
|
||||||
|
Protocol 2
|
||||||
|
|
||||||
|
# Log more verbosely
|
||||||
|
LogLevel VERBOSE
|
||||||
|
|
||||||
|
# Keep-alive packets to ensure connection stability
|
||||||
|
TCPKeepAlive yes
|
||||||
|
ClientAliveInterval 60
|
||||||
|
ClientAliveCountMax 10
|
||||||
|
dest: /etc/ssh/sshd_config.d/best_practices.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: Restart sshd
|
||||||
|
|
||||||
|
- name: Verify SSH configuration settings
|
||||||
|
shell: "sshd -T"
|
||||||
|
register: ssh_config_result
|
||||||
|
|
||||||
|
- name: Check specific SSH settings
|
||||||
|
debug:
|
||||||
|
msg: "{{ ssh_config_result.stdout_lines | select('search', 'passwordauthentication no') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'challengeresponseauthentication no') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'permitrootlogin yes') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'permitemptypasswords no') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'x11forwarding no') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'protocol 2') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'loglevel verbose') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'clientaliveinterval 60') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'clientalivecountmax 3') | list }}\n
|
||||||
|
{{ ssh_config_result.stdout_lines | select('search', 'tcpkeepalive yes') | list }}"
|
||||||
3
ansible/roles/rootless_host/tasks/main.yml
Normal file
3
ansible/roles/rootless_host/tasks/main.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
- name: Allow rootless ports for podman
|
||||||
|
include_tasks: rootless_ports.yml
|
||||||
14
ansible/roles/rootless_host/tasks/rootless_ports.yml
Normal file
14
ansible/roles/rootless_host/tasks/rootless_ports.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
- name: Set sysctl to allow normal users to bind to ports starting from 80
|
||||||
|
sysctl:
|
||||||
|
name: net.ipv4.ip_unprivileged_port_start
|
||||||
|
value: 80
|
||||||
|
state: present
|
||||||
|
reload: yes
|
||||||
|
|
||||||
|
- name: Verify the sysctl setting
|
||||||
|
command: sysctl net.ipv4.ip_unprivileged_port_start
|
||||||
|
register: sysctl_result
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "net.ipv4.ip_unprivileged_port_start: {{ sysctl_result.stdout }}"
|
||||||
7
ansible/roles/traefik/tasks/main.yml
Normal file
7
ansible/roles/traefik/tasks/main.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
- name: Synchronize Traefik configuration files
|
||||||
|
synchronize:
|
||||||
|
src: ./
|
||||||
|
dest: /var/vol/traefik/
|
||||||
|
rsync_opts:
|
||||||
|
- "--chown=traefik:traefik"
|
||||||
Loading…
Reference in New Issue
Block a user