Skip to main content

Implementing Security Best Practices

1. Using Ansible Vault

Command Description Example
ansible-vault create Create a new encrypted file ansible-vault create secret.yml
ansible-vault edit Edit an existing encrypted file ansible-vault edit secret.yml
ansible-vault view View the contents of an encrypted file ansible-vault view secret.yml
ansible-vault encrypt Encrypt an existing file ansible-vault encrypt secret.yml
ansible-vault decrypt Decrypt an existing file ansible-vault decrypt secret.yml

Example: Encrypting a Variables File

ansible-vault create group_vars/all/vault.yml

Example: Using Vault in Playbook

- name: Example Playbook with Vault
  hosts: all
  vars:
    secret_key: "{{ vault_secret_key }}"
  tasks:
    - name: Print secret
      debug:
        msg: "Secret key is {{ secret_key }}"
Note: Vault requires a password to encrypt/decrypt files. This password can be provided via --vault-password-file or interactively.
Warning: Never store vault passwords in plain text files or commit them to version control.
Option Description Default
--vault-id Specify a vault ID to use default
--vault-password-file Path to a file containing the vault password None
--ask-vault-pass Ask for vault password at runtime false

2. Managing SSH Keys

Property Description Default Notes
ansible_ssh_private_key_file Path to the private SSH key file used for authentication. None Must be a valid path to a private key file (e.g., ~/.ssh/id_rsa)
ansible_ssh_public_key_file Path to the public SSH key file used for authentication. None Used for validating host keys or setting up key-based auth.
ansible_ssh_pass Password for SSH authentication (not recommended for production). None Deprecated in favor of key-based authentication.
ansible_ssh_user Username to use for SSH connections. root Can be overridden per host or group.
ansible_ssh_port Port to use for SSH connections. 22 Change if SSH is running on a non-standard port.

Example: Using SSH Key for Authentication

---
- name: Deploy application using SSH key
  hosts: webservers
  vars:
    ansible_ssh_private_key_file: "~/.ssh/deploy_key"
  tasks:
    - name: Ensure application directory exists
      file:
        path: /opt/myapp
        state: directory
Note: It is highly recommended to use SSH key-based authentication instead of passwords for Ansible automation. Passwords are less secure and harder to manage at scale.
Warning: Never store SSH private keys in plain text within playbooks or inventories. Use ansible-vault to encrypt sensitive data like private keys.

Best Practices for SSH Key Management

  • Use dedicated deployment keys with minimal permissions.
  • Rotate SSH keys regularly (e.g., every 90 days).
  • Store private keys securely with restricted file permissions (e.g., chmod 600).
  • Use ansible-vault to encrypt sensitive inventory variables.
  • Implement key revocation procedures for compromised keys.

3. Setting Become Password

Parameter Description Default Notes
become_password Password for privilege escalation None Used with become to provide password for sudo/su

Example: Using become_password in a playbook

- hosts: all
  become: yes
  become_password: "{{ vault_become_pass }}"
  tasks:
    - name: Install a package
      apt:
        name: nginx
        state: present
Note: It is recommended to store passwords in encrypted vaults rather than plain text.
Warning: Storing passwords in plain text files is a security risk. Use Ansible Vault for sensitive data.

4. Disabling Root Login

Configuration Description Value
ansible_become Enables privilege escalation true
ansible_become_method Method used for privilege escalation sudo
ansible_become_user User to escalate to root

Example: Disabling Root Login via SSH

sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config
sudo systemctl restart sshd
Note: Ensure that alternative user accounts with appropriate permissions are configured before disabling root login.
Warning: Disabling root login can prevent emergency access if SSH keys are lost or compromised.

5. Validating Module Sources

Source Type Validation Method Notes
Ansible Galaxy ansible-galaxy install --collections-path ./collections ansible.posix Verify collection integrity using checksums from Galaxy
Git Repositories ansible-galaxy collection install git+https://github.com/owner/repo.git Ensure repository is from a trusted source and has valid GPG signatures
Local Files ansible-galaxy collection install ./my_collection.tar.gz Validate tarball integrity with SHA256 checksums before installation

Example: Verifying Collection Integrity

ansible-galaxy collection install --collections-path ./collections ansible.posix
# Output includes verification steps
Note: Always verify GPG signatures when installing collections from untrusted sources.
Warning: Do not install collections from unknown sources without validating their integrity.

6. Setting File Permissions

Permission Octal Value Description
Read (r) 4 Allows reading the file content
Write (w) 2 Allows modifying the file content
Execute (x) 1 Allows executing the file as a program

Example: Setting File Permissions with Ansible

- name: Set file permissions to 644
  ansible.builtin.file:
    path: /etc/myapp/config.ini
    mode: '0644'
    owner: myuser
    group: mygroup

Example: Setting Directory Permissions with Ansible

- name: Set directory permissions to 755
  ansible.builtin.file:
    path: /var/www/html
    state: directory
    mode: '0755'
    owner: www-data
    group: www-data
Note: The mode parameter in Ansible uses octal notation. For example, 0644 means owner has read/write (6), group and others have read-only (4).
Warning: Be cautious when setting permissions to 0777 or similar overly permissive values, as they can expose sensitive files to unauthorized access.

Key Points for File Permissions

  • Use octal notation (e.g., 0644) for setting permissions in Ansible
  • Ensure proper ownership using owner and group parameters
  • Avoid overly permissive permissions like 0777 for security reasons
  • Use ansible.builtin.file module to manage file and directory permissions

7. Limiting Privilege Escalation

Directive Description Default Behavior Notes
become Enables privilege escalation for a task false Set to true to escalate privileges
become_method Specifies the privilege escalation method (e.g., sudo, su) sudo Must be supported by the target system
become_user Specifies the user to escalate to root Can be any valid system user
become_flags Additional flags to pass to the become method (e.g., -H) None Used to configure behavior of sudo or su

Example: Using become with sudo

- name: Install package with elevated privileges
  apt:
    name: nginx
    state: present
  become: true
  become_method: sudo
  become_user: root
Note: Privilege escalation should be limited to only necessary tasks and users. Avoid using become in roles or playbooks unless strictly required.
Warning: Misconfiguring become can lead to security vulnerabilities. Ensure that only authorized users or roles have access to tasks requiring privilege escalation.

8. Using Separate Vault Files

File Type Description Usage
.vault Encrypted files containing sensitive data Store credentials, keys, and secrets
.yml YAML files with encrypted content Used in playbooks or roles

Example: Encrypting a Vault File

ansible-vault encrypt secret_data.yml

Example: Using Vault File in Playbook

- name: Use Vault Data
  hosts: all
  vars:
    secret_key: "{{ vault_secret_key }}"
  tasks:
    - debug:
        msg: "Secret key is {{ secret_key }}"
Note: Vault files must be decrypted during runtime to access their contents.
Warning: Never commit unencrypted vault files to version control.

9. Auditing Playbook Runs

Aspect Description Notes
ansible-playbook --check ansible-playbook --check --diff playbook.yml Simulates run without making changes; shows differences
--diff ansible-playbook --diff playbook.yml Shows changes made to files during execution
--verbose ansible-playbook -vvv playbook.yml Increases verbosity for detailed logging
log_path ansible.cfg Configures where logs are stored (e.g., log_path = /var/log/ansible.log)
callback_plugins ansible.cfg Enables custom logging plugins (e.g., callback_plugins = /path/to/custom_logger)

Example: Enable Verbose Logging

[defaults]
log_path = /var/log/ansible.log
verbose = 3

Example: Run with Diff and Check Mode

ansible-playbook --check --diff playbook.yml
Note: Use --check mode to preview changes before applying them in production environments.
Warning: Ensure log paths are secure and accessible only to authorized users.

10. Implementing RBAC

Role Description Permissions Assignment
admin Full access to all Ansible components All actions on inventories, playbooks, and configurations Assigned to system administrators
operator Manage playbooks and inventory Read/write access to playbooks, read-only to inventory Assigned to operational staff
viewer Read-only access to Ansible components Read-only access to all resources Assigned to auditors or support staff

Example: Role Assignment in Ansible Tower

---
- name: Assign roles to users
  hosts: localhost
  tasks:
    - name: Add user to admin group
      tower_role:
        user: admin_user
        role: admin
        organization: my_org
Note: RBAC in Ansible Tower is managed through the UI or API. Ensure that roles are assigned based on the principle of least privilege.

11. Using Jump Hosts

Jump hosts (also known as bastion hosts) are used to securely access systems that are not directly accessible from the control node. This is particularly useful in environments where systems are behind firewalls or in private networks.

Parameter Description Example
ansible_ssh_jump Specifies the jump host to use for connecting to a target host. ansible_ssh_jump=jump.example.com
ansible_ssh_jump_host Alternative parameter for specifying the jump host. ansible_ssh_jump_host=jump.example.com
ansible_ssh_proxy_command Custom SSH proxy command to use for connecting through the jump host. ansible_ssh_proxy_command=ssh -W %h:%p jump.example.com

Example: Using Jump Host in Inventory

[webservers]
web1 ansible_host=10.0.1.10 ansible_ssh_jump=jump.example.com

[jump_hosts]
jump.example.com ansible_host=192.168.1.10

Example: Using Proxy Command in Playbook

- name: Configure web server via jump host
  hosts: web1
  vars:
    ansible_ssh_proxy_command: "ssh -W %h:%p jump.example.com"
  tasks:
    - name: Ensure nginx is installed
      apt:
        name: nginx
        state: present
Note: Ensure that the jump host has appropriate SSH keys and permissions to access the target systems.
Warning: Misconfiguring jump hosts can lead to security vulnerabilities or connectivity issues. Always test configurations in a non-production environment.

12. Validating Input

Input Type Description Validation Method Example
Inventory Variables Variables defined in inventory files or groups Use validate with type and required ansible_host: "{{ hostvars[inventory_hostname].ansible_host | default('localhost') }}"
Host Facts System information gathered by Ansible Use gather_facts and validate with assert
assert:
  that:
    - ansible_os_family == 'RedHat'
  fail_msg: "This playbook requires Red Hat family OS"
User Input Variables passed via command line or extra vars Use vars_prompt and validate
vars_prompt:
  - name: "environment"
    prompt: "Enter environment (prod/staging/dev)"
    default: "dev"
    validator: "^(prod|staging|dev)$"

Example: Validating User Input in Playbook

---
- hosts: all
  vars_prompt:
    - name: "environment"
      prompt: "Enter environment (prod/staging/dev)"
      default: "dev"
      validator: "^(prod|staging|dev)$"
  tasks:
    - name: Ensure environment is valid
      assert:
        that:
          - "environment in ['prod', 'staging', 'dev']"
        fail_msg: "Invalid environment provided: {{ environment }}"

Was this article helpful?