Skip to content

Ansible Best Practices Suggestions for MikroTik Playbooks #10

@JanWelker

Description

@JanWelker

After reviewing your MikroTik Ansible playbooks, here are my recommendations for improvements based on Ansible best practices:

Structure and Organization

Convert to Roles-Based Structure

roles/
  mikrotik-common/
    defaults/
    tasks/
    handlers/
    templates/
  mikrotik-backup/
  mikrotik-security/
  mikrotik-network/

Recommendation: Convert your playbooks into roles for better organization and reusability. Group related functionality (backup, configuration, security) into separate roles.

Use Include/Import for Common Tasks
Current Issue: Several playbooks repeat the same tasks (e.g., creating backup directories).
Recommendation: Create task files for common operations and use include_tasks or import_tasks.

# common-tasks/create-backup-dir.yml
- name: Create backups folder in the ansible control host
  ansible.builtin.file:
    path: "{{ local_backups_top_folder }}/{{ inventory_hostname }}"
    state: directory
    mode: '0700'
  delegate_to: localhost
  become: false

Clean Up Commented Code
Current Issue: Many playbooks contain commented-out code blocks.
Recommendation: Remove commented code or document why it's kept for reference.

Variable Management

Use Default Variables
Recommendation: Define default variables in role defaults and override them in inventory when needed.

# roles/mikrotik-backup/defaults/main.yml
local_backups_top_folder: "{{ playbook_dir }}/../backups"
backup_retention_days: 30

Use Ansible Vault for Sensitive Data
Current Issue: Credentials appear to be stored in inventory variables.
Recommendation: Use Ansible Vault for sensitive data like API credentials.

# Create encrypted file
ansible-vault create group_vars/mikrotik/vault.yml
# Reference in your playbook
- name: Configure RouterOS switches
  hosts: mikrotik
  vars_files:
    - group_vars/mikrotik/vault.yml

Standardize Variable Naming
Current Issue: Variable naming is inconsistent (mix of routeros_ prefix and others).
Recommendation: Adopt a consistent naming convention for all variables.

Error Handling and Idempotency

Improve Error Handling
Current Issue: Basic error handling with ignore_errors: True in some playbooks.
Recommendation: Use block/rescue/always for more sophisticated error handling.

- name: Backup configuration with proper error handling
  block:
    - name: Perform backup
      community.routeros.command:
        commands: "/export show-sensitive terse file={{ inventory_hostname }}.cfg.backup"
  rescue:
    - name: Log backup failure
      ansible.builtin.debug:
        msg: "Backup failed for {{ inventory_hostname }}"
    - name: Send notification
      ansible.builtin.mail:
        subject: "Backup failed for {{ inventory_hostname }}"
  always:
    - name: Ensure cleanup happens
      community.routeros.command:
        commands: "/file/remove {{ inventory_hostname }}.cfg.backup"
      ignore_errors: yes

Add Conditional Checks
Recommendation: Add checks before operations to ensure idempotency.

- name: Check if backup file exists
  ansible.builtin.stat:
    path: "{{ local_backups_top_folder }}/{{ inventory_hostname }}/{{ inventory_hostname }}.cfg.backup.rsc"
  register: backup_stat
  delegate_to: localhost

- name: Perform backup only if needed
  block:
    # Backup tasks
  when: not backup_stat.stat.exists or backup_stat.stat.mtime < (ansible_date_time.epoch|int - 86400)

Task Naming and Documentation

Improve Task Names
Current Issue: Some task names are generic or unclear.
Recommendation: Make task names more descriptive and action-oriented.

# Before
- name: "Import the certificates in the switch"

# After
- name: "Import CA certificate into RouterOS certificate store"

Add Playbook Documentation
Recommendation: Add comprehensive documentation at the beginning of each playbook.

---
# Playbook: mikrotik-backup-config.yml
# Description: Creates configuration backups of MikroTik devices
# 
# Prerequisites:
#   - Network connectivity to MikroTik devices
#   - Valid API credentials in inventory
#
# Variables:
#   - local_backups_top_folder: Directory to store backups
#
# Tags:
#   - backup
#   - config

Security Enhancements

Improve Certificate Management
Current Issue: Certificate generation is good but could be more secure.
Recommendation: Add more security options and validation.

- name: Create SSL private key with stronger parameters
  community.crypto.openssl_privatekey:
    path: "{{ local_certs_destination_folder }}/{{ local_ca_privkey }}"
    type: 'RSA'
    size: 4096  # Increased from 2048
    cipher: auto
    passphrase: "{{ ca_key_passphrase }}"

Add Backup Encryption
Recommendation: Encrypt sensitive backup files.

- name: Encrypt backup file
  ansible.builtin.command:
    cmd: "openssl enc -aes-256-cbc -salt -in {{ local_backups_top_folder }}/{{ inventory_hostname }}/{{ inventory_hostname }}.cfg.backup.rsc -out {{ local_backups_top_folder }}/{{ inventory_hostname }}/{{ inventory_hostname }}.cfg.backup.rsc.enc -k {{ backup_encryption_key }}"
  delegate_to: localhost
  when: encrypt_backups | default(true)

Performance and Efficiency

Use API Instead of Commands Where Possible
Current Issue: Some playbooks use community.routeros.command where API calls would be more efficient.
Recommendation: Replace command modules with API modules where possible.

# Before
- name: "Starting ROS Configuration Backup to memory"
  community.routeros.command:
    commands: "/export show-sensitive terse file={{ inventory_hostname }}.cfg.backup"

# After (if possible with API)
- name: "Export configuration using API"
  community.routeros.api_command:
    path: "system backup"
    command: "save"
    args:
      name: "{{ inventory_hostname }}.cfg.backup"

Add Tags for Selective Execution
Current Issue: Some playbooks have tags, but they could be more comprehensive.
Recommendation: Add tags to all tasks for more granular execution.

- name: Write the config to switch's memory and copy it to ansible control host
  block:
    # Tasks
  tags: 
    - backup
    - config
    - export

Testing and Validation

Add Pre-flight Checks
Recommendation: Add validation tasks before making changes.

- name: Verify connectivity before making changes
  community.routeros.command:
    commands: "/system identity print"
  register: identity_check
  failed_when: identity_check.failed

- name: Verify API access
  community.routeros.api_info:
    path: "system identity"
  register: api_check

Add Post-change Validation
Recommendation: Validate changes after they're applied.

- name: Verify configuration after changes
  community.routeros.command:
    commands: "/system resource print"
  register: post_change_check
  failed_when: post_change_check.failed

Specific Playbook Improvements

mikrotik-backup-config.yml and mikrotik-backup-system.yml
Recommendation: Combine these into a single role with different tasks.

mikrotik-configure.yml
Recommendation: Split this large playbook into smaller, focused roles.
Issue: The commented rollback mechanism should be implemented properly.

mikrotik-enable-api-ssl.yml
Issue: Duplicate task names for certificate imports.
Recommendation: Use unique, descriptive names for each certificate import.

mikrotik-dump-cfg-vars-to-disk.yml
Issue: Very large list of API endpoints hardcoded in the playbook.
Recommendation: Move this to a separate variable file or use dynamic discovery.

By implementing these suggestions, your Ansible playbooks will be more maintainable, secure, and aligned with best practices. The role-based structure will make it easier to reuse code and maintain consistency across your infrastructure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions