Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

luks_device: unexpected behavior involving devices named "*crypt" #409

Closed
maxchaos opened this issue Feb 24, 2022 · 4 comments · Fixed by #410
Closed

luks_device: unexpected behavior involving devices named "*crypt" #409

maxchaos opened this issue Feb 24, 2022 · 4 comments · Fixed by #410

Comments

@maxchaos
Copy link

SUMMARY

I have several LVM2 devices encrypted with LUKS whose names end with "_crypt", i.e., the file of each device after activation is of the form /dev/VG/LV_crypt where VG and LV are placeholders for the name of the associated LVM2 volume group and the prefix of the logical volume's name, respectively. Trying to open any of these devices using the luks_device module fails differently depending on whether I set the parameter name or not.

Particularly, when running the task described in the minimal test-case below while explicitly specifying a name for new device fails
whereas running the same task without the parameter name appears to succeed but no device mapped to the encrypted volume is actually created.

Digging around in the implementation, this cause appears to be the current implementation of luks_device.CryptHandler.get_container_name_by_device and the regular expression LUKS_NAME_REGEX when combined with the fact that the output of executing `lsblk DEVFILE -nlo type,name' yields a result of the form

...
lvm VG-LV_crypt
...

for the setup described above.

Obviously, not prefixing the names of any block device with the word "crypt" is a valid workaround for my use case but given that this module deals with encrypted data, it may be worth fixing altogether.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

luks_device

ANSIBLE VERSION
ansible [core 2.12.2]
  config file = /home/max/Workspace/proj/4c4326b0-12a3/sw/ansible/ansible.cfg
  configured module search path = ['/home/max/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /gnu/store/wwbh2agzsja6isphqb2m9pym39vi6r8q-profile/lib/python3.9/site-packages/ansible
  ansible collection location = /home/max/.ansible/collections:/usr/share/ansible/collections
  executable location = /gnu/store/kdvif63isrrbsf0a43jq8l1602f350n8-ansible-core-2.12.2/bin/ansible
  python version = 3.9.9 (main, Jan  1 1970, 00:00:01) [GCC 10.3.0]
  jinja version = 3.0.1
  libyaml = True
COLLECTION VERSION
# /gnu/store/wwbh2agzsja6isphqb2m9pym39vi6r8q-profile/lib/python3.9/site-packages/ansible_collections
Collection       Version
---------------- -------
community.crypto 2.2.0  

# /home/max/.guix-profile/lib/python3.9/site-packages/ansible_collections
Collection       Version
---------------- -------
community.crypto 1.9.5
CONFIGURATION
DEFAULT_HOST_LIST(/home/max/Workspace/proj/4c4326b0-12a3/sw/ansible/ansible.cfg) = ['/home/max/Workspace/proj/4c4326b0-12a3/sw/ansible/inventory.yml']
OS / ENVIRONMENT

Host: Void Linux using Guix as package manager for installing ansible.
Remote: Arch Linux

STEPS TO REPRODUCE

Particularly, the following task

- name: Decrypt device
  community.crypto.luks_device:
    device: "/dev/VG/LV_crypt"
    state: opened
    type: luks2
    name: LV_opened
    passphrase: "{{ lvcrypt_pass }}"
EXPECTED RESULTS

Open "/dev/VG/LV_crypt" and create a device "/dev/mapper/LV_opened" mapped to the former.

ACTUAL RESULTS

Fails with error

FAILED! => {"changed": false, "msg": "LUKS container is already opened under different name ''."}
@felixfontein
Copy link
Contributor

I guess going through the output of lsblk line for line, and changing the regex to ^crypt\s+([^\s]*)\s*$, should produce a better result.

@felixfontein
Copy link
Contributor

The following code might work:

    def get_container_name_by_device(self, device):
        ''' obtain LUKS container name based on the device where it is located
            return None if not found
            raise ValueError if lsblk command fails
        '''
        result = self._run_command([self._lsblk_bin, device, '-nlo', 'type,name'])
        if result[RETURN_CODE] != 0:
            raise ValueError('Error while obtaining LUKS name for %s: %s'
                             % (device, result[STDERR]))

        r = re.compile(r'^crypt\s+([^\s]*)\s*$')
        for line in result[STDOUT].splitlines(False):
            m = r.match(line)
            if m:
                return m.group(1)
        return None

@maxchaos can you try that out?

@maxchaos
Copy link
Author

Yes, the above fix works for my case. Thanks a lot for looking at this so fast!

@felixfontein
Copy link
Contributor

Great to hear! I created a PR out of it: #410

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants