
    Vhk                     >   d dl mZmZmZ eZdZdZdZd dl	Z	d dl
Z
d dlZd dlmZ d dlmZ d dlmZmZ d Zd	Zd
Z e
j,                  d      Z e
j,                  d      ZdZdZg dZdZd Z G d de      Z G d de      Z  G d de      Z!d Z"d Z#e$dk(  r e#        yy)    )absolute_importdivisionprint_functiona"3  
module: luks_device

short_description: Manage encrypted (LUKS) devices

description:
  - Module manages L(LUKS,https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup) on given device. Supports creating, destroying,
    opening and closing of LUKS container and adding or removing new keys and passphrases.
extends_documentation_fragment:
  - community.crypto.attributes

attributes:
  check_mode:
    support: full
  diff_mode:
    support: none
  idempotent:
    support: full

options:
  device:
    description:
      - Device to work with (for example V(/dev/sda1)). Needed in most cases. Can be omitted only when O(state=closed) together
        with O(name) is provided.
    type: str
  state:
    description:
      - Desired state of the LUKS container. Based on its value creates, destroys, opens or closes the LUKS container on a
        given device.
      - V(present) will create LUKS container unless already present. Requires O(device) and either O(keyfile) or O(passphrase)
        options to be provided.
      - V(absent) will remove existing LUKS container if it exists. Requires O(device) or O(name) to be specified.
      - V(opened) will unlock the LUKS container. If it does not exist it will be created first. Requires O(device) and either
        O(keyfile) or O(passphrase) to be specified. Use the O(name) option to set the name of the opened container. Otherwise
        the name will be generated automatically and returned as a part of the result.
      - V(closed) will lock the LUKS container. However if the container does not exist it will be created. Requires O(device)
        and either O(keyfile) or O(passphrase) options to be provided. If container does already exist O(device) or O(name)
        will suffice.
    type: str
    default: present
    choices: [present, absent, opened, closed]
  name:
    description:
      - Sets container name when O(state=opened). Can be used instead of O(device) when closing the existing container (that
        is, when O(state=closed)).
    type: str
  keyfile:
    description:
      - Used to unlock the container. Either a O(keyfile) or a O(passphrase) is needed for most of the operations. Parameter
        value is the path to the keyfile with the passphrase.
      - BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.
    type: path
  passphrase:
    description:
      - Used to unlock the container. Either a O(passphrase) or a O(keyfile) is needed for most of the operations. Parameter
        value is a string with the passphrase.
      - B(Note) that the passphrase must be UTF-8 encoded text. If you want to use arbitrary binary data, or text using
        another encoding, use the O(passphrase_encoding) option and provide the passphrase Base64 encoded.
    type: str
    version_added: '1.0.0'
  passphrase_encoding:
    description:
      - Determine how passphrases are provided to parameters such as O(passphrase), O(new_passphrase), and O(remove_passphrase).
    type: str
    default: text
    choices:
      text:
        - The passphrase is provided as UTF-8 encoded text.
      base64:
        - The passphrase is provided as Base64 encoded bytes.
        - Use the P(ansible.builtin.b64encode#filter) filter to Base64-encode binary data.
    version_added: 2.23.0
  keyslot:
    description:
      - Adds the O(keyfile) or O(passphrase) to a specific keyslot when creating a new container on O(device). Parameter value
        is the number of the keyslot.
      - B(Note) that a device of O(type=luks1) supports the keyslot numbers V(0)-V(7) and a device of O(type=luks2) supports
        the keyslot numbers V(0)-V(31). In order to use the keyslots V(8)-V(31) when creating a new container, setting O(type)
        to V(luks2) is required.
    type: int
    version_added: '2.16.0'
  keysize:
    description:
      - Sets the key size only if LUKS container does not exist.
    type: int
    version_added: '1.0.0'
  new_keyfile:
    description:
      - Adds additional key to given container on O(device). Needs O(keyfile) or O(passphrase) option for authorization. LUKS
        container supports up to 8 keyslots. Parameter value is the path to the keyfile with the passphrase.
      - NOTE that adding additional keys is idempotent only since community.crypto 1.4.0. For older versions, a new keyslot
        will be used even if another keyslot already exists for this keyfile.
      - BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.
    type: path
  new_passphrase:
    description:
      - Adds additional passphrase to given container on O(device). Needs O(keyfile) or O(passphrase) option for authorization.
        LUKS container supports up to 8 keyslots. Parameter value is a string with the new passphrase.
      - NOTE that adding additional passphrase is idempotent only since community.crypto 1.4.0. For older versions, a new
        keyslot will be used even if another keyslot already exists for this passphrase.
      - B(Note) that the passphrase must be UTF-8 encoded text. If you want to use arbitrary binary data, or text using
        another encoding, use the O(passphrase_encoding) option and provide the passphrase Base64 encoded.
    type: str
    version_added: '1.0.0'
  new_keyslot:
    description:
      - Adds the additional O(new_keyfile) or O(new_passphrase) to a specific keyslot on the given O(device). Parameter value
        is the number of the keyslot.
      - B(Note) that a device of O(type=luks1) supports the keyslot numbers V(0)-V(7) and a device of O(type=luks2) supports
        the keyslot numbers V(0)-V(31).
    type: int
    version_added: '2.16.0'
  remove_keyfile:
    description:
      - Removes given key from the container on O(device). Does not remove the keyfile from filesystem. Parameter value is
        the path to the keyfile with the passphrase.
      - NOTE that removing keys is idempotent only since community.crypto 1.4.0. For older versions, trying to remove a key
        which no longer exists results in an error.
      - NOTE that to remove the last key from a LUKS container, the O(force_remove_last_key) option must be set to V(true).
      - BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.
    type: path
  remove_passphrase:
    description:
      - Removes given passphrase from the container on O(device). Parameter value is a string with the passphrase to remove.
      - NOTE that removing passphrases is idempotent only since community.crypto 1.4.0. For older versions, trying to remove
        a passphrase which no longer exists results in an error.
      - NOTE that to remove the last keyslot from a LUKS container, the O(force_remove_last_key) option must be set to V(true).
      - B(Note) that the passphrase must be UTF-8 encoded text. If you want to use arbitrary binary data, or text using
        another encoding, use the O(passphrase_encoding) option and provide the passphrase Base64 encoded.
    type: str
    version_added: '1.0.0'
  remove_keyslot:
    description:
      - Removes the key in the given slot on O(device). Needs O(keyfile) or O(passphrase) for authorization.
      - B(Note) that a device of O(type=luks1) supports the keyslot numbers V(0)-V(7) and a device of O(type=luks2) supports
        the keyslot numbers V(0)-V(31).
      - B(Note) that the given O(keyfile) or O(passphrase) must not be in the slot to be removed.
    type: int
    version_added: '2.16.0'
  force_remove_last_key:
    description:
      - If set to V(true), allows removing the last key from a container.
      - BEWARE that when the last key has been removed from a container, the container can no longer be opened!
    type: bool
    default: false
  label:
    description:
      - This option allow the user to create a LUKS2 format container with label support, respectively to identify the container
        by label on later usages.
      - Will only be used on container creation, or when O(device) is not specified.
      - This cannot be specified if O(type) is set to V(luks1).
    type: str
    version_added: '1.0.0'
  uuid:
    description:
      - With this option user can identify the LUKS container by UUID.
      - Will only be used when O(device) and O(label) are not specified.
    type: str
    version_added: '1.0.0'
  type:
    description:
      - This option allow the user explicit define the format of LUKS container that wants to work with. Options are V(luks1)
        or V(luks2).
    type: str
    choices: [luks1, luks2]
    version_added: '1.0.0'
  cipher:
    description:
      - This option allows the user to define the cipher specification string for the LUKS container.
      - Will only be used on container creation.
      - For pre-2.6.10 kernels, use V(aes-plain) as they do not understand the new cipher spec strings. To use ESSIV, use
        V(aes-cbc-essiv:sha256).
    type: str
    version_added: '1.1.0'
  hash:
    description:
      - This option allows the user to specify the hash function used in LUKS key setup scheme and volume key digest.
      - Will only be used on container creation.
    type: str
    version_added: '1.1.0'
  pbkdf:
    description:
      - This option allows the user to configure the Password-Based Key Derivation Function (PBKDF) used.
      - Will only be used on container creation, and when adding keys to an existing container.
    type: dict
    version_added: '1.4.0'
    suboptions:
      iteration_time:
        description:
          - Specify the iteration time used for the PBKDF.
          - Note that this is in B(seconds), not in milliseconds as on the command line.
          - Mutually exclusive with O(pbkdf.iteration_count).
        type: float
      iteration_count:
        description:
          - Specify the iteration count used for the PBKDF.
          - Mutually exclusive with O(pbkdf.iteration_time).
        type: int
      algorithm:
        description:
          - The algorithm to use.
          - Only available for the LUKS 2 format.
        choices:
          - argon2i
          - argon2id
          - pbkdf2
        type: str
      memory:
        description:
          - The memory cost limit in kilobytes for the PBKDF.
          - This is not used for PBKDF2, but only for the Argon PBKDFs.
        type: int
      parallel:
        description:
          - The parallel cost for the PBKDF. This is the number of threads that run in parallel.
          - This is not used for PBKDF2, but only for the Argon PBKDFs.
        type: int
  sector_size:
    description:
      - This option allows the user to specify the sector size (in bytes) used for LUKS2 containers.
      - Will only be used on container creation.
    type: int
    version_added: '1.5.0'
  perf_same_cpu_crypt:
    description:
      - Allows the user to perform encryption using the same CPU that IO was submitted on.
      - The default is to use an unbound workqueue so that encryption work is automatically balanced between available CPUs.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.3.0'
  perf_submit_from_crypt_cpus:
    description:
      - Allows the user to disable offloading writes to a separate thread after encryption.
      - There are some situations where offloading block write IO operations from the encryption threads to a single thread
        degrades performance significantly.
      - The default is to offload block write IO operations to the same thread.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.3.0'
  perf_no_read_workqueue:
    description:
      - Allows the user to bypass dm-crypt internal workqueue and process read requests synchronously.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.3.0'
  perf_no_write_workqueue:
    description:
      - Allows the user to bypass dm-crypt internal workqueue and process write requests synchronously.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.3.0'
  persistent:
    description:
      - Allows the user to store options into container's metadata persistently and automatically use them next time. Only
        O(perf_same_cpu_crypt), O(perf_submit_from_crypt_cpus), O(perf_no_read_workqueue), O(perf_no_write_workqueue), and
        O(allow_discards) can be stored persistently.
      - Will only work with LUKS2 containers.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.3.0'
  allow_discards:
    description:
      - Allow discards (also known as TRIM) requests for device.
      - Will only be used when opening containers.
    type: bool
    default: false
    version_added: '2.17.0'

requirements:
  - "cryptsetup"
  - "wipefs (when O(state) is V(absent))"
  - "lsblk"
  - "blkid (when O(label) or O(uuid) options are used)"

author: Jan Pokorny (@japokorn)
a  
---
- name: Create LUKS container (remains unchanged if it already exists)
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    keyfile: "/vault/keyfile"

- name: Create LUKS container with a passphrase
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    passphrase: "foo"

- name: Create LUKS container with specific encryption
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    cipher: "aes"
    hash: "sha256"

- name: (Create and) open the LUKS container; name it "mycrypt"
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "opened"
    name: "mycrypt"
    keyfile: "/vault/keyfile"

- name: Close the existing LUKS container "mycrypt"
  community.crypto.luks_device:
    state: "closed"
    name: "mycrypt"

- name: Make sure LUKS container exists and is closed
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "closed"
    keyfile: "/vault/keyfile"

- name: Create container if it does not exist and add new key to it
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    keyfile: "/vault/keyfile"
    new_keyfile: "/vault/keyfile2"

- name: Add new key to the LUKS container (container has to exist)
  community.crypto.luks_device:
    device: "/dev/loop0"
    keyfile: "/vault/keyfile"
    new_keyfile: "/vault/keyfile2"

- name: Add new passphrase to the LUKS container
  community.crypto.luks_device:
    device: "/dev/loop0"
    keyfile: "/vault/keyfile"
    new_passphrase: "foo"

- name: Remove existing keyfile from the LUKS container
  community.crypto.luks_device:
    device: "/dev/loop0"
    remove_keyfile: "/vault/keyfile2"

- name: Remove existing passphrase from the LUKS container
  community.crypto.luks_device:
    device: "/dev/loop0"
    remove_passphrase: "foo"

- name: Completely remove the LUKS container and its contents
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "absent"

- name: Create a container with label
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    keyfile: "/vault/keyfile"
    label: personalLabelName

- name: Open the LUKS container based on label without device; name it "mycrypt"
  community.crypto.luks_device:
    label: "personalLabelName"
    state: "opened"
    name: "mycrypt"
    keyfile: "/vault/keyfile"

- name: Close container based on UUID
  community.crypto.luks_device:
    uuid: 03ecd578-fad4-4e6c-9348-842e3e8fa340
    state: "closed"
    name: "mycrypt"

- name: Create a container using luks2 format
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    keyfile: "/vault/keyfile"
    type: luks2

- name: Create a container with key in slot 4
  community.crypto.luks_device:
    device: "/dev/loop0"
    state: "present"
    keyfile: "/vault/keyfile"
    keyslot: 4

- name: Add a new key in slot 5
  community.crypto.luks_device:
    device: "/dev/loop0"
    keyfile: "/vault/keyfile"
    new_keyfile: "/vault/keyfile"
    new_keyslot: 5

- name: Remove the key from slot 4 (given keyfile must not be slot 4)
  community.crypto.luks_device:
    device: "/dev/loop0"
    keyfile: "/vault/keyfile"
    remove_keyslot: 4
z
name:
  description: When O(state=opened) returns (generated or given) name of LUKS container. Returns None if no name is supplied.
  returned: success
  type: str
  sample: "luks-c1da9a58-2fde-4256-9d9f-6ab008b4dd1b"
N)	b64decode)AnsibleModule)to_bytes	to_native      z^crypt\s+([^\s]*)\s*$z\s*device:\s+([^\s]*)\s*s   LUKS   )	i @  i   i   i   i   i   i   i    i  @ s   SKULc                    g }t        | d      5 }|j                  t              }|t        k(  r|j	                  d       t
        D ]C  }|j                  |       |j                  t              }|t        k(  s3|j	                  |       E 	 d d d        |r@t        | d      5 }|D ]$  }|j                  |       |j                  d       & 	 d d d        y y # 1 sw Y   LxY w# 1 sw Y   y xY w)Nrbr   wbs         )	openreadLUKS_HEADER_LLUKS_HEADERappendLUKS2_HEADER_OFFSETSseekLUKS2_HEADER2write)devicewipe_offsetsfdataoffsets        p/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/crypto/plugins/modules/luks_device.pywipe_luks_headersr     s    L	fd	 	,qvvm$;"* 	,FFF6N66-(D}$##F+		,	, &$ 	51& 5v345	5 	5 	, 	,	5 	5s   A(C8C"*C#C #C,c                   2    e Zd Zd Zd ZddZd Zd Zd Zy)	Handlerc                 |    || _         | j                   j                  dd      | _        |j                  d   | _        y )NlsblkTpassphrase_encoding)_moduleget_bin_path
_lsblk_binparams_passphrase_encoding)selfmodules     r   __init__zHandler.__init__  s3    ,,33GTB$*MM2G$H!    c                    | j                   j                  |   }|y | j                  dk(  rt        |      S 	 t	        t        |            S # t        $ r6}| j                   j                  dj                  ||             Y d }~y d }~ww xY w)Ntextz5Error while base64-decoding '{parameter_name}': {exc})parameter_nameexc)	r%   r(   r)   r   r   r	   	Exception	fail_jsonformat)r*   r0   
passphraser1   s       r   !get_passphrase_from_module_paramsz)Handler.get_passphrase_from_module_params  s    \\((8
$$.J''	Yz233 	LL""GNN#1s O  	s   A 	B,BBNc                 >    | j                   j                  ||d      S )NT)r   binary_data)r%   run_command)r*   commandr   s      r   _run_commandzHandler._run_command  s    ||''d'MMr-   c                     | j                   j                  dd      | _        | j                   j                  d   }|y| j	                  | j                  d|g      }|t
           dk7  ry|t           j                         S )z1Returns the device that holds UUID passed by userblkidTuuidNz--uuidr   r%   r&   
_blkid_binr(   r;   RETURN_CODESTDOUTstrip)r*   r>   results      r   get_device_by_uuidzHandler.get_device_by_uuid  st    ,,33GTB||""6*<""DOOXt#DE+!#f~##%%r-   c                     | j                   j                  dd      | _        | j                   j                  d   }|y| j	                  | j                  d|g      }|t
           dk7  ry|t           j                         S )z2Returns the device that holds label passed by userr=   TlabelN--labelr   r?   )r*   rG   rD   s      r   get_device_by_labelzHandler.get_device_by_label  st    ,,33GTB##G,=""DOOY#FG+!#f~##%%r-   c                     | j                  | j                  d|ddg      }|t           dk7  rt        d|d|t                 |t
           j                         }d|z  S )z}Generate name for luks based on device UUID ('luks-<UUID>').
        Raises ValueError when obtaining of UUID fails.
        z-nz-oUUIDr   z%Error while generating LUKS name for : zluks-%s)r;   r'   rA   
ValueErrorSTDERRrB   rC   )r*   r   rD   dev_uuids       r   generate_luks_namezHandler.generate_luks_name  si     ""DOOT64#PQ+!#AGPVX  &>'')8##r-   N)	__name__
__module____qualname__r,   r6   r;   rE   rI   rP    r-   r   r!   r!     s"    I
N	&	&$r-   r!   c                   r     e Zd Z fdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Z	 ddZddZ xZS )CryptHandlerc                 n    t         t        |   |       | j                  j	                  dd      | _        y )N
cryptsetupT)superrW   r,   r%   r&   _cryptsetup_bin)r*   r+   	__class__s     r   r,   zCryptHandler.__init__!  s+    lD*62#||88tLr-   c                    | j                  | j                  |ddg      }|t           dk7  rt        d|d|t                 |t
           j                  d      D ],  }t        j                  |      }|s|j                  d      c S  y)	zobtain LUKS container name based on the device where it is located
        return None if not found
        raise ValueError if lsblk command fails
        z-nloz	type,namer   z$Error while obtaining LUKS name for rL   Fr
   N)
r;   r'   rA   rM   rN   rB   
splitlinesLUKS_NAME_REGEXmatchgroup)r*   r   rD   linems        r   get_container_name_by_devicez)CryptHandler.get_container_name_by_device%  s    
 ""DOOVV[#QR+!#@FvW  6N--e4 	"D%%d+Awwqz!	" r-   c                     | j                  | j                  d|g      }|t           dk7  ryt        j	                  |t
                 }|j                  d      }|S )zobtain device name based on the LUKS container name
        return None if not found
        raise ValueError if lsblk command fails
        statusr   Nr
   )r;   r[   rA   LUKS_DEVICE_REGEXsearchrB   ra   )r*   namerD   rc   r   s        r   get_container_device_by_namez)CryptHandler.get_container_device_by_name6  sW     ""D$8$8(D#IJ+!#$$VF^4r-   c                 V    | j                  | j                  d|g      }|t           dk(  S )z&check if the LUKS container does existisLuksr   )r;   r[   rA   )r*   r   rD   s      r   is_lukszCryptHandler.is_luksD  s/    ""D$8$8(F#KLk"a''r-   c                     | j                  |      r[t        |d      5 }t        D ];  }|j                  |       |j	                  t
              }|t        k(  s3 ddd       y 	 ddd       yy# 1 sw Y   yxY w)zget the luks type of a devicer   Nluks2luks1)rm   r   r   r   r   r   r   )r*   r   r   r   r   s        r   get_luks_typezCryptHandler.get_luks_typeI  s{    <<fd# q2 'FFF6N66-0D},& '
    s   9A.A."A..A7c                     | j                  | j                  d|g      }|t           dk7  rt        d|      d|z  |t           v }d|z  |t           v }|xs |S )zcheck if a keyslot is setluksDumpr   %Error while dumping LUKS header from zKey Slot %d: ENABLEDz
 %d: luks2)r;   r[   rA   rM   rB   )r*   r   keyslotrD   result_luks1result_luks2s         r   is_luks_slot_setzCryptHandler.is_luks_slot_setU  sk    ""D$8$8*f#MN+!#&RSS-9VF^K#w/6&>A+|+r-   c           	      t   |d   +|j                  dt        t        |d   dz              g       |d   |j                  dt        |d         g       |d   |j                  d|d   g       |d   |j                  d	t        |d         g       |d
    |j                  dt        |d
         g       y y )Niteration_timez--iter-timei  iteration_countz--pbkdf-force-iterations	algorithmz--pbkdfmemoryz--pbkdf-memoryparallelz--pbkdf-parallel)extendstrint)r*   optionspbkdfs      r   _add_pbkdf_optionszCryptHandler._add_pbkdf_options^  s    !".NNM3s59I3JT3Q/R+STU"#/NN6EBS<T8UVW)NNIu['9:;?&NN,c%/.BCD(NN.E*4E0FGH )r-   c
                    | j                   j                  d   }
| j                   j                  d   }g }||j                  dt        |      z          ||j	                  d|g       d}
|
|j	                  d|
g       ||j	                  d|g       ||j	                  d|g       |	| j                  ||	       ||j	                  d	t        |      g       ||j	                  d
t        |      g       | j                  dg}|j	                  |       |j	                  d|g       |r|j                  |       n|j                  d       | j                  ||      }|t           dk7  rt        d|d|t                 y )NtyperG   z--key-size=rH   ro   --typez--cipherz--hashz--sector-size
--key-slot
luksFormat-q-r   r   zError while creating LUKS on rL   )r%   r(   r   r   r   r   r[   r;   rA   rM   rN   )r*   r   keyfiler5   ru   keysizecipherhash_sector_sizer   	luks_typerG   r   argsrD   s                  r   run_luks_createzCryptHandler.run_luks_createj  s    LL''/	##G,NN=3w<78NNIu-.I NNHi01NNJ/0NNHe,-##GU3"NNOS-=>?NNL#g,78$$l3GT6N#KK KK""4j"9+!#9?P  $r-   c                    | j                   g}|r|j                  d|g       n|j                  ddg       |r|j                  dg       |r|j                  dg       |r|j                  dg       |r|j                  dg       |r|j                  dg       |	r|j                  dg       |j                  d	d
d||
g       | j                  ||      }|t           dk7  rt	        d|d|t
                 y )N
