tangled
alpha
login
or
join now
tjh.dev
/
nixpkgs
0
fork
atom
Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
0
fork
atom
overview
issues
pulls
pipelines
google-compute-config: update config
Nikolay Amiantov
4 years ago
524aecf6
077d0524
+47
-153
8 changed files
expand all
collapse all
unified
split
nixos
modules
security
google_oslogin.nix
pam.nix
virtualisation
fetch-instance-ssh-keys.bash
google-compute-config.nix
tests
google-oslogin
default.nix
server.nix
server.py
ssh-keys.nix
+6
-3
nixos/modules/security/google_oslogin.nix
···
5
5
let
6
6
7
7
cfg = config.security.googleOsLogin;
8
8
-
package = pkgs.google-compute-engine-oslogin;
8
8
+
package = pkgs.google-guest-oslogin;
9
9
10
10
in
11
11
···
17
17
type = types.bool;
18
18
default = false;
19
19
description = ''
20
20
-
Whether to enable Google OS Login
20
20
+
Whether to enable Google OS Login.
21
21
22
22
The OS Login package enables the following components:
23
23
AuthorizedKeysCommand to query valid SSH keys from the user's OS Login
···
36
36
security.pam.services.sshd = {
37
37
makeHomeDir = true;
38
38
googleOsLoginAccountVerification = true;
39
39
-
# disabled for now: googleOsLoginAuthentication = true;
39
39
+
googleOsLoginAuthentication = true;
40
40
};
41
41
42
42
security.sudo.extraConfig = ''
···
46
46
"d /run/google-sudoers.d 750 root root -"
47
47
"d /var/google-users.d 750 root root -"
48
48
];
49
49
+
50
50
+
systemd.packages = [ package ];
51
51
+
systemd.timers.google-oslogin-cache.wantedBy = [ "timers.target" ];
49
52
50
53
# enable the nss module, so user lookups etc. work
51
54
system.nssModules = [ package ];
+6
-6
nixos/modules/security/pam.nix
···
444
444
account sufficient ${pam_krb5}/lib/security/pam_krb5.so
445
445
'' +
446
446
optionalString cfg.googleOsLoginAccountVerification ''
447
447
-
account [success=ok ignore=ignore default=die] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
448
448
-
account [success=ok default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so
447
447
+
account [success=ok ignore=ignore default=die] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so
448
448
+
account [success=ok default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so
449
449
'' +
450
450
''
451
451
452
452
# Authentication management.
453
453
'' +
454
454
optionalString cfg.googleOsLoginAuthentication ''
455
455
-
auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
455
455
+
auth [success=done perm_denied=die default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so
456
456
'' +
457
457
optionalString cfg.rootOK ''
458
458
auth sufficient pam_rootok.so
···
1091
1091
mr ${pam_ccreds}/lib/security/pam_ccreds.so,
1092
1092
'' +
1093
1093
optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) ''
1094
1094
-
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
1095
1095
-
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so,
1094
1094
+
mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so,
1095
1095
+
mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so,
1096
1096
'' +
1097
1097
optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication)) ''
1098
1098
-
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
1098
1098
+
mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so,
1099
1099
'' +
1100
1100
optionalString (config.security.pam.enableSSHAgentAuth
1101
1101
&& isEnabled (cfg: cfg.sshAgentAuth)) ''
-36
nixos/modules/virtualisation/fetch-instance-ssh-keys.bash
···
1
1
-
#!/usr/bin/env bash
2
2
-
3
3
-
set -euo pipefail
4
4
-
5
5
-
WGET() {
6
6
-
wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google' "$@"
7
7
-
}
8
8
-
9
9
-
# When dealing with cryptographic keys, we want to keep things private.
10
10
-
umask 077
11
11
-
mkdir -p /root/.ssh
12
12
-
13
13
-
echo "Fetching authorized keys..."
14
14
-
WGET -O /tmp/auth_keys http://metadata.google.internal/computeMetadata/v1/instance/attributes/sshKeys
15
15
-
16
16
-
# Read keys one by one, split in case Google decided
17
17
-
# to append metadata (it does sometimes) and add to
18
18
-
# authorized_keys if not already present.
19
19
-
touch /root/.ssh/authorized_keys
20
20
-
while IFS='' read -r line || [[ -n "$line" ]]; do
21
21
-
keyLine=$(echo -n "$line" | cut -d ':' -f2)
22
22
-
IFS=' ' read -r -a array <<<"$keyLine"
23
23
-
if [[ ${#array[@]} -ge 3 ]]; then
24
24
-
echo "${array[@]:0:3}" >>/tmp/new_keys
25
25
-
echo "Added ${array[*]:2} to authorized_keys"
26
26
-
fi
27
27
-
done </tmp/auth_keys
28
28
-
mv /tmp/new_keys /root/.ssh/authorized_keys
29
29
-
chmod 600 /root/.ssh/authorized_keys
30
30
-
31
31
-
echo "Fetching host keys..."
32
32
-
WGET -O /tmp/ssh_host_ed25519_key http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key
33
33
-
WGET -O /tmp/ssh_host_ed25519_key.pub http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key_pub
34
34
-
mv -f /tmp/ssh_host_ed25519_key* /etc/ssh/
35
35
-
chmod 600 /etc/ssh/ssh_host_ed25519_key
36
36
-
chmod 644 /etc/ssh/ssh_host_ed25519_key.pub
+31
-102
nixos/modules/virtualisation/google-compute-config.nix
···
1
1
{ config, lib, pkgs, ... }:
2
2
with lib;
3
3
-
let
4
4
-
gce = pkgs.google-compute-engine;
5
5
-
in
6
3
{
7
4
imports = [
8
5
../profiles/headless.nix
···
40
37
security.googleOsLogin.enable = true;
41
38
42
39
# Use GCE udev rules for dynamic disk volumes
43
43
-
services.udev.packages = [ gce ];
40
40
+
services.udev.packages = [ pkgs.google-guest-configs ];
41
41
+
services.udev.path = [ pkgs.google-guest-configs ];
44
42
45
43
# Force getting the hostname from Google Compute.
46
44
networking.hostName = mkDefault "";
47
45
48
46
# Always include cryptsetup so that NixOps can use it.
49
47
environment.systemPackages = [ pkgs.cryptsetup ];
50
50
-
51
51
-
# Make sure GCE image does not replace host key that NixOps sets
52
52
-
environment.etc."default/instance_configs.cfg".text = lib.mkDefault ''
53
53
-
[InstanceSetup]
54
54
-
set_host_keys = false
55
55
-
'';
56
48
57
49
# Rely on GCP's firewall instead
58
50
networking.firewall.enable = mkDefault false;
···
69
61
# GC has 1460 MTU
70
62
networking.interfaces.eth0.mtu = 1460;
71
63
72
72
-
# Used by NixOps
73
73
-
systemd.services.fetch-instance-ssh-keys = {
74
74
-
description = "Fetch host keys and authorized_keys for root user";
64
64
+
systemd.packages = [ pkgs.google-guest-agent ];
65
65
+
systemd.services.google-guest-agent = {
66
66
+
wantedBy = [ "multi-user.target" ];
67
67
+
restartTriggers = [ config.environment.etc."default/instance_configs.cfg".source ];
68
68
+
path = lib.optional config.users.mutableUsers pkgs.shadow;
69
69
+
};
70
70
+
systemd.services.google-startup-scripts.wantedBy = [ "multi-user.target" ];
71
71
+
systemd.services.google-shutdown-scripts.wantedBy = [ "multi-user.target" ];
75
72
76
76
-
wantedBy = [ "sshd.service" ];
77
77
-
before = [ "sshd.service" ];
78
78
-
after = [ "network-online.target" ];
79
79
-
wants = [ "network-online.target" ];
80
80
-
path = [ pkgs.wget ];
73
73
+
security.sudo.extraRules = mkIf config.users.mutableUsers [
74
74
+
{ groups = [ "google-sudoers" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ]; }
75
75
+
];
81
76
82
82
-
serviceConfig = {
83
83
-
Type = "oneshot";
84
84
-
ExecStart = pkgs.runCommand "fetch-instance-ssh-keys" { } ''
85
85
-
cp ${./fetch-instance-ssh-keys.bash} $out
86
86
-
chmod +x $out
87
87
-
${pkgs.shfmt}/bin/shfmt -i 4 -d $out
88
88
-
${pkgs.shellcheck}/bin/shellcheck $out
89
89
-
patchShebangs $out
90
90
-
'';
91
91
-
PrivateTmp = true;
92
92
-
StandardError = "journal+console";
93
93
-
StandardOutput = "journal+console";
94
94
-
};
95
95
-
};
77
77
+
users.groups.google-sudoers = mkIf config.users.mutableUsers { };
96
78
97
97
-
systemd.services.google-instance-setup = {
98
98
-
description = "Google Compute Engine Instance Setup";
99
99
-
after = [ "network-online.target" "network.target" "rsyslog.service" ];
100
100
-
before = [ "sshd.service" ];
101
101
-
path = with pkgs; [ coreutils ethtool openssh ];
102
102
-
serviceConfig = {
103
103
-
ExecStart = "${gce}/bin/google_instance_setup";
104
104
-
StandardOutput="journal+console";
105
105
-
Type = "oneshot";
106
106
-
};
107
107
-
wantedBy = [ "sshd.service" "multi-user.target" ];
108
108
-
};
79
79
+
boot.extraModprobeConfig = lib.readFile "${pkgs.google-guest-configs}/etc/modprobe.d/gce-blacklist.conf";
109
80
110
110
-
systemd.services.google-network-daemon = {
111
111
-
description = "Google Compute Engine Network Daemon";
112
112
-
after = [ "network-online.target" "network.target" "google-instance-setup.service" ];
113
113
-
path = with pkgs; [ iproute2 ];
114
114
-
serviceConfig = {
115
115
-
ExecStart = "${gce}/bin/google_network_daemon";
116
116
-
StandardOutput="journal+console";
117
117
-
Type="simple";
118
118
-
};
119
119
-
wantedBy = [ "multi-user.target" ];
120
120
-
};
81
81
+
environment.etc."sysctl.d/60-gce-network-security.conf".source = "${pkgs.google-guest-configs}/etc/sysctl.d/60-gce-network-security.conf";
121
82
122
122
-
systemd.services.google-clock-skew-daemon = {
123
123
-
description = "Google Compute Engine Clock Skew Daemon";
124
124
-
after = [ "network.target" "google-instance-setup.service" "google-network-daemon.service" ];
125
125
-
serviceConfig = {
126
126
-
ExecStart = "${gce}/bin/google_clock_skew_daemon";
127
127
-
StandardOutput="journal+console";
128
128
-
Type = "simple";
129
129
-
};
130
130
-
wantedBy = ["multi-user.target"];
131
131
-
};
83
83
+
environment.etc."default/instance_configs.cfg".text = ''
84
84
+
[Accounts]
85
85
+
useradd_cmd = useradd -m -s /run/current-system/sw/bin/bash -p * {user}
132
86
87
87
+
[Daemons]
88
88
+
accounts_daemon = ${boolToString config.users.mutableUsers}
133
89
134
134
-
systemd.services.google-shutdown-scripts = {
135
135
-
description = "Google Compute Engine Shutdown Scripts";
136
136
-
after = [
137
137
-
"network-online.target"
138
138
-
"network.target"
139
139
-
"rsyslog.service"
140
140
-
"google-instance-setup.service"
141
141
-
"google-network-daemon.service"
142
142
-
];
143
143
-
serviceConfig = {
144
144
-
ExecStart = "${pkgs.coreutils}/bin/true";
145
145
-
ExecStop = "${gce}/bin/google_metadata_script_runner --script-type shutdown";
146
146
-
RemainAfterExit = true;
147
147
-
StandardOutput="journal+console";
148
148
-
TimeoutStopSec = "0";
149
149
-
Type = "oneshot";
150
150
-
};
151
151
-
wantedBy = [ "multi-user.target" ];
152
152
-
};
90
90
+
[InstanceSetup]
91
91
+
# Make sure GCE image does not replace host key that NixOps sets.
92
92
+
set_host_keys = false
153
93
154
154
-
systemd.services.google-startup-scripts = {
155
155
-
description = "Google Compute Engine Startup Scripts";
156
156
-
after = [
157
157
-
"network-online.target"
158
158
-
"network.target"
159
159
-
"rsyslog.service"
160
160
-
"google-instance-setup.service"
161
161
-
"google-network-daemon.service"
162
162
-
];
163
163
-
serviceConfig = {
164
164
-
ExecStart = "${gce}/bin/google_metadata_script_runner --script-type startup";
165
165
-
KillMode = "process";
166
166
-
StandardOutput = "journal+console";
167
167
-
Type = "oneshot";
168
168
-
};
169
169
-
wantedBy = [ "multi-user.target" ];
170
170
-
};
94
94
+
[MetadataScripts]
95
95
+
default_shell = ${pkgs.stdenv.shell}
171
96
172
172
-
environment.etc."sysctl.d/11-gce-network-security.conf".source = "${gce}/sysctl.d/11-gce-network-security.conf";
97
97
+
[NetworkInterfaces]
98
98
+
dhclient_script = ${pkgs.google-guest-configs}/bin/google-dhclient-script
99
99
+
# We set up network interfaces declaratively.
100
100
+
setup = false
101
101
+
'';
173
102
}
+2
-2
nixos/tests/google-oslogin/default.nix
···
31
31
32
32
# mockserver should return a non-expired ssh key for both mockuser and mockadmin
33
33
server.succeed(
34
34
-
f'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
34
34
+
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
35
35
)
36
36
server.succeed(
37
37
-
f'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
37
37
+
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
38
38
)
39
39
40
40
# install snakeoil ssh key on the client, and provision .ssh/config file
+1
-3
nixos/tests/google-oslogin/server.nix
···
23
23
security.googleOsLogin.enable = true;
24
24
25
25
# Mock google service
26
26
-
networking.extraHosts = ''
27
27
-
127.0.0.1 metadata.google.internal
28
28
-
'';
26
26
+
networking.interfaces.lo.ipv4.addresses = [ { address = "169.254.169.254"; prefixLength = 32; } ];
29
27
}
nixos/tests/google-oslogin/server.py
+1
-1
nixos/tests/ssh-keys.nix
···
10
10
snakeOilPublicKey = pkgs.lib.concatStrings [
11
11
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA"
12
12
"yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa"
13
13
-
"9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil"
13
13
+
"9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= snakeoil"
14
14
];
15
15
}