Skip to content

Commit

Permalink
Move some functionality to a utils module (#162)
Browse files Browse the repository at this point in the history
* Move some functionality to a utils module

This code will be shared with the authorized keys command, which will be built as a separate binary.

* Time parsing and lint fixes.

* gofmt updates

* Rename google_guest_utils to utils

* Return errors from utils functions

* Update a couple of missed calls.

* Fix some formatting errors.

* Fixes from comments

* Update logging to log bad keys once to the user

This restores "badExpire" for windows_accounts and diagnostics, and adds logging of all bad keys for SSH keys.

* gofmt fixes
  • Loading branch information
wrigri authored Apr 29, 2022
1 parent 25c217f commit 23c66a1
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 103 deletions.
23 changes: 12 additions & 11 deletions google_guest_agent/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"
"time"

"github.com/GoogleCloudPlatform/guest-agent/utils"
"github.com/GoogleCloudPlatform/guest-logging-go/logger"
)

Expand Down Expand Up @@ -87,13 +88,13 @@ func getForwardsFromRegistry(mac string) ([]string, error) {

func compareRoutes(configuredRoutes, desiredRoutes []string) (toAdd, toRm []string) {
for _, desiredRoute := range desiredRoutes {
if !containsString(desiredRoute, configuredRoutes) {
if !utils.ContainsString(desiredRoute, configuredRoutes) {
toAdd = append(toAdd, desiredRoute)
}
}

for _, configuredRoute := range configuredRoutes {
if !containsString(configuredRoute, desiredRoutes) {
if !utils.ContainsString(configuredRoute, desiredRoutes) {
toRm = append(toRm, configuredRoute)
}
}
Expand Down Expand Up @@ -220,15 +221,15 @@ func (a *addressMgr) applyWSFCFilter() {
for idx := range interfaces {
var filteredForwardedIps []string
for _, ip := range interfaces[idx].ForwardedIps {
if !containsString(ip, wsfcAddrs) {
if !utils.ContainsString(ip, wsfcAddrs) {
filteredForwardedIps = append(filteredForwardedIps, ip)
}
}
interfaces[idx].ForwardedIps = filteredForwardedIps

var filteredTargetInstanceIps []string
for _, ip := range interfaces[idx].TargetInstanceIps {
if !containsString(ip, wsfcAddrs) {
if !utils.ContainsString(ip, wsfcAddrs) {
filteredTargetInstanceIps = append(filteredTargetInstanceIps, ip)
}
}
Expand Down Expand Up @@ -319,7 +320,7 @@ func (a *addressMgr) set() error {
for _, ni := range newMetadata.Instance.NetworkInterfaces {
iface, err := getInterfaceByMAC(ni.Mac)
if err != nil {
if !containsString(ni.Mac, badMAC) {
if !utils.ContainsString(ni.Mac, badMAC) {
logger.Errorf("Error getting interface: %s", err)
badMAC = append(badMAC, ni.Mac)
}
Expand Down Expand Up @@ -352,7 +353,7 @@ func (a *addressMgr) set() error {
}
for _, ip := range configuredIPs {
// Only add to `forwardedIPs` if it is recorded in the registry.
if containsString(ip, regFwdIPs) {
if utils.ContainsString(ip, regFwdIPs) {
forwardedIPs = append(forwardedIPs, ip)
}
}
Expand Down Expand Up @@ -395,14 +396,14 @@ func (a *addressMgr) set() error {
var registryEntries []string
for _, ip := range wantIPs {
// If the IP is not in toAdd, add to registry list and continue.
if !containsString(ip, toAdd) {
if !utils.ContainsString(ip, toAdd) {
registryEntries = append(registryEntries, ip)
continue
}
var err error
if runtime.GOOS == "windows" {
// Don't addAddress if this is already configured.
if !containsString(ip, configuredIPs) {
if !utils.ContainsString(ip, configuredIPs) {
err = addAddress(net.ParseIP(ip), net.IPv4Mask(255, 255, 255, 255), uint32(iface.Index))
}
} else {
Expand All @@ -418,7 +419,7 @@ func (a *addressMgr) set() error {
for _, ip := range toRm {
var err error
if runtime.GOOS == "windows" {
if !containsString(ip, configuredIPs) {
if !utils.ContainsString(ip, configuredIPs) {
continue
}
err = removeAddress(net.ParseIP(ip), uint32(iface.Index))
Expand Down Expand Up @@ -511,7 +512,7 @@ func enableNetworkInterfaces() error {
for _, ni := range newMetadata.Instance.NetworkInterfaces[1:] {
iface, err := getInterfaceByMAC(ni.Mac)
if err != nil {
if !containsString(ni.Mac, badMAC) {
if !utils.ContainsString(ni.Mac, badMAC) {
logger.Errorf("Error getting interface: %s", err)
badMAC = append(badMAC, ni.Mac)
}
Expand All @@ -527,7 +528,7 @@ func enableNetworkInterfaces() error {
}
iface, err := getInterfaceByMAC(ni.Mac)
if err != nil {
if !containsString(ni.Mac, badMAC) {
if !utils.ContainsString(ni.Mac, badMAC) {
logger.Errorf("Error getting interface: %s", err)
badMAC = append(badMAC, ni.Mac)
}
Expand Down
12 changes: 6 additions & 6 deletions google_guest_agent/diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"reflect"
"strconv"
"sync/atomic"
"time"

"github.com/GoogleCloudPlatform/guest-agent/utils"
"github.com/GoogleCloudPlatform/guest-logging-go/logger"
)

Expand All @@ -42,15 +42,15 @@ type diagnosticsEntry struct {
}

func (k diagnosticsEntry) expired() bool {
t, err := time.Parse(time.RFC3339, k.ExpireOn)
expired, err := utils.CheckExpired(k.ExpireOn)
if err != nil {
if !containsString(k.ExpireOn, badExpire) {
logger.Errorf("Error parsing time: %s", err)
if !utils.ContainsString(k.ExpireOn, badExpire) {
logger.Errorf("error parsing time: %s", err)
badExpire = append(badExpire, k.ExpireOn)
}
return true
}
return t.Before(time.Now())
return expired
}

type diagnosticsMgr struct{}
Expand Down Expand Up @@ -100,7 +100,7 @@ func (d *diagnosticsMgr) set() error {
}

strEntry := newMetadata.Instance.Attributes.Diagnostics
if containsString(strEntry, diagnosticsEntries) {
if utils.ContainsString(strEntry, diagnosticsEntries) {
return nil
}
diagnosticsEntries = append(diagnosticsEntries, strEntry)
Expand Down
9 changes: 0 additions & 9 deletions google_guest_agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,6 @@ func runCmdOutputWithTimeout(timeoutSec time.Duration, name string, args ...stri
return execResult
}

func containsString(s string, ss []string) bool {
for _, a := range ss {
if a == s {
return true
}
}
return false
}

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.
Expand Down
20 changes: 0 additions & 20 deletions google_guest_agent/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,3 @@
// limitations under the License.

package main

import (
"testing"
)

func TestContainsString(t *testing.T) {
table := []struct {
a string
slice []string
want bool
}{
{"a", []string{"a", "b"}, true},
{"c", []string{"a", "b"}, false},
}
for _, tt := range table {
if got, want := containsString(tt.a, tt.slice), tt.want; got != want {
t.Errorf("containsString(%s, %v) incorrect return: got %v, want %t", tt.a, tt.slice, got, want)
}
}
}
3 changes: 2 additions & 1 deletion google_guest_agent/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"
"time"

"github.com/GoogleCloudPlatform/guest-agent/utils"
"github.com/GoogleCloudPlatform/guest-logging-go/logger"
)

Expand Down Expand Up @@ -140,7 +141,7 @@ func (k *windowsKeys) UnmarshalJSON(b []byte) error {
for _, jskey := range strings.Split(s, "\n") {
var wk windowsKey
if err := json.Unmarshal([]byte(jskey), &wk); err != nil {
if !containsString(jskey, badKeys) {
if !utils.ContainsString(jskey, badKeys) {
logger.Errorf("failed to unmarshal windows key from metadata: %s", err)
badKeys = append(badKeys, jskey)
}
Expand Down
67 changes: 16 additions & 51 deletions google_guest_agent/non_windows_accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
Expand All @@ -26,8 +25,8 @@ import (
"sort"
"strconv"
"strings"
"time"

"github.com/GoogleCloudPlatform/guest-agent/utils"
"github.com/GoogleCloudPlatform/guest-logging-go/logger"
)

Expand Down Expand Up @@ -182,6 +181,8 @@ func (a *accountsMgr) set() error {
return nil
}

var badSSHKeys []string

// getUserKeys returns the keys which are not expired and non-expiring key.
// valid formats are:
// user:ssh-rsa [KEY_VALUE] [USERNAME]
Expand All @@ -190,43 +191,22 @@ func (a *accountsMgr) set() error {
func getUserKeys(mdkeys []string) map[string][]string {
mdKeyMap := make(map[string][]string)
for i := 0; i < len(mdkeys); i++ {
key := strings.Trim(mdkeys[i], " ")
if key == "" {
logger.Debugf("invalid ssh key entry: %q", key)
continue
}
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
}
fields := strings.SplitN(key, " ", 4)
if len(fields) == 3 && fields[2] == "google-ssh" {
logger.Debugf("invalid ssh key entry: %q", key)
// expiring key without expiration format.
continue
}
if len(fields) > 3 {
lkey := linuxKey{}
if err := json.Unmarshal([]byte(fields[3]), &lkey); err != nil {
// invalid expiration format.
logger.Debugf("invalid ssh key entry: %q", key)
continue
}
if lkey.expired() {
logger.Debugf("expired ssh key entry: %q", key)
trimmedKey := strings.Trim(mdkeys[i], " ")
if trimmedKey != "" {
user, keyVal, err := utils.GetUserKey(trimmedKey)
if err != nil {
if !utils.ContainsString(trimmedKey, badSSHKeys) {
logger.Errorf("%s: %s", err.Error(), trimmedKey)
badSSHKeys = append(badSSHKeys, trimmedKey)
}
continue
}

// key which is not expired or non-expiring key, add it.
userKeys := mdKeyMap[user]
userKeys = append(userKeys, keyVal)
mdKeyMap[user] = userKeys
}
// key which is not expired or non-expiring key, add it.
userKeys := mdKeyMap[user]
userKeys = append(userKeys, key[idx+1:])
mdKeyMap[user] = userKeys
}
return mdKeyMap
}
Expand Down Expand Up @@ -330,21 +310,6 @@ func readGoogleUsersFile() (map[string]string, error) {
return res, nil
}

type linuxKey windowsKey

// expired returns true if the key's expireOn field is in the past, false otherwise.
func (k linuxKey) expired() bool {
t, err := time.Parse("2006-01-02T15:04:05-0700", k.ExpireOn)
if err != nil {
if !containsString(k.ExpireOn, badExpire) {
logger.Errorf("Error parsing time: %v.", err)
badExpire = append(badExpire, k.ExpireOn)
}
return true
}
return t.Before(time.Now())
}

// Replaces {user} or {group} in command string. Supports legacy python-era
// user command overrides.
func createUserGroupCmd(cmd, user, group string) *exec.Cmd {
Expand Down
10 changes: 5 additions & 5 deletions google_guest_agent/windows_accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import (
"hash"
"math/big"
"reflect"
"time"

"github.com/GoogleCloudPlatform/guest-agent/utils"
"github.com/GoogleCloudPlatform/guest-logging-go/logger"
)

Expand Down Expand Up @@ -111,15 +111,15 @@ func printCreds(creds *credsJSON) error {
var badExpire []string

func (k windowsKey) expired() bool {
t, err := time.Parse(time.RFC3339, k.ExpireOn)
expired, err := utils.CheckExpired(k.ExpireOn)
if err != nil {
if !containsString(k.ExpireOn, badExpire) {
if !utils.ContainsString(k.ExpireOn, badExpire) {
logger.Errorf("error parsing time: %s", err)
badExpire = append(badExpire, k.ExpireOn)
}
return true
}
return t.Before(time.Now())
return expired
}

func (k windowsKey) createOrResetPwd() (*credsJSON, error) {
Expand Down Expand Up @@ -281,7 +281,7 @@ func compareAccounts(newKeys windowsKeys, oldStrKeys []string) windowsKeys {
for _, s := range oldStrKeys {
var key windowsKey
if err := json.Unmarshal([]byte(s), &key); err != nil {
if !containsString(s, badReg) {
if !utils.ContainsString(s, badReg) {
logger.Errorf("Bad windows key from registry: %s", err)
badReg = append(badReg, s)
}
Expand Down
Loading

0 comments on commit 23c66a1

Please sign in to comment.