[Nix-dev] [Nix-commits] SVN commit: nix - r30611 - in nixos/trunk/modules: config services/networking/ssh
Nicolas Pierron
nicolas.b.pierron at gmail.com
Tue Nov 29 07:14:12 CET 2011
On Tue, Nov 29, 2011 at 07:08, Nicolas Pierron
<nicolas.b.pierron at gmail.com> wrote:
> Author: NicolasPierron
> Date: Tue Nov 29 06:08:55 2011
> New Revision: 30611
> URL: https://nixos.org/websvn/nix/?rev=30611&sc=1
>
> Log:
> Convert users.extraUsers to an option set and add support for openssh
> authorized_keys file generation.
Sorry, I forgot to mention that this patch was contributed by Rickard Nilsson.
Thanks again, for this nice patch.
> Modified:
> nixos/trunk/modules/config/users-groups.nix
> nixos/trunk/modules/services/networking/ssh/sshd.nix
>
> Modified: nixos/trunk/modules/config/users-groups.nix
> ==============================================================================
> --- nixos/trunk/modules/config/users-groups.nix Tue Nov 29 05:13:20 2011 (r30610)
> +++ nixos/trunk/modules/config/users-groups.nix Tue Nov 29 06:08:55 2011 (r30611)
> @@ -5,43 +5,83 @@
> let
>
> ids = config.ids;
> + users = config.users;
>
> + userOpts = {name, config, ...}:
>
> - # User accounts to be created/updated by NixOS.
> - users =
> - let
> - defaultUsers =
> - [ { name = "root";
> - uid = ids.uids.root;
> - description = "System administrator";
> - home = "/root";
> - shell = config.users.defaultUserShell;
> - group = "root";
> - }
> - { name = "nobody";
> - uid = ids.uids.nobody;
> - description = "Unprivileged account (don't use!)";
> - }
> - ];
> -
> - # !!! Use NixOS module system to add default attributes.
> - addAttrs =
> - { name
> - , description
> - , uid ? ""
> - , group ? "nogroup"
> - , extraGroups ? []
> - , home ? "/var/empty"
> - , shell ? (if useDefaultShell then config.users.defaultUserShell else "/noshell")
> - , createHome ? false
> - , useDefaultShell ? false
> - , password ? null
> - , isSystemUser ? true
> - }:
> - { inherit name description uid group extraGroups home shell createHome password isSystemUser; };
> -
> - in map addAttrs (defaultUsers ++ config.users.extraUsers);
> + {
> + options = {
> + name = mkOption {
> + type = with types; uniq string;
> + description = "The name of the user account. If undefined, the name of the attribute set will be used.";
> + };
> + description = mkOption {
> + type = with types; uniq string;
> + default = "";
> + description = "A short description of the user account.";
> + };
> + uid = mkOption {
> + type = with types; uniq (nullOr int);
> + default = null;
> + description = "The account UID. If undefined, NixOS will select a UID.";
> + };
> + group = mkOption {
> + type = with types; uniq string;
> + default = "nogroup";
> + description = "The user's primary group.";
> + };
> + extraGroups = mkOption {
> + type = types.listOf types.string;
> + default = [];
> + description = "The user's auxiliary groups.";
> + };
> + home = mkOption {
> + type = with types; uniq string;
> + default = "/var/empty";
> + description = "The user's home directory.";
> + };
> + shell = mkOption {
> + type = with types; uniq string;
> + default = "/noshell";
> + description = "The path to the user's shell.";
> + };
> + createHome = mkOption {
> + type = types.bool;
> + default = false;
> + description = "If true, the home directory will be created automatically.";
> + };
> + useDefaultShell = mkOption {
> + type = types.bool;
> + default = false;
> + description = "If true, the user's shell will be set to <literal>users.defaultUserShell</literal>.";
> + };
> + password = mkOption {
> + type = with types; uniq (nullOr string);
> + default = null;
> + description = "The user's password. If undefined, no password is set for the user. Warning: do not set confidential information here because this data would be readable by all. This option should only be used for public account such as guest.";
> + };
> + isSystemUser = mkOption {
> + type = types.bool;
> + default = true;
> + description = "Indicates if the user is a system user or not.";
> + };
> + createUser = mkOption {
> + type = types.bool;
> + default = true;
> + description = "
> + Indicates if the user should be created automatically as a local user.
> + Set this to false if the user for instance is an LDAP user. NixOS will
> + then not modify any of the basic properties for the user account.
> + ";
> + };
> + };
>
> + config = {
> + name = mkDefault name;
> + uid = mkDefault (attrByPath [name] null ids.uids);
> + shell = mkIf config.useDefaultShell (mkDefault users.defaultUserShell);
> + };
> + };
>
> # Groups to be created/updated by NixOS.
> groups =
> @@ -109,11 +149,14 @@
>
> # Note: the 'X' in front of the password is to distinguish between
> # having an empty password, and not having a password.
> - serializedUser = u: "${u.name}\n${u.description}\n${toString u.uid}\n${u.group}\n${toString (concatStringsSep "," u.extraGroups)}\n${u.home}\n${u.shell}\n${toString u.createHome}\n${if u.password != null then "X" + u.password else ""}\n${toString u.isSystemUser}\n";
> + serializedUser = userName: let u = getAttr userName config.users.extraUsers; in "${u.name}\n${u.description}\n${if u.uid != null then toString u.uid else ""}\n${u.group}\n${toString (concatStringsSep "," u.extraGroups)}\n${u.home}\n${u.shell}\n${toString u.createHome}\n${if u.password != null then "X" + u.password else ""}\n${toString u.isSystemUser}\n${if u.createUser then "yes" else "no"}\n";
> +
> serializedGroup = g: "${g.name}\n${toString g.gid}";
>
> # keep this extra file so that cat can be used to pass special chars such as "`" which is used in the avahi daemon
> - usersFile = pkgs.writeText "users" (concatStrings (map serializedUser users));
> + usersFile = pkgs.writeText "users" (
> + concatMapStrings serializedUser (attrNames config.users.extraUsers)
> + );
>
> in
>
> @@ -124,22 +167,24 @@
> options = {
>
> users.extraUsers = mkOption {
> - default = [];
> - example =
> - [ { name = "alice";
> - uid = 1234;
> - description = "Alice";
> - home = "/home/alice";
> - createHome = true;
> - group = "users";
> - extraGroups = ["wheel"];
> - shell = "/bin/sh";
> - password = "foobar";
> - }
> - ];
> + default = {};
> + type = types.loaOf types.optionSet;
> + example = {
> + alice = {
> + uid = 1234;
> + description = "Alice";
> + home = "/home/alice";
> + createHome = true;
> + group = "users";
> + extraGroups = ["wheel"];
> + shell = "/bin/sh";
> + password = "foobar";
> + };
> + };
> description = ''
> Additional user accounts to be created automatically by the system.
> '';
> + options = [ userOpts ];
> };
>
> users.extraGroups = mkOption {
> @@ -154,6 +199,15 @@
> '';
> };
>
> + user = mkOption {
> + default = {};
> + description = ''
> + This option defines settings for individual users on the system.
> + '';
> + type = types.loaOf types.optionSet;
> + options = [ ];
> + };
> +
> };
>
>
> @@ -161,6 +215,18 @@
>
> config = {
>
> + users.extraUsers = {
> + root = {
> + description = "System administrator";
> + home = "/root";
> + shell = config.users.defaultUserShell;
> + group = "root";
> + };
> + nobody = {
> + description = "Unprivileged account (don't use!)";
> + };
> + };
> +
> system.activationScripts.rootPasswd = stringAfter [ "etc" ]
> ''
> # If there is no password file yet, create a root account with an
> @@ -192,6 +258,11 @@
> read createHome
> read password
> read isSystemUser
> + read createUser
> +
> + if ! test "$createUser" = "yes"; then
> + continue
> + fi
>
> if ! curEnt=$(getent passwd "$name"); then
> useradd ''${isSystemUser:+--system} \
>
> Modified: nixos/trunk/modules/services/networking/ssh/sshd.nix
> ==============================================================================
> --- nixos/trunk/modules/services/networking/ssh/sshd.nix Tue Nov 29 05:13:20 2011 (r30610)
> +++ nixos/trunk/modules/services/networking/ssh/sshd.nix Tue Nov 29 06:08:55 2011 (r30611)
> @@ -14,6 +14,98 @@
> v == "forced-commands-only" ||
> v == "no";
>
> + userOptions = {
> + openssh.authorizedKeys = {
> +
> + preserveExistingKeys = mkOption {
> + type = types.bool;
> + default = true;
> + description = ''
> + If this option is enabled, the keys specified in
> + <literal>keys</literal> and/or <literal>keyFiles</literal> will be
> + placed in a special section of the user's authorized_keys file
> + and any existing keys will be preserved. That section will be
> + regenerated each time NixOS is activated. However, if
> + <literal>preserveExisting</literal> isn't enabled, the complete file
> + will be generated, and any user modifications will be wiped out.
> + '';
> + };
> +
> + keys = mkOption {
> + type = types.listOf types.string;
> + default = [];
> + description = ''
> + A list of verbatim OpenSSH public keys that should be inserted into the
> + user's authorized_keys file. You can combine the <literal>keys</literal> and
> + <literal>keyFiles</literal> options.
> + '';
> + };
> +
> + keyFiles = mkOption {
> + type = types.listOf types.string;
> + default = [];
> + description = ''
> + A list of files each containing one OpenSSH public keys that should be
> + inserted into the user's authorized_keys file. You can combine
> + the <literal>keyFiles</literal> and
> + <literal>keys</literal> options.
> + '';
> + };
> +
> + };
> + };
> +
> + mkAuthkeyScript =
> + let
> + marker1 = "### NixOS will regenerate this line and every line below it.";
> + marker2 = "### NixOS will regenerate this file. Do not edit!";
> + users = map (userName: getAttr userName config.users.extraUsers) (attrNames config.users.extraUsers);
> + usersWithKeys = flip filter users (u:
> + length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0
> + );
> + userLoop = flip concatMapStrings usersWithKeys (u:
> + let
> + authKeys = concatStringsSep "," u.openssh.authorizedKeys.keys;
> + authKeyFiles = concatStringsSep "," u.openssh.authorizedKeys.keyFiles;
> + preserveExisting = if u.openssh.authorizedKeys.preserveExistingKeys then "true" else "false";
> + in ''
> + mkAuthKeysFile "${u.name}" "${authKeys}" "${authKeyFiles}" "${preserveExisting}"
> + ''
> + );
> + in ''
> + mkAuthKeysFile() {
> + local userName="$1"
> + local authKeys="$2"
> + local authKeyFiles="$3"
> + local preserveExisting="$4"
> + IFS=","
> +
> + for f in $authKeyFiles; do
> + if [ -f "$f" ]; then
> + authKeys="$(${pkgs.coreutils}/bin/cat "$f"),$authKeys"
> + fi
> + done
> +
> + if [ -n "$authKeys" ]; then
> + eval authfile=~$userName/.ssh/authorized_keys
> + ${pkgs.coreutils}/bin/mkdir -p "$(dirname $authfile)"
> + ${pkgs.coreutils}/bin/touch "$authfile"
> + if [ "$preserveExisting" == "false" ]; then
> + rm -f "$authfile"
> + authKeys="${marker2},$authKeys"
> + else
> + ${pkgs.gnused}/bin/sed -i '/^### NixOS.*$/,$d' "$authfile"
> + authKeys="${marker1},$authKeys"
> + fi
> + for key in $authKeys; do ${pkgs.coreutils}/bin/echo "$key" >> "$authfile"; done
> + fi
> +
> + unset IFS
> + }
> + ${userLoop}
> + '';
> +
> +
> in
>
> {
> @@ -102,6 +194,10 @@
>
> };
>
> + users.extraUsers = mkOption {
> + options = [ userOptions ];
> + };
> +
> };
>
>
> @@ -135,6 +231,8 @@
>
> preStart =
> ''
> + ${mkAuthkeyScript}
> +
> mkdir -m 0755 -p /etc/ssh
>
> if ! test -f /etc/ssh/ssh_host_dsa_key; then
> _______________________________________________
> nix-commits mailing list
> nix-commits at lists.science.uu.nl
> http://lists.science.uu.nl/mailman/listinfo/nix-commits
>
--
Nicolas Pierron
http://www.linkedin.com/in/nicolasbpierron - http://nbp.name/
More information about the nix-dev
mailing list