How to Extract MySQL Password from INI File to Ansible Variable for Database Automation


2 views

The /etc/mysql/debian.cnf file follows standard INI format with sections ([client], [mysql_upgrade]) and key-value pairs. We need to extract the password value from the [client] section programmatically.

Ansible provides several approaches to handle INI files:

Option 1: Using the ini_file Lookup Plugin


- name: Read MySQL password from INI file
  ansible.builtin.set_fact:
    mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"

Option 2: Using the community.general.ini Module


- name: Parse INI file with dedicated module
  community.general.ini:
    path: /etc/mysql/debian.cnf
    section: client
    option: password
    dest: mysql_password

Here's a full implementation for creating a MySQL user with the extracted password:


- hosts: database_servers
  vars:
    new_mysql_user: app_user
    new_mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
  
  tasks:
    - name: Ensure MySQL user exists
      community.mysql.mysql_user:
        name: "{{ new_mysql_user }}"
        password: "{{ new_mysql_password }}"
        priv: "*.*:ALL"
        state: present
        login_user: root
        login_password: "{{ new_mysql_password }}"

When working with sensitive passwords:

  • Always use no_log: true for tasks handling credentials
  • Consider using Ansible Vault for storing sensitive values
  • Set appropriate file permissions on the INI file (600 recommended)

For more complex scenarios:


- name: Safe extraction with default value
  set_fact:
    mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') | default('fallback_password') }}"

When automating MySQL administration tasks with Ansible, we often need to retrieve credentials from configuration files. The /etc/mysql/debian.cnf file presents a common challenge with its INI-style format containing multiple sections.

Ansible provides the ini lookup plugin that can handle basic INI file parsing. Here's how to use it:


- name: Read MySQL password from debian.cnf
  ansible.builtin.set_fact:
    mysql_password: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"

For files with multiple sections like debian.cnf, we need to specify which section contains our target value:


- name: Get password from specific section
  ansible.builtin.set_fact:
    db_creds: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf type=properties') }}"

Here's a full playbook example that reads the password and uses it to create a MySQL user:


- hosts: database_servers
  tasks:
    - name: Extract MySQL root password
      ansible.builtin.set_fact:
        mysql_root_pass: "{{ lookup('ini', 'password section=client file=/etc/mysql/debian.cnf') }}"
      
    - name: Create new database user
      community.mysql.mysql_user:
        name: "new_user"
        password: "secure_password123"
        priv: "*.*:ALL"
        state: present
        login_user: "root"
        login_password: "{{ mysql_root_pass }}"

For more complex parsing needs, you might combine lineinfile with regex:


- name: Extract password using regex
  ansible.builtin.shell: |
    grep -oP '^password\s*=\s*\K.*' /etc/mysql/debian.cnf | head -1
  register: mysql_pass
  changed_when: false
  
- name: Set password fact
  ansible.builtin.set_fact:
    extracted_pass: "{{ mysql_pass.stdout }}"

When working with sensitive credentials:

  • Use no_log: true to prevent password exposure in logs
  • Consider using Ansible Vault for credential management
  • Ensure minimal permissions on configuration files

Common issues and solutions:


# If encountering encoding issues:
- name: Read file with proper encoding
  ansible.builtin.slurp:
    src: /etc/mysql/debian.cnf
  register: config_file
  
- name: Decode content
  ansible.builtin.set_fact:
    file_content: "{{ config_file.content | b64decode }}"