diff --git a/modules/02-create-filevault-user.sh b/modules/02-create-filevault-user.sh index 3ca4077..b30962e 100755 --- a/modules/02-create-filevault-user.sh +++ b/modules/02-create-filevault-user.sh @@ -1,23 +1,12 @@ #!/usr/bin/env zsh # vi: set ft=zsh tw=80 ts=2 -function getComputerName() { - local moduleAnswer - local computerName="`scutil --get ComputerName 2> /dev/null`" - getModuleAnswerByKeyRegEx '_hostname$' && computerName=$moduleAnswer - print -- $computerName -} - function getDefaultFullname() { - local computerName="`getComputerName`" - lop -- -d 'Default full name based on current computer name is:' -d "$computerName" - print "${computerName}" + print "Astzweig Device" } function getDefaultUsername() { - local username="`getDefaultFullname | tr '[:upper:]' '[:lower:]' | tr -C '[:alnum:]\n' '-'`" - lop -- -d 'Default username based on current computer name is:' -d "$username" - print "${username}" + print 'azwdevice' } function isAPFSFilesystem() { @@ -166,18 +155,6 @@ function allowFileVaultUserToUnlockDisk() { indicateActivity -- "Allow FileVault user to unlock disk" _allowUserToUnlockDisk ${filevault_username} ${filevault_password} } -function _allowOnlyFileVaultUserToUnlock() { - local fdeuser - for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do - [[ ${fdeuser} != ${filevault_username} ]] && fdesetup remove -user "${fdeuser}" - done - return 0 -} - -function allowOnlyFileVaultUserToUnlock() { - indicateActivity -- "Disallow everyone else from unlocking disk" _allowOnlyFileVaultUserToUnlock -} - function configure_system() { lop -y h1 -- -i 'Setup FileVault System' checkSecureTokenForUser "${secure_token_user_username}" || { lop -- -e 'The provided secure token user has no secure token.'; return 10 } @@ -194,7 +171,6 @@ function configure_system() { enableFileVaultForSecureTokenUser || { lop -- -e 'Could not enable FileVault for secure token user.'; return 16 } checkSecureTokenForUser "${filevault_username}" || configureSecureToken || { lop -- -e 'Could not configure secure token for FileVault user.'; return 17 } canUserUnlockDisk ${filevault_username} || allowFileVaultUserToUnlockDisk || { lop -- -e 'Was not able to allow FileVault user to unlock disk.'; return 18 } - allowOnlyFileVaultUserToUnlock "${filevault_username}" || { lop -- -e 'Was not able to deactivate all other user from unlocking disk.'; return 19 } indicateActivity -- 'Update APFS preboot volume' diskutil apfs updatePreboot / || { lop -- -e 'Was not able to update APFS preboot volume.'; return 20 } } diff --git a/modules/02-single-filevault-user.sh b/modules/02-single-filevault-user.sh new file mode 100755 index 0000000..5148e2c --- /dev/null +++ b/modules/02-single-filevault-user.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env zsh +# vi: set ft=zsh tw=80 ts=2 + +function getDefaultFilevaultUsername() { + print 'azwdevice' +} + +function createEnsurerBinary() { + [[ -x $binaryPath ]] && return + cat > $binaryPath <<- BINARY + #!/usr/bin/env zsh + function { + local username="\$1" + + function doesFilevaultUserExist() { + dscl . -list /Users | grep \${username} >&! /dev/null + } + + function isFilevaultUserEnabled() { + fdesetup list | grep \${username} &> /dev/null + } + + function isFilevaultEnabled() { + fdesetup status | grep On &> /dev/null + } + + function allowOnlyFilevaultUserToUnlock() { + local fdeuser + for fdeuser in \${(f)"\$(fdesetup list | cut -d',' -f1)"}; do + [[ \${fdeuser} != \${username} ]] && fdesetup remove -user "\${fdeuser}" + done + return 0 + } + + [[ \$(id -un) == 'root' ] || return + isFilevaultEnabled || return + doesFilevaultUserExist && isFilevaultUserEnabled && allowOnlyFilevaultUserToUnlock + } + BINARY + chown root:wheel $binaryPath + chmod ug=rx,o=r $binaryPath +} + +function createLaunchDaemon() { + cat > ${launchDaemonPath} <<- LDAEMON + + + + + Label + ${serviceName} + ProgramArguments + + ${$binaryPath} + ${filevault_username} + + OnDemand + + LaunchOnlyOnce + + + + LDAEMON + ensureRightAccess ${launchDaemonPath} + chown root:wheel $binaryPath + chmod ugo=r $binaryPath +} + +function enableLaunchDaemon() { + launchctl enable system/${launchDaemonPath%.*} + launchctl bootstrap system ${launchDaemonPath} +} + +function createLaunchdService() { + local serviceName='de.astzweig.macos.launchdaemons.ensure-single-filevault-user' + local launchDaemonPath="/Library/LaunchDaemons/${serviceName}.plist" + [[ -f ${launchDaemonPath} ]] || indicateActivity -- 'Create Launch Daemon' createLaunchDaemon + indicateActivity -- 'Enable Launch Daemon' enableLaunchDaemon +} + +function configure_system() { + lop -y h1 -- -i 'Allow only Filevault user to unlock disk' + local binaryPath = '/usr/local/bin/ensure-single-filevault-user' + indicateActivity -- 'Create ensurer binary' createEnsurerBinary + createLaunchdService +} + +function getHelpPrerequisites() { + cmds=() + addDocoptsToCmds +} + +function getQuestionsPrerequisites() { + cmds=() +} + +function getExecPrerequisites() { + cmds=( + [awk]='' + [cat]='' + [fdesetup]='' + ) + requireRootPrivileges +} + +function getQuestions() { + local defaultUsername="`getDefaultFilevaultUsername`" + questions=( + 'i: filevault-username=What shall the FileVault user'\''s username be? # default:'"${defaultUsername}" + ) +} + +function getUsage() { + local cmdName=$1 text='' varname= + local defaultUsername="`getDefaultFilevaultUsername`" + read -r -d '' text <<- USAGE + Usage: + $cmdName show-questions [ ]... + $cmdName [-v] [-d FILE] [--filevault-username NAME] + + Create a script that ensures only a specified user of all FileVault enabled + users can unlock FileVault. That way a secure password can be used to + unlock the disk as opposed to macOS standard, where each user is allowed to + unlock the disk with his password that may or may not be secure (in terms of + length and randomness). + + Options: + --filevault-username NAME Username of the designated FileVault user [default: ${defaultUsername}]. + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. + ---- + $cmdName 0.1.0 + Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG + License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. + USAGE + print -- ${text} +} + +if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" +fi