Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/installer: Allow setting a password on cmdline for pxe boot #358722

Merged
merged 4 commits into from
Dec 4, 2024

Conversation

max06
Copy link
Contributor

@max06 max06 commented Nov 24, 2024

Copied isoImage-functionality for setting a password on boot for the nixos-user to the pxe image.

The pxe images come without passwords for the nixos and root accounts. This works great when doing local installations, but it prevents you from using ssh into the live-system without setting a password first. Adding live.nixos.passwd=somesecretpassword to the cmdline in any pxe configuration eliminates this requirement. This change also eliminates the need to build own images to achive this goal.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Nov 24, 2024
@max06
Copy link
Contributor Author

max06 commented Nov 24, 2024

PR is caused by nix-community/nixos-images#303

@NixOSInfra NixOSInfra added the 12. first-time contribution This PR is the author's first one; please be gentle! label Nov 24, 2024
# Allows using nixos-anywhere in headless environments
for o in $(</proc/cmdline); do
case "$o" in
live.nixos.passwd=*)
Copy link
Member

Choose a reason for hiding this comment

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

I was thinking about how to make this a bit more secure, netboot often is not encrypted and while we cannot protect against active attacker trying to intercept/change the traffic, we shouldn't have a service where we can just ask for the password using the netboot protocol. This is a bit different from the ISO usecase which is just local and requires physical access.
So our perl script currently supports setting password via password hashes like this:

foreach my $u (values %usersOut) {
    next if defined $shadowSeen{$u->{name}};
    my $hashedPassword = "!";
    $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword};
    my $expires = "";
    $expires = dateToDays($u->{expires}) if defined $u->{expires};
    # FIXME: set correct value for sp_lstchg.
    push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::", $expires, "") . "\n";
}

Could we change this bash instead or awk and do something similar?

This is how to generate a password hash:

echo foo | mkpasswd -m sha-512 -s

Copy link
Member

@Mic92 Mic92 Nov 24, 2024

Choose a reason for hiding this comment

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

Here is some untested code:

#!/bin/bash

# Precomputed SHA-512 password hash for "foo"
PRECOMPUTED_HASH='$6$someSalt$5bPlhBOL/PV.CWzi4UUE0DXQeWawY/kD1uYBdX.h2/s5XPz.vGmvCDmdDlEKZq8nCtOdXIuGFS9Hi0uEaRBnq.'

# File to check
SHADOW_FILE="/etc/shadow"

# Function to update the root password hash
update_root_password() {
    if [ "$(id -u)" -ne 0 ]; then
        echo "This script must be run as root!"
        exit 1
    fi

    if grep -q '^root::' "$SHADOW_FILE"; then
        echo "Root password is not set. Updating..."
        sed -i "s/^root::/root:${PRECOMPUTED_HASH}:/" "$SHADOW_FILE"
        echo "Root password updated successfully."
    else
        echo "Root password is already set. No action needed."
    fi
}

update_root_password

You might need to run it as an activation script after /etc/passwd has been populated.
Here is a snippet how sops-nix install secrets after user have been created. The password adding code should be run in a similar way.

https://github.com/Mic92/sops-nix/blob/53c853fb1a7e4f25f68805ee25c83d5de18dc699/modules/sops/default.nix#L451

You would also need to duplicate it for userborn/sysusers in a systemd service: https://github.com/Mic92/sops-nix/blob/53c853fb1a7e4f25f68805ee25c83d5de18dc699/modules/sops/default.nix#L436

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure if I get your points:

  • non-local intercept: Possible, but unlikely. While the image component are loaded from the web, the kernel arguments are set by the handling pxe server, in the local network. An attacker in that position has already won.
  • Hash instead of password makes no difference in security terms. An attacker can easily set a password hash instead of a password.

Re asking the pxe server for the password: I added live.nixos.passwordHash as second option. It has priority over password. Also I changed the script to not allow password-changes (with both options) if there is already a password set, eg in custom images. And just for common unterstanding: This password is only for the live system and does not persist in an installation done from there.

Please let me know if I missed something!


Fun fact: I asked an LLM about a simple script for this (because I was interested in it's output). It refused to help until I changed the query to "update password for user x" instead of root. Definitely no chance AI takes over my job 🤣

Copy link
Member

@Mic92 Mic92 Nov 24, 2024

Choose a reason for hiding this comment

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

There is a difference between an attacker that can ask the PXE server for the same configuration (passive) and an attacker that pretends to be the PXE server and alters the response (active)

Copy link
Member

Choose a reason for hiding this comment

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

You said you add the option, but I can't see it. Did you forgot to push?

Copy link
Member

Choose a reason for hiding this comment

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

Another advantage of password hashes is, that you don't leak passwords to the nix store in case you build a configuration with nix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An attacker altering the response still makes no difference if it's a password or a hash. Needless to say an attacker in the position to run a pxe server (he needs control over the dhcp server as well for that) doesn't need a nixos netboot image to do harm. But I get your point with the cleartext password in the nix store.

No, not forgotten. Just adding the test scenario. Pushing my current state though for your feedback.

@Mic92
Copy link
Member

Mic92 commented Nov 24, 2024

It would be great if you could add the new parameter to boot.kernelParams here:

{ key = "serial"; }

And than check /etc/shadow if it also contains the generated password.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 labels Nov 25, 2024
@max06
Copy link
Contributor Author

max06 commented Nov 26, 2024

It would be great if you could add the new parameter to boot.kernelParams here:

{ key = "serial"; }

I'm not sure if that even works:

After adding machine.succeed("cat /proc/cmdline; grep 'serial' /proc/cmdline") to the test-script...

machine: must succeed: cat /proc/cmdline; grep 'serial' /proc/cmdline
machine: output: bzImage init=/nix/store/xskdcn0dpzslay1sz59gq8dmyjjdwh6g-nixos-system-nixos-25.05pre-git/init initrd=initrd console=ttyS0 console=tty0 panic=1 boot.panic_on_fail clocksource=acpi_pm loglevel=7 net.ifnames=0 

(In other words: I have no clue how to fix that.)

@max06
Copy link
Contributor Author

max06 commented Nov 28, 2024

@Mic92 I fixed the missing kernel parameters and added the live.nixos.passwordHash-Option as well for testing. I also replaced the first implementation with sed by usermod, less issues with characters in the password hash.

Please review and merge, if there's nothing else to do here.
Thanks alot!

@max06 max06 requested a review from Mic92 December 4, 2024 15:14
@Mic92 Mic92 merged commit 6541fe7 into NixOS:master Dec 4, 2024
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 12. first-time contribution This PR is the author's first one; please be gentle!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants