Allow to configure PBKDF (#163)
* Allow to configure PBKDF. * Also add PBKDF options to key add operation. * Simplify code. * Update plugins/modules/luks_device.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Fix indent. * Use more of the options. * Bump iteration count. * Increase memory limit. * Fall back to default PBKDF. * Apply suggestions from code review Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>pull/178/head
parent
3ca4c48b00
commit
d921ff1f68
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- "luks_device - allow to configure PBKDF (https://github.com/ansible-collections/community.crypto/pull/163)."
|
|
@ -170,6 +170,47 @@ options:
|
|||
- "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 I(iteration_count).
|
||||
type: float
|
||||
iteration_count:
|
||||
description:
|
||||
- Specify the iteration count used for the PBKDF.
|
||||
- Mutually exclusive with I(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
|
||||
|
||||
requirements:
|
||||
- "cryptsetup"
|
||||
|
@ -399,7 +440,19 @@ class CryptHandler(Handler):
|
|||
result = self._run_command([self._cryptsetup_bin, 'isLuks', device])
|
||||
return result[RETURN_CODE] == 0
|
||||
|
||||
def run_luks_create(self, device, keyfile, passphrase, keysize, cipher, hash_):
|
||||
def _add_pbkdf_options(self, options, pbkdf):
|
||||
if pbkdf['iteration_time'] is not None:
|
||||
options.extend(['--iter-time', str(int(pbkdf['iteration_time'] * 1000))])
|
||||
if pbkdf['iteration_count'] is not None:
|
||||
options.extend(['--pbkdf-force-iterations', str(pbkdf['iteration_count'])])
|
||||
if pbkdf['algorithm'] is not None:
|
||||
options.extend(['--pbkdf', pbkdf['algorithm']])
|
||||
if pbkdf['memory'] is not None:
|
||||
options.extend(['--pbkdf-memory', str(pbkdf['memory'])])
|
||||
if pbkdf['parallel'] is not None:
|
||||
options.extend(['--pbkdf-parallel', str(pbkdf['parallel'])])
|
||||
|
||||
def run_luks_create(self, device, keyfile, passphrase, keysize, cipher, hash_, pbkdf):
|
||||
# create a new luks container; use batch mode to auto confirm
|
||||
luks_type = self._module.params['type']
|
||||
label = self._module.params['label']
|
||||
|
@ -416,6 +469,8 @@ class CryptHandler(Handler):
|
|||
options.extend(['--cipher', cipher])
|
||||
if hash_ is not None:
|
||||
options.extend(['--hash', hash_])
|
||||
if pbkdf is not None:
|
||||
self._add_pbkdf_options(options, pbkdf)
|
||||
|
||||
args = [self._cryptsetup_bin, 'luksFormat']
|
||||
args.extend(options)
|
||||
|
@ -456,13 +511,15 @@ class CryptHandler(Handler):
|
|||
% (device, result[STDERR]))
|
||||
|
||||
def run_luks_add_key(self, device, keyfile, passphrase, new_keyfile,
|
||||
new_passphrase):
|
||||
new_passphrase, pbkdf):
|
||||
''' Add new key from a keyfile or passphrase to given 'device';
|
||||
authentication done using 'keyfile' or 'passphrase'.
|
||||
Raises ValueError when command fails.
|
||||
'''
|
||||
data = []
|
||||
args = [self._cryptsetup_bin, 'luksAddKey', device]
|
||||
if pbkdf is not None:
|
||||
self._add_pbkdf_options(args, pbkdf)
|
||||
|
||||
if keyfile:
|
||||
args.extend(['--key-file', keyfile])
|
||||
|
@ -691,6 +748,17 @@ def run_module():
|
|||
type=dict(type='str', choices=['luks1', 'luks2']),
|
||||
cipher=dict(type='str'),
|
||||
hash=dict(type='str'),
|
||||
pbkdf=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
iteration_time=dict(type='float'),
|
||||
iteration_count=dict(type='int'),
|
||||
algorithm=dict(type='str', choices=['argon2i', 'argon2id', 'pbkdf2']),
|
||||
memory=dict(type='int'),
|
||||
parallel=dict(type='int'),
|
||||
),
|
||||
mutually_exclusive=[('iteration_time', 'iteration_count')],
|
||||
),
|
||||
)
|
||||
|
||||
mutually_exclusive = [
|
||||
|
@ -738,6 +806,7 @@ def run_module():
|
|||
module.params['keysize'],
|
||||
module.params['cipher'],
|
||||
module.params['hash'],
|
||||
module.params['pbkdf'],
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
|
@ -799,7 +868,8 @@ def run_module():
|
|||
module.params['keyfile'],
|
||||
module.params['passphrase'],
|
||||
module.params['new_keyfile'],
|
||||
module.params['new_passphrase'])
|
||||
module.params['new_passphrase'],
|
||||
module.params['pbkdf'])
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
result['changed'] = True
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
become: yes
|
||||
register: create_check
|
||||
|
@ -12,6 +14,8 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
register: create
|
||||
- name: Create (idempotent)
|
||||
|
@ -19,6 +23,8 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
register: create_idem
|
||||
- name: Create (idempotent, check)
|
||||
|
@ -26,6 +32,8 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
become: yes
|
||||
register: create_idem_check
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
device: /dev/asdfasdfasdf
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
ignore_errors: yes
|
||||
become: yes
|
||||
|
@ -13,6 +15,8 @@
|
|||
device: /dev/asdfasdfasdf
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
ignore_errors: yes
|
||||
become: yes
|
||||
register: create
|
||||
|
@ -28,6 +32,8 @@
|
|||
device: /tmp/
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
ignore_errors: yes
|
||||
become: yes
|
||||
|
@ -37,6 +43,8 @@
|
|||
device: /tmp/
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
ignore_errors: yes
|
||||
become: yes
|
||||
register: create
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
|
||||
# Access: keyfile1
|
||||
|
@ -43,6 +45,8 @@
|
|||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile2"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
register: result_1
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keysize: 256
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
become: yes
|
||||
register: create_with_keysize
|
||||
- name: Create with keysize (idempotent)
|
||||
|
@ -13,6 +15,8 @@
|
|||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keysize: 256
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
become: yes
|
||||
register: create_idem_with_keysize
|
||||
- name: Create with different keysize (idempotent since we do not update keysize)
|
||||
|
@ -21,6 +25,8 @@
|
|||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keysize: 512
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
become: yes
|
||||
register: create_idem_with_diff_keysize
|
||||
- name: Create with ambiguous arguments
|
||||
|
@ -29,6 +35,8 @@
|
|||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
ignore_errors: yes
|
||||
become: yes
|
||||
register: create_with_ambiguous
|
||||
|
|
|
@ -4,7 +4,29 @@
|
|||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
algorithm: argon2i
|
||||
memory: 1000
|
||||
parallel: 1
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: create_passphrase_1
|
||||
|
||||
- name: Make sure that the previous task only fails because the LUKS version used cannot handle the PBKDF parameters
|
||||
assert:
|
||||
that:
|
||||
- create_passphrase_1 is not failed or 'Failed to set pbkdf parameters' in create_passphrase_1.msg
|
||||
|
||||
- name: Create with passphrase1 (without argon2i)
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
when: create_passphrase_1 is failed and 'Failed to set pbkdf parameters' in create_passphrase_1.msg
|
||||
|
||||
- name: Open with passphrase1
|
||||
luks_device:
|
||||
|
@ -30,6 +52,8 @@
|
|||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
new_passphrase: "{{ cryptfile_passphrase2 }}"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: new_try
|
||||
|
@ -55,6 +79,8 @@
|
|||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
new_passphrase: "{{ cryptfile_passphrase2 }}"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
register: result_1
|
||||
|
||||
|
@ -107,6 +133,8 @@
|
|||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
|
||||
- name: Remove access with ambiguous remove_ arguments
|
||||
|
@ -190,6 +218,8 @@
|
|||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_passphrase: "{{ cryptfile_passphrase3 }}"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
|
||||
- name: Open with passphrase3
|
||||
|
|
Loading…
Reference in New Issue