--key-filer   z--perf-same_cpu_cryptz--perf-submit_from_crypt_cpusz--perf-no_read_workqueuez--perf-no_write_workqueuez--persistentz--allow-discardsr   r   luksr   r   z&Error while opening LUKS container on rL   )r[   r   r;   rA   rM   rN   )r*   r   r   r5   perf_same_cpu_cryptperf_submit_from_crypt_cpusperf_no_read_workqueueperf_no_write_workqueue
persistentallow_discardsri   r   rD   s                r   run_luks_openzCryptHandler.run_luks_open  s    $$%KKw/0KKs+,KK012&KK89:!KK345"KK456KK()KK+,-VXvvt<=""4j"9+!#6&>+  $r-   c                 t    | j                  | j                  d|g      }|t           dk7  rt        d|z        y )Ncloser   z%Error while closing LUKS container %s)r;   r[   rA   rM   )r*   ri   rD   s      r   run_luks_closezCryptHandler.run_luks_close  sB    ""D$8$8'4#HI+!#DMNN $r-   c                 P   | j                   j                  dd      }| j                  |      }|| j                  |       | j	                  |d|g      }|t
           dk7  rt        d|d|t                 	 t        |       y # t        $ r}t        d|d|      d }~ww xY w)NwipefsTz--allr   z1Error while wiping LUKS container signatures for rL   )
r%   r&   rd   r   r;   rA   rM   rN   r   r2   )r*   r   
wipefs_binri   rD   r1   s         r   run_luks_removezCryptHandler.run_luks_remove  s    \\..x>
008%""J#@A+!#6&>+ 	f% 	3  	s   :B 	B%B  B%c           
      &   g }| j                   d|g}	|| j                  |	|       ||	j                  dt        |      g       |r|	j                  d|g       n8|	j                  dddt        t	        |            g       |j                  |       |r|	j                  |       n"|	j                  d       |j                  |       | j                  |	dj                  |      xs d      }
|
t           d	k7  rt        d
|d|
t                 y)zAdd new key from a keyfile or passphrase to given 'device';
        authentication done using 'keyfile' or 'passphrase'.
        Raises ValueError when command fails.
        
luksAddKeyNr   r   r   z--keyfile-sizer-   r   r   z'Error while adding new LUKS keyslot to rL   )r[   r   r   r   lenr   r;   joinrA   rM   rN   )r*   r   r   r5   new_keyfilenew_passphrasenew_keyslotr   r   r   rD   s              r   run_luks_add_keyzCryptHandler.run_luks_add_key  s    $$lF;##D%0"KKs;'789KKw/0KKs,<c#j/>RSTKK
#KK$KKKK'""4chhtn.D"E+!#6&>+  $r-   c                    |s| j                  | j                  d|g      }|t           dk7  rt        d|      d}d}t	        j
                  d      }	|t           j                         D ]c  }
|
j                  d      rd}|
j                  d      r|s+|
d	   d
v s3|dz  }9|
j                  d      rK|	j                  |
      r|dz  }bd}e |d	k  r| j                  j                  d|z         |<| j                  d|dg}|r|j                  d|g       n2|0|j                  ddg       n| j                  d|dt        |      g}d}| j                  ||      }|t           dk7  rt        d|d|t                 y)zRRemove key from given device
        Raises ValueError when command fails
        rs   r   rt   Fz^Key Slot [0-9]+: ENABLEDz	Keyslots:Tz  r   
0123456789r
   	z{LUKS device %s has less than two active keyslots. To be able to remove a key, please set `force_remove_last_key` to `true`.msgNluksRemoveKeyr   r   r   luksKillSlotr   z#Error while removing LUKS key from rL   )r;   r[   rA   rM   recompilerB   r^   
startswithr`   r%   r3   r   r   rN   )r*   r   r   r5   ru   force_remove_last_keyrD   keyslot_countkeyslot_area
keyslot_rerb   r   s               r   run_luks_remove_keyz CryptHandler.run_luks_remove_key  s    %&&(<(<j&'QRFk"a' f!VWWM L$@AJv113 )??;/#'L__T* $Q<(?%*__T*%%d+ "Q&M#(L!)" q &&9;AB '  ?((/64HD\734'\3/0 ((.&$GUDJ""4j"9+!#?Evf~V  $r-   c                    d}| j                   dd|g}|r|j                  d|g       n|j                  ddg       |}||j                  dt        |      g       | j                  ||      }|t           dk(  ry	t
        t        fD ]  }d
||   v r yd||   v s y |t           dk(  r||t
           dk(  r|t           dk(  ryt        d|d|t                 )zeCheck whether the keyfile or passphrase works.
        Raises ValueError when command fails.
        NluksOpenz--test-passphraser   r   r   r   r   Tz%No key available with this passphraseFzNo usable keyslot is available.r
    z.Error while testing whether keyslot exists on rL   )r[   r   r   r;   rA   rB   rN   rM   )	r*   r   r   r5   ru   r   r   rD   outputs	            r   luks_test_keyzCryptHandler.luks_test_key=  s    $$j2EvNKKw/0KKs+,DKKs7|45""4d"3+!#v& 	F6&.H0F6NB		 ;1$#v"$v"$vf~'
 	
r-   )FrQ   )rR   rS   rT   r,   rd   rj   rm   rq   rx   r   r   r   r   r   r   r   r   __classcell__r\   s   @r   rW   rW     sW    M"(

,
I/b%NO
0'T KP3j&
r-   rW   c                   T     e Zd Z fdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Z xZS )ConditionsHandlerc                 d    t         t        |   |       || _        | j	                         | _        y rQ   )rZ   r   r,   _crypthandlerget_device_namer   )r*   r+   crypthandlerr\   s      r   r,   zConditionsHandler.__init__h  s+    /7)**,r-   c                    | j                   j                  j                  d      }| j                   j                  j                  d      }| j                   j                  j                  d      }| j                   j                  j                  d      }||| j                  |      }|S ||| j	                  |      }|S ||| j
                  j                  |      }|S )Nr   rG   r>   ri   )r%   r(   getrI   rE   r   rj   )r*   r   rG   r>   ri   s        r   r   z!ConditionsHandler.get_device_namem  s    $$((2##''0||""&&v.||""&&v.>e/--e4F  ^ 0,,T2F  ^ 0''DDTJFr-   c                    | j                   d uxr} | j                  j                  d   d uxs | j                  j                  d   d uxrC | j                  j                  d   dv xr& | j                  j	                  | j                          S )Nr   r5   state)presentopenedclosedr   r%   r(   r   rm   r*   s    r   luks_createzConditionsHandler.luks_create|  s    KKt# <##I.d: A<<&&|4D@<
 ##G,0OO< &&..t{{;;	
r-   c                 <   | j                   j                  d   dk7  ry| j                  j                  | j                        }|y| j                   j                  d   |S || j                   j                  d   k7  r| j                   j                  d|z         |S )zIf luks is already opened, return its name.
        If 'name' parameter is specified and differs
        from obtained value, fail.
        Return None otherwise
        r   r   Nri   z;LUKS container is already opened under different name '%s'.r   )r%   r(   r   rd   r   r3   r*   ri   s     r   opened_luks_namez"ConditionsHandler.opened_luks_name  s     <<w'83 !!>>t{{K<<<v&.K4<<&&v.. LL""-/34 #  r-   c                     | j                   j                  d   | j                   j                  d   (| j                  | j                   j                  d   dk7  ry| j                         }|yy)Nr   r5   r   r   FT)r%   r(   r   r   r   s     r   	luks_openzConditionsHandler.luks_open  sm     ##I.6LL''5={{"||""7+x7 $$&<r-   c                    | j                   j                  d   | j                  | j                   j                  d   dk7  ry| j                  )| j                  j	                  | j                        }|d u}| j                   j                  d   E| j                  j                  | j                   j                  d         | _        | j                  d u}S )Nri   r   r   F)r%   r(   r   r   rd   rj   )r*   ri   luks_is_opens      r   
luks_closezConditionsHandler.luks_close  s    LL'/DKK4G\\  )X5;;"%%BB4;;ODt+L<<v&2,,II##F+DK  ;;d2Lr-   c                 0   | j                   d| j                  j                  d   | j                  j                  d   2| j                  j                  d   | j                  j                  d   y| j                  j                  d   dk(  r| j                  j                  d	       | j                  j                  | j                   | j                  j                  d   | j                  d            }| j                  j                  d
   | j                  j                  | j                   | j                  j                  d   | j                  d      | j                  j                  d
         }|r|s| j                  j                  d	       | S )Nr   r5   r   r   Fr   absentz;Contradiction in setup: Asking to add a key to absent LUKS.r   r   z9Trying to add key that is already present in another slot)r   r%   r(   r3   r   r   r6   )r*   key_presentkey_present_slots      r   luks_add_keyzConditionsHandler.luks_add_key  sm   KK##I.6LL''5= ##M2:LL''(89A <<w'83LL""T #  ((66KKLL.223CD

 <<}-9#11??##M2667GH##M2	  #3&&S '  r-   c                    | j                   K| j                  j                  d   3| j                  j                  d   | j                  j                  d   y| j                  j                  d   dk(  r| j                  j                  d       | j                  j                  d   | j                  j                  | j                   | j                  j                  d         sy| j                  j                  | j                   | j                  j                  d	   | j                  d
            }| j                  j                  | j                   | j                  j                  d	   | j                  d
      | j                  j                  d         r| j                  j                  d       |S | j                  j                  | j                   | j                  j                  d   | j                  d            S )Nremove_keyfileremove_passphraseremove_keyslotFr   r   z@Contradiction in setup: Asking to remove a key from absent LUKS.r   r   r5   z>Cannot remove keyslot with keyfile or passphrase in same slot.)r   r%   r(   r3   r   rx   r   r6   )r*   rD   s     r   luks_remove_keyz!ConditionsHandler.luks_remove_key  s   ;;LL 019##$78@##$45= <<w'83LL""1 # 
 <</0<%%66T\\001AB ''55##I.66|DF
 !!//##I.66|D##$45	 &&X '  M!!//KKLL 01223FG
 	
r-   c                     | j                   d uxrC | j                  j                  d   dk(  xr% | j                  j	                  | j                         S )Nr   r   r   r   s    r   luks_removezConditionsHandler.luks_remove  sL    KKt# 8##G,88""**4;;7	
r-   c                    | j                   j                  |   K||dk(  rd| j                   j                  |   cxk  rdk  r n n| j                   j                  d       n@d| j                   j                  |   cxk  rdk  sn | j                   j                  d       |d	k(  r[d| j                   j                  |   cxk  rdk  s9n | j                   j                  d
| j                   j                  |   z         y |dk(  r\d| j                   j                  |   cxk  rdk  s9n | j                   j                  d| j                   j                  |   z         y y y y )Nru         zQYou must specify type=luks2 when creating a new LUKS device to use keyslots 8-31.r   r      z>When not specifying a type, only the keyslots 0-7 are allowed.rp   z,%s must be between 0 and 7 when using LUKS1.ro   z-%s must be between 0 and 31 when using LUKS2.)r%   r(   r3   )r*   paramr   s      r   validate_keyslotz"ConditionsHandler.validate_keyslot%  sM   <<u%1 Ui%7++E28b8LL**o +  t||2259>Q>LL**\ +  G#A1D1DU1K,Pq,P&&Fll))%01 '  g%a4<<3F3Fu3M.SQS.S&&Gll))%01 '  /T%! 2r-   )rR   rS   rT   r,   r   r   r   r   r   r   r   r   r   r   r   s   @r   r   r   f  s7    -
	
>$*%N(
T
r-   r   c                     t        dCi dt        ddg d      dt        d      dt        d      d	t        d
      dt        d
      dt        d
      dt        dd      dt        dd      dt        dd      dt        ddddgd      dt        dd      dt        dd      dt        dd      dt        dd      dt        d      dt        d      d t        d      d!t        dd"d#g$      d%t        d      d&t        d      d't        d(t        t        d)      t        d      t        dg d*$      t        d      t        d      +      d,g-      d.t        d      d/t        dd      d0t        dd      d1t        dd      d2t        dd      d3t        dd      d4t        dd      } g d5}t        dd 6      }t        | d|7      }t        d8d8d8d89      |_        |j                  d   	 t	        j
                  |j                  d         }|j                  }t        j                  |      s<t        j                  |      s't        d:j                  |j                  d               t        |      }t        ||      }|j                  d   $|j                  d!   d"k(  r|j                  d<;       |j                  d   |j                  d   |j                  d   X|j                  |j!                               }	|	|j                  d!   |j                  d!   }	d=D ]  }
|j#                  |
|	        d>D ]D  }
|j                  |
   |j                  d	   #|j                  d   3|j                  d?;       F |j%                         r|j&                  s	 |j)                  |j*                  |j                  d	   |j-                  d      |j                  d   |j                  d   |j                  d%   |j                  d&   |j                  d.   |j                  d'   	       d|dA<   |j&                  r |j0                  dCi | |j3                         }|||d<   |j5                         r|j                  d   }|	 |j7                  |j*                        }|j&                  s	 |j9                  |j*                  |j                  d	   |j-                  d      |j                  d/   |j                  d0   |j                  d1   |j                  d2   |j                  d3   |j                  d4   |
       ||d<   d|dA<   |j&                  r |j0                  dCi | |j;                         r~|j*                  	 |j=                  |j*                        }n|j                  d   }|j&                  s	 |j?                  |       ||d<   d|dA<   |j&                  r |j0                  dCi | |jA                         r|j&                  st	 |jC                  |j*                  |j                  d	   |j-                  d      |j                  d   |j-                  d      |j                  d   |j                  d'          d|dA<   |j&                  r |j0                  dCi | |jE                         r|j&                  sY	 |j                  d   }|jG                  |j*                  |j                  d   |j-                  d      |j                  d   |B       d|dA<   |j&                  r |j0                  dCi | |jI                         rK|j&                  s	 |jK                  |j*                         d|dA<   |j&                  r |j0                  dCi |  |j0                  dCi | y # t        $ r&}|j                  t        |      ;       Y d }~md }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~[d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w# t.        $ r }|j                  d@|z  ;       Y d }~d }~ww xY w)DNr   r   r   )r   r   r   r   )r   defaultchoicesr   )r   ri   r   pathr   r   r5   T)r   no_logr   r   r$   r/   base64F)r   r   r   r   ru   r   r   r   r   bool)r   r   r   rG   r>   r   rp   ro   )r   r   r   hashr   dictfloat)argon2iargon2idpbkdf2)rz   r{   r|   r}   r~   )rz   r{   )r   r   mutually_exclusiver   r   r   r   r   r   r   ))r   r5   )r   r   )r   r   r   )changedri   )argument_specsupports_check_moder   C)LANGLC_ALLLC_MESSAGESLC_CTYPEz{0} is not a devicer   z4You cannot combine type luks1 with the label option.)ru   r   r   )r   r   zFRemoving a keyslot requires the passphrase or keyfile of another slot.zluks_device error: %sr   )r   rU   )&r   r   run_command_environ_updater(   osstatst_modeS_ISBLKS_ISCHRr2   r4   r3   r   rW   r   rq   r   r   r   
check_moder   r   r6   rM   	exit_jsonr   r   rP   r   r   rd   r   r   r   r   r   r   r   )module_argsr   rD   r+   statinfomodeecrypt
conditionsr   r   ri   last_keys                r   
run_moduler  =  s	    -=
- - u- &!- f%- (- U40- t4- E$7- !0B5
-" %.#-$ eE2%-& u5'-( #>)-* % +-, --. u/-0 uw&891-2 3-4 u5-6 #1 $% 0E3TU'5) !FF

7-L e$M-N !fe<O-P %)fe$DQ-R  $?S-T !%&% @U-V VU3W-X 7Y-K^ %d+F! -F
 )-#)F% }}X*	)wwv}}X67H##D<<%dll4.@ 5 < <V]]8=T UVV  E"651J }}W)fmmF.Cw.NST 	i ,=='3==)*6''
(B(B(DE	v!6!Bf-IA 	:E''y9	: 3 MM% ,i(0l+3\     B%%%%MM),@@NMM),MM),MM(+MM&)MM-0MM'*
 !yF&v& &&(Dv}}V$<B//
0A0AB   B##%%MM),@@NMM"78MM"?@MM":;MM";<MM,/MM"23 v yF&v& (B99*:K:KL ==(D  B$$T* v yF&v&    B&&%%MM),@@NMM-0@@AQRMM-0MM'* !yF&v& !!#  
B!==)@A))%%MM"23@@ATUMM"23*2 *  !yF&v&   B%%j&7&78 !yF&v& Fv{  	)Q((	)b  B  %<q%@ AAB"  B  %<q%@ AAB   B  %<q%@ AAB  B  %<q%@ AAB  B  %<q%@ AAB(  B  %<q%@ AAB$  B  %<q%@ AAB  B  %<q%@ AABs   A?_ B` 5`8 Ba$ 0b (b< >A3c( 1Ad 	e  	`	#``		`5`00`58	a!aa!$	b-bb	b9b44b9<	c%c  c%(	d1dd	d=d88d= 	e)	e$$e)c                      t                y rQ   )r  rU   r-   r   mainr  &  s    Lr-   __main__)%
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNr  r   r  r   r   ansible.module_utils.basicr   +ansible.module_utils.common.text.convertersr   r	   rA   rB   rN   r   r_   rg   r   r   r   r   r   objectr!   rW   r   r  r  rR   rU   r-   r   <module>r     s    A @ Xtwr
 
 	   4 K 	
	
 "**56 BJJ:;  
   5(:$f :$zD
7 D
N
T TnfR zF r-   