summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/security/google_oslogin.nix9
-rw-r--r--nixos/modules/security/pam.nix12
-rw-r--r--nixos/modules/virtualisation/fetch-instance-ssh-keys.bash36
-rw-r--r--nixos/modules/virtualisation/google-compute-config.nix135
-rw-r--r--nixos/tests/google-oslogin/default.nix4
-rw-r--r--nixos/tests/google-oslogin/server.nix4
-rwxr-xr-x[-rw-r--r--]nixos/tests/google-oslogin/server.py0
-rw-r--r--nixos/tests/ssh-keys.nix2
-rw-r--r--pkgs/tools/virtualization/google-guest-agent/default.nix53
-rw-r--r--pkgs/tools/virtualization/google-guest-agent/disable-etc-mutation.patch54
-rw-r--r--pkgs/tools/virtualization/google-guest-agent/fix-paths.patch43
-rw-r--r--pkgs/tools/virtualization/google-guest-configs/default.nix52
-rw-r--r--pkgs/tools/virtualization/google-guest-configs/fix-paths.patch61
-rw-r--r--pkgs/tools/virtualization/google-guest-oslogin/default.nix (renamed from pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix)28
-rw-r--r--pkgs/top-level/all-packages.nix6
15 files changed, 331 insertions, 168 deletions
diff --git a/nixos/modules/security/google_oslogin.nix b/nixos/modules/security/google_oslogin.nix
index c2889a0f0d1..cf416035ef6 100644
--- a/nixos/modules/security/google_oslogin.nix
+++ b/nixos/modules/security/google_oslogin.nix
@@ -5,7 +5,7 @@ with lib;
 let
 
   cfg = config.security.googleOsLogin;
-  package = pkgs.google-compute-engine-oslogin;
+  package = pkgs.google-guest-oslogin;
 
 in
 
@@ -17,7 +17,7 @@ in
       type = types.bool;
       default = false;
       description = ''
-        Whether to enable Google OS Login
+        Whether to enable Google OS Login.
 
         The OS Login package enables the following components:
         AuthorizedKeysCommand to query valid SSH keys from the user's OS Login
@@ -36,7 +36,7 @@ in
     security.pam.services.sshd = {
       makeHomeDir = true;
       googleOsLoginAccountVerification = true;
-      # disabled for now: googleOsLoginAuthentication = true;
+      googleOsLoginAuthentication = true;
     };
 
     security.sudo.extraConfig = ''
@@ -47,6 +47,9 @@ in
       "d /var/google-users.d 750 root root -"
     ];
 
+    systemd.packages = [ package ];
+    systemd.timers.google-oslogin-cache.wantedBy = [ "timers.target" ];
+
     # enable the nss module, so user lookups etc. work
     system.nssModules = [ package ];
     system.nssDatabases.passwd = [ "cache_oslogin" "oslogin" ];
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 964cfe7040c..9f295db84fd 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -444,15 +444,15 @@ let
             account sufficient ${pam_krb5}/lib/security/pam_krb5.so
           '' +
           optionalString cfg.googleOsLoginAccountVerification ''
-            account [success=ok ignore=ignore default=die] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
-            account [success=ok default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so
+            account [success=ok ignore=ignore default=die] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so
+            account [success=ok default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so
           '' +
           ''
 
             # Authentication management.
           '' +
           optionalString cfg.googleOsLoginAuthentication ''
-            auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
+            auth [success=done perm_denied=die default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so
           '' +
           optionalString cfg.rootOK ''
             auth sufficient pam_rootok.so
@@ -1091,11 +1091,11 @@ in
         mr ${pam_ccreds}/lib/security/pam_ccreds.so,
       '' +
       optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) ''
-        mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
-        mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so,
+        mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so,
+        mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so,
       '' +
       optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication)) ''
-        mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
+        mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so,
       '' +
       optionalString (config.security.pam.enableSSHAgentAuth
                      && isEnabled (cfg: cfg.sshAgentAuth)) ''
