Skip to content

kvvloten/ansible_modules_and_plugins

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ansible modules and plugins

A collection of modules and plugins for Ansible.

Tested on Ansible 2.9

Filter plugins:

  • dns_reverse
  • hide_sensitive_data
  • usable_ipaddresses
  • vaultwarden_*

Modules:

  • difflines
  • ldap_search
  • samba_dns_record
  • samba_dns_zone
  • lxc_subordinate

Filter plugins

dns_reverse

Given a subnet it returns the reverse dns-zone (IPv6 not implemented):

- debug:
    msg: "{{ '192.168.1.73/29' | dns_reverse_zone }}"

Output:

ok: [host] => {
    "msg": "73.1.168.192.in-addr.arpa."
}

hide_sensitive_data

Create obfuscated output for Windows unattend.xml files

    <LocalAccount wcm:action="add">
        <Password>
            <Value>{{ local_administrator_password | hide_sensitive_data() }}</Value>
            <PlainText>false</PlainText>
        </Password>
        <DisplayName>Local Administrator</DisplayName>
        <Group>Administrators</Group>
        <Name>local_admin</Name>
    </LocalAccount>

usable_ipaddress

Given a subnet it returns a range of ipadresses:

- debug:
    msg: "{{ '192.168.1.73/29' | usable_ipaddr }}"

Output:

ok: [host] => {
    "msg": [
        "192.168.1.73",
        "192.168.1.74",
        "192.168.1.75",
        "192.168.1.76",
        "192.168.1.77",
        "192.168.1.78"
    ]
}

This can be used to iterate over usable ips:

{% for ipaddress in "192.168.1.73/29" | usable_ipaddr() %}
{{ ipaddress }}
{% endfor %}

vaultwarden

vaultwarden is an "Unofficial Bitwarden compatible server written in Rust".

A great help to install Vaultwarden in Debian is vaultwarden debian package helper

A set of filters for all crypto operations in Vaultwarden (or Bitwarden).

  • vaultwarden_master_key
  • vaultwarden_symmetric_key
  • vaultwarden_hashed_password
  • vaultwarden_encrypt_key
  • vaultwarden_decrypt_key
  • vaultwarden_encrypt
  • vaultwarden_decrypt
  • vaultwarden_string_encrypt
  • vaultwarden_string_decrypt
  • vaultwarden_rsa_generate_keypair
  • vaultwarden_rsa_get_keypair
  • vaultwarden_rsa_encrypt
  • vaultwarden_rsa_decrypt
  • vaultwarden_email_verify_token
  • vaultwarden_org_invite_token
  • vaultwarden_get_users_overview

This set of filter-plugins enables management of users and organizations in Vaultwarden (or Bitwarden) by Ansible.

Options are:

  • Admin login with token: (un)lock users, remove users, remove 2fa
  • Create user and validate email, add logins etc, add organization(s)
  • Create organization And much more as long as the API calls are known.

API documentation is incomplete, some helpful links are:

Reverse engineering of API calls can easily be done by using the web-interface. Put the browser in developer mode and watch client-server calls in 'Network'-tab.

An example: create user and automatically accept the email invitation

- name: "user data"
  set_fact:
    user_email: "test1@example.com"
    user_displayname: "firstname lastname"
    user_password: "initial_password_of_user_test1"

- name: "get prelogin data"
  uri:
    method: "POST"
    url: "http://localhost/vaultwarden/api/accounts/prelogin"
    body_format: "json"
    body: >
      {
        "email": "{{ user_email }}"
      }
    status_code: [200, 500]
  register: r_prelogin

- name: "create keys"
  set_fact:
    user_master_key: "{{ user_email | vaultwarden_master_key(user_password, r_prelogin.json.KdfIterations) }}"
    register_symmetric_key: "{{ '' | vaultwarden_symmetric_key }}"
    register_rsa_keypair: "{{ '' | vaultwarden_rsa_generate_keypair }}"

- name: "register new user"
  uri:
    method: "POST"
    url: "http://localhost/vaultwarden/api/accounts/register"
    body_format: "json"
    # because the json contains a number (in kdfIterations) it must be a folded string block in yaml
    #   otherwise yaml + jinja2 + ansible will put quotes around all values, i.e. make it strings,
    #   that results in "http 422: Unprocessable Entity"
    # https://stackoverflow.com/questions/53307595/ansible-how-print-number-instead-string-in-json-module-uri
    body: >
      {
        "name": "{{ user_displayname }}",
        "email": "{{ user_email }}",
        "masterPasswordHash": "{{ user_email | vaultwarden_hashed_password(user_password, r_prelogin.json.KdfIterations) }}",
        "masterPasswordHint": "",
        "kdfIterations": {{ r_prelogin.json.KdfIterations }},
        "key": "{{ register_symmetric_key | vaultwarden_encrypt_key(user_master_key) }}",
        "keys": {
          "encryptedPrivateKey": "{{ register_rsa_keypair['private_key'] | vaultwarden_encrypt(register_symmetric_key) }}",
          "publicKey": "{{ register_rsa_keypair['public_key'] }}"
        }
      }
    status_code: [200, 400]
  register: r_register

