|
|
|
@ -70,6 +70,9 @@ options:
|
|
|
|
|
Needs I(keyfile) option for authorization. LUKS container
|
|
|
|
|
supports up to 8 keys. Parameter value is the path
|
|
|
|
|
to the keyfile with the passphrase."
|
|
|
|
|
- "NOTE that adding additional keys is I(not idempotent).
|
|
|
|
|
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
|
|
|
|
@ -78,12 +81,20 @@ options:
|
|
|
|
|
- "Removes given key from the container on I(device). Does not
|
|
|
|
|
remove the keyfile from filesystem.
|
|
|
|
|
Parameter value is the path to the keyfile with the passphrase."
|
|
|
|
|
- "BEWARE that it is possible to remove even the last key from the
|
|
|
|
|
container. Data in there will be irreversibly lost
|
|
|
|
|
without a warning."
|
|
|
|
|
- "NOTE that removing keys is I(not idempotent). 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
|
|
|
|
|
I(force_remove_last_key) option must be set to C(yes)."
|
|
|
|
|
- "BEWARE that working with keyfiles in plaintext is dangerous.
|
|
|
|
|
Make sure that they are protected."
|
|
|
|
|
type: path
|
|
|
|
|
force_remove_last_key:
|
|
|
|
|
description:
|
|
|
|
|
- "If set to C(yes), 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: no
|
|
|
|
|
|
|
|
|
|
requirements:
|
|
|
|
|
- "cryptsetup"
|
|
|
|
@ -284,10 +295,40 @@ class CryptHandler(Handler):
|
|
|
|
|
raise ValueError('Error while adding new LUKS key to %s: %s'
|
|
|
|
|
% (device, result[STDERR]))
|
|
|
|
|
|
|
|
|
|
def run_luks_remove_key(self, device, keyfile):
|
|
|
|
|
def run_luks_remove_key(self, device, keyfile, force_remove_last_key=False):
|
|
|
|
|
''' Remove key from given device
|
|
|
|
|
Raises ValueError when command fails
|
|
|
|
|
'''
|
|
|
|
|
if not force_remove_last_key:
|
|
|
|
|
result = self._run_command([self._cryptsetup_bin, 'luksDump', device])
|
|
|
|
|
if result[RETURN_CODE] != 0:
|
|
|
|
|
raise ValueError('Error while dumping LUKS header from %s'
|
|
|
|
|
% (device, ))
|
|
|
|
|
keyslot_count = 0
|
|
|
|
|
keyslot_area = False
|
|
|
|
|
keyslot_re = re.compile(r'^Key Slot [0-9]+: ENABLED')
|
|
|
|
|
for line in result[STDOUT].splitlines():
|
|
|
|
|
if line.startswith('Keyslots:'):
|
|
|
|
|
keyslot_area = True
|
|
|
|
|
elif line.startswith(' '):
|
|
|
|
|
# LUKS2 header dumps use human-readable indented output.
|
|
|
|
|
# Thus we have to look out for 'Keyslots:' and count the
|
|
|
|
|
# number of indented keyslot numbers.
|
|
|
|
|
if keyslot_area and line[2] in '0123456789':
|
|
|
|
|
keyslot_count += 1
|
|
|
|
|
elif line.startswith('\t'):
|
|
|
|
|
pass
|
|
|
|
|
elif keyslot_re.match(line):
|
|
|
|
|
# LUKS1 header dumps have one line per keyslot with ENABLED
|
|
|
|
|
# or DISABLED in them. We count such lines with ENABLED.
|
|
|
|
|
keyslot_count += 1
|
|
|
|
|
else:
|
|
|
|
|
keyslot_area = False
|
|
|
|
|
if keyslot_count < 2:
|
|
|
|
|
self._module.fail_json(msg="LUKS device %s has less than two active keyslots. "
|
|
|
|
|
"To be able to remove a key, please set "
|
|
|
|
|
"`force_remove_last_key` to `yes`." % device)
|
|
|
|
|
|
|
|
|
|
result = self._run_command([self._cryptsetup_bin, 'luksRemoveKey', device,
|
|
|
|
|
'-q', '--key-file', keyfile])
|
|
|
|
|
if result[RETURN_CODE] != 0:
|
|
|
|
@ -412,7 +453,8 @@ def run_module():
|
|
|
|
|
name=dict(type='str'),
|
|
|
|
|
keyfile=dict(type='path'),
|
|
|
|
|
new_keyfile=dict(type='path'),
|
|
|
|
|
remove_keyfile=dict(type='path')
|
|
|
|
|
remove_keyfile=dict(type='path'),
|
|
|
|
|
force_remove_last_key=dict(type='bool', default=False),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# seed the result dict in the object
|
|
|
|
@ -491,7 +533,8 @@ def run_module():
|
|
|
|
|
if conditions.luks_remove_key():
|
|
|
|
|
try:
|
|
|
|
|
crypt.run_luks_remove_key(module.params['device'],
|
|
|
|
|
module.params['remove_keyfile'])
|
|
|
|
|
module.params['remove_keyfile'],
|
|
|
|
|
force_remove_last_key=module.params['force_remove_last_key'])
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
module.fail_json(msg="luks_device error: %s" % e)
|
|
|
|
|
result['changed'] = True
|
|
|
|
|