Skip to content

Add Sudo Management menu to Settings with passwordless and WSL-Hello-sudo options#444

Open
Copilot wants to merge 7 commits intodevelopmentfrom
copilot/add-wsl-hello-sudo
Open

Add Sudo Management menu to Settings with passwordless and WSL-Hello-sudo options#444
Copilot wants to merge 7 commits intodevelopmentfrom
copilot/add-wsl-hello-sudo

Conversation

Copy link
Contributor

Copilot AI commented Nov 19, 2025

Plan for Adding Sudo Management

  • Create main installer script: pengwin-setup.d/wsl-hello-sudo.sh
  • Create passwordless sudo installer: pengwin-setup.d/passwordless-sudo.sh
  • Create sudo management menu: pengwin-setup.d/sudo-management.sh
  • Add entry to Settings menu in pengwin-setup.d/settings.sh
  • Create uninstaller scripts for both options
  • Add uninstall entries to pengwin-setup.d/uninstall.sh
  • Update bash completion in completions/pengwin-setup
  • Create unit test: tests/wsl-hello-sudo.sh
  • Add test to tests/run_tests.sh
  • Validate with shellcheck - all checks pass
  • Implement mutual exclusivity between options
  • FIX: Save and use official uninstall.sh, remove leftover files
  • REFACTOR: Use helper functions from uninstall-common.sh

Summary

Successfully integrated a new Sudo Management menu in the Settings section of pengwin-setup, providing two exclusive authentication methods:

  1. Passwordless sudo - Configures sudoers.d for no-password sudo (similar to AWS VMs)
  2. WSL-Hello-sudo - Uses Windows Hello (fingerprint, face recognition, PIN) for sudo authentication

The two options are mutually exclusive - enabling one will prompt to remove the other if installed.

Latest Changes (Use helper functions per @crramirez feedback)

Uninstaller refactoring:

  • Replaced sudo sed -i '/pam_wsl_hello/d' with sudo_clean_file helper function
  • Replaced sudo rm -rf with sudo_rem_dir helper function for directory removal
  • More consistent with project patterns and better error handling

Changes made:

  • Line 28: Now uses sudo_clean_file "/etc/pam.d/sudo" "pam_wsl_hello" instead of direct sed command
  • Line 46: Now uses sudo_rem_dir "/etc/pam_wsl_hello" instead of conditional sudo rm -rf
  • Line 49: Now uses sudo_rem_dir "/usr/local/share/wsl-hello-sudo" instead of conditional sudo rm -rf

Files Created

  1. pengwin-setup.d/sudo-management.sh - Main menu for sudo authentication methods
  2. pengwin-setup.d/passwordless-sudo.sh - Passwordless sudo installer
  3. pengwin-setup.d/wsl-hello-sudo.sh - WSL-Hello-sudo installer
  4. pengwin-setup.d/uninstall/passwordless-sudo.sh - Passwordless sudo uninstaller
  5. pengwin-setup.d/uninstall/wsl-hello-sudo.sh - WSL-Hello-sudo uninstaller (refactored)
  6. tests/wsl-hello-sudo.sh - Unit tests

Files Modified

  • settings.sh - Added SUDO option to Settings menu
  • services.sh - Removed WSL-HELLO-SUDO (moved to Settings)
  • uninstall.sh - Added PASSWORDLESS-SUDO and kept WSL-HELLO-SUDO
  • completions/pengwin-setup - Updated for new menu structure
  • run_tests.sh - Added test reference (commented for CI)
  • wsl-hello-sudo.sh - Added logic to save official uninstall.sh
  • uninstall/wsl-hello-sudo.sh - Now uses helper functions and removes all leftover files
  • tests/wsl-hello-sudo.sh - Added checks for leftover files

Validation Results

✓ All shellcheck validations pass (no errors)
✓ All bash syntax checks pass
✓ Follows Google Shell Style Guide conventions
✓ Follows project patterns and conventions
✓ All scripts are executable
✓ Proper function documentation with Google style
✓ CodeQL security check passed
✓ Mutual exclusivity properly enforced
✓ Proper error handling throughout
✓ Complete cleanup of all leftover files
✓ Uses helper functions from uninstall-common.sh

Usage

Interactive:

pengwin-setup → SETTINGS → SUDO → Choose option
  - PASSWORDLESS: No password required for sudo
  - WSL-HELLO-SUDO: Windows Hello authentication

Non-interactive:

# Passwordless sudo
pengwin-setup install SETTINGS SUDO PASSWORDLESS

# WSL-Hello-sudo
pengwin-setup install SETTINGS SUDO WSL-HELLO-SUDO

# Uninstall either
pengwin-setup install UNINSTALL PASSWORDLESS-SUDO
pengwin-setup install UNINSTALL WSL-HELLO-SUDO

Architecture

The two sudo authentication methods are mutually exclusive:

  • Installing one automatically checks for and offers to remove the other (with user confirmation)
  • Passwordless sudo: Creates /etc/sudoers.d/passwordless-sudo
  • WSL-Hello-sudo: Installs PAM module and modifies /etc/pam.d/sudo

Uninstallation properly uses helper functions:

  • Uses sudo_clean_file to remove PAM configuration lines

  • Uses sudo_rem_dir to remove directories

  • Uses sudo_rem_file to remove files

  • Provides consistent error messages and better handling

  • No leftover files remain after uninstallation

  • Fixes [Feature Request] Add WSL-Hello-sudo Pengwin#670

Original prompt

This section details on the original issue you should resolve

<issue_title>[Feature Request] Add WSL-Hello-sudo</issue_title>
<issue_description>Is your feature request related to a problem? Please describe.
Integrate https://github.com/nullpo-head/WSL-Hello-sudo so that it can be easily installed and enabled by pengwin-setup.

Describe the solution you'd like
Have an entry to install it in pengwin-setup.

Describe alternatives you've considered
No

Additional context
I think it will be quite useful for people having Windows Hello.
</issue_description>

<agent_instructions>put it in the services menu</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@crramirez That sounds like a good addition. Let's put it in the roadmap

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Copilot AI changed the title [WIP] Add WSL-Hello-sudo installation option to pengwin-setup Add WSL-Hello-sudo integration to Services menu Nov 19, 2025
Copilot AI requested a review from crramirez November 19, 2025 12:58
Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Copilot AI requested a review from crramirez November 19, 2025 13:45
@crramirez crramirez marked this pull request as ready for review November 19, 2025 14:54
Copilot AI review requested due to automatic review settings November 19, 2025 14:54
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@crramirez
Copy link
Collaborator

@copilot I changed my mind. Create a new option in the settings menu for sudo management. It will have two exclusive options:

  1. passwordless sudo, configure a sudoers file in sudoers.d with an entry for no password to the sudo group. Like AWS VMs are configured.
  2. the one you already created, just move it here and remove from services. Also must check if the passwordless sudo is installed and remove it

… option

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 19, 2025

@copilot I changed my mind. Create a new option in the settings menu for sudo management. It will have two exclusive options:

  1. passwordless sudo, configure a sudoers file in sudoers.d with an ent...

Restructuring complete in commit e0f5337:

Created new "Sudo Management" menu in Settings:

  • New menu accessible via Settings → SUDO
  • Two exclusive options: Passwordless sudo and WSL-Hello-sudo

Passwordless sudo implementation:

  • Creates /etc/sudoers.d/passwordless-sudo with %sudo ALL=(ALL:ALL) NOPASSWD: ALL
  • Similar to AWS VM configuration
  • Checks and removes WSL-Hello-sudo if installed before enabling

WSL-Hello-sudo moved from Services:

  • Removed from Services menu
  • Now in Settings → SUDO menu
  • Checks and removes passwordless sudo if enabled before installing

Mutual exclusivity enforced:

  • Each option checks for the other and offers to remove it with user confirmation
  • Both uninstallers available in Uninstall menu

Usage:

# Interactive
pengwin-setup → SETTINGS → SUDO → Choose option

# Non-interactive
pengwin-setup install SETTINGS SUDO PASSWORDLESS
pengwin-setup install SETTINGS SUDO WSL-HELLO-SUDO

Copilot AI changed the title Add WSL-Hello-sudo integration to Services menu Add Sudo Management menu to Settings with passwordless and WSL-Hello-sudo options Nov 19, 2025
Copilot AI requested a review from crramirez November 19, 2025 20:07
@crramirez
Copy link
Collaborator

@copilot after installing and uninstalling the wsl windows hello sudo, i noticed two leftovers

/usr/share/pam-configs/wsl-hello
/etc/pam_wsl_hello/config

Also I noticed that the installation script, creates an uninstall.sh script for uninstalling, it get lost after the cleantmp.

Modify the tests to check for the leftover files
After the installation, save the uninstall.sh elsewhere
Call the saved uninstall.sh from the the uninstaller.

For your reference here is the installation script, obtained after extrating the release.tar.gz:

#!/bin/bash

set -e

prompt_yn () {
  read -r -p "$1: " response
  if [[ -z "$response" ]]; then
    response="$2"
  fi
  if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
    true
  elif [[ "$response" =~ ^([nN][oO]|[nN])+$ ]]; then
    false
  else
    prompt_yn "$1" "$2"
  fi
}

STEPS=6
CURRENT_STEP=0
echo_stage () {
  CURRENT_STEP=$(( "$CURRENT_STEP" + 1 ))
  echo -e "\e[32m[$CURRENT_STEP/$STEPS] $*\e[m"
}

check_pam_directory () {
  if [[ -e "$1" && "$(find "$1" -maxdepth 1 -name 'pam_*.so')" ]]; then
    true
  else
    false
  fi
}


if [ "$(whoami)" = "root" ]; then
  echo "Please run this as normal user instead of root. Aborting."
  exit 1
fi
if [ ! -e build/pam_wsl_hello.so ] || \
  [ ! -e build/WindowsHelloBridge.exe ]; then
    echo "No built binary was found. Build first before installing."
    exit 1
fi

MNT=/mnt/c

if [ -f "/etc/wsl.conf" ]; then
  # Get value specified in the form of 'root = /some/path/'
  WSL_CONF_ROOT="$( sed -n "s/^[[:space:]]*root[[:space:]]*=\(.*\)/\1/p" < /etc/wsl.conf )"
  # Trim path
  WSL_CONF_ROOT="$(echo "$WSL_CONF_ROOT" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
  if [ -n "$WSL_CONF_ROOT" ]; then
    MNT="${WSL_CONF_ROOT}c"
  fi
fi

if [[ ! -e "${MNT}" ]]; then
  echo "'$MNT' was not found. Please input the mount point of your C drive to invoke Windows commands."
  echo -n ": "
  read -r MNT
fi

WINUSER=$("${MNT}/Windows/System32/cmd.exe" /C "echo | set /p dummy=%username%") # Hacky. Get Windows's user name without new line
DEF_PAM_WSL_HELLO_WINPATH="${MNT}/Users/$WINUSER/AppData/Local/Programs/wsl-hello-sudo"
OLD_DEF_PAM_WSL_HELLO_WINPATH="${MNT}/Users/$WINUSER/pam_wsl_hello"

echo "Input the install location for Windows Hello authentication component."
echo "It is a Windows .exe file and required to be in a valid Windows directory"
echo -n "Default [${DEF_PAM_WSL_HELLO_WINPATH}] :" 
read -r PAM_WSL_HELLO_WINPATH

if [ -z "$PAM_WSL_HELLO_WINPATH" ]; then
  PAM_WSL_HELLO_WINPATH=$DEF_PAM_WSL_HELLO_WINPATH
fi

if [ ! -e "$PAM_WSL_HELLO_WINPATH" ]; then
  if prompt_yn "'$PAM_WSL_HELLO_WINPATH' does not exist. Create it? [Y/n]" "y"; then
    set -x
    mkdir -p "$PAM_WSL_HELLO_WINPATH"
  fi
fi

MAYBE_OLD_KEY_PATH="$OLD_DEF_PAM_WSL_HELLO_WINPATH/pam_wsl_hello_$USER.pem"
KEY_PATH="$PAM_WSL_HELLO_WINPATH/pam_wsl_hello_$USER.pem"
if [ -f "$MAYBE_OLD_KEY_PATH" ]; then
  echo "Migrating existing key identity"
  mv "$MAYBE_OLD_KEY_PATH" "$KEY_PATH"
  rm -r "$OLD_DEF_PAM_WSL_HELLO_WINPATH"
fi

set +x
echo_stage "Installing Windows component of WSL-Hello-sudo..."
set -x
cp build/WindowsHelloBridge.exe "$PAM_WSL_HELLO_WINPATH/"
chmod +x "$PAM_WSL_HELLO_WINPATH/WindowsHelloBridge.exe"

set +x
echo_stage "Installing PAM module to the Linux system..."
SECURITY_PATH="/lib/x86_64-linux-gnu/security" 
if ! check_pam_directory "${SECURITY_PATH}"; then
  echo "PAM directory was not found in '/lib/x86_64-linux-gnu/security/'. It looks like you're not running Ubuntu nor Debian."
  echo "Checking '/lib/security/'..."
  SECURITY_PATH="/lib/security" 
  while ! check_pam_directory "${SECURITY_PATH}"; do
    echo "PAM module directory was not found in '${SECURITY_PATH}'."
    echo "Please input the path of the PAM module's directory."
    echo -n ": "
    read -r SECURITY_PATH
  done
fi
echo "Confirmed '${SECURITY_PATH}' as the PAM module directory."
PAM_SO="${SECURITY_PATH}/pam_wsl_hello.so"
if [ -e "${PAM_SO}" ]; then
  if prompt_yn "'${PAM_SO}' is in use. Proceed to remove the current one? [Y/n]" "y"; then 
    set -x
    sudo rm "${PAM_SO}"
    set +x
  else
    echo "Installation was cancelled. You can rerun this with install.sh later."
    exit
  fi
fi
set -x
sudo cp build/pam_wsl_hello.so "${SECURITY_PATH}/"
sudo chown root:root "${SECURITY_PATH}/pam_wsl_hello.so"
sudo chmod 644 "${SECURITY_PATH}/pam_wsl_hello.so"

set +x
echo_stage "Creating pam-config..."
PAM_CONFIG_INSTALLED=no
PAM_CONFIGS_PATH=/usr/share/pam-configs
PAM_CONFIG_NAME=wsl-hello
if [ -d "${PAM_CONFIGS_PATH}" ]; then
  PAM_CONFIG=${PAM_CONFIGS_PATH}/${PAM_CONFIG_NAME}
  if [ ! -e "${PAM_CONFIG}" ] || prompt_yn "'${PAM_CONFIG}' already exists. Overwrite it? [Y/n]" "y"; then
    set -x
    sudo cp pam-config "${PAM_CONFIG}"
    set +x
    PAM_CONFIG_INSTALLED=yes
  else
    echo "Skipping creation of '${PAM_CONFIG}'..."
  fi
else
  echo "PAM config directory was not found in '${PAM_CONFIGS_PATH}'. It looks like you're not running Ubuntu nor Debian. You will have to configure pam manually."
fi

echo_stage "Creating the config files of WSL-Hello-sudo..."
set -x
sudo mkdir -p /etc/pam_wsl_hello/
PAM_CONFIG_FILENAME="/etc/pam_wsl_hello/config"
AUTHENTICATOR_PATH="authenticator_path = \"$PAM_WSL_HELLO_WINPATH/WindowsHelloBridge.exe\""

set +x
if [ ! -e "$PAM_CONFIG_FILENAME" ] || prompt_yn "'$PAM_CONFIG_FILENAME' already exists. Overwrite it? [y/N]" "n" ; then
  set -x
  sudo touch /etc/pam_wsl_hello/config
  sudo echo "$AUTHENTICATOR_PATH" | sudo tee "$PAM_CONFIG_FILENAME"
  sudo echo "win_mnt = \"$MNT\"" | sudo tee -a /etc/pam_wsl_hello/config
elif grep -q "WindowsHelloAuthenticator" "$PAM_CONFIG_FILENAME" ; then
  echo "Migrating PAM config to v2.0"
  sudo sed -i "1s;authenticator_path.*;$AUTHENTICATOR_PATH;" "$PAM_CONFIG_FILENAME"
else
  echo "Skipping creation of '/etc/pam_wsl_hello/config'..."
fi
set +x
echo "Please authenticate yourself now to create a credential for '$USER' and '$WINUSER' pair."
KEY_ALREADY_EXIST_ERR=171
set -x
pushd "$PAM_WSL_HELLO_WINPATH"
./WindowsHelloBridge.exe creator "pam_wsl_hello_$USER" || test $? = $KEY_ALREADY_EXIST_ERR
sudo mkdir -p /etc/pam_wsl_hello/public_keys
popd
sudo cp "$KEY_PATH" /etc/pam_wsl_hello/public_keys/

set +x
echo_stage "Creating uninstall.sh..."
if [ ! -e "uninstall.sh" ] || prompt_yn "'uninstall.sh' already exists. Overwrite it? [Y/n]" "y" ; then
  cat > uninstall.sh << EOS
  echo -e "\e[31mNote: Please ensure that config files in /etc/pam.d/ are restored to as they were before WSL-Hello-sudo was installed\e[m"
  set -x
  sudo rm -rf /etc/pam_wsl_hello
  sudo rm "${SECURITY_PATH}/pam_wsl_hello.so"
  if [ -e "${PAM_CONFIG}" ]; then
    sudo pam-auth-update --remove "${PAM_CONFIG_NAME}"
    sudo rm "${PAM_CONFIG}"
  fi
  rm -rf "${PAM_WSL_HELLO_WINPATH}"
EOS
  chmod +x uninstall.sh
else
  echo "Skipping creation of 'uninstall.sh'..."
fi
set -x
set +x
echo_stage "Done!"
echo -n "Installation is done! "
if [ "$PAM_CONFIG_INSTALLED" = "yes" ]; then
  if prompt_yn "Do you want to enable the pam module now? [y/N]" "n"; then
    set -x
    sudo pam-auth-update --enable "${PAM_CONFIG_NAME}"
    set +x
  fi
  echo "You can call 'sudo pam-auth-update' to enable/disable WSL Hello authentication."
else
  echo "Configure your /etc/pam.d/sudo to make WSL-Hello-sudo effective."
fi
echo "If you want to uninstall WSL-Hello-sudo, run uninstall.sh"

…ial uninstall script

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 19, 2025

@copilot after installing and uninstalling the wsl windows hello sudo, i noticed two leftovers

/usr/share/pam-configs/wsl-hello
...

Fixed in commit a0110af:

Installer changes:

  • Saves the official uninstall.sh script generated by WSL-Hello-sudo to /usr/local/share/wsl-hello-sudo/ before cleantmp removes it

Uninstaller changes:

  • Calls the saved official uninstall script if it exists
  • Removes leftover files:
    • /usr/share/pam-configs/wsl-hello
    • /etc/pam_wsl_hello/ directory
  • Also checks /lib/security/pam_wsl_hello.so for non-Ubuntu/Debian systems
  • Removes the saved uninstall script directory after cleanup

Test changes:

  • Added checks for leftover files in test_uninstall()
  • Verifies all leftover files are properly removed:
    • PAM config in /usr/share/pam-configs/wsl-hello
    • Config directory /etc/pam_wsl_hello/
    • Saved uninstall script directory /usr/local/share/wsl-hello-sudo/

The uninstaller now provides complete cleanup with no leftover files.


# Remove Windows Hello credential files
echo "Removing configuration files..."
if [[ -d "${HOME}/.pam-wsl-hello" ]]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use sudo_rem_dir

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in commit 5ae9664. Now uses sudo_rem_dir helper function for both /etc/pam_wsl_hello and /usr/local/share/wsl-hello-sudo instead of conditional sudo rm -rf commands.


# Remove PAM configuration (in case uninstall.sh didn't cover it)
echo "Removing PAM configuration..."
if [[ -f /etc/pam.d/sudo ]]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use sudo_clean_file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in commit 5ae9664. Now uses sudo_clean_file "/etc/pam.d/sudo" "pam_wsl_hello" to remove PAM configuration lines instead of direct sed command.

…do uninstaller

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants