<p>This was caused by the fact that I was starting the Let's Encrypt challenges using a <code>with_items</code> loop. From <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables" rel="nofollow noreferrer">here</a>:</p>

<blockquote>
  <p>When using register with a loop, the data structure placed in the variable during the loop will contain a results attribute, that is a list of all responses from the module. For a more in-depth example of how this works, see the Loops section on using register with a loop.</p>
</blockquote>

<p>The solution is to have a separate task for each Let's Encrypt challenge, rather than having them all in one.</p>

CC BY-SA 4.0
2019-02-06T22:16:24.697Z
2019-02-06T22:16:24.697Z
rubberband876
<p>For those searching, I found this post while experiencing the same issue.  I was able to resolve this by adding the array index to my loop:</p>
<pre><code>  copy:
    content: &quot;{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource_value'] }}&quot;
    dest: &quot;/var/www/{{ item.hostname }}/{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource'] }}&quot;
    owner: root
    group: root
    mode: u=rw,g=r,o=r
  loop: &quot;{{ hosted_sites }}&quot;
  loop_control:
    loop_var: item
    extended: yes
</code></pre>
<p>The specific changes here being converting with_items to a loop and adding the loop_control parameter extended.  This allows for usage of ansible_loop.index0.</p>

CC BY-SA 4.0
2020-12-20T01:20:06.647Z
2020-12-20T01:20:06.647Z
Justin
<p>I am attempting to use the Ansible <code>acme_certificate</code> module to acquire a Let's Encrypt TLS certificate.</p>

<p>I have successfully generated the private keys, CSRs, etc, and then started the challenge using the following task:</p>

<pre><code>- name: Start challenge
  acme_certificate:
    acme_version: 1
    account_key_src: /etc/letsencrypt/account/account.key
    challenge: http-01
    csr: /etc/letsencrypt/csrs/{{ item }}.csr
    dest: /etc/letsencrypt/certs/{{ item }}.crt
    fullchain_dest: /etc/letsencrypt/certs/fullchain_{{ item }}.crt
  with_items:
  - www.example.com
  register: acme_challenge
</code></pre>

<p>I then attempt to satisfy the <code>http-01</code> challenge using:</p>

<pre><code>- name: Implement challenge
  copy:
    content: "{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource-value'] }}"
    dest: "/var/www/html/{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource'] }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r
</code></pre>

<p>However, this results in the following error:</p>

<p><code>The error was: 'list object' has no attribute 'challenge_data'</code></p>

<p>I have tried accessing the <code>acme_challenge</code> variable in different ways, for example using <code>{{ acme_challenge.challenge_data['www.example.com']['http-01']['resource'] }}</code>, as well of various other combinations of square brackets and dots.</p>

<p>I've also copied the example of accessing the variable directly from the Ansible documentation, <a href="https://docs.ansible.com/ansible/2.4/letsencrypt_module.html" rel="nofollow noreferrer">here</a> and <a href="https://docs.ansible.com/ansible/latest/modules/acme_certificate_module.html" rel="nofollow noreferrer">here</a>, but that gives the same error.</p>

<p>After around 3 hours of trying I cannot read the challenge data at all. I've used a <code>debug</code> statement and I can confirm that it's all there properly, I just can't read the variable with this syntax.</p>

<p>Is this a known problem, or does anybody have a suggestion?</p>

<ansible>
How can I issue a Let's Encrypt certificate with Ansible when 'challenge_data' cannot be found?
rubberband876
# How can I issue a Let's Encrypt certificate with Ansible when 'challenge_data' cannot be found?

(Asked by: username_0 on 2019-02-06)

I am attempting to use the Ansible acme_certificate module to acquire a Let's Encrypt TLS certificate.
I have successfully generated the private keys, CSRs, etc, and then started the challenge using the following task:
- name: Start challenge
  acme_certificate:
    acme_version: 1
    account_key_src: /etc/letsencrypt/account/account.key
    challenge: http-01
    csr: /etc/letsencrypt/csrs/{{ item }}.csr
    dest: /etc/letsencrypt/certs/{{ item }}.crt
    fullchain_dest: /etc/letsencrypt/certs/fullchain_{{ item }}.crt
  with_items:
  - www.example.com
  register: acme_challenge

I then attempt to satisfy the http-01 challenge using:
- name: Implement challenge
  copy:
    content: "{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource-value'] }}"
    dest: "/var/www/html/{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource'] }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r

However, this results in the following error:
The error was: 'list object' has no attribute 'challenge_data'
I have tried accessing the acme_challenge variable in different ways, for example using {{ acme_challenge.challenge_data['www.example.com']['http-01']['resource'] }}, as well of various other combinations of square brackets and dots.
I've also copied the example of accessing the variable directly from the Ansible documentation, here and here, but that gives the same error.
After around 3 hours of trying I cannot read the challenge data at all. I've used a debug statement and I can confirm that it's all there properly, I just can't read the variable with this syntax.
Is this a known problem, or does anybody have a suggestion?

**Tags:** ansible


---

## 2 answers

### Answer by username_0 on 2019-02-06. Score: 1

This was caused by the fact that I was starting the Let's Encrypt challenges using a `with_items` loop. From [here](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables):

> When using register with a loop, the data structure placed in the variable during the loop will contain a results attribute, that is a list of all responses from the module. For a more in-depth example of how this works, see the Loops section on using register with a loop.

The solution is to have a separate task for each Let's Encrypt challenge, rather than having them all in one.


---

### Answer by username_1 on 2020-12-20. Score: 1

For those searching, I found this post while experiencing the same issue.  I was able to resolve this by adding the array index to my loop:
  copy:
    content: "{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource_value'] }}"
    dest: "/var/www/{{ item.hostname }}/{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource'] }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r
  loop: "{{ hosted_sites }}"
  loop_control:
    loop_var: item
    extended: yes

The specific changes here being converting with_items to a loop and adding the loop_control parameter extended.  This allows for usage of ansible_loop.index0.


---

