summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzimbatm <zimbatm@zimbatm.com>2022-11-30 14:54:59 +0100
committerzimbatm <zimbatm@zimbatm.com>2022-11-30 21:09:41 +0100
commit9da75fdaf147dc525861e8a534780d563c897dba (patch)
tree54592762208f3249ee1713f714cb1107ef027acb
parentd40fea9aeb8840fea0d377baa4b38e39b9582458 (diff)
nixos/update-users-groups: add support for account expiry
Introduce a `users.users.<name>.expires` option to allows setting an expiry date to user accounts. This is useful when members should gain temporary access and you don't want to have to roll out another system update to disable them.
-rw-r--r--nixos/modules/config/update-users-groups.pl33
-rw-r--r--nixos/modules/config/users-groups.nix15
2 files changed, 39 insertions, 9 deletions
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index 4368ec24ea9e..7ec4235db51a 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -4,6 +4,7 @@ use File::Path qw(make_path);
use File::Slurp;
use Getopt::Long;
use JSON;
+use DateTime;
# Keep track of deleted uids and gids.
my $uidMapFile = "/var/lib/nixos/uid-map";
@@ -22,6 +23,22 @@ sub updateFile {
write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die;
}
+# Converts an ISO date to number of days since 1970-01-01
+sub dateToDays {
+ my ($date) = @_;
+ my ($year, $month, $day) = split('-', $date, -3);
+ my $dt = DateTime->new(
+ year => $year,
+ month => $month,
+ day => $day,
+ hour => 0,
+ minute => 0,
+ second => 0,
+ time_zone => 'UTC',
+ );
+ return $dt->epoch / 86400;
+}
+
sub nscdInvalidate {
system("nscd", "--invalidate", $_[0]) unless $is_dry;
}
@@ -283,14 +300,16 @@ my %shadowSeen;
foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) {
chomp $line;
- my ($name, $hashedPassword, @rest) = split(':', $line, -9);
- my $u = $usersOut{$name};;
+ # struct name copied from `man 3 shadow`
+ my ($sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) = split(':', $line, -9);
+ my $u = $usersOut{$sp_namp};;
next if !defined $u;
- $hashedPassword = "!" if !$spec->{mutableUsers};
- $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
- chomp $hashedPassword;
- push @shadowNew, join(":", $name, $hashedPassword, @rest) . "\n";
- $shadowSeen{$name} = 1;
+ $sp_pwdp = "!" if !$spec->{mutableUsers};
+ $sp_pwdp = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
+ $sp_expire = dateToDays($u->{expires}) if defined $u->{expires};
+ chomp $sp_pwdp;
+ push @shadowNew, join(":", $sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) . "\n";
+ $shadowSeen{$sp_namp} = 1;
}
foreach my $u (values %usersOut) {
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index b538a0119c06..69fd04a8c06f 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -308,6 +308,17 @@ let
'';
};
+ expires = mkOption {
+ type = types.nullOr (types.strMatching "[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}");
+ default = null;
+ description = lib.mdDoc ''
+ Set the date on which the user's account will no longer be
+ accessible. The date is expressed in the format YYYY-MM-DD, or null
+ to disable the expiry.
+ A user whose account is locked must contact the system
+ administrator before being able to use the system again.
+ '';
+ };
};
config = mkMerge
@@ -433,7 +444,7 @@ let
name uid group description home homeMode createHome isSystemUser
password passwordFile hashedPassword
autoSubUidGidRange subUidRanges subGidRanges
- initialPassword initialHashedPassword;
+ initialPassword initialHashedPassword expires;
shell = utils.toShellPath u.shell;
}) cfg.users;
groups = attrValues cfg.groups;
@@ -587,7 +598,7 @@ in {
install -m 0700 -d /root
install -m 0755 -d /home
- ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON ])}/bin/perl \
+ ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON p.DateTime ])}/bin/perl \
-w ${./update-users-groups.pl} ${spec}
'';
};