maintenance-scripts/playbooks/archive_logs.yml
rebecca 3574b47a5f Initialize infrastructure maintenance scripts with Ansible playbooks
Add Ansible-based maintenance scripts for infrastructure operations:
- CVE scanner using NIST NVD database
- Package update checker with OpenAI risk assessment
- Docker cleanup playbook
- Log archiver for rotated logs
- Disk space analyzer

Supports Ubuntu 20.04/22.04/24.04, Debian 11/12/13, and Alpine Linux
2026-01-22 10:37:08 -03:00

177 lines
7.2 KiB
YAML

---
- name: Archive and Send Rotated Logs
hosts: all
gather_facts: true
vars:
log_directory: "/var/log"
archive_pattern: "*.gz"
remote_storage_path: "{{ lookup('env', 'REMOTE_STORAGE_PATH') | default('/mnt/log-archive', true) }}"
temp_archive_dir: "/tmp/log_archive_{{ ansible_date_time.iso8601_basic_short }}"
local_temp_dir: "/tmp/received_logs_{{ ansible_date_time.iso8601_basic_short }}"
retention_days: 30
archive_filename: "logs_{{ ansible_hostname }}_{{ ansible_default_ipv4.address | replace('.', '-') }}_{{ ansible_date_time.date }}.tar.gz"
output_file: "/tmp/log_archive_report_{{ ansible_date_time.iso8601_basic_short }}.json"
tasks:
- name: Create temporary local directory for logs
file:
path: "{{ local_temp_dir }}"
state: directory
mode: '0700'
delegate_to: localhost
run_once: true
- name: Find rotated log files (gzipped)
find:
paths: "{{ log_directory }}"
patterns: "{{ archive_pattern }}"
recurse: true
register: rotated_logs
failed_when: false
- name: Check if rotated logs exist
fail:
msg: "No rotated log files found matching {{ archive_pattern }} in {{ log_directory }}"
when: rotated_logs.matched == 0
- name: Display found log files
debug:
msg: "Found {{ rotated_logs.matched }} rotated log files to archive"
- name: Create temporary archive directory
file:
path: "{{ temp_archive_dir }}"
state: directory
mode: '0700'
- name: Organize logs in temporary directory with metadata
shell: >-
mkdir -p "{{ temp_archive_dir }}/{{ ansible_hostname }}/{{ ansible_date_time.date }}/{{ ansible_default_ipv4.address | replace('.', '-') }}/{{ item.path | dirname | replace(log_directory, '') }}" &&
cp -p {{ item.path }} "{{ temp_archive_dir }}/{{ ansible_hostname }}/{{ ansible_date_time.date }}/{{ ansible_default_ipv4.address | replace('.', '-') }}/{{ item.path | dirname | replace(log_directory, '') }}/"
loop: "{{ rotated_logs.files }}"
loop_control:
loop_var: item
- name: Create metadata file for archive
copy:
dest: "{{ temp_archive_dir }}/metadata.json"
content: >-
{
"hostname": "{{ ansible_hostname }}",
"ip_address": "{{ ansible_default_ipv4.address }}",
"fqdn": "{{ ansible_fqdn }}",
"os": "{{ ansible_distribution }} {{ ansible_distribution_version }}",
"kernel": "{{ ansible_kernel }}",
"architecture": "{{ ansible_architecture }}",
"collection_date": "{{ ansible_date_time.iso8601 }}",
"log_files_count": {{ rotated_logs.matched }},
"source_directory": "{{ log_directory }}",
"archive_pattern": "{{ archive_pattern }}"
}
mode: '0644'
- name: Create tar archive of organized logs
archive:
path: "{{ temp_archive_dir }}/*"
dest: "/tmp/{{ archive_filename }}"
format: gz
mode: '0600'
- name: Calculate archive size
stat:
path: "/tmp/{{ archive_filename }}"
register: archive_stat
- name: Create remote storage directory structure
file:
path: "{{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}"
state: directory
mode: '0755'
delegate_to: localhost
run_once: true
- name: Fetch archive to localhost
fetch:
src: "/tmp/{{ archive_filename }}"
dest: "{{ local_temp_dir }}/{{ archive_filename }}"
flat: true
- name: Copy archive to remote storage location
copy:
src: "{{ local_temp_dir }}/{{ archive_filename }}"
dest: "{{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}/{{ archive_filename }}"
mode: '0644'
delegate_to: localhost
run_once: true
- name: Verify archive was transferred successfully
stat:
path: "{{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}/{{ archive_filename }}"
register: remote_archive_stat
delegate_to: localhost
run_once: true
- name: Remove original rotated log files after successful transfer
file:
path: "{{ item.path }}"
state: absent
loop: "{{ rotated_logs.files }}"
loop_control:
loop_var: item
when: remote_archive_stat.stat.exists
- name: Clean up temporary directories
file:
path: "{{ item }}"
state: absent
loop:
- "{{ temp_archive_dir }}"
- "/tmp/{{ archive_filename }}"
failed_when: false
- name: Generate archive report
copy:
dest: "{{ output_file }}"
content: >-
{
"hostname": "{{ ansible_hostname }}",
"ip_address": "{{ ansible_default_ipv4.address }}",
"os": "{{ ansible_distribution }} {{ ansible_distribution_version }}",
"archive_date": "{{ ansible_date_time.iso8601 }}",
"log_directory": "{{ log_directory }}",
"archive_pattern": "{{ archive_pattern }}",
"logs_archived": {{ rotated_logs.matched }},
"archive_filename": "{{ archive_filename }}",
"archive_size_bytes": {{ archive_stat.stat.size | default(0) }},
"archive_size_human": "{{ archive_stat.stat.size | default(0) | human_readable }}",
"remote_storage_path": "{{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}/{{ archive_filename }}",
"transfer_successful": {{ remote_archive_stat.stat.exists | default(false) }},
"original_logs_deleted": {{ remote_archive_stat.stat.exists | default(false) }}
}
mode: '0600'
- name: Display archive summary
debug:
msg:
- "Log archive completed on {{ ansible_hostname }}"
- "Files archived: {{ rotated_logs.matched }}"
- "Archive size: {{ archive_stat.stat.size | default(0) | human_readable }}"
- "Remote location: {{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}/{{ archive_filename }}"
- "Transfer successful: {{ remote_archive_stat.stat.exists | default(false) }}"
- "Original logs deleted: {{ remote_archive_stat.stat.exists | default(false) }}"
- "Report saved to: {{ output_file }}"
- name: Return archive findings
set_fact:
log_archive_report:
hostname: ansible_hostname
ip_address: ansible_default_ipv4.address
os: ansible_distribution + ' ' + ansible_distribution_version
logs_archived: rotated_logs.matched
archive_filename: archive_filename
archive_size_bytes: archive_stat.stat.size | default(0)
remote_storage_path: "{{ remote_storage_path }}/{{ ansible_date_time.year }}/{{ ansible_date_time.month }}/{{ ansible_date_time.day }}/{{ archive_filename }}"
transfer_successful: remote_archive_stat.stat.exists | default(false)
archive_date: ansible_date_time.iso8601
report_file: output_file