Parsing a local file to get variables

48 views
Skip to first unread message

Dimitri Yioulos

unread,
Mar 6, 2024, 9:08:56 AM3/6/24
to Ansible Project
Good morning. Here's a bit of a challenge. I'm working on a playbook to get certs from letsencrypt, then put those into zone files. Rather than use the Ansible letsencrypt module, we've written a Perl script to get the certs. For each domain that we get certs for, a separate file named <domain>-le.txt is created in /etc/ansible/playbooks/files. It looks like this:

mydomain.com
cert1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cert2yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

I need to extract the certs and put them into the domain's zone file. This is what the playbook looks like right now, where we currently have to paste in the certs, as can be seen from the two prompts. That's what I'm trying to further automate:

---

- hosts: dns1,dns2
  gather_facts: yes
  become: yes
  become_method: sudo

  vars_prompt:

    - name: "zonefile"
      prompt: "Enter host domain name"
      private: no

    - name: "acmechallenge1"
      prompt: "Enter first DNS TXT record"
      private: no

    - name: "acmechallenge2"
      prompt: "Enter second DNS TXT record"
      private: no

  vars:
    serial_num: "{{ lookup('pipe', 'date +%Y%m%d%S') }}"
    year: "{{ lookup('pipe', 'date +%Y) }}"
    zonedir: '/var/named/chroot/var/named/'

  tasks:

    - name: Create backup of zone file
      shell: cp /var/named/chroot/var/named/{{ zonefile }}.hosts /root/zonebackups/{{ zonefile }}.hosts.{{ ansible_date_time.iso8601 }}
      tags:
        - backup

    - name: Remove old TXT entries
      replace:
        path: "{{ item }}"
        regexp: '^_acme-challenge.*\n'
        replace: ''
        after: "Lets Encrypt Validation"
        backup: yes
      with_items: '{{ zonedir }}{{ zonefile }}.hosts'
      tags:
        - remove

    - name: Update serial number
      replace:
        dest: "{{ item }}"
        regexp: '202[3-5][0-1][0-9][0-9][0-9][0-9][0-9]'
        replace: '{{ serial_num }}'
      with_items: '{{ zonedir }}{{ zonefile }}.hosts'
      tags:
        - updsrl

    - name: Add TXT entry 1 to zone file
      lineinfile:
        dest: "{{ item }}"
        insertafter: EOF
        line: '_acme-challenge                                 TXT     "{{ acmechallenge1 }}"'
      with_items: '{{ zonedir }}{{ zonefile }}.hosts'
      register: add_txt1

    - name: Add TXT entry 2 to zone file
      lineinfile:
        dest: "{{ item }}"
        insertafter: EOF
        line: '_acme-challenge                                 TXT     "{{ acmechallenge2 }}"'
      with_items: '{{ zonedir }}{{ zonefile }}.hosts'
      register: add_txt2

    - name: Show add_txt
      ansible.builtin.debug:
        var: add_txt1

    - name: Show add_txt
      ansible.builtin.debug:
        var: add_txt2

    - name: reload named-chroot
      service:
        name: named-chroot
        state: reloaded
      tags:
        - restart_named


Getting this more fullu automated would be huge. Your help would be most appreciated.

Stuart Lowe

unread,
Mar 6, 2024, 11:02:09 AM3/6/24
to ansible...@googlegroups.com

Probably dirty but something like reading out the file and setting facts based on the line?

- name: Read certificate file

      shell: cat {{ certdir }}/{{ zonefile }}-le.txt

      register: cert_content

 

    - name: Set cert variables from file

      set_fact:

        acmechallenge1: "{{ cert_content.stdout_lines[1] }}"

        acmechallenge2: "{{ cert_content.stdout_lines[2] }}"

 

From: ansible...@googlegroups.com <ansible...@googlegroups.com> On Behalf Of Dimitri Yioulos
Sent: Wednesday, March 6, 2024 2:09 PM
To: Ansible Project <ansible...@googlegroups.com>
Subject: [ansible-project] Parsing a local file to get variables

 

You don't often get email from dyio...@gmail.com. Learn why this is important

 

Caution: This email originated from outside of the organisation. Do not click links or open attachments unless you recognise the sender and know the content is safe

 

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/54de77a5-70fc-4b99-b240-ead1e7b09246n%40googlegroups.com.

---------------

Stuart Lowe He/Him
Zen Cloud Engineering - Team Leader
Zen Internet
Team: 01706 902009
www.zen.co.uk

Proud to be a certified B Corporation

This message is private and confidential. If you have received this message in error, please notify us and remove it from your system.

Zen Internet Limited may monitor email traffic data to manage billing, to handle customer enquiries, and for the prevention and detection of fraud. We may also monitor the content of emails sent to and/or from Zen Internet Limited for the purposes of security, staff training and to monitor the quality of service.
Zen Internet Limited is registered in England and Wales, Sandbrook Park, Sandbrook Way, Rochdale, OL11 1RY Company No. 03101568 VAT Reg No. 686 0495 01

