Rework portfolio around Linux operations, Zabbix monitoring, migration validation, and ELK/Grafana log observability. Add AAP-style LVM resize workflow, Zabbix server/proxy/agent automation assets, Linux/AIX monitoring templates, and updated validation CI.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# Base Provision Role
|
||||
|
||||
Provision basic infrastructure on enterprise nodes with security hardening.
|
||||
|
||||
## Features
|
||||
|
||||
- **Idempotent**: All tasks use proper idempotency markers (`changed_when`, `failed_when`)
|
||||
- **Handlers**: SSH and fail2ban restarts use handlers instead of direct service calls
|
||||
- **Variables**: All configuration in `defaults/main.yml` - no hardcoding
|
||||
- **Validation**: Pre-flight checks for system requirements
|
||||
- **Firewall**: UFW firewall configuration with configurable rules
|
||||
- **SSH Security**: Root login disabled, password auth disabled, key-based auth only
|
||||
|
||||
## Role Variables
|
||||
|
||||
See `defaults/main.yml` for all available variables.
|
||||
|
||||
### Key Variables
|
||||
|
||||
- `node_timezone`: System timezone (default: UTC)
|
||||
- `admin_user`: Admin username for infrastructure access
|
||||
- `ssh_port`: SSH service port (default: 22)
|
||||
- `base_packages`: List of base packages to install
|
||||
- `firewall_enabled`: Enable UFW firewall (default: true)
|
||||
- `firewall_allowed_tcp_ports`: Allowed TCP ports for firewall
|
||||
|
||||
## Secret Variables
|
||||
|
||||
This portfolio demo does not require secrets for offline validation. If you extend it with real passwords or keys, copy `group_vars/vault.example.yml` into an encrypted Ansible Vault file and keep real values out of normal git history.
|
||||
|
||||
## Usage
|
||||
|
||||
```yaml
|
||||
- role: base_provision
|
||||
vars:
|
||||
node_timezone: "Europe/Warsaw"
|
||||
firewall_enabled: true
|
||||
```
|
||||
|
||||
## Handlers
|
||||
|
||||
- `restart sshd`: Restarts SSH service (triggered by config changes)
|
||||
- `restart fail2ban`: Restarts fail2ban service (triggered by config changes)
|
||||
|
||||
## Tags
|
||||
|
||||
- `provision`: All provisioning tasks
|
||||
- `base`: Base provision role tasks
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
# Base provisioning configuration
|
||||
node_timezone: "UTC"
|
||||
admin_user: "infra-admin"
|
||||
ssh_port: 22
|
||||
ssh_disabled_root_login: true
|
||||
ssh_disable_password_auth: true
|
||||
|
||||
# Packages to install
|
||||
base_packages:
|
||||
- curl
|
||||
- wget
|
||||
- vim
|
||||
- htop
|
||||
- net-tools
|
||||
- iptables
|
||||
- fail2ban
|
||||
- unattended-upgrades
|
||||
|
||||
# Firewall rules
|
||||
firewall_enabled: true
|
||||
firewall_default_policy: deny
|
||||
firewall_allowed_tcp_ports:
|
||||
- 22
|
||||
- 80
|
||||
- 443
|
||||
|
||||
# Application directories
|
||||
app_directories:
|
||||
- path: /opt/application
|
||||
owner: "{{ admin_user }}"
|
||||
group: "{{ admin_user }}"
|
||||
mode: '0755'
|
||||
- path: /var/log/application
|
||||
owner: "{{ admin_user }}"
|
||||
group: "{{ admin_user }}"
|
||||
mode: '0755'
|
||||
- path: /etc/application
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
# Service verification
|
||||
services_to_verify: []
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: restart sshd
|
||||
ansible.builtin.service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
|
||||
- name: restart fail2ban
|
||||
ansible.builtin.service:
|
||||
name: fail2ban
|
||||
state: restarted
|
||||
enabled: true
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
- name: Validate system requirements
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_os_family == "Debian"
|
||||
- ansible_python_version is version('3.6', '>=')
|
||||
fail_msg: "Unsupported system - requires Debian and Python 3.6+"
|
||||
|
||||
- name: Update package cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
changed_when: false
|
||||
|
||||
- name: Install base packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ base_packages }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Check if admin user exists
|
||||
ansible.builtin.getent:
|
||||
database: passwd
|
||||
key: "{{ admin_user }}"
|
||||
register: admin_check
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Create admin user
|
||||
ansible.builtin.user:
|
||||
name: "{{ admin_user }}"
|
||||
groups: sudo
|
||||
append: true
|
||||
create_home: true
|
||||
shell: /bin/bash
|
||||
when: admin_check.failed
|
||||
|
||||
- name: Configure timezone
|
||||
community.general.timezone:
|
||||
name: "{{ node_timezone }}"
|
||||
|
||||
- name: Configure SSH security
|
||||
block:
|
||||
- name: Disable root SSH login
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^PermitRootLogin'
|
||||
line: 'PermitRootLogin no'
|
||||
state: present
|
||||
when: ssh_disabled_root_login
|
||||
notify: restart sshd
|
||||
|
||||
- name: Set SSH port
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^Port'
|
||||
line: "Port {{ ssh_port }}"
|
||||
state: present
|
||||
notify: restart sshd
|
||||
|
||||
- name: Disable password authentication
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^PasswordAuthentication'
|
||||
line: 'PasswordAuthentication no'
|
||||
state: present
|
||||
when: ssh_disable_password_auth
|
||||
notify: restart sshd
|
||||
|
||||
- name: Configure firewall
|
||||
block:
|
||||
- name: Enable UFW firewall
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: "{{ firewall_default_policy }}"
|
||||
when: firewall_enabled
|
||||
|
||||
- name: Allow SSH access
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
when: firewall_enabled
|
||||
|
||||
- name: Allow HTTP/HTTPS
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop: "{{ firewall_allowed_tcp_ports }}"
|
||||
when: firewall_enabled and item not in [ssh_port]
|
||||
|
||||
- name: Configure fail2ban
|
||||
ansible.builtin.template:
|
||||
src: jail.local.j2
|
||||
dest: /etc/fail2ban/jail.local
|
||||
backup: true
|
||||
mode: '0644'
|
||||
notify: restart fail2ban
|
||||
|
||||
- name: Enable unattended upgrades
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
regexp: '^APT::Periodic::Unattended-Upgrade'
|
||||
line: 'APT::Periodic::Unattended-Upgrade "1";'
|
||||
state: present
|
||||
|
||||
- name: Create application directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: directory
|
||||
owner: "{{ item.owner }}"
|
||||
group: "{{ item.group }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop: "{{ app_directories }}"
|
||||
|
||||
- name: Record role-specific service intent
|
||||
ansible.builtin.debug:
|
||||
msg: "Would configure {{ node_type | default('generic') }} service components in a full lab deployment"
|
||||
|
||||
- name: Verify services are running
|
||||
ansible.builtin.service:
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
enabled: true
|
||||
loop: "{{ services_to_verify }}"
|
||||
when: services_to_verify | length > 0
|
||||
failed_when: false
|
||||
|
||||
- name: Run health checks
|
||||
ansible.builtin.uri:
|
||||
url: http://localhost/health
|
||||
method: GET
|
||||
status_code: 200
|
||||
register: health_check
|
||||
failed_when: false
|
||||
ignore_errors: true
|
||||
when: "'webservers' in group_names"
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# fail2ban configuration
|
||||
[DEFAULT]
|
||||
bantime = 3600
|
||||
findtime = 600
|
||||
maxretry = 5
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = {{ ssh_port }}
|
||||
logpath = /var/log/auth.log
|
||||
maxretry = 3
|
||||
|
||||
[recidive]
|
||||
enabled = true
|
||||
Reference in New Issue
Block a user