diff --git a/nixos/modules/virtualisation/fetch-instance-ssh-keys.bash b/nixos/modules/virtualisation/fetch-instance-ssh-keys.bash
deleted file mode 100644
index 4a860196111..00000000000
--- a/nixos/modules/virtualisation/fetch-instance-ssh-keys.bash
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-WGET() {
-    wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google' "$@"
-}
-
-# When dealing with cryptographic keys, we want to keep things private.
-umask 077
-mkdir -p /root/.ssh
-
-echo "Fetching authorized keys..."
-WGET -O /tmp/auth_keys http://metadata.google.internal/computeMetadata/v1/instance/attributes/sshKeys
-
-# Read keys one by one, split in case Google decided
-# to append metadata (it does sometimes) and add to
-# authorized_keys if not already present.
-touch /root/.ssh/authorized_keys
-while IFS='' read -r line || [[ -n "$line" ]]; do
-    keyLine=$(echo -n "$line" | cut -d ':' -f2)
-    IFS=' ' read -r -a array <<<"$keyLine"
-    if [[ ${#array[@]} -ge 3 ]]; then
-        echo "${array[@]:0:3}" >>/tmp/new_keys
-        echo "Added ${array[*]:2} to authorized_keys"
-    fi
-done </tmp/auth_keys
-mv /tmp/new_keys /root/.ssh/authorized_keys
-chmod 600 /root/.ssh/authorized_keys
-
-echo "Fetching host keys..."
-WGET -O /tmp/ssh_host_ed25519_key http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key
-WGET -O /tmp/ssh_host_ed25519_key.pub http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key_pub
-mv -f /tmp/ssh_host_ed25519_key* /etc/ssh/
-chmod 600 /etc/ssh/ssh_host_ed25519_key
-chmod 644 /etc/ssh/ssh_host_ed25519_key.pub
diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix
index cff48d20b2b..44d2a589511 100644
--- a/nixos/modules/virtualisation/google-compute-config.nix
+++ b/nixos/modules/virtualisation/google-compute-config.nix
@@ -1,8 +1,5 @@
 { config, lib, pkgs, ... }:
 with lib;
-let
-  gce = pkgs.google-compute-engine;
-in
 {
   imports = [
     ../profiles/headless.nix
@@ -40,7 +37,8 @@ in
   security.googleOsLogin.enable = true;
 
   # Use GCE udev rules for dynamic disk volumes
-  services.udev.packages = [ gce ];
+  services.udev.packages = [ pkgs.google-guest-configs ];
+  services.udev.path = [ pkgs.google-guest-configs ];
 
   # Force getting the hostname from Google Compute.
   networking.hostName = mkDefault "";
@@ -48,12 +46,6 @@ in
   # Always include cryptsetup so that NixOps can use it.
   environment.systemPackages = [ pkgs.cryptsetup ];
 
-  # Make sure GCE image does not replace host key that NixOps sets
-  environment.etc."default/instance_configs.cfg".text = lib.mkDefault ''
-    [InstanceSetup]
-    set_host_keys = false
-  '';
-
   # Rely on GCP's firewall instead
   networking.firewall.enable = mkDefault false;
 
@@ -69,105 +61,42 @@ in
   # GC has 1460 MTU
   networking.interfaces.eth0.mtu = 1460;
 
-  # Used by NixOps
-  systemd.services.fetch-instance-ssh-keys = {
-    description = "Fetch host keys and authorized_keys for root user";
-
-    wantedBy = [ "sshd.service" ];
-    before = [ "sshd.service" ];
-    after = [ "network-online.target" ];
-    wants = [ "network-online.target" ];
-    path = [ pkgs.wget ];
-
-    serviceConfig = {
-      Type = "oneshot";
-      ExecStart = pkgs.runCommand "fetch-instance-ssh-keys" { } ''
-        cp ${./fetch-instance-ssh-keys.bash} $out
-        chmod +x $out
-        ${pkgs.shfmt}/bin/shfmt -i 4 -d $out
-        ${pkgs.shellcheck}/bin/shellcheck $out
-        patchShebangs $out
-      '';
-      PrivateTmp = true;
-      StandardError = "journal+console";
-      StandardOutput = "journal+console";
-    };
+  systemd.packages = [ pkgs.google-guest-agent ];
+  systemd.services.google-guest-agent = {
+    wantedBy = [ "multi-user.target" ];
+    restartTriggers = [ config.environment.etc."default/instance_configs.cfg".source ];
+    path = lib.optional config.users.mutableUsers pkgs.shadow;
   };
+  systemd.services.google-startup-scripts.wantedBy = [ "multi-user.target" ];
+  systemd.services.google-shutdown-scripts.wantedBy = [ "multi-user.target" ];
 
-  systemd.services.google-instance-setup = {
-    description = "Google Compute Engine Instance Setup";
-    after = [ "network-online.target" "network.target" "rsyslog.service" ];
-    before = [ "sshd.service" ];
-    path = with pkgs; [ coreutils ethtool openssh ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_instance_setup";
-      StandardOutput="journal+console";
-      Type = "oneshot";
-    };
-    wantedBy = [ "sshd.service" "multi-user.target" ];
-  };
+  security.sudo.extraRules = mkIf config.users.mutableUsers [
+    { groups = [ "google-sudoers" ]; commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ]; }
+  ];
 
-  systemd.services.google-network-daemon = {
-    description = "Google Compute Engine Network Daemon";
-    after = [ "network-online.target" "network.target" "google-instance-setup.service" ];
-    path = with pkgs; [ iproute2 ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_network_daemon";
-      StandardOutput="journal+console";
-      Type="simple";
-    };
-    wantedBy = [ "multi-user.target" ];
-  };
+  users.groups.google-sudoers = mkIf config.users.mutableUsers { };
 
-  systemd.services.google-clock-skew-daemon = {
-    description = "Google Compute Engine Clock Skew Daemon";
-    after = [ "network.target" "google-instance-setup.service" "google-network-daemon.service" ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_clock_skew_daemon";
-      StandardOutput="journal+console";
-      Type = "simple";
-    };
-    wantedBy = ["multi-user.target"];
-  };
+  boot.extraModprobeConfig = lib.readFile "${pkgs.google-guest-configs}/etc/modprobe.d/gce-blacklist.conf";
 
+  environment.etc."sysctl.d/60-gce-network-security.conf".source = "${pkgs.google-guest-configs}/etc/sysctl.d/60-gce-network-security.conf";
 
-  systemd.services.google-shutdown-scripts = {
-    description = "Google Compute Engine Shutdown Scripts";
-    after = [
-      "network-online.target"
-      "network.target"
-      "rsyslog.service"
-      "google-instance-setup.service"
-      "google-network-daemon.service"
-    ];
-    serviceConfig = {
-      ExecStart = "${pkgs.coreutils}/bin/true";
-      ExecStop = "${gce}/bin/google_metadata_script_runner --script-type shutdown";
-      RemainAfterExit = true;
-      StandardOutput="journal+console";
-      TimeoutStopSec = "0";
-      Type = "oneshot";
-    };
-    wantedBy = [ "multi-user.target" ];
-  };
+  environment.etc."default/instance_configs.cfg".text = ''
+    [Accounts]
+    useradd_cmd = useradd -m -s /run/current-system/sw/bin/bash -p * {user}
 
-  systemd.services.google-startup-scripts = {
-    description = "Google Compute Engine Startup Scripts";
-    after = [
-      "network-online.target"
-      "network.target"
-      "rsyslog.service"
-      "google-instance-setup.service"
-      "google-network-daemon.service"
-    ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_metadata_script_runner --script-type startup";
-      KillMode = "process";
-      StandardOutput = "journal+console";
-      Type = "oneshot";
-    };
-    wantedBy = [ "multi-user.target" ];
-  };
+    [Daemons]
+    accounts_daemon = ${boolToString config.users.mutableUsers}
 
-  environment.etc."sysctl.d/11-gce-network-security.conf".source = "${gce}/sysctl.d/11-gce-network-security.conf";
+    [InstanceSetup]
+    # Make sure GCE image does not replace host key that NixOps sets.
+    set_host_keys = false
+
+    [MetadataScripts]
+    default_shell = ${pkgs.stdenv.shell}
+
+    [NetworkInterfaces]
+    dhclient_script = ${pkgs.google-guest-configs}/bin/google-dhclient-script
+    # We set up network interfaces declaratively.
+    setup = false
+  '';
 }
diff --git a/nixos/tests/google-oslogin/default.nix b/nixos/tests/google-oslogin/default.nix
index dea660ed05a..72c87d7153b 100644
--- a/nixos/tests/google-oslogin/default.nix
+++ b/nixos/tests/google-oslogin/default.nix
@@ -31,10 +31,10 @@ in {
 
     # mockserver should return a non-expired ssh key for both mockuser and mockadmin
     server.succeed(
-        f'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
+        f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
     )
     server.succeed(
-        f'${pkgs.google-compute-engine-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
+        f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
     )
 
     # install snakeoil ssh key on the client, and provision .ssh/config file
diff --git a/nixos/tests/google-oslogin/server.nix b/nixos/tests/google-oslogin/server.nix
index a0a3144ae69..faf5e847d7e 100644
--- a/nixos/tests/google-oslogin/server.nix
+++ b/nixos/tests/google-oslogin/server.nix
@@ -23,7 +23,5 @@ in {
   security.googleOsLogin.enable = true;
 
   # Mock google service
-  networking.extraHosts = ''
-    127.0.0.1 metadata.google.internal
-  '';
+  networking.interfaces.lo.ipv4.addresses = [ { address = "169.254.169.254"; prefixLength = 32; } ];
 }
diff --git a/nixos/tests/google-oslogin/server.py b/nixos/tests/google-oslogin/server.py
index 5ea9bbd2c96..5ea9bbd2c96 100644..100755
--- a/nixos/tests/google-oslogin/server.py
+++ b/nixos/tests/google-oslogin/server.py
diff --git a/nixos/tests/ssh-keys.nix b/nixos/tests/ssh-keys.nix
index 07d422196ef..df9ff38a3b2 100644
--- a/nixos/tests/ssh-keys.nix
+++ b/nixos/tests/ssh-keys.nix
@@ -10,6 +10,6 @@ pkgs:
   snakeOilPublicKey = pkgs.lib.concatStrings [
     "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA"
     "yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa"
-    "9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil"
+    "9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= snakeoil"
   ];
 }
diff --git a/pkgs/tools/virtualization/google-guest-agent/default.nix b/pkgs/tools/virtualization/google-guest-agent/default.nix
new file mode 100644
index 00000000000..a4ebd2db8f5
--- /dev/null
+++ b/pkgs/tools/virtualization/google-guest-agent/default.nix
@@ -0,0 +1,53 @@
+{ buildGoModule, fetchFromGitHub, fetchpatch, lib, coreutils, makeWrapper
+, google-guest-configs, google-guest-oslogin, iproute2, dhcp, procps
+}:
+
+buildGoModule rec {
+  pname = "guest-agent";
+  version = "20220104.00";
+
+  src = fetchFromGitHub {
+    owner = "GoogleCloudPlatform";
+    repo = pname;
+    rev = version;
+    sha256 = "sha256-BC2qpnGJU/D0z8jlmAEwvmFwBk1n0ZvqPBB6Zon9N/U=";
+  };
+
+  vendorSha256 = "sha256-YcWKSiN715Z9lmNAQx+sHEgxWnhFhenCNXBS7gdMV4M=";
+
+  patches = [ ./disable-etc-mutation.patch ];
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  postPatch = ''
+    substitute ${./fix-paths.patch} fix-paths.patch \
+      --subst-var out \
+      --subst-var-by true "${coreutils}/bin/true"
+    patch -p1 < ./fix-paths.patch
+  '';
+
+  # We don't add `shadow` here; it's added to PATH if `mutableUsers` is enabled.
+  binPath = lib.makeBinPath [ google-guest-configs google-guest-oslogin iproute2 dhcp procps ];
+
+  # Skip tests which require networking.
+  preCheck = ''
+    rm google_guest_agent/wsfc_test.go
+  '';
+
+  postInstall = ''
+    mkdir -p $out/etc/systemd/system
+    cp *.service $out/etc/systemd/system
+    install -Dm644 instance_configs.cfg $out/etc/default/instance_configs.cfg
+
+    wrapProgram $out/bin/google_guest_agent \
+      --prefix PATH ":" "$binPath"
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/GoogleCloudPlatform/guest-agent";
+    description = "Guest Agent for Google Compute Engine";
+    license = licenses.asl20;
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ abbradar ];
+  };
+}
diff --git a/pkgs/tools/virtualization/google-guest-agent/disable-etc-mutation.patch b/pkgs/tools/virtualization/google-guest-agent/disable-etc-mutation.patch
new file mode 100644
index 00000000000..fe076baacd2
--- /dev/null
+++ b/pkgs/tools/virtualization/google-guest-agent/disable-etc-mutation.patch
@@ -0,0 +1,54 @@
+From 2e8060f9ade13ba18ae5930c0781227bfcce11a5 Mon Sep 17 00:00:00 2001
+From: Nikolay Amiantov <ab@fmap.me>
+Date: Mon, 10 Jan 2022 22:16:38 +0300
+Subject: [PATCH] Disable accounts setup phase and oslogin
+
+On NixOS we set up necessary groups and sudoers rules declaratively,
+and have most of `/etc` directory read-only. This creates (harmless)
+error messages when trying to create google-sudoers file.
+
+"oslogin" daemon sets up configuration necessary for OS Login to
+work, including PAM, NSS and sudoers. On NixOS we perform all this
+configuration declaratively and have most of /etc mounted read-only.
+This creates (harmless) error messages when running the daemon.
+---
+ google_guest_agent/non_windows_accounts.go | 9 ---------
+ google_guest_agent/oslogin.go              | 2 +-
+ 2 files changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/google_guest_agent/non_windows_accounts.go b/google_guest_agent/non_windows_accounts.go
+index 81013e3..05b830f 100644
+--- a/google_guest_agent/non_windows_accounts.go
++++ b/google_guest_agent/non_windows_accounts.go
+@@ -104,15 +104,6 @@ func (a *accountsMgr) set() error {
+ 		sshKeys = make(map[string][]string)
+ 	}
+ 
+-	logger.Debugf("create sudoers file if needed")
+-	if err := createSudoersFile(); err != nil {
+-		logger.Errorf("Error creating google-sudoers file: %v.", err)
+-	}
+-	logger.Debugf("create sudoers group if needed")
+-	if err := createSudoersGroup(); err != nil {
+-		logger.Errorf("Error creating google-sudoers group: %v.", err)
+-	}
+-
+ 	mdkeys := newMetadata.Instance.Attributes.SSHKeys
+ 	if !newMetadata.Instance.Attributes.BlockProjectKeys {
+ 		mdkeys = append(mdkeys, newMetadata.Project.Attributes.SSHKeys...)
+diff --git a/google_guest_agent/oslogin.go b/google_guest_agent/oslogin.go
+index d05f733..980e84c 100644
+--- a/google_guest_agent/oslogin.go
++++ b/google_guest_agent/oslogin.go
+@@ -76,7 +76,7 @@ func (o *osloginMgr) timeout() bool {
+ }
+ 
+ func (o *osloginMgr) disabled(os string) bool {
+-	return os == "windows"
++	return true
+ }
+ 
+ func (o *osloginMgr) set() error {
+-- 
+2.34.1
+
diff --git a/pkgs/tools/virtualization/google-guest-agent/fix-paths.patch b/pkgs/tools/virtualization/google-guest-agent/fix-paths.patch
new file mode 100644
index 00000000000..07bb112ae28
--- /dev/null
+++ b/pkgs/tools/virtualization/google-guest-agent/fix-paths.patch
@@ -0,0 +1,43 @@
+diff --git a/google-guest-agent.service b/google-guest-agent.service
+index 79b8e39..a39097b 100644
+--- a/google-guest-agent.service
++++ b/google-guest-agent.service
+@@ -14,7 +14,7 @@ PartOf=network.service networking.service NetworkManager.service systemd-network
+ 
+ [Service]
+ Type=notify
+-ExecStart=/usr/bin/google_guest_agent
++ExecStart=@out@/bin/google_guest_agent
+ OOMScoreAdjust=-999
+ Restart=always
+ 
+diff --git a/google-shutdown-scripts.service b/google-shutdown-scripts.service
+index 16bb9c2..ae02067 100644
+--- a/google-shutdown-scripts.service
++++ b/google-shutdown-scripts.service
+@@ -5,10 +5,10 @@ After=network-online.target rsyslog.service
+ 
+ [Service]
+ Type=oneshot
+-ExecStart=/bin/true
++ExecStart=@true@
+ RemainAfterExit=true
+ # This service does nothing on start, and runs shutdown scripts on stop.
+-ExecStop=/usr/bin/google_metadata_script_runner shutdown
++ExecStop=@out@/bin/google_metadata_script_runner shutdown
+ TimeoutStopSec=0
+ KillMode=process
+ 
+diff --git a/google-startup-scripts.service b/google-startup-scripts.service
+index dfc9838..2465265 100644
+--- a/google-startup-scripts.service
++++ b/google-startup-scripts.service
+@@ -6,7 +6,7 @@ Before=apt-daily.service
+ 
+ [Service]
+ Type=oneshot
+-ExecStart=/usr/bin/google_metadata_script_runner startup
++ExecStart=@out@/bin/google_metadata_script_runner startup
+ #TimeoutStartSec is ignored for Type=oneshot service units.
+ KillMode=process
+ 
diff --git a/pkgs/tools/virtualization/google-guest-configs/default.nix b/pkgs/tools/virtualization/google-guest-configs/default.nix
new file mode 100644
index 00000000000..dd3c01c6229
--- /dev/null
+++ b/pkgs/tools/virtualization/google-guest-configs/default.nix
@@ -0,0 +1,52 @@
+{ stdenv, lib, fetchFromGitHub, makeWrapper, substituteAll
+, ipcalc, iproute2, util-linux, coreutils, ethtool, gnugrep, gnused, nvme-cli }:
+
+stdenv.mkDerivation rec {
+  pname = "google-guest-configs";
+  version = "20211116.00";
+
+  src = fetchFromGitHub {
+    owner = "GoogleCloudPlatform";
+    repo = "guest-configs";
+    rev = version;
+    sha256 = "sha256-0SRu6p/DsHNNI20mkXJitt/Ee5S2ooiy5hNmD+ndecM=";
+  };
+
+  binDeps = lib.makeBinPath [ coreutils util-linux gnugrep gnused ethtool ipcalc iproute2 ];
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  dontConfigure = true;
+  dontBuild = true;
+
+  postPatch = ''
+    substitute ${./fix-paths.patch} fix-paths.patch \
+      --subst-var out \
+      --subst-var-by nvme "${nvme-cli}/bin/nvme" \
+      --subst-var-by sh "${stdenv.shell}" \
+      --subst-var-by umount "${util-linux}/bin/umount" \
+      --subst-var-by logger "${util-linux}/bin/logger"
+    patch -p1 < ./fix-paths.patch
+  '';
+
+  installPhase = ''
+    mkdir -p $out/{bin,etc,lib}
+    cp -r src/etc/{modprobe.d,sysctl.d} $out/etc
+    cp -r src/lib/udev $out/lib
+    cp -r src/sbin/* $out/bin
+    cp -r src/usr/bin/* $out/bin
+
+    for i in $out/bin/* $out/lib/udev/google_nvme_id; do
+      wrapProgram "$i" \
+        --prefix "PATH" ":" "$binDeps"
+    done
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/GoogleCloudPlatform/guest-configs";
+    description = "Linux Guest Environment for Google Compute Engine";
+    license = licenses.asl20;
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ abbradar ];
+  };
+}
diff --git a/pkgs/tools/virtualization/google-guest-configs/fix-paths.patch b/pkgs/tools/virtualization/google-guest-configs/fix-paths.patch
new file mode 100644
index 00000000000..7c9a86f1060
--- /dev/null
+++ b/pkgs/tools/virtualization/google-guest-configs/fix-paths.patch
@@ -0,0 +1,61 @@
+diff -ru3 source.old/src/lib/udev/google_nvme_id source.new/src/lib/udev/google_nvme_id
+--- source.old/src/lib/udev/google_nvme_id	1970-01-01 03:00:01.000000000 +0300
++++ source.new/src/lib/udev/google_nvme_id	2022-02-05 13:30:00.986242869 +0300
+@@ -17,7 +17,7 @@
+ # the metadata server
+ 
+ # Locations of the script's dependencies
+-readonly nvme_cli_bin=/usr/sbin/nvme
++readonly nvme_cli_bin=@nvme@
+ 
+ # Bash regex to parse device paths and controller identification
+ readonly NAMESPACE_NUMBER_REGEX="/dev/nvme[[:digit:]]+n([[:digit:]]+).*"
+diff -ru3 source.old/src/lib/udev/rules.d/64-gce-disk-removal.rules source.new/src/lib/udev/rules.d/64-gce-disk-removal.rules
+--- source.old/src/lib/udev/rules.d/64-gce-disk-removal.rules	1970-01-01 03:00:01.000000000 +0300
++++ source.new/src/lib/udev/rules.d/64-gce-disk-removal.rules	2022-02-05 13:27:42.635300567 +0300
+@@ -14,4 +14,4 @@
+ #
+ # When a disk is removed, unmount any remaining attached volumes.
+ 
+-ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd*|vd*|nvme*", RUN+="/bin/sh -c '/bin/umount -fl /dev/$name && /usr/bin/logger -p daemon.warn -s WARNING: hot-removed /dev/$name that was still mounted, data may have been corrupted'"
++ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd*|vd*|nvme*", RUN+="@sh@ -c '@umount@ -fl /dev/$name && @logger@ -p daemon.warn -s WARNING: hot-removed /dev/$name that was still mounted, data may have been corrupted'"
+diff -ru3 source.old/src/lib/udev/rules.d/65-gce-disk-naming.rules source.new/src/lib/udev/rules.d/65-gce-disk-naming.rules
+--- source.old/src/lib/udev/rules.d/65-gce-disk-naming.rules	1970-01-01 03:00:01.000000000 +0300
++++ source.new/src/lib/udev/rules.d/65-gce-disk-naming.rules	2022-02-05 13:27:05.053107964 +0300
+@@ -21,11 +21,11 @@
+ KERNEL=="sd*|vd*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode"
+ 
+ # NVME Local SSD naming
+-KERNEL=="nvme*n*", ATTRS{model}=="nvme_card", PROGRAM="/bin/sh -c 'nsid=$$(echo %k|sed -re s/nvme[0-9]+n\([0-9]+\).\*/\\1/); echo $$((nsid-1))'", ENV{ID_SERIAL_SHORT}="local-nvme-ssd-%c"
++KERNEL=="nvme*n*", ATTRS{model}=="nvme_card", PROGRAM="@sh@ -c 'nsid=$$(echo %k|sed -re s/nvme[0-9]+n\([0-9]+\).\*/\\1/); echo $$((nsid-1))'", ENV{ID_SERIAL_SHORT}="local-nvme-ssd-%c"
+ KERNEL=="nvme*", ATTRS{model}=="nvme_card", ENV{ID_SERIAL}="Google_EphemeralDisk_$env{ID_SERIAL_SHORT}"
+ 
+ # NVME Persistent Disk Naming
+-KERNEL=="nvme*n*", ATTRS{model}=="nvme_card-pd", IMPORT{program}="google_nvme_id -d $tempnode"
++KERNEL=="nvme*n*", ATTRS{model}=="nvme_card-pd", IMPORT{program}="@out@/lib/udev/google_nvme_id -d $tempnode"
+ 
+ # Symlinks
+ KERNEL=="sd*|vd*|nvme*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/google-$env{ID_SERIAL_SHORT}"
+diff -ru3 source.old/src/sbin/google-dhclient-script source.new/src/sbin/google-dhclient-script
+--- source.old/src/sbin/google-dhclient-script	1970-01-01 03:00:01.000000000 +0300
++++ source.new/src/sbin/google-dhclient-script	2022-02-05 13:29:37.430058984 +0300
+@@ -31,7 +31,6 @@
+ # This script is found in EL 7 and used to fix local routing in EL 6.
+ # ----------
+ 
+-PATH=/bin:/usr/bin:/sbin
+ # scripts in dhclient.d/ use $SAVEDIR (#833054)
+ SAVEDIR=/var/lib/dhclient
+ 
+@@ -58,9 +57,9 @@
+     if need_hostname; then
+         status=1
+         if [ -n "${new_ip_address}" ]; then
+-            eval $(/bin/ipcalc --silent --hostname ${new_ip_address} ; echo "status=$?")
++            eval $(ipcalc --silent --hostname ${new_ip_address} ; echo "status=$?")
+         elif [ -n "${new_ip6_address}" ]; then
+-            eval $(/bin/ipcalc --silent --hostname ${new_ip6_address} ; echo "status=$?")
++            eval $(ipcalc --silent --hostname ${new_ip6_address} ; echo "status=$?")
+         fi
+ 
+         if [ ${status} -eq 0 ]; then
diff --git a/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix b/pkgs/tools/virtualization/google-guest-oslogin/default.nix
index 0718e437b06..6dceeecfd6e 100644
--- a/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix
+++ b/pkgs/tools/virtualization/google-guest-oslogin/default.nix
@@ -9,38 +9,39 @@
 }:
 
 stdenv.mkDerivation rec {
-  pname = "google-compute-engine-oslogin";
-  version = "20210429.00";
+  pname = "google-guest-oslogin";
+  version = "20211213.00";
 
   src = fetchFromGitHub {
     owner = "GoogleCloudPlatform";
     repo = "guest-oslogin";
     rev = version;
-    sha256 = "eHAg9K5oxcygEzqaac81jSFHF+zsW6uB7q2Kfo9hSrA=";
+    sha256 = "sha256-8RuLYdWfk8zPfoF06r5E/6eHQ7tziZbgGhZlLCUW600=";
   };
 
   postPatch = ''
     # change sudoers dir from /var/google-sudoers.d to /run/google-sudoers.d (managed through systemd-tmpfiles)
     substituteInPlace src/pam/pam_oslogin_admin.cc --replace /var/google-sudoers.d /run/google-sudoers.d
     # fix "User foo not allowed because shell /bin/bash does not exist"
-    substituteInPlace src/include/compat.h --replace /bin/bash ${bashInteractive}/bin/bash
+    substituteInPlace src/include/compat.h --replace /bin/bash /run/current-system/sw/bin/bash
   '';
 
-  buildInputs = [ curl.dev pam ];
+  buildInputs = [ curl.dev pam json_c ];
 
-  NIX_CFLAGS_COMPILE = "-I${json_c.dev}/include/json-c";
-  NIX_CFLAGS_LINK = "-L${json_c}/lib";
+  NIX_CFLAGS_COMPILE = [ "-I${json_c.dev}/include/json-c" ];
 
   makeFlags = [
     "VERSION=${version}"
-    "DESTDIR=${placeholder "out"}"
-    "PREFIX=/"
-    "BINDIR=/bin"
-    "LIBDIR=/lib"
-    "PAMDIR=/lib"
-    "MANDIR=/share/man"
+    "PREFIX=$(out)"
+    "MANDIR=$(out)/share/man"
+    "SYSTEMDDIR=$(out)/etc/systemd/system"
+    "PRESETDIR=$(out)/etc/systemd/system-preset"
   ];
 
+  postInstall = ''
+    sed -i "s,/usr/bin/,$out/bin/,g" $out/etc/systemd/system/google-oslogin-cache.service
+  '';
+
   enableParallelBuilding = true;
 
   passthru.tests = {
@@ -51,6 +52,7 @@ stdenv.mkDerivation rec {
     homepage = "https://github.com/GoogleCloudPlatform/compute-image-packages";
     description = "OS Login Guest Environment for Google Compute Engine";
     license = licenses.asl20;
+    platforms = platforms.linux;
     maintainers = with maintainers; [ flokli ];
   };
 }
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index f34c38a6766..48d3aa18db7 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -6119,12 +6119,16 @@ with pkgs;
 
   google-compute-engine = with python38.pkgs; toPythonApplication google-compute-engine;
 
-  google-compute-engine-oslogin = callPackage ../tools/virtualization/google-compute-engine-oslogin { };
+  google-guest-oslogin = callPackage ../tools/virtualization/google-guest-oslogin { };
 
   google-cloud-cpp = callPackage ../development/libraries/google-cloud-cpp { };
 
   google-java-format = callPackage ../development/tools/google-java-format { };
 
+  google-guest-agent = callPackage ../tools/virtualization/google-guest-agent { };
+
+  google-guest-configs = callPackage ../tools/virtualization/google-guest-configs { };
+
   gdown = with python3Packages; toPythonApplication gdown;
 
   gopro = callPackage ../tools/video/gopro { };