Dimitri Yioulos

unread,
Mar 6, 2024, 11:52:00 AM3/6/24
to Ansible Project
Hey, Stuart. Yup, use of  set_fact was really the key (pardon the pun). Here's the playbook, which now works perfectly, if it might be useful to anyone else (the debug stuff in it can, of course, be removed):

---

- hosts: dns1,dns2
  gather_facts: True

  become: yes
  become_method: sudo

  vars_prompt:

    - name: "domain"

      prompt: "Enter host domain name"
      private: no

  vars:
    serial_num: "{{ lookup('pipe', 'date +%Y%m%d%S') }}"
    year: "{{ lookup('pipe', 'date +%Y) }}"
    zonedir: '/var/named/chroot/var/named/'
    keys: "{{ lookup('file', '{{ domain }}-le.txt') }}"

  tasks:

    - name: Run scripts to create Letsencrypt keys
      script: renew_le_domain.pl
      delegate_to: localhost
      tags:
        - createkeys

    - name: set fact
      set_fact:
        extract_key1: "{{ keys.split('\n')[1] }}"
        extract_key2: "{{ keys.split('\n')[2] }}"
      tags:
        - key

    - name: Print le file
      ansible.builtin.debug:
         msg: "{{ item }}"
      with_items:
        - "{{ extract_key1 }}"
        - "{{ extract_key2 }}"
      delegate_to: localhost
      run_once: yes
      tags:
        - key


    - name: Create backup of zone file
      shell: cp /var/named/chroot/var/named/{{ domain }}.hosts /root/zonebackups/{{ domain }}.hosts.{{ ansible_date_time.iso8601 }}

      tags:
        - backup

    - name: Remove old TXT entries
      become: yes

      replace:
        path: "{{ item }}"
        regexp: '^_acme-challenge.*\n'
        replace: ''
        after: "Lets Encrypt Validation"
        backup: yes
      with_items: '{{ zonedir }}{{ domain }}.hosts'
      tags:
        - remove

    - name: Update serial number
      become: yes

      replace:
        dest: "{{ item }}"
        regexp: '202[3-5][0-1][0-9][0-9][0-9][0-9][0-9]'
        replace: '{{ serial_num }}'
      with_items: '{{ zonedir }}{{ domain }}.hosts'

      tags:
        - updsrl

    - name: Add TXT entry 1 to zone file
      become: yes

      lineinfile:
        dest: "{{ item }}"
        insertafter: EOF
        line: '_acme-challenge                                 TXT     "{{ extract_key1 }}"'
      with_items: '{{ zonedir }}{{ domain }}.hosts'

      register: add_txt1

    - name: Add TXT entry 2 to zone file
      lineinfile:
        dest: "{{ item }}"
        insertafter: EOF
        line: '_acme-challenge                                 TXT     "{{ extract_key2 }}"'
      with_items: '{{ zonedir }}{{ domain }}.hosts'
      register: add_txt2

    - name: Show add_txt
      ansible.builtin.debug:
        var: add_txt1

    - name: Show add_txt
      ansible.builtin.debug:
        var: add_txt2

    - name: reload named-chroot
      service:
        name: named-chroot
        state: reloaded
      tags:
        - restart_named

Dimitri Yioulos

unread,
Mar 6, 2024, 3:33:00 PM3/6/24
to Ansible Project
Ah, I thought I was done with this. But,now, running the Perl script failed. I guess the script module only works with bash scripts? So, that's probably out. Among other things, I tried this, but it didn't work:

  tasks:

    - name: Run scripts to create Letsencrypt keys
      local_action: ansible.builtin.shell /etc/ansible/playbooks/files/renew_le_domain.pl {{ domain }}

    ~

This is the last piece I need to make this work completely.

Dimitri Yioulos

unread,
Mar 6, 2024, 5:31:35 PM3/6/24
to Ansible Project
Some additional info. With the above play, i get the following error:

fatal: [dns1 -> localhost]: FAILED! => changed=true
  cmd: /etc/ansible/playbooks/files/renew_le_domain.pl mydomain.com
  delta: '0:00:00.019169'
  end: '2024-03-06 17:22:01.951852'
  msg: non-zero return code
  rc: 25
  start: '2024-03-06 17:22:01.932683'
  stderr: done
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

The command " /etc/ansible/playbooks/files/renew_le_domain.pl mydomain.com" appears correct (where " mydomain.com" is an argument that the Perl script expects). The script has to run on the command node, and must generate a file file on the command node. When I run "last" on dns1, it looks like the ansible user has tried to connect to it.

Reply all
Reply to author
Forward
0 new messages