1

I'm losing my mind here but i just cant seem to see where my problem lies! Im trying to have ansible create me users on a Cisco ASA and im using Jinja 2 templates.

I have a host vars file where i am specifying the users (sensitised data):

users:
  tom:
    sshkey: "xxxx"
    privilegelevel: 15
  dick:
    sshkey: "xxxx"
    privilegelevel: 15
  harry:
    password: "yyyy"
    privilegelevel: 15

My templates for creating the users (users.j2):

{% if users is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
{% endfor %}
{% endif %}

and if they have an ssh key (users-ssh.j2):

{% if users and 'sshkey' is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
username {{ value }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}
{% endif %}

And last but not least the playbook:

- name: create users
  asa_config:
    src: templates/users.j2
    provider: "{{ cli }}"
    save: yes
  tags: users

- name: create ssh pubkey auth
  asa_config:
    src: templates/users-ssh.j2
    provider: "{{ cli }}"
    save: yes
  tags: users

When running the playbook, the user.j2 works fine, but user-ssh.j2 fails with:

fatal: [HOSTNAME_HERE]: FAILED! => {"changed": false, "msg": "'dict object' has no attribute 'sshkey'"}

When calling the dict values with:

- name: Output dict
  debug:
    msg: "User is {{ item.key }} and the ssh key is {{ item.value.sshkey }}"
  loop: "{{ lookup('dict', users) }}"
  tags: users

It gives me the correct values:

ok: [fw01.prd.sc1] => (item={'key': 'tom', 'value': {'sshkey': 'xxxx', 'privilegelevel': 15}}) => {
    "msg": "User is tom and the ssh key is xxxx"
}
ok: [fw01.prd.sc1] => (item={'key': 'dick', 'value': {'sshkey': 'xxxx', 'privilegelevel': 15}}) => {
    "msg": "User is dick and the ssh key is xxxx"
}

Can anyone see where i may be going wrong with my J2 templating as ive a fair few things but getting nowhere!

Many thanks in advance :)

Kris

DreadnautKris
  • 13
  • 1
  • 3

1 Answers1

2

This loop...

{% if users and 'sshkey' is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
username {{ value }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}
{% endif %}

...doesn't check if a user has an sshkey attribute. The expression if users and 'sshkey' is defined is identical to writing if users, because the expressionif 'sshkey' is defined will always be true -- 'sshkey' is a literal string, not a variable.

Since the loop runs for all users, it fails when you get to harry, because harry doesn't have an sshkey attribute.

You need to filter your users for those that have an sshkey attribute, for example by using a loop filtering as described in the documentation:

{% for user, value in users.items() if value.sshkey is defined %}
username {{ user }} privilege {{ value.privilegelevel }}
username {{ user }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}

Note that I've also replaced username {{ value }} with username {{ user }}, because I'm reasonably sure the former was not what you meant.


For example, this playbook:

- hosts: localhost
  gather_facts: false
  vars:
    users:
      tom:
        sshkey: "xxxx"
        privilegelevel: 15
      dick:
        sshkey: "xxxx"
        privilegelevel: 15
      harry:
        password: "yyyy"
        privilegelevel: 15

  tasks:
    - copy:
        dest: users.txt
        content: |
          {% for user, value in users.items() if value.sshkey is defined %}
          username {{ user }} privilege {{ value.privilegelevel }}
          username {{ user }} attributes
            ssh authentication publickey {{ value.sshkey }}
          {% endfor %}

Produces as output in users.txt:

username tom privilege 15
username tom attributes
  ssh authentication publickey xxxx
username dick privilege 15
username dick attributes
  ssh authentication publickey xxxx
larsks
  • 277,717
  • 41
  • 399
  • 399
  • That is indeed what i meant when i put {{ value }}! Well would you look at that, that makes so much more sense now. Helps out with a few other playbooks as well :D many thanks for this larsks! – DreadnautKris Aug 06 '21 at 18:04