- name: "login user"
  # Since the user is just created, we can login with the initial password
  uri:
    method: "POST"
    url: "http://localhost/vaultwarden/identity/connect/token"
    body_format: "form-urlencoded"
     # browser types:
     #   https://github.com/bitwarden/server/blob/c9a2e67d0965fd046a0b3099e9511c26f0201acd/src/Core/Enums/DeviceType.cs
    body: >
      {
        "grant_type": "password",
        "username": "{{ user_email }}",
        "password": "{{ user_mail | vaultwarden_hashed_password(user_password, r_prelogin.json.KdfIterations) }}",
        "scope": "api offline_access",
        "client_id": "browser",
        "deviceType": 3,
        "deviceIdentifier": "aac2e34a-44db-42ab-a733-5322dd582c3d",
        "deviceName": "firefox",
        "devicePushToken": ""
      }
    status_code: [200, 400]
  register: r_login

- name: "stop when login failed"
  assert:
    - not ansible_check_mode
    - r_login.status == 200

- name: "set access token and symmetic key"
  set_fact:
    i_user_access_token: "{{ r_login.json.access_token }}"
    i_user_symmetric_key: "{{ r_login.json.Key | vaultwarden_decrypt_key(user_master_key) }}"

- name: "set rsa keypair"
  set_fact:
    i_user_rsa_keypair: "{{ r_login.json.PrivateKey | vaultwarden_decrypt(i_user_symmetric_key) | vaultwarden_rsa_get_keypair }}"

- name: " get user profile"
  uri:
    method: "GET"
    url: "http://localhost/vaultwarden/api/accounts/profile"
    headers:
      authorization: "Bearer {{ i_user_access_token }}"
    status_code: [200]
  register: r_user_profile

- name: "api_user_profile_get.yml - set organizations"
  set_fact:
    i_user_profile: "{{ r_user_profile.json }}"

- name: "verify account email"
  uri:
    method: "POST"
    url: "http://localhost/vaultwarden/api/accounts/verify-email-token"
    headers:
      authorization: "Bearer {{ i_user_access_token }}"
    body_format: "json"
    body:
      userId: "{{ i_user_profile.Id }}"
      token: "{{ i_user_access_token | vaultwarden_email_verify_token(vaultwarden_private_der) }}"
    status_code: [200]

Modules

difflines

Compares two texts line by lines. Text can be in a file or in a variable.

- difflines:
    source: "file_one"
    target: "file_two"
    source_type: file
    target_type: file
  register: diff

- debug:
    msg: "{{ diff.lines_removed }}"

- debug:
    msg: "{{ diff.lines_added }}"

samba_dns

Manage a zone in samba-dns (IPv6 not implemented)

-  samba_dns_zone:
    name: "192.168.1.73/29"
    state: "present"
    samba_username: "{{ samba_user }}"
    samba_password: "{{ samba_password }}"

Manage records in a zone in samba-dns (IPv6 not implemented)

-  samba_dns_record:
    zone: "192.168.1.73/29"
    name: "my_host"
    type: "A"
    value: "192.168.1.75"
    state: "present"
    samba_username: "{{ samba_user }}"
    samba_password: "{{ samba_password }}"

lxc_subordinate

Manage subordinate ranges for lxc containers. It maintains ranges in /etc/subuid and /etc/subgid, because those file do not store enough information an extra cache file is used to make it idempotent

-   lxc_subordinate:
    name: "mycontainer"
    path: "/etc/lxc/ansible_subordinates"  # path to subordinate cache file
    range_count: 65536
    owner: "root"  # owner/group of the container
    group: "root"
    map_users: ["mapped-user1", "mapped-user2"]  # must exist on the host, gets mapped into the container
    map_groups: ["mapped-user1", "mapped-user2", "group1"]  
  register: r_subordinate
  #  Updated /etc/subuid, /etc/subgid, /etc/lxc/ansible_subordinates
  #  returns:
  #    lxc_config: []  
  #    rootfs: {owner:, group:}  # uid,gid for container rootfs 

- file:
    path: "/var/lib/lxc/mycontainer/rootfs"
    owner: "{{ r_subordinate.rootfs.owner }}"
    group: "{{ r_subordinate.rootfs.group }}"
    mode: "0755"
    state: "directory"

- set_fact:
    container_conf: "{%- set config = [] -%}
                     {%- for item in r_subordinate.lxc_config -%}
                        {{- config.append('lxc.idmap = {}'.format(item)) -}}
                     {%- endfor -%}
                     {{- config -}}"

About

Collection of Ansible modules and plugins

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages