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 ++++++