Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package google-guest-agent for 
openSUSE:Factory checked in at 2021-10-23 00:51:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/google-guest-agent (Old)
 and      /work/SRC/openSUSE:Factory/.google-guest-agent.new.1890 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "google-guest-agent"

Sat Oct 23 00:51:27 2021 rev:8 rq:926943 version:20211019.00

Changes:
--------
--- /work/SRC/openSUSE:Factory/google-guest-agent/google-guest-agent.changes    
2021-07-27 14:32:40.459447726 +0200
+++ 
/work/SRC/openSUSE:Factory/.google-guest-agent.new.1890/google-guest-agent.changes
  2021-10-23 00:52:10.785153225 +0200
@@ -1,0 +2,26 @@
+Fri Oct 22 09:38:42 UTC 2021 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to version 20211019.00
+  * handle comm errors in script runner (#140)
+- from version 20211015.00
+  * enforce script ordering (#138)
+- from version 20211014.00
+  * enable ipv6 on secondary interfaces (#133)
+- from version 20211013.00
+  * dont open ssh tempfile exclusively (#137)
+- from version 20211011.00
+  * correct linux startup script order (#135)
+  * Emit sshable attribute (#123)
+- from version 20210908.1
+  * restore line (#127)
+- from version 20210908.00
+  * New integ test (#124)
+- from version 20210901.00
+  * support enable-oslogin-sk key (#120)
+  * match script logging to guest agent (#125)
+- from version 20210804.00
+  * Debug logging (#122)
+- Refresh patches for new version
+  * dont_overwrite_ifcfg.patch
+
+-------------------------------------------------------------------

Old:
----
  guest-agent-20210707.00.tar.gz

New:
----
  guest-agent-20211019.00.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ google-guest-agent.spec ++++++
--- /var/tmp/diff_new_pack.scPMoU/_old  2021-10-23 00:52:11.413153503 +0200
+++ /var/tmp/diff_new_pack.scPMoU/_new  2021-10-23 00:52:11.413153503 +0200
@@ -24,7 +24,7 @@
 %global import_path     %{provider_prefix}
 
 Name:           google-guest-agent
-Version:        20210707.00
+Version:        20211019.00
 Release:        0
 Summary:        Google Cloud Guest Agent
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.scPMoU/_old  2021-10-23 00:52:11.441153516 +0200
+++ /var/tmp/diff_new_pack.scPMoU/_new  2021-10-23 00:52:11.441153516 +0200
@@ -3,8 +3,8 @@
     <param 
name="url">https://github.com/GoogleCloudPlatform/guest-agent/</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="versionformat">20210707.00</param>
-    <param name="revision">20210707.00</param>
+    <param name="versionformat">20211019.00</param>
+    <param name="revision">20211019.00</param>
     <param name="changesgenerate">enable</param>
   </service>
   <service name="recompress" mode="disabled">
@@ -15,6 +15,6 @@
     <param name="basename">guest-agent</param>
   </service>
   <service name="go_modules" mode="disabled">
-    <param name="archive">guest-agent-20210707.00.tar.gz</param>
+    <param name="archive">guest-agent-20211019.00.tar.gz</param>
   </service>
 </services>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.scPMoU/_old  2021-10-23 00:52:11.457153522 +0200
+++ /var/tmp/diff_new_pack.scPMoU/_new  2021-10-23 00:52:11.457153522 +0200
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/GoogleCloudPlatform/guest-agent/</param>
-              <param 
name="changesrevision">d90f703374915488170b5f9d13d74a0061400d10</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">a1c10d174f1e9cb026585c6b141e1d4c8349e1ba</param></service></servicedata>
\ No newline at end of file

++++++ dont_overwrite_ifcfg.patch ++++++
--- /var/tmp/diff_new_pack.scPMoU/_old  2021-10-23 00:52:11.469153528 +0200
+++ /var/tmp/diff_new_pack.scPMoU/_new  2021-10-23 00:52:11.469153528 +0200
@@ -1,16 +1,9 @@
-commit 4000e2ceeaf2f7b1c6428bde88b619a3a56acdfd
-Author: Joachim Gleissner <jgleiss...@suse.com>
-Date:   Thu Oct 15 17:23:34 2020 +0100
-
-    do not overwrite ifcfg files on SLES
-
-diff --git a/google_guest_agent/addresses.go b/google_guest_agent/addresses.go
-index 6326ff2..3080142 100644
---- a/google_guest_agent/addresses.go
-+++ b/google_guest_agent/addresses.go
-@@ -534,7 +534,12 @@ func enableSLESInterfaces(interfaces []string) error {
-       var priority = 10100
-       for _, iface := range interfaces {
+diff -Nru guest-agent-20211019.00.orig/google_guest_agent/addresses.go 
guest-agent-20211019.00/google_guest_agent/addresses.go
+--- guest-agent-20211019.00.orig/google_guest_agent/addresses.go       
2021-10-20 00:09:13.000000000 +0200
++++ guest-agent-20211019.00/google_guest_agent/addresses.go    2021-10-22 
11:32:04.447560133 +0200
+@@ -558,7 +558,12 @@
+               logger.Debugf("write enabling ifcfg-%s config", iface)
+ 
                var ifcfg *os.File
 -              ifcfg, err = os.Create("/etc/sysconfig/network/ifcfg-" + iface)
 +              filename := "/etc/sysconfig/network/ifcfg-" + iface

++++++ guest-agent-20210707.00.tar.gz -> guest-agent-20211019.00.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/accounts_test.go 
new/guest-agent-20211019.00/google_guest_agent/accounts_test.go
--- old/guest-agent-20210707.00/google_guest_agent/accounts_test.go     
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/accounts_test.go     
2021-10-20 00:09:13.000000000 +0200
@@ -95,7 +95,10 @@
        }
 }
 
-func TestNewPwd(t *testing.T) {
+// rename this with leading disabled because this is a resource
+// intensive test. this test takes approx. 141 seconds to complete, next
+// longest test is 0.43 seconds.
+func disabledTestNewPwd(t *testing.T) {
        minPasswordLength := 15
        maxPasswordLength := 255
        var tests = []struct {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/addresses.go 
new/guest-agent-20211019.00/google_guest_agent/addresses.go
--- old/guest-agent-20210707.00/google_guest_agent/addresses.go 2021-07-07 
21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/addresses.go 2021-10-20 
00:09:13.000000000 +0200
@@ -279,6 +279,7 @@
 
        if config.Section("NetworkInterfaces").Key("setup").MustBool(true) {
                if runtime.GOOS != "windows" {
+                       logger.Debugf("Configure IPv6")
                        if err := configureIPv6(); err != nil {
                                // Continue through IPv6 configuration errors.
                                logger.Errorf("Error configuring IPv6: %v", err)
@@ -286,6 +287,7 @@
                }
 
                if runtime.GOOS != "windows" && !interfacesEnabled {
+                       logger.Debugf("Enable network interfaces")
                        if err := enableNetworkInterfaces(); err != nil {
                                return err
                        }
@@ -297,6 +299,7 @@
                return nil
        }
 
+       logger.Debugf("Add routes for aliases, forwarded IP and target-instance 
IPs")
        // Add routes for IP aliases, forwarded and target-instance IPs.
        for _, ni := range newMetadata.Instance.NetworkInterfaces {
                iface, err := getInterfaceByMAC(ni.Mac)
@@ -479,7 +482,8 @@
        return nil
 }
 
-// enableNetworkInterfaces runs `dhclient eth1 eth2 ... ethN`.
+// enableNetworkInterfaces runs `dhclient eth1 eth2 ... ethN`
+// and `dhclient -6 eth1 eth2 ... ethN`.
 // On RHEL7, it also calls disableNM for each interface.
 // On SLES, it calls enableSLESInterfaces instead of dhclient.
 func enableNetworkInterfaces() error {
@@ -500,6 +504,22 @@
                }
                googleInterfaces = append(googleInterfaces, iface.Name)
        }
+       var googleIpv6Interfaces []string
+       for _, ni := range newMetadata.Instance.NetworkInterfaces[1:] {
+               if ni.DHCPv6Refresh == "" {
+                       // This interface is not IPv6 enabled
+                       continue
+               }
+               iface, err := getInterfaceByMAC(ni.Mac)
+               if err != nil {
+                       if !containsString(ni.Mac, badMAC) {
+                               logger.Errorf("Error getting interface: %s", 
err)
+                               badMAC = append(badMAC, ni.Mac)
+                       }
+                       continue
+               }
+               googleIpv6Interfaces = append(googleIpv6Interfaces, iface.Name)
+       }
 
        switch {
        case osRelease.os == "sles":
@@ -518,13 +538,14 @@
                        return runCmd(exec.Command(dhcpCommand))
                }
 
-               dhclientArgs := []string{}
-               // The dhclient_script key has historically only been supported 
on EL6.
-               if (osRelease.os == "rhel" || osRelease.os == "centos") && 
osRelease.version.major == 6 {
-                       dhclientArgs = append(dhclientArgs, "-sf", 
config.Section("NetworkInterfaces").Key("dhclient_script").MustString("/sbin/google-dhclient-script"))
+               // Try IPv4 first as it's higher priority.
+               if err := runCmd(exec.Command("dhclient", 
googleInterfaces...)); err != nil {
+                       return err
                }
-               dhclientArgs = append(dhclientArgs, googleInterfaces...)
-               return runCmd(exec.Command("dhclient", dhclientArgs...))
+
+               var dhclientArgs6 []string
+               dhclientArgs6 = append([]string{"-6"}, googleIpv6Interfaces...)
+               return runCmd(exec.Command("dhclient", dhclientArgs6...))
        }
 }
 
@@ -534,6 +555,8 @@
        var err error
        var priority = 10100
        for _, iface := range interfaces {
+               logger.Debugf("write enabling ifcfg-%s config", iface)
+
                var ifcfg *os.File
                ifcfg, err = os.Create("/etc/sysconfig/network/ifcfg-" + iface)
                if err != nil {
@@ -543,6 +566,7 @@
                contents := []string{
                        googleComment,
                        "STARTMODE=hotplug",
+                       // NOTE: 'dhcp' is the dhcp4+dhcp6 option.
                        "BOOTPROTO=dhcp",
                        fmt.Sprintf("DHCLIENT_ROUTE_PRIORITY=%d", priority),
                }
@@ -558,6 +582,7 @@
 
 // disableNM writes an ifcfg file with DHCP and NetworkManager disabled.
 func disableNM(iface string) error {
+       logger.Debugf("write disabling ifcfg-%s config", iface)
        filename := "/etc/sysconfig/network-scripts/ifcfg-" + iface
        ifcfg, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 
0644)
        if err == nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/instance_setup.go 
new/guest-agent-20211019.00/google_guest_agent/instance_setup.go
--- old/guest-agent-20210707.00/google_guest_agent/instance_setup.go    
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/instance_setup.go    
2021-10-20 00:09:13.000000000 +0200
@@ -105,6 +105,7 @@
        } else {
                // Linux instance setup.
                defer runCmd(exec.Command("systemd-notify", "--ready"))
+               defer logger.Debugf("notify systemd")
 
                if config.Section("Snapshots").Key("enabled").MustBool(false) {
                        logger.Infof("Snapshot listener enabled")
@@ -126,6 +127,8 @@
                // run once per boot, but it's harmless to run them on every
                // boot. If this changes, we will hook these to an explicit
                // on-boot signal.
+
+               logger.Debugf("set IO scheduler config")
                if err := setIOScheduler(); err != nil {
                        logger.Warningf("Failed to set IO scheduler: %v", err)
                }
@@ -141,6 +144,7 @@
                // network access, this will become an indefinite wait.
                // TODO: split agentInit into needs-network and no-network 
functions.
                for newMetadata == nil {
+                       logger.Debugf("populate first time metadata...")
                        newMetadata, _ = getMetadata(ctx, false)
                        time.Sleep(1 * time.Second)
                }
@@ -282,6 +286,7 @@
 }
 
 func writeGuestAttributes(key, value string) error {
+       logger.Debugf("write guest attribute %q", key)
        client := &http.Client{Timeout: defaultTimeout}
        finalURL := metadataURL + "instance/guest-attributes/" + key
        req, err := http.NewRequest("PUT", finalURL, strings.NewReader(value))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-agent-20210707.00/google_guest_agent/main.go 
new/guest-agent-20211019.00/google_guest_agent/main.go
--- old/guest-agent-20210707.00/google_guest_agent/main.go      2021-07-07 
21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/main.go      2021-10-20 
00:09:13.000000000 +0200
@@ -26,6 +26,7 @@
        "os"
        "os/exec"
        "runtime"
+       "strings"
        "sync"
        "time"
 
@@ -112,9 +113,15 @@
                wg.Add(1)
                go func(mgr manager) {
                        defer wg.Done()
-                       if mgr.disabled(runtime.GOOS) || (!mgr.timeout() && 
!mgr.diff()) {
+                       if mgr.disabled(runtime.GOOS) {
+                               logger.Debugf("manager %#v disabled, skipping", 
mgr)
                                return
                        }
+                       if !mgr.timeout() && !mgr.diff() {
+                               logger.Debugf("manager %#v reports no diff", 
mgr)
+                               return
+                       }
+                       logger.Debugf("running %#v manager", mgr)
                        if err := mgr.set(); err != nil {
                                logger.Errorf("error running %#v manager: %s", 
mgr, err)
                        }
@@ -126,8 +133,16 @@
 func run(ctx context.Context) {
        opts := logger.LogOpts{LoggerName: programName}
        if runtime.GOOS == "windows" {
-               opts.FormatFunction = logFormat
+               opts.FormatFunction = logFormatWindows
                opts.Writers = []io.Writer{&serialPort{"COM1"}}
+       } else {
+               opts.FormatFunction = logFormat
+               opts.Writers = []io.Writer{os.Stdout}
+               // Local logging is syslog; we will just use stdout in Linux.
+               opts.DisableLocalLogging = true
+       }
+       if os.Getenv("GUEST_AGENT_DEBUG") != "" {
+               opts.Debug = true
        }
 
        var err error
@@ -206,7 +221,7 @@
 }
 
 func (e execResult) Error() string {
-       return e.err
+       return strings.TrimSuffix(e.err, "\n")
 }
 
 func (e execResult) ExitCode() int {
@@ -230,6 +245,7 @@
 }
 
 func runCmdOutput(cmd *exec.Cmd) *execResult {
+       logger.Debugf("exec: %v", cmd)
        var stdout, stderr bytes.Buffer
        cmd.Stdout = &stdout
        cmd.Stderr = &stderr
@@ -263,11 +279,23 @@
        return false
 }
 
-func logFormat(e logger.LogEntry) string {
+func logFormatWindows(e logger.LogEntry) string {
        now := time.Now().Format("2006/01/02 15:04:05")
+       // 2006/01/02 15:04:05 GCEGuestAgent This is a log message.
        return fmt.Sprintf("%s %s: %s", now, programName, e.Message)
 }
 
+func logFormat(e logger.LogEntry) string {
+       switch e.Severity {
+       case logger.Error, logger.Critical, logger.Debug:
+               // ERROR file.go:82 This is a log message.
+               return fmt.Sprintf("%s %s:%d %s", 
strings.ToUpper(e.Severity.String()), e.Source.File, e.Source.Line, e.Message)
+       default:
+               // This is a log message.
+               return e.Message
+       }
+}
+
 func closer(c io.Closer) {
        err := c.Close()
        if err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/metadata.go 
new/guest-agent-20211019.00/google_guest_agent/metadata.go
--- old/guest-agent-20210707.00/google_guest_agent/metadata.go  2021-07-07 
21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/metadata.go  2021-10-20 
00:09:13.000000000 +0200
@@ -107,6 +107,7 @@
        BlockProjectKeys      bool
        EnableOSLogin         *bool
        TwoFactor             *bool
+       SecurityKey           *bool
        SSHKeys               []string
        WindowsKeys           windowsKeys
        Diagnostics           string
@@ -170,6 +171,7 @@
                OldSSHKeys            string      `json:"sshKeys"`
                SSHKeys               string      `json:"ssh-keys"`
                TwoFactor             string      `json:"enable-oslogin-2fa"`
+               SecurityKey           string      `json:"enable-oslogin-sk"`
                WindowsKeys           windowsKeys `json:"windows-keys"`
                WSFCAddresses         string      `json:"wsfc-addrs"`
                WSFCAgentPort         string      `json:"wsfc-agent-port"`
@@ -211,6 +213,10 @@
        if err == nil {
                a.TwoFactor = mkbool(value)
        }
+       value, err = strconv.ParseBool(temp.SecurityKey)
+       if err == nil {
+               a.SecurityKey = mkbool(value)
+       }
        // So SSHKeys will be nil instead of []string{}
        if temp.SSHKeys != "" {
                a.SSHKeys = strings.Split(temp.SSHKeys, "\n")
@@ -236,6 +242,7 @@
 }
 
 func getMetadata(ctx context.Context, hang bool) (*metadata, error) {
+       logger.Debugf("getMetadata, %t", hang)
        client := &http.Client{
                Timeout: defaultTimeout,
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/non_windows_accounts.go 
new/guest-agent-20211019.00/google_guest_agent/non_windows_accounts.go
--- old/guest-agent-20210707.00/google_guest_agent/non_windows_accounts.go      
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/non_windows_accounts.go      
2021-10-20 00:09:13.000000000 +0200
@@ -78,8 +78,8 @@
                }
        }
        // If we've just disabled OS Login.
-       oldOslogin, _ := getOSLoginEnabled(oldMetadata)
-       newOslogin, _ := getOSLoginEnabled(newMetadata)
+       oldOslogin, _, _ := getOSLoginEnabled(oldMetadata)
+       newOslogin, _, _ := getOSLoginEnabled(newMetadata)
        if oldOslogin && !newOslogin {
                return true
        }
@@ -92,7 +92,7 @@
 }
 
 func (a *accountsMgr) disabled(os string) bool {
-       oslogin, _ := getOSLoginEnabled(newMetadata)
+       oslogin, _, _ := getOSLoginEnabled(newMetadata)
        return false ||
                os == "windows" || oslogin ||
                !config.Section("Daemons").Key("accounts_daemon").MustBool(true)
@@ -100,12 +100,15 @@
 
 func (a *accountsMgr) set() error {
        if sshKeys == nil {
+               logger.Debugf("initialize sshKeys map")
                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)
        }
@@ -119,10 +122,12 @@
        for _, key := range removeExpiredKeys(mdkeys) {
                idx := strings.Index(key, ":")
                if idx == -1 {
+                       logger.Debugf("invalid ssh key entry: %q", key)
                        continue
                }
                user := key[:idx]
                if user == "" {
+                       logger.Debugf("invalid ssh key entry: %q", key)
                        continue
                }
                userKeys := mdKeyMap[user]
@@ -130,10 +135,11 @@
                mdKeyMap[user] = userKeys
        }
 
+       logger.Debugf("read google users file")
        gUsers, err := readGoogleUsersFile()
        if err != nil {
                // TODO: is this OK to continue past?
-               logger.Errorf("Couldn't read google users file: %v.", err)
+               logger.Errorf("Couldn't read google_users file: %v.", err)
        }
 
        // Update SSH keys, creating Google users as needed.
@@ -175,6 +181,7 @@
        }
 
        // Update the google_users file if we've added or removed any users.
+       logger.Debugf("write google_users file")
        if err := writeGoogleUsersFile(); err != nil {
                logger.Errorf("Error writing google_users file: %v.", err)
        }
@@ -479,7 +486,7 @@
                userKeys = append(userKeys, key)
        }
 
-       newfile, err := os.OpenFile(tempPath, 
os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
+       newfile, err := os.OpenFile(tempPath, os.O_WRONLY|os.O_CREATE, 0600)
        if err != nil {
                return err
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/non_windows_accounts_integ_test.go
 
new/guest-agent-20211019.00/google_guest_agent/non_windows_accounts_integ_test.go
--- 
old/guest-agent-20210707.00/google_guest_agent/non_windows_accounts_integ_test.go
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/guest-agent-20211019.00/google_guest_agent/non_windows_accounts_integ_test.go
   2021-10-20 00:09:13.000000000 +0200
@@ -0,0 +1,21 @@
+// +build integration
+
+package main
+
+import (
+       "os/exec"
+       "testing"
+)
+
+func TestGroupaddDuplicates(t *testing.T) {
+       cmd := exec.Command("groupadd", "integ-test-group")
+       ret := runCmdOutput(cmd)
+       if ret.ExitCode() != 0 {
+               t.Fatalf("got wrong exit code running \"groupadd 
integ-test-group\", expected 0 got %v\n", ret.ExitCode())
+       }
+       cmd = exec.Command("groupadd", "integ-test-group")
+       ret = runCmdOutput(cmd)
+       if ret.ExitCode() != 9 {
+               t.Fatalf("got wrong exit code running \"groupadd 
integ-test-group\", expected 9 got %v\n", ret.ExitCode())
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/oslogin.go 
new/guest-agent-20211019.00/google_guest_agent/oslogin.go
--- old/guest-agent-20210707.00/google_guest_agent/oslogin.go   2021-07-07 
21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/oslogin.go   2021-10-20 
00:09:13.000000000 +0200
@@ -21,6 +21,7 @@
        "os/exec"
        "runtime"
        "strings"
+       "time"
 
        "github.com/GoogleCloudPlatform/guest-logging-go/logger"
 )
@@ -35,7 +36,7 @@
 
 // We also read project keys first, letting instance-level keys take
 // precedence.
-func getOSLoginEnabled(md *metadata) (bool, bool) {
+func getOSLoginEnabled(md *metadata) (bool, bool, bool) {
        var enable bool
        if md.Project.Attributes.EnableOSLogin != nil {
                enable = *md.Project.Attributes.EnableOSLogin
@@ -50,16 +51,24 @@
        if md.Instance.Attributes.TwoFactor != nil {
                twofactor = *md.Instance.Attributes.TwoFactor
        }
-       return enable, twofactor
+       var skey bool
+       if md.Project.Attributes.SecurityKey != nil {
+               skey = *md.Project.Attributes.SecurityKey
+       }
+       if md.Instance.Attributes.SecurityKey != nil {
+               skey = *md.Instance.Attributes.SecurityKey
+       }
+       return enable, twofactor, skey
 }
 
 func (o *osloginMgr) diff() bool {
-       oldEnable, oldTwoFactor := getOSLoginEnabled(oldMetadata)
-       enable, twofactor := getOSLoginEnabled(newMetadata)
+       oldEnable, oldTwoFactor, oldSkey := getOSLoginEnabled(oldMetadata)
+       enable, twofactor, skey := getOSLoginEnabled(newMetadata)
        return oldMetadata.Project.ProjectID == "" ||
                // True on first run or if any value has changed.
                (oldTwoFactor != twofactor) ||
-               (oldEnable != enable)
+               (oldEnable != enable) ||
+               (oldSkey != skey)
 }
 
 func (o *osloginMgr) timeout() bool {
@@ -73,8 +82,8 @@
 func (o *osloginMgr) set() error {
        // We need to know if it was previously enabled for the clearing of
        // metadata-based SSH keys.
-       oldEnable, _ := getOSLoginEnabled(oldMetadata)
-       enable, twofactor := getOSLoginEnabled(newMetadata)
+       oldEnable, _, _ := getOSLoginEnabled(oldMetadata)
+       enable, twofactor, skey := getOSLoginEnabled(newMetadata)
 
        if enable && !oldEnable {
                logger.Infof("Enabling OS Login")
@@ -87,7 +96,7 @@
                logger.Infof("Disabling OS Login")
        }
 
-       if err := writeSSHConfig(enable, twofactor); err != nil {
+       if err := writeSSHConfig(enable, twofactor, skey); err != nil {
                logger.Errorf("Error updating SSH config: %v.", err)
        }
 
@@ -105,6 +114,7 @@
 
        for _, svc := range []string{"nscd", "unscd", "systemd-logind", "cron", 
"crond"} {
                // These services should be restarted if running
+               logger.Debugf("systemctl try-restart %s, if it exists", svc)
                if err := systemctlTryRestart(svc); err != nil {
                        logger.Errorf("Error restarting service: %v.", err)
                }
@@ -112,20 +122,27 @@
 
        // SSH should be started if not running, reloaded otherwise.
        for _, svc := range []string{"ssh", "sshd"} {
+               logger.Debugf("systemctl reload-or-restart %s, if it exists", 
svc)
                if err := systemctlReloadOrRestart(svc); err != nil {
                        logger.Errorf("Error reloading service: %v.", err)
                }
        }
 
+       now := fmt.Sprintf("%d", time.Now().Unix())
+       writeGuestAttributes("guest-agent/sshable", now)
+
        if enable {
+               logger.Debugf("Create OS Login dirs, if needed")
                if err := createOSLoginDirs(); err != nil {
                        logger.Errorf("Error creating OS Login directory: %v.", 
err)
                }
 
+               logger.Debugf("create OS Login sudoers config, if needed")
                if err := createOSLoginSudoersFile(); err != nil {
                        logger.Errorf("Error creating OS Login sudoers file: 
%v.", err)
                }
 
+               logger.Debugf("starting OS Login nss cache fill")
                if err := runCmd(exec.Command("google_oslogin_nss_cache")); err 
!= nil {
                        logger.Errorf("Error updating NSS cache: %v.", err)
                }
@@ -157,6 +174,7 @@
 }
 
 func writeConfigFile(path, contents string) error {
+       logger.Debugf("writing %s", path)
        file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
        if err != nil {
                return err
@@ -166,12 +184,18 @@
        return nil
 }
 
-func updateSSHConfig(sshConfig string, enable, twofactor bool) string {
+func updateSSHConfig(sshConfig string, enable, twofactor, skey bool) string {
        // TODO: this feels like a case for a text/template
        challengeResponseEnable := "ChallengeResponseAuthentication yes"
        authorizedKeysCommand := "AuthorizedKeysCommand 
/usr/bin/google_authorized_keys"
+       if skey {
+               authorizedKeysCommand = "AuthorizedKeysCommand 
/usr/bin/google_authorized_keys_sk"
+       }
        if runtime.GOOS == "freebsd" {
                authorizedKeysCommand = "AuthorizedKeysCommand 
/usr/local/bin/google_authorized_keys"
+               if skey {
+                       authorizedKeysCommand = "AuthorizedKeysCommand 
/usr/local/bin/google_authorized_keys_sk"
+               }
        }
        authorizedKeysUser := "AuthorizedKeysCommandUser root"
        twoFactorAuthMethods := "AuthenticationMethods 
publickey,keyboard-interactive"
@@ -199,12 +223,12 @@
        return strings.Join(filtered, "\n")
 }
 
-func writeSSHConfig(enable, twofactor bool) error {
+func writeSSHConfig(enable, twofactor, skey bool) error {
        sshConfig, err := ioutil.ReadFile("/etc/ssh/sshd_config")
        if err != nil {
                return err
        }
-       proposed := updateSSHConfig(string(sshConfig), enable, twofactor)
+       proposed := updateSSHConfig(string(sshConfig), enable, twofactor, skey)
        if proposed == string(sshConfig) {
                return nil
        }
@@ -351,17 +375,31 @@
 // systemctlTryRestart tries to restart a systemd service if it is already
 // running. Stopped services will be ignored.
 func systemctlTryRestart(servicename string) error {
+       if !systemctlUnitExists(servicename) {
+               return nil
+       }
        return runCmd(exec.Command("systemctl", "try-restart", 
servicename+".service"))
 }
 
 // systemctlReloadOrRestart tries to reload a running systemd service if
 // supported, restart otherwise. Stopped services will be started.
 func systemctlReloadOrRestart(servicename string) error {
+       if !systemctlUnitExists(servicename) {
+               return nil
+       }
        return runCmd(exec.Command("systemctl", "reload-or-restart", 
servicename+".service"))
 }
 
 // systemctlStart tries to start a stopped systemd service. Started services
 // will be ignored.
 func systemctlStart(servicename string) error {
+       if !systemctlUnitExists(servicename) {
+               return nil
+       }
        return runCmd(exec.Command("systemctl", "start", 
servicename+".service"))
 }
+
+func systemctlUnitExists(servicename string) bool {
+       res := runCmdOutput(exec.Command("systemctl", "list-units", "--all", 
servicename+".service"))
+       return !strings.Contains(res.Stdout(), "0 loaded units listed")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_guest_agent/oslogin_test.go 
new/guest-agent-20211019.00/google_guest_agent/oslogin_test.go
--- old/guest-agent-20210707.00/google_guest_agent/oslogin_test.go      
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_guest_agent/oslogin_test.go      
2021-10-20 00:09:13.000000000 +0200
@@ -182,14 +182,15 @@
 func TestUpdateSSHConfig(t *testing.T) {
        challengeResponseEnable := "ChallengeResponseAuthentication yes"
        authorizedKeysCommand := "AuthorizedKeysCommand 
/usr/bin/google_authorized_keys"
+       authorizedKeysCommandSk := "AuthorizedKeysCommand 
/usr/bin/google_authorized_keys_sk"
        authorizedKeysUser := "AuthorizedKeysCommandUser root"
        twoFactorAuthMethods := "AuthenticationMethods 
publickey,keyboard-interactive"
        matchblock1 := `Match User sa_*`
        matchblock2 := `       AuthenticationMethods publickey`
 
        var tests = []struct {
-               contents, want    []string
-               enable, twofactor bool
+               contents, want          []string
+               enable, twofactor, skey bool
        }{
                {
                        // Full block is created, any others removed.
@@ -214,6 +215,7 @@
                        },
                        enable:    true,
                        twofactor: true,
+                       skey:      false,
                },
                {
                        // Full block is created, google comments removed.
@@ -239,6 +241,7 @@
                        },
                        enable:    true,
                        twofactor: true,
+                       skey:      false,
                },
                {
                        // Block is created without two-factor options.
@@ -256,6 +259,7 @@
                        },
                        enable:    true,
                        twofactor: false,
+                       skey:      false,
                },
                {
                        // Existing block is removed.
@@ -272,6 +276,28 @@
                        },
                        enable:    false,
                        twofactor: true,
+                       skey:      false,
+               },
+               {
+                       // Skey binary is chosen instead.
+                       contents: []string{
+                               "line1",
+                               "line2",
+                               googleBlockStart,
+                               "line3",
+                               googleBlockEnd,
+                       },
+                       want: []string{
+                               googleBlockStart,
+                               authorizedKeysCommandSk,
+                               authorizedKeysUser,
+                               googleBlockEnd,
+                               "line1",
+                               "line2",
+                       },
+                       enable:    true,
+                       twofactor: false,
+                       skey:      true,
                },
        }
 
@@ -279,7 +305,7 @@
                contents := strings.Join(tt.contents, "\n")
                want := strings.Join(tt.want, "\n")
 
-               if res := updateSSHConfig(contents, tt.enable, tt.twofactor); 
res != want {
+               if res := updateSSHConfig(contents, tt.enable, tt.twofactor, 
tt.skey); res != want {
                        t.Errorf("test %v\nwant:\n%v\ngot:\n%v\n", idx, want, 
res)
                }
        }
@@ -440,42 +466,55 @@
 
 func TestGetOSLoginEnabled(t *testing.T) {
        var tests = []struct {
-               md                string
-               enable, twofactor bool
+               md                      string
+               enable, twofactor, skey bool
        }{
                {
                        md:        `{"instance": {"attributes": 
{"enable-oslogin": "true", "enable-oslogin-2fa": "true"}}}`,
                        enable:    true,
                        twofactor: true,
+                       skey:      false,
                },
                {
                        md:        `{"project": {"attributes": 
{"enable-oslogin": "true", "enable-oslogin-2fa": "true"}}}`,
                        enable:    true,
                        twofactor: true,
+                       skey:      false,
                },
                {
                        // Instance keys take precedence
                        md:        `{"project": {"attributes": 
{"enable-oslogin": "false", "enable-oslogin-2fa": "false"}}, "instance": 
{"attributes": {"enable-oslogin": "true", "enable-oslogin-2fa": "true"}}}`,
                        enable:    true,
                        twofactor: true,
+                       skey:      false,
                },
                {
                        // Instance keys take precedence
                        md:        `{"project": {"attributes": 
{"enable-oslogin": "true", "enable-oslogin-2fa": "true"}}, "instance": 
{"attributes": {"enable-oslogin": "false", "enable-oslogin-2fa": "false"}}}`,
                        enable:    false,
                        twofactor: false,
+                       skey:      false,
                },
                {
                        // Handle weird values
                        md:        `{"instance": {"attributes": 
{"enable-oslogin": "TRUE", "enable-oslogin-2fa": "foobar"}}}`,
                        enable:    true,
                        twofactor: false,
+                       skey:      false,
                },
                {
                        // Mixed test
                        md:        `{"project": {"attributes": 
{"enable-oslogin": "true", "enable-oslogin-2fa": "true"}}, "instance": 
{"attributes": {"enable-oslogin-2fa": "false"}}}`,
                        enable:    true,
                        twofactor: false,
+                       skey:      false,
+               },
+               {
+                       // Skey test
+                       md:        `{"instance": {"attributes": 
{"enable-oslogin": "true", "enable-oslogin-2fa": "true", "enable-oslogin-sk": 
"true"}}}`,
+                       enable:    true,
+                       twofactor: true,
+                       skey:      true,
                },
        }
 
@@ -484,9 +523,9 @@
                if err := json.Unmarshal([]byte(tt.md), &md); err != nil {
                        t.Errorf("Failed to unmarshal metadata JSON for test 
%v: %v", idx, err)
                }
-               enable, twofactor := getOSLoginEnabled(&md)
-               if enable != tt.enable || twofactor != tt.twofactor {
-                       t.Errorf("Test %v failed. Expected: %v/%v Got: %v/%v", 
idx, tt.enable, tt.twofactor, enable, twofactor)
+               enable, twofactor, skey := getOSLoginEnabled(&md)
+               if enable != tt.enable || twofactor != tt.twofactor || skey != 
tt.skey {
+                       t.Errorf("Test %v failed. Expected: %v/%v/%v Got: 
%v/%v/%v", idx, tt.enable, tt.twofactor, tt.skey, enable, twofactor, skey)
                }
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_metadata_script_runner/main.go 
new/guest-agent-20211019.00/google_metadata_script_runner/main.go
--- old/guest-agent-20210707.00/google_metadata_script_runner/main.go   
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_metadata_script_runner/main.go   
2021-10-20 00:09:13.000000000 +0200
@@ -319,13 +319,20 @@
        pw.Close()
 
        in := bufio.NewScanner(pr)
-       for in.Scan() {
+       for {
+               if !in.Scan() {
+                       if err := in.Err(); err != nil {
+                               logger.Errorf("error while communicating with 
%q script: %v", name, err)
+                       }
+                       break
+               }
                logger.Log(logger.LogEntry{
                        Message:   fmt.Sprintf("%s: %s", name, in.Text()),
                        CallDepth: 3,
                        Severity:  logger.Info,
                })
        }
+       pr.Close()
 
        return c.Wait()
 }
@@ -351,21 +358,19 @@
        }
 
        var mdkeys []string
-       suffixes := []string{"url"}
+       var suffixes []string
        if os == "windows" {
-               // This ordering matters. URL is last on Windows, first 
otherwise.
                suffixes = []string{"ps1", "cmd", "bat", "url"}
+       } else {
+               suffixes = []string{"url"}
+               // The 'bare' startup-script or shutdown-script key, not 
supported on Windows.
+               mdkeys = append(mdkeys, fmt.Sprintf("%s-script", prefix))
        }
 
        for _, suffix := range suffixes {
                mdkeys = append(mdkeys, fmt.Sprintf("%s-script-%s", prefix, 
suffix))
        }
 
-       // The 'bare' startup-script or shutdown-script key, not supported on 
Windows.
-       if os != "windows" {
-               mdkeys = append(mdkeys, fmt.Sprintf("%s-script", prefix))
-       }
-
        return mdkeys, nil
 }
 
@@ -410,8 +415,9 @@
        return p.Write(b)
 }
 
-func logFormat(e logger.LogEntry) string {
+func logFormatWindows(e logger.LogEntry) string {
        now := time.Now().Format("2006/01/02 15:04:05")
+       // 2006/01/02 15:04:05 GCEMetadataScripts This is a log message.
        return fmt.Sprintf("%s %s: %s", now, programName, e.Message)
 }
 
@@ -427,15 +433,18 @@
 func main() {
        ctx := context.Background()
 
-       opts := logger.LogOpts{
-               LoggerName:     programName,
-               FormatFunction: logFormat,
-       }
+       opts := logger.LogOpts{LoggerName: programName}
 
        cfgfile := configPath
        if runtime.GOOS == "windows" {
                cfgfile = winConfigPath
                opts.Writers = []io.Writer{&serialPort{"COM1"}, os.Stdout}
+               opts.FormatFunction = logFormatWindows
+       } else {
+               opts.Writers = []io.Writer{os.Stdout}
+               opts.FormatFunction = func(e logger.LogEntry) string { return 
e.Message }
+               // Local logging is syslog; we will just use stdout in Linux.
+               opts.DisableLocalLogging = true
        }
 
        var err error
@@ -470,13 +479,17 @@
                return
        }
 
-       for key, value := range scripts {
-               logger.Infof("Found %s in metadata.", key)
-               if err := runScript(ctx, key, value); err != nil {
-                       logger.Infof("%s %s", key, err)
+       for _, wantedKey := range wantedKeys {
+               value, ok := scripts[wantedKey]
+               if !ok {
+                       continue
+               }
+               logger.Infof("Found %s in metadata.", wantedKey)
+               if err := runScript(ctx, wantedKey, value); err != nil {
+                       logger.Infof("%s %s", wantedKey, err)
                        continue
                }
-               logger.Infof("%s exit status 0", key)
+               logger.Infof("%s exit status 0", wantedKey)
        }
 
        logger.Infof("Finished running %s scripts.", os.Args[1])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20210707.00/google_metadata_script_runner/main_test.go 
new/guest-agent-20211019.00/google_metadata_script_runner/main_test.go
--- old/guest-agent-20210707.00/google_metadata_script_runner/main_test.go      
2021-07-07 21:18:49.000000000 +0200
+++ new/guest-agent-20211019.00/google_metadata_script_runner/main_test.go      
2021-10-20 00:09:13.000000000 +0200
@@ -68,16 +68,16 @@
                        "startup",
                        "linux",
                        []string{
-                               "startup-script-url",
                                "startup-script",
+                               "startup-script-url",
                        },
                },
                {
                        "shutdown",
                        "linux",
                        []string{
-                               "shutdown-script-url",
                                "shutdown-script",
+                               "shutdown-script-url",
                        },
                },
        }

++++++ vendor.tar.gz ++++++

Reply via email to