Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible/jinja2: issue reading a utf-16-le file and decoding into a usable string

I have a playbook that reads a few files, some of which are formatted in utf-16-le rather than utf-8. When reading them I am getting a bunch of useless garbage and I seem to struggle with decoding/encoding it back to something useable.

file is read using: lookup('file', file)
output of debug task:

    "msg": "��W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000 \u0000R\u0000e\u0000g\u0000i\u0000s\u0000t\u0000r\u0000y\u0000 \u0000E\u0000d\u0000i\u0000t\u0000o\u0000r\u0000 \u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000 \u00005\u0000.\u00000\u00000\u0000\r\u0000\n\u0000\r\u0000\n\u0000[\u0000H\u0000K\u0000E\u0000Y\u0000_\u0000L\u0000O\u0000C\u0000A\u0000L\u0000_\u0000M\u0000A\u0000C\u0000H\u0000I\u0000N\u0000E\u0000\\\u0000S\u0000O\u0000F\u0000T\u0000W\u0000A\u0000R\u0000E\u0000\\\u0000M\u0000i\u0000c\u0000r\u0000o\u0000s\u0000o\u0000f\u0000t\u0000\\\u0000W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000\\\u0000C\u0000u\u0000r\u0000r\u0000e\u0000n\u0000t\u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000\\\u0000P\u0000o\u0000l\u0000i\u0000c\u0000i\u0000e\u0000s\u0000\\\u0000S\u0000y\u0000s\u0000t\u0000e\u0000m\u0000]\u0000\r\u0000\n\u0000\"\u0000C\u0000o\u0000n\u0000s\u0000e\u0000n\u0000t\u0000P\u0000r\u0000o\u0000m\u0000p\u0000t\u0000B\u0000e\u0000h\u0000a\u0000v\u0000i\u0000o\u0000r\u0000A\u0000d\u0000m\u0000i\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000C\u0000o\u0000n\u0000s\u0000e\u0000n\u0000t\u0000P\u0000r\u0000o\u0000m\u0000p\u0000t\u0000B\u0000e\u0000h\u0000a\u0000v\u0000i\u0000o\u0000r\u0000U\u0000s\u0000e\u0000r\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00003\u0000\r\u0000\n\u0000\"\u0000D\u0000S\u0000C\u0000A\u0000u\u0000t\u0000o\u0000m\u0000a\u0000t\u0000i\u0000o\u0000n\u0000H\u0000o\u0000s\u0000t\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000d\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00002\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000C\u0000u\u0000r\u0000s\u0000o\u0000r\u0000S\u0000u\u0000p\u0000p\u0000r\u0000e\u0000s\u0000s\u0000i\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000F\u0000u\u0000l\u0000l\u0000T\u0000r\u0000u\u0000s\u0000t\u0000S\u0000t\u0000a\u0000r\u0000t\u0000u\u0000p\u0000T\u0000a\u0000s\u0000k\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00002\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000I\u0000n\u0000s\u0000t\u0000a\u0000l\u0000l\u0000e\u0000r\u0000D\u0000e\u0000t\u0000e\u0000c\u0000t\u0000i\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000L\u0000U\u0000A\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000S\u0000e\u0000c\u0000u\u0000r\u0000e\u0000U\u0000I\u0000A\u0000P\u0000a\u0000t\u0000h\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000U\u0000I\u0000A\u0000D\u0000e\u0000s\u0000k\u0000t\u0000o\u0000p\u0000T\u0000o\u0000g\u0000g\u0000l\u0000e\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000U\u0000w\u0000p\u0000S\u0000t\u0000a\u0000r\u0000t\u0000u\u0000p\u0000T\u0000a\u0000s\u0000k\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00002\u0000\r\u0000\n\u0000\"\u0000E\u0000n\u0000a\u0000b\u0000l\u0000e\u0000V\u0000i\u0000r\u0000t\u0000u\u0000a\u0000l\u0000i\u0000z\u0000a\u0000t\u0000i\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000P\u0000r\u0000o\u0000m\u0000p\u0000t\u0000O\u0000n\u0000S\u0000e\u0000c\u0000u\u0000r\u0000e\u0000D\u0000e\u0000s\u0000k\u0000t\u0000o\u0000p\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000S\u0000u\u0000p\u0000p\u0000o\u0000r\u0000t\u0000F\u0000u\u0000l\u0000l\u0000T\u0000r\u0000u\u0000s\u0000t\u0000S\u0000t\u0000a\u0000r\u0000t\u0000u\u0000p\u0000T\u0000a\u0000s\u0000k\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000S\u0000u\u0000p\u0000p\u0000o\u0000r\u0000t\u0000U\u0000w\u0000p\u0000S\u0000t\u0000a\u0000r\u0000t\u0000u\u0000p\u0000T\u0000a\u0000s\u0000k\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000V\u0000a\u0000l\u0000i\u0000d\u0000a\u0000t\u0000e\u0000A\u0000d\u0000m\u0000i\u0000n\u0000C\u0000o\u0000d\u0000e\u0000S\u0000i\u0000g\u0000n\u0000a\u0000t\u0000u\u0000r\u0000e\u0000s\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u0000\r\u0000\n\u0000\"\u0000d\u0000o\u0000n\u0000t\u0000d\u0000i\u0000s\u0000p\u0000l\u0000a\u0000y\u0000l\u0000a\u0000s\u0000t\u0000u\u0000s\u0000e\u0000r\u0000n\u0000a\u0000m\u0000e\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u0000\r\u0000\n\u0000\"\u0000l\u0000e\u0000g\u0000a\u0000l\u0000n\u0000o\u0000t\u0000i\u0000c\u0000e\u0000c\u0000a\u0000p\u0000t\u0000i\u0000o\u0000n\u0000\"\u0000=\u0000\"\u0000\"\u0000\r\u0000\n\u0000\"\u0000l\u0000e\u0000g\u0000a\u0000l\u0000n\u0000o\u0000t\u0000i\u0000c\u0000e\u0000t\u0000e\u0000x\u0000t\u0000\"\u0000=\u0000\"\u0000\"\u0000\r\u0000\n\u0000\"\u0000s\u0000c\u0000f\u0000o\u0000r\u0000c\u0000e\u0000o\u0000p\u0000t\u0000i\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u0000\r\u0000\n\u0000\"\u0000s\u0000h\u0000u\u0000t\u0000d\u0000o\u0000w\u0000n\u0000w\u0000i\u0000t\u0000h\u0000o\u0000u\u0000t\u0000l\u0000o\u0000g\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000u\u0000n\u0000d\u0000o\u0000c\u0000k\u0000w\u0000i\u0000t\u0000h\u0000o\u0000u\u0000t\u0000l\u0000o\u0000g\u0000o\u0000n\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\r\u0000\n\u0000[\u0000H\u0000K\u0000E\u0000Y\u0000_\u0000L\u0000O\u0000C\u0000A\u0000L\u0000_\u0000M\u0000A\u0000C\u0000H\u0000I\u0000N\u0000E\u0000\\\u0000S\u0000O\u0000F\u0000T\u0000W\u0000A\u0000R\u0000E\u0000\\\u0000M\u0000i\u0000c\u0000r\u0000o\u0000s\u0000o\u0000f\u0000t\u0000\\\u0000W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000\\\u0000C\u0000u\u0000r\u0000r\u0000e\u0000n\u0000t\u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000\\\u0000P\u0000o\u0000l\u0000i\u0000c\u0000i\u0000e\u0000s\u0000\\\u0000S\u0000y\u0000s\u0000t\u0000e\u0000m\u0000\\\u0000A\u0000u\u0000d\u0000i\u0000t\u0000]\u0000\r\u0000\n\u0000\r\u0000\n\u0000[\u0000H\u0000K\u0000E\u0000Y\u0000_\u0000L\u0000O\u0000C\u0000A\u0000L\u0000_\u0000M\u0000A\u0000C\u0000H\u0000I\u0000N\u0000E\u0000\\\u0000S\u0000O\u0000F\u0000T\u0000W\u0000A\u0000R\u0000E\u0000\\\u0000M\u0000i\u0000c\u0000r\u0000o\u0000s\u0000o\u0000f\u0000t\u0000\\\u0000W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000\\\u0000C\u0000u\u0000r\u0000r\u0000e\u0000n\u0000t\u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000\\\u0000P\u0000o\u0000l\u0000i\u0000c\u0000i\u0000e\u0000s\u0000\\\u0000S\u0000y\u0000s\u0000t\u0000e\u0000m\u0000\\\u0000U\u0000I\u0000P\u0000I\u0000]\u0000\r\u0000\n\u0000\r\u0000\n\u0000[\u0000H\u0000K\u0000E\u0000Y\u0000_\u0000L\u0000O\u0000C\u0000A\u0000L\u0000_\u0000M\u0000A\u0000C\u0000H\u0000I\u0000N\u0000E\u0000\\\u0000S\u0000O\u0000F\u0000T\u0000W\u0000A\u0000R\u0000E\u0000\\\u0000M\u0000i\u0000c\u0000r\u0000o\u0000s\u0000o\u0000f\u0000t\u0000\\\u0000W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000\\\u0000C\u0000u\u0000r\u0000r\u0000e\u0000n\u0000t\u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000\\\u0000P\u0000o\u0000l\u0000i\u0000c\u0000i\u0000e\u0000s\u0000\\\u0000S\u0000y\u0000s\u0000t\u0000e\u0000m\u0000\\\u0000U\u0000I\u0000P\u0000I\u0000\\\u0000C\u0000l\u0000i\u0000p\u0000b\u0000o\u0000a\u0000r\u0000d\u0000]\u0000\r\u0000\n\u0000\r\u0000\n\u0000[\u0000H\u0000K\u0000E\u0000Y\u0000_\u0000L\u0000O\u0000C\u0000A\u0000L\u0000_\u0000M\u0000A\u0000C\u0000H\u0000I\u0000N\u0000E\u0000\\\u0000S\u0000O\u0000F\u0000T\u0000W\u0000A\u0000R\u0000E\u0000\\\u0000M\u0000i\u0000c\u0000r\u0000o\u0000s\u0000o\u0000f\u0000t\u0000\\\u0000W\u0000i\u0000n\u0000d\u0000o\u0000w\u0000s\u0000\\\u0000C\u0000u\u0000r\u0000r\u0000e\u0000n\u0000t\u0000V\u0000e\u0000r\u0000s\u0000i\u0000o\u0000n\u0000\\\u0000P\u0000o\u0000l\u0000i\u0000c\u0000i\u0000e\u0000s\u0000\\\u0000S\u0000y\u0000s\u0000t\u0000e\u0000m\u0000\\\u0000U\u0000I\u0000P\u0000I\u0000\\\u0000C\u0000l\u0000i\u0000p\u0000b\u0000o\u0000a\u0000r\u0000d\u0000\\\u0000E\u0000x\u0000c\u0000e\u0000p\u0000t\u0000i\u0000o\u0000n\u0000F\u0000o\u0000r\u0000m\u0000a\u0000t\u0000s\u0000]\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000B\u0000I\u0000T\u0000M\u0000A\u0000P\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00002\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000D\u0000I\u0000B\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00008\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000D\u0000I\u0000B\u0000V\u00005\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u00001\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000O\u0000E\u0000M\u0000T\u0000E\u0000X\u0000T\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00007\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000P\u0000A\u0000L\u0000E\u0000T\u0000T\u0000E\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00009\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000T\u0000E\u0000X\u0000T\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u00001\u0000\r\u0000\n\u0000\"\u0000C\u0000F\u0000_\u0000U\u0000N\u0000I\u0000C\u0000O\u0000D\u0000E\u0000T\u0000E\u0000X\u0000T\u0000\"\u0000=\u0000d\u0000w\u0000o\u0000r\u0000d\u0000:\u00000\u00000\u00000\u00000\u00000\u00000\u00000\u0000d\u0000\r\u0000\n\u0000\r\u0000\n\u0000\n"

the file https://raw.githubusercontent.com/YoraiLevi/MyFuckingWikiOfEverything/DEV/etc/Ansible/playbooks/roles/windows-configurations/files/registry_edits/personal_settings/admin_uac_password.reg

Thanks, I can't figure it out...

like image 771
Yorai Levi Avatar asked Aug 31 '25 01:08

Yorai Levi


2 Answers

To my surprise, this was way harder than I thought. Below a quickNdirty solution that I would not run as is on production, which definitely needs hardening, error control, documentation...

As you will see, this required to go through a custom lookup plugin

Here is the layout for a plugin adjacent to the playbook:

$ tree
.
├── lookup_plugins
│   └── file_utf_16.py
└── viewutf16.yml

The /lookup_plugins/file_utf_16.py:

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.module_utils.common.text.converters import to_text, to_native


class LookupModule(LookupBase):

    def run(self, terms, variables=None, **kwargs):
        ret = []

        try:
            for path in terms:
                with open(path, 'rb') as byte_stream:
                    text = byte_stream.read()
                    ret.append(to_text(text.decode('UTF-16')))
        except Exception as e:
            raise AnsibleError(to_native(repr(e)))

        return ret

And the test viewutf16.yml playbook:

- hosts: localhost
  gather_facts: false

  tasks:
    - get_url:
        url: https://raw.githubusercontent.com/YoraiLevi/MyFuckingWikiOfEverything/DEV/etc/Ansible/playbooks/roles/windows-configurations/files/registry_edits/personal_settings/admin_uac_password.reg
        dest: .
      register: download

    - debug:
        msg: "{{ lookup('file_utf_16', download.dest).split('\n') }}"

Gives (note: I splitted on \n for reading convenience, the fight for leftover \r is yours):

$ ansible-playbook viewutf16.yml

PLAY [localhost] ************************************************************

TASK [get_url] **************************************************************
ok: [localhost]

TASK [debug] ****************************************************************
ok: [localhost] => {
    "msg": [
        "Windows Registry Editor Version 5.00\r",
        "\r",
        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System]\r",
        "\"ConsentPromptBehaviorAdmin\"=dword:00000001\r",
        "\"ConsentPromptBehaviorUser\"=dword:00000003\r",
        "\"DSCAutomationHostEnabled\"=dword:00000002\r",
        "\"EnableCursorSuppression\"=dword:00000001\r",
        "\"EnableFullTrustStartupTasks\"=dword:00000002\r",
        "\"EnableInstallerDetection\"=dword:00000001\r",
        "\"EnableLUA\"=dword:00000001\r",
        "\"EnableSecureUIAPaths\"=dword:00000001\r",
        "\"EnableUIADesktopToggle\"=dword:00000000\r",
        "\"EnableUwpStartupTasks\"=dword:00000002\r",
        "\"EnableVirtualization\"=dword:00000001\r",
        "\"PromptOnSecureDesktop\"=dword:00000001\r",
        "\"SupportFullTrustStartupTasks\"=dword:00000001\r",
        "\"SupportUwpStartupTasks\"=dword:00000001\r",
        "\"ValidateAdminCodeSignatures\"=dword:00000000\r",
        "\"dontdisplaylastusername\"=dword:00000000\r",
        "\"legalnoticecaption\"=\"\"\r",
        "\"legalnoticetext\"=\"\"\r",
        "\"scforceoption\"=dword:00000000\r",
        "\"shutdownwithoutlogon\"=dword:00000001\r",
        "\"undockwithoutlogon\"=dword:00000001\r",
        "\r",
        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\Audit]\r",
        "\r",
        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\UIPI]\r",
        "\r",
        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\UIPI\\Clipboard]\r",
        "\r",
        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\UIPI\\Clipboard\\ExceptionFormats]\r",
        "\"CF_BITMAP\"=dword:00000002\r",
        "\"CF_DIB\"=dword:00000008\r",
        "\"CF_DIBV5\"=dword:00000011\r",
        "\"CF_OEMTEXT\"=dword:00000007\r",
        "\"CF_PALETTE\"=dword:00000009\r",
        "\"CF_TEXT\"=dword:00000001\r",
        "\"CF_UNICODETEXT\"=dword:0000000d\r",
        "\r",
        ""
    ]
}

PLAY RECAP ******************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
like image 70
Zeitounator Avatar answered Sep 02 '25 15:09

Zeitounator


I know this isn't an exact answer for the OP's question, but I just wanted to add that if you're using slurp instead of a lookup, you can use the b64decode with the undocumented argument encoding to get the native UTF-8 encoded string for normal Ansible usage:

- name: "Slurp file"
  slurp:
    src: "file"
  register: file_contents_encoded

- debug:
    msg: "{{ file_contents_encoded.content | b64decode(encoding='utf-16-le') }}"
like image 45
DustWolf Avatar answered Sep 02 '25 15:09

DustWolf