Add kdumpctl setup-crypttab subcommand
Resolves: https://issues.redhat.com/browse/RHEL-104940 Conflict: None commit ddd33c8d0f552cb46097aeade86178266637aa05 Author: Coiby Xu <coxu@redhat.com> Date: Tue Sep 16 16:22:18 2025 +0800 Add kdumpctl setup-crypttab subcommand Resolves: https://issues.redhat.com/browse/RHEL-29037 Relates: https://issues.redhat.com/browse/RHEL-29039 This subcommand is to add the 'link-volume-key' option to /etc/crypttab so the volume keys can be passed to the crash kernel to unlock LUKS-encrypted device automatically. This API will be also be called by kdump-anaconda-addon to set up /etc/crypttab on installation. Signed-off-by: Coiby Xu <coxu@redhat.com> Assisted-by: Google Gemini Signed-off-by: Coiby Xu <coxu@redhat.com>
This commit is contained in:
parent
936e845423
commit
10253d9e05
108
kdumpctl
108
kdumpctl
@ -1080,7 +1080,8 @@ _get_luks_key_by_unlock()
|
||||
while [ "$_attempt" -le "$_max_retries" ]; do
|
||||
if cryptsetup open "UUID=$_devuuid" DUMMY "--link-vk-to-keyring=@u::%logon:$_key_des" --test-passphrase; then
|
||||
ddebug "Success: LUKS device unlocked."
|
||||
dwarn "To avoid manually running kdumpctl, ensure the link-volume-key=@u::%logon:$_key_des option is correctly set up in /etc/crypttab (see man crypttab)."
|
||||
# For an interactive terminal, it's possible an user manually entered a passphrase
|
||||
[ -t 0 ] && dwarn "If you typed passphrase to unlock it manually, please run 'kdumpctl setup-crypttab' (see man kdumpctl)."
|
||||
return 0
|
||||
fi
|
||||
_attempt=$((_attempt + 1))
|
||||
@ -1175,6 +1176,106 @@ start()
|
||||
dinfo "Starting kdump: [OK]"
|
||||
}
|
||||
|
||||
# @description Updates a crypttab file to add the 'link-volume-key' option for kdump devices.
|
||||
#
|
||||
# It gets the list of kdump-related UUIDs by calling the 'get_all_kdump_crypt_dev' function.
|
||||
# The function is idempotent and performs pre-flight checks before making any modifications.
|
||||
#
|
||||
# @exitcode 0 If the update was successful or no changes were needed.
|
||||
# @exitcode 1 If there is an error (e.g. UUID mismatch).
|
||||
#
|
||||
# @stdout No output on success.
|
||||
# @stderr Progress and error messages are printed to stderr.
|
||||
CRYPTTAB_FILE=/etc/crypttab
|
||||
setup_crypttab()
|
||||
{
|
||||
local _devuuid uuids_string temp_file
|
||||
declare -a _luks_devs
|
||||
|
||||
if [[ ! -f $CRYPTTAB_FILE ]]; then
|
||||
dinfo "$CRYPTTAB_FILE doesn't exist, skip setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mapfile -t _luks_devs < <(get_all_kdump_crypt_dev)
|
||||
if [[ ${#_luks_devs[@]} -eq 0 ]]; then
|
||||
dinfo "No LUKS-encrypted device found to process. Exiting."
|
||||
return 0
|
||||
fi
|
||||
|
||||
for _devuuid in "${_luks_devs[@]}"; do
|
||||
if ! awk -v devuuid="$_devuuid" '!/^[[:space:]]*#/ && $2 == "UUID="devuuid { found=1; exit } END { exit !found }' "$CRYPTTAB_FILE"; then
|
||||
derror "Device UUID=${_devuuid} doesn't exist."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
uuids_string="${_luks_devs[*]}"
|
||||
temp_file=$(mktemp)
|
||||
|
||||
local status_updates
|
||||
|
||||
status_updates=$({
|
||||
awk -v prefix="$LUKS_KEY_PRFIX" -v targets="$uuids_string" '
|
||||
BEGIN {
|
||||
split(targets, temp_arr, " ")
|
||||
for (i in temp_arr) { target_uuids[temp_arr[i]] = 1 }
|
||||
}
|
||||
/^#|^$/ { print; next }
|
||||
{
|
||||
split($2, uuid_parts, "=")
|
||||
current_uuid = uuid_parts[2]
|
||||
|
||||
if (current_uuid in target_uuids) {
|
||||
target_option = "link-volume-key=@u::%logon:" prefix current_uuid
|
||||
|
||||
if (!index($0, target_option)) {
|
||||
# If we need to modify, check if we are replacing or adding
|
||||
if (index($0, "link-volume-key=")) {
|
||||
print "STATUS:REPLACED:" current_uuid > "/dev/stderr"
|
||||
} else {
|
||||
print "STATUS:ADDED:" current_uuid > "/dev/stderr"
|
||||
}
|
||||
|
||||
# Remove any existing, incorrect link-volume-key option
|
||||
sub(/,?link-volume-key=[^, ]+/, "", $4)
|
||||
sub(/^,/, "", $4)
|
||||
|
||||
# Add the correct option
|
||||
if (NF < 3 || $3 == "") { $3 = "none" }
|
||||
if ($4 == "" || $4 == "none") {
|
||||
$4 = target_option
|
||||
} else {
|
||||
$4 = $4 "," target_option
|
||||
}
|
||||
}
|
||||
}
|
||||
print
|
||||
}' "$CRYPTTAB_FILE" > "$temp_file"
|
||||
} 2>&1)
|
||||
|
||||
if cmp -s "$CRYPTTAB_FILE" "$temp_file"; then
|
||||
dinfo "No changes were needed. $CRYPTTAB_FILE is already up to date."
|
||||
rm "$temp_file"
|
||||
return 0
|
||||
else
|
||||
mv "$temp_file" "$CRYPTTAB_FILE"
|
||||
dinfo "Success! $CRYPTTAB_FILE has been updated."
|
||||
|
||||
# Parse status updates and report on each changed UUID
|
||||
while IFS=: read -r _ status uuid; do
|
||||
if [[ $status == "ADDED" ]]; then
|
||||
dinfo " - Added link-volume-key for UUID: $uuid"
|
||||
elif [[ $status == "REPLACED" ]]; then
|
||||
dinfo " - Replaced link-volume-key for UUID: $uuid"
|
||||
fi
|
||||
done < <(echo "$status_updates" | grep "STATUS:")
|
||||
dinfo "If the dump target is rootfs and you call this command manually, you will need to run 'dracut -f --regenerate-all' to regenerate initramfs."
|
||||
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
reload()
|
||||
{
|
||||
if ! is_kernel_loaded "$DEFAULT_DUMP_MODE"; then
|
||||
@ -2127,8 +2228,11 @@ main()
|
||||
reset_crashkernel_for_installed_kernel "$2"
|
||||
fi
|
||||
;;
|
||||
setup-crypttab)
|
||||
setup_crypttab
|
||||
;;
|
||||
*)
|
||||
dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem|test}"
|
||||
dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem|test|setup-crypttab}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
11
kdumpctl.8
11
kdumpctl.8
@ -76,6 +76,17 @@ by "kdumpctl status". Note, fadump is not supported.
|
||||
If the optional parameter [--force] is provided, there will be no confirmation
|
||||
before triggering the system crash. Dangerous though, this option is meant
|
||||
for automation testing.
|
||||
.TP
|
||||
.I setup-crypttab
|
||||
Add the 'link-volume-key' option to /etc/crypttab so vmcore can be saved to
|
||||
LUKS-encrypted disk volume. For more info on link-volume-key option,
|
||||
please "man crypttab".
|
||||
|
||||
This step is optional. If kdump.service can start successfully, there is no
|
||||
need for this step. You can confirm if this step is needed by running "kdumpctl
|
||||
restart". If you need to input any passpharse to unlock the the encrypted
|
||||
volume, please run "kdumpctl setup-crypttab".
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR kdump.conf (5),
|
||||
.BR mkdumprd (8)
|
||||
|
||||
90
spec/kdumpctl_setup_crypttab_spec.sh
Normal file
90
spec/kdumpctl_setup_crypttab_spec.sh
Normal file
@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
Describe "kdumpctl "
|
||||
Include ./kdumpctl
|
||||
# dinfo is a bit complex for unit tets, simply mock it
|
||||
dinfo() {
|
||||
echo "$1"
|
||||
}
|
||||
Describe "setup_crypttab()"
|
||||
# Set up global variables and mocks for each test
|
||||
# shellcheck disable=SC2016 # expand expression later
|
||||
BeforeEach 'CRYPTTAB_FILE=$(mktemp)'
|
||||
# shellcheck disable=SC2016 # expand expression later
|
||||
AfterEach 'rm -f "$CRYPTTAB_FILE"'
|
||||
|
||||
Context "when everything is correct"
|
||||
It "adds link-volume-key to specified UUIDs"
|
||||
# Arrange
|
||||
get_all_kdump_crypt_dev() {
|
||||
echo "uuid-001"
|
||||
echo "uuid-003"
|
||||
echo "uuid-005"
|
||||
echo "uuid-006"
|
||||
echo "uuid-007"
|
||||
}
|
||||
cat >"$CRYPTTAB_FILE" <<EOF
|
||||
luks-001 UUID=uuid-001 none discard
|
||||
luks-002 UUID=uuid-002 none discard
|
||||
# only two mandatory fields
|
||||
luks-003 UUID=uuid-003
|
||||
# two mandatory fields + one optional field
|
||||
luks-005 UUID=uuid-005 -
|
||||
# tab as delimiter
|
||||
luks-006 UUID=uuid-006
|
||||
luks-007 UUID=uuid-007 none discard,link-volume-key=TO_RE_REPLACED
|
||||
EOF
|
||||
When call setup_crypttab
|
||||
The status should be success
|
||||
The output should include "Success! $CRYPTTAB_FILE has been updated."
|
||||
The output should include "to run 'dracut -f --regenerate-all'"
|
||||
The file "$CRYPTTAB_FILE" should be file
|
||||
The contents of file "$CRYPTTAB_FILE" should eq \
|
||||
"luks-001 UUID=uuid-001 none discard,link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-001
|
||||
luks-002 UUID=uuid-002 none discard
|
||||
# only two mandatory fields
|
||||
luks-003 UUID=uuid-003 none link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-003
|
||||
# two mandatory fields + one optional field
|
||||
luks-005 UUID=uuid-005 - link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-005
|
||||
# tab as delimiter
|
||||
luks-006 UUID=uuid-006 none link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-006
|
||||
luks-007 UUID=uuid-007 none discard,link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-007"
|
||||
End
|
||||
End
|
||||
|
||||
Context "with safety checks and edge cases"
|
||||
|
||||
It "succeeds if no LUKS device used for kdump"
|
||||
get_all_kdump_crypt_dev() { return 0; }
|
||||
echo "luks-001 UUID=uuid-001" >"$CRYPTTAB_FILE"
|
||||
When call setup_crypttab
|
||||
The status should be success
|
||||
The output should include "No LUKS-encrypted device found to process. Exiting."
|
||||
End
|
||||
|
||||
It "aborts if target UUID is not in crypttab"
|
||||
get_all_kdump_crypt_dev() { echo "uuid-nonexistent"; }
|
||||
echo "luks-001 UUID=uuid-001" >"$CRYPTTAB_FILE"
|
||||
When call setup_crypttab
|
||||
The status should be failure
|
||||
The stderr should include "Device UUID=$(get_all_kdump_crypt_dev) doesn't exist"
|
||||
End
|
||||
|
||||
It "aborts if target UUID is only in a commented-out line"
|
||||
get_all_kdump_crypt_dev() { echo "uuid-001"; }
|
||||
echo "#luks-001 UUID=uuid-001" >"$CRYPTTAB_FILE"
|
||||
When call setup_crypttab
|
||||
The status should be failure
|
||||
The stderr should include "Device UUID=$(get_all_kdump_crypt_dev) doesn't exist"
|
||||
End
|
||||
|
||||
It "succeeds with no changes if crypttab is already correct"
|
||||
get_all_kdump_crypt_dev() { echo "uuid-001"; }
|
||||
echo "luks-001 UUID=uuid-001 none link-volume-key=@u::%logon:${LUKS_KEY_PRFIX}uuid-001" >"$CRYPTTAB_FILE"
|
||||
When call setup_crypttab
|
||||
The status should be success
|
||||
The output should include "No changes were needed."
|
||||
End
|
||||
End
|
||||
|
||||
End
|
||||
End
|
||||
Loading…
Reference in New Issue
Block a user