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 2022-09-17 20:10:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/google-guest-agent (Old)
 and      /work/SRC/openSUSE:Factory/.google-guest-agent.new.2083 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "google-guest-agent"

Sat Sep 17 20:10:38 2022 rev:15 rq:1004182 version:20220824.00

Changes:
--------
--- /work/SRC/openSUSE:Factory/google-guest-agent/google-guest-agent.changes    
2022-08-16 17:07:10.539776179 +0200
+++ 
/work/SRC/openSUSE:Factory/.google-guest-agent.new.2083/google-guest-agent.changes
  2022-09-17 20:10:50.637244094 +0200
@@ -1,0 +2,10 @@
+Fri Sep 16 15:27:23 UTC 2022 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to version 20220824.00
+  * Workload certs (#177)
+- from version 20220823.00
+  * add members to OWNERS (#178)
+  * Expired key tests (#176)
+  * correct expired key handling (#175)
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ google-guest-agent.spec ++++++
--- /var/tmp/diff_new_pack.x2SqGF/_old  2022-09-17 20:10:51.457246459 +0200
+++ /var/tmp/diff_new_pack.x2SqGF/_new  2022-09-17 20:10:51.457246459 +0200
@@ -24,7 +24,7 @@
 %global import_path     %{provider_prefix}
 
 Name:           google-guest-agent
-Version:        20220713.00
+Version:        20220824.00
 Release:        0
 Summary:        Google Cloud Guest Agent
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.x2SqGF/_old  2022-09-17 20:10:51.493246563 +0200
+++ /var/tmp/diff_new_pack.x2SqGF/_new  2022-09-17 20:10:51.493246563 +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">20220713.00</param>
-    <param name="revision">20220713.00</param>
+    <param name="versionformat">20220824.00</param>
+    <param name="revision">20220824.00</param>
     <param name="changesgenerate">enable</param>
   </service>
   <service name="recompress" mode="disabled">
@@ -15,7 +15,7 @@
     <param name="basename">guest-agent</param>
   </service>
   <service name="go_modules" mode="disabled">
-    <param name="archive">guest-agent-20220713.00.tar.gz</param>
+    <param name="archive">guest-agent-20220824.00.tar.gz</param>
   </service>
 </services>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.x2SqGF/_old  2022-09-17 20:10:51.517246632 +0200
+++ /var/tmp/diff_new_pack.x2SqGF/_new  2022-09-17 20:10:51.525246656 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/GoogleCloudPlatform/guest-agent/</param>
-              <param 
name="changesrevision">792fce795218633bcbde505fb3457a0b24f26d37</param></service></servicedata>
+              <param 
name="changesrevision">1bdde681dd3b700159392eb87efbef5c1bb5515c</param></service></servicedata>
 (No newline at EOF)
 

++++++ guest-agent-20220713.00.tar.gz -> guest-agent-20220824.00.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-agent-20220713.00/OWNERS 
new/guest-agent-20220824.00/OWNERS
--- old/guest-agent-20220713.00/OWNERS  2022-06-22 23:00:27.000000000 +0200
+++ new/guest-agent-20220824.00/OWNERS  2022-08-24 03:13:05.000000000 +0200
@@ -6,8 +6,14 @@
   - hopkiw
   - zmarano
   - bkatyl
+  - dorileo
+  - jjerger
+  - koln67
 reviewers:
   - adjackura
   - hopkiw
   - zmarano
   - bkatyl
+  - dorileo
+  - jjerger
+  - koln67
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20220713.00/gce_workload_certs_refresh/main.go 
new/guest-agent-20220824.00/gce_workload_certs_refresh/main.go
--- old/guest-agent-20220713.00/gce_workload_certs_refresh/main.go      
1970-01-01 01:00:00.000000000 +0100
+++ new/guest-agent-20220824.00/gce_workload_certs_refresh/main.go      
2022-08-24 03:13:05.000000000 +0200
@@ -0,0 +1,289 @@
+//  Copyright 2022 Google LLC
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+
+// GoogleAuthorizedKeys obtains SSH keys from metadata.
+package main
+
+import (
+       "context"
+       "encoding/json"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "os"
+       "time"
+
+       "github.com/GoogleCloudPlatform/guest-logging-go/logger"
+)
+
+const (
+       contentDirPrefix  = "/run/secrets/workload-spiffe-contents"
+       tempSymlinkPrefix = "/run/secrets/workload-spiffe-symlink"
+       symlink           = "/run/secrets/workload-spiffe-credentials"
+)
+
+var (
+       programName    = "gce_workload_certs_refresh"
+       version        string
+       metadataURL    = "http://169.254.169.254/computeMetadata/v1/";
+       defaultTimeout = 2 * time.Second
+)
+
+func logFormat(e logger.LogEntry) string {
+       now := time.Now().Format("2006/01/02 15:04:05")
+       return fmt.Sprintf("%s: %s", now, e.Message)
+}
+
+func getMetadata(key string) ([]byte, error) {
+       client := &http.Client{
+               Timeout: defaultTimeout,
+       }
+
+       url := metadataURL + key
+       req, err := http.NewRequest("GET", url, nil)
+       if err != nil {
+               return nil, err
+       }
+       req.Header.Add("Metadata-Flavor", "Google")
+
+       var res *http.Response
+
+       // Retry up to 5 times
+       for i := 1; i < 6; i++ {
+               res, err = client.Do(req)
+               if err == nil {
+                       break
+               }
+               logger.Errorf("error connecting to metadata server, retrying in 
3s, error: %v", err)
+               time.Sleep(time.Duration(3) * time.Second)
+       }
+       if err != nil {
+               return nil, err
+       }
+       defer res.Body.Close()
+
+       md, err := ioutil.ReadAll(res.Body)
+       if err != nil {
+               return nil, err
+       }
+       return md, nil
+}
+
+/*
+metadata key instance/workload-identities
+
+       {
+        "status": "OK",
+        "workloadCredentials": {
+         "PROJECT.svc.id.goog": {
+          "metadata": {
+           "workload_creds_dir_path": 
"/var/run/secrets/workload-spiffe-credentials"
+          },
+          "certificatePem": "-----BEGIN CERTIFICATE-----datahere-----END 
CERTIFICATE-----",
+          "privateKeyPem": "-----BEGIN PRIVATE KEY-----datahere-----END 
PRIVATE KEY-----"
+         }
+        }
+       }
+*/
+
+// WorkloadIdentities represents Workload Identities in metadata.
+type WorkloadIdentities struct {
+       Status              string
+       WorkloadCredentials map[string]WorkloadCredential
+}
+
+// UnmarshalJSON is a custom JSON unmarshaller for WorkloadIdentities.
+func (wi *WorkloadIdentities) UnmarshalJSON(b []byte) error {
+       tmp := map[string]json.RawMessage{}
+       err := json.Unmarshal(b, &tmp)
+       if err != nil {
+               return err
+       }
+
+       if err := json.Unmarshal(tmp["status"], &wi.Status); err != nil {
+               return err
+       }
+
+       wi.WorkloadCredentials = map[string]WorkloadCredential{}
+       wcs := map[string]json.RawMessage{}
+       if err := json.Unmarshal(tmp["workloadCredentials"], &wcs); err != nil {
+               return err
+       }
+
+       for domain, value := range wcs {
+               wc := WorkloadCredential{}
+               err := json.Unmarshal(value, &wc)
+               if err != nil {
+                       return err
+               }
+               wi.WorkloadCredentials[domain] = wc
+       }
+
+       return nil
+}
+
+// WorkloadCredential represents Workload Credentials in metadata.
+type WorkloadCredential struct {
+       Metadata       Metadata
+       CertificatePem string
+       PrivateKeyPem  string
+}
+
+/*
+metadata key instance/workload-trusted-root-certs
+
+       {
+        "status": "OK",
+        "rootCertificates": {
+         "PROJECT.svc.id.goog": {
+          "metadata": {
+           "workload_creds_dir_path": 
"/var/run/secrets/workload-spiffe-credentials"
+          },
+          "rootCertificatesPem": "-----BEGIN CERTIFICATE-----datahere-----END 
CERTIFICATE-----"
+         }
+        }
+       }
+*/
+
+// WorkloadTrustedRootCerts represents Workload Trusted Root Certs in metadata.
+type WorkloadTrustedRootCerts struct {
+       Status           string
+       RootCertificates map[string]RootCertificate
+}
+
+// UnmarshalJSON is a custom JSON unmarshaller for WorkloadTrustedRootCerts
+func (wtrc *WorkloadTrustedRootCerts) UnmarshalJSON(b []byte) error {
+       tmp := map[string]json.RawMessage{}
+       err := json.Unmarshal(b, &tmp)
+       if err != nil {
+               return err
+       }
+
+       if err := json.Unmarshal(tmp["status"], &wtrc.Status); err != nil {
+               return err
+       }
+
+       wtrc.RootCertificates = map[string]RootCertificate{}
+       rcs := map[string]json.RawMessage{}
+       if err := json.Unmarshal(tmp["rootCertificates"], &rcs); err != nil {
+               return err
+       }
+
+       for domain, value := range rcs {
+               rc := RootCertificate{}
+               err := json.Unmarshal(value, &rc)
+               if err != nil {
+                       return err
+               }
+               wtrc.RootCertificates[domain] = rc
+       }
+
+       return nil
+}
+
+// RootCertificate represents a Root Certificate in metadata
+type RootCertificate struct {
+       Metadata            Metadata
+       RootCertificatesPem string
+}
+
+// Metadata represents Metadata in metadata
+type Metadata struct {
+       WorkloadCredsDirPath string
+}
+
+func main() {
+       ctx := context.Background()
+
+       opts := logger.LogOpts{
+               LoggerName:     programName,
+               FormatFunction: logFormat,
+       }
+
+       opts.Writers = []io.Writer{os.Stderr}
+       logger.Init(ctx, opts)
+       defer logger.Infof("Done")
+
+       // TODO: prune old dirs
+
+       if err := refreshCreds(); err != nil {
+               logger.Fatalf(err.Error())
+       }
+
+}
+
+func refreshCreds() error {
+       project, err := getMetadata("project/project-id")
+       if err != nil {
+               return fmt.Errorf("Error getting project ID: %v", err)
+       }
+       domain := fmt.Sprintf("%s.svc.id.goog", project)
+       logger.Infof("Rotating workload credentials for domain %s", domain)
+
+       wisMd, err := getMetadata("instance/workload-identities")
+       if err != nil {
+               return fmt.Errorf("Error getting workload-identities: %v", err)
+       }
+
+       wtrcsMd, err := getMetadata("instance/workload-trusted-root-certs")
+       if err != nil {
+               return fmt.Errorf("Error getting workload-identities: %v", err)
+       }
+
+       wis := WorkloadIdentities{}
+       if err := json.Unmarshal(wisMd, &wis); err != nil {
+               return fmt.Errorf("Error unmarshaling workload trusted root 
certs: %v", err)
+       }
+
+       wtrcs := WorkloadTrustedRootCerts{}
+       if err := json.Unmarshal(wtrcsMd, &wtrcs); err != nil {
+               return fmt.Errorf("Error unmarshaling workload trusted root 
certs: %v", err)
+       }
+
+       now := time.Now().Format(time.RFC3339)
+       contentDir := fmt.Sprintf("%s-%s", contentDirPrefix, now)
+       tempSymlink := fmt.Sprintf("%s-%s", tempSymlinkPrefix, now)
+
+       logger.Infof("Creating timestamp contents dir %s", contentDir)
+
+       // TODO: validate filesystem permissions
+       if err := os.MkdirAll(contentDir, 0750); err != nil {
+               return fmt.Errorf("Error creating contents dir: %v", err)
+       }
+
+       if err := os.WriteFile(fmt.Sprintf("%s/certificates.pem", contentDir), 
[]byte(wis.WorkloadCredentials[domain].CertificatePem), 0666); err != nil {
+               return fmt.Errorf("Error writing certificates.pem: %v", err)
+       }
+
+       if err := os.WriteFile(fmt.Sprintf("%s/private_key.pem", contentDir), 
[]byte(wis.WorkloadCredentials[domain].PrivateKeyPem), 0666); err != nil {
+               return fmt.Errorf("Error writing private_key.pem: %v", err)
+       }
+
+       if err := os.WriteFile(fmt.Sprintf("%s/ca_certificates.pem", 
contentDir), []byte(wtrcs.RootCertificates[domain].RootCertificatesPem), 0666); 
err != nil {
+               return fmt.Errorf("Error writing ca_certificates.pem: %v", err)
+       }
+
+       if err := os.Symlink(contentDir, tempSymlink); err != nil {
+               return fmt.Errorf("Error creating temporary link: %v", err)
+       }
+
+       logger.Infof("Rotating symlink %s", symlink)
+
+       if err := os.Rename(tempSymlink, symlink); err != nil {
+               return fmt.Errorf("Error rotating target link: %v", err)
+       }
+
+       return nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20220713.00/google_guest_agent/non_windows_accounts.go 
new/guest-agent-20220824.00/google_guest_agent/non_windows_accounts.go
--- old/guest-agent-20220713.00/google_guest_agent/non_windows_accounts.go      
2022-06-22 23:00:27.000000000 +0200
+++ new/guest-agent-20220824.00/google_guest_agent/non_windows_accounts.go      
2022-08-24 03:13:05.000000000 +0200
@@ -56,6 +56,16 @@
        return true
 }
 
+func removeExpiredKeys(keys []string) []string {
+       var validKeys []string
+       for _, key := range keys {
+               if err := utils.CheckExpiredKey(key); err == nil {
+                       validKeys = append(validKeys, key)
+               }
+       }
+       return validKeys
+}
+
 type accountsMgr struct{}
 
 func (a *accountsMgr) diff() bool {
@@ -72,7 +82,7 @@
 
        // If any on-disk keys have expired.
        for _, keys := range sshKeys {
-               if len(keys) != len(getUserKeys(keys)) {
+               if len(keys) != len(removeExpiredKeys(keys)) {
                        return true
                }
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/guest-agent-20220713.00/google_guest_agent/windows_accounts_test.go 
new/guest-agent-20220824.00/google_guest_agent/windows_accounts_test.go
--- old/guest-agent-20220713.00/google_guest_agent/windows_accounts_test.go     
2022-06-22 23:00:27.000000000 +0200
+++ new/guest-agent-20220824.00/google_guest_agent/windows_accounts_test.go     
2022-08-24 03:13:05.000000000 +0200
@@ -264,6 +264,46 @@
        }
 }
 
+func TestRemoveExpiredKeys(t *testing.T) {
+       var tests = []struct {
+               key   string
+               valid bool
+       }{
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0000"}`, true},
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0700"}`, true},
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0700", "futureField": 
"UNUSED_FIELDS_IGNORED"}`, true},
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2018-11-08T19:30:46+0000"}`, false},
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2018-11-08T19:30:46+0700"}`, false},
+               {`user:ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"INVALID_TIMESTAMP"}`, false},
+               {`user:ssh-rsa [KEY] google-ssh`, false},
+               {`user:ssh-rsa [KEY] user`, true},
+               {`user:ssh-rsa [KEY]`, true},
+               // having the user: prefix should not affect whether a key is 
expired, repeat test cases without user: prefix
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0000"}`, true},
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0700"}`, true},
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2028-11-08T19:30:47+0700", "futureField": 
"UNUSED_FIELDS_IGNORED"}`, true},
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2018-11-08T19:30:46+0000"}`, false},
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"2018-11-08T19:30:46+0700"}`, false},
+               {`ssh-rsa [KEY] google-ssh {"userName":"u...@email.com", 
"expireOn":"INVALID_TIMESTAMP"}`, false},
+               {`ssh-rsa [KEY] google-ssh`, false},
+               {`ssh-rsa [KEY] user`, true},
+               {`ssh-rsa [KEY]`, true},
+               {},
+       }
+
+       for _, tt := range tests {
+               ret := removeExpiredKeys([]string{tt.key})
+               if tt.valid {
+                       if len(ret) == 0 || ret[0] != tt.key {
+                               t.Errorf("valid key was removed: %q", tt.key)
+                       }
+               }
+               if !tt.valid && len(ret) == 1 {
+                       t.Errorf("invalid key was kept: %q", tt.key)
+               }
+       }
+}
+
 func TestVersionOk(t *testing.T) {
        tests := []struct {
                version    versionInfo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-agent-20220713.00/utils/main.go 
new/guest-agent-20220824.00/utils/main.go
--- old/guest-agent-20220713.00/utils/main.go   2022-06-22 23:00:27.000000000 
+0200
+++ new/guest-agent-20220824.00/utils/main.go   2022-08-24 03:13:05.000000000 
+0200
@@ -25,7 +25,7 @@
        "github.com/tarm/serial"
 )
 
-//ContainsString checks for the presence of a string in a slice.
+// ContainsString checks for the presence of a string in a slice.
 func ContainsString(s string, ss []string) bool {
        for _, a := range ss {
                if a == s {
@@ -35,12 +35,46 @@
        return false
 }
 
-type sshKeyData struct {
+type sshExpiration struct {
        ExpireOn string
        UserName string
 }
 
-//CheckExpired takes a time string and determines if it represents a time in 
the past.
+// CheckExpiredKey validates whether a key has expired. Keys with invalid 
expiration formats will result in an
+// error.
+func CheckExpiredKey(key string) error {
+       trimmedKey := strings.Trim(key, " ")
+       if trimmedKey == "" {
+               return errors.New("Invalid ssh key entry - empty key")
+       }
+       fields := strings.SplitN(trimmedKey, " ", 4)
+       if len(fields) < 3 {
+               // Non-expiring key.
+               return nil
+       }
+       if len(fields) == 3 && fields[2] == "google-ssh" {
+               // expiring key without expiration format.
+               return errors.New("Invalid ssh key entry - expiration missing")
+       }
+       if len(fields) > 3 {
+               lkey := sshExpiration{}
+               if err := json.Unmarshal([]byte(fields[3]), &lkey); err != nil {
+                       // invalid expiration format.
+                       return err
+               }
+               expired, err := CheckExpired(lkey.ExpireOn)
+               if err != nil {
+                       return err
+               }
+               if expired {
+                       return errors.New("Invalid ssh key entry - expired key")
+               }
+       }
+
+       return nil
+}
+
+// CheckExpired takes a time string and determines if it represents a time in 
the past.
 func CheckExpired(expireOn string) (bool, error) {
        t, err := time.Parse(time.RFC3339, expireOn)
        if err != nil {
@@ -54,10 +88,9 @@
 
 }
 
-//GetUserKey takes a string and determines if it is a valid SSH key and returns
-//the user and key if valid, nil otherwise.
+// GetUserKey takes a string and determines if it is a valid SSH key and 
returns
+// the user and key if valid, nil otherwise.
 func GetUserKey(rawKey string) (string, string, error) {
-
        key := strings.Trim(rawKey, " ")
        if key == "" {
                return "", "", errors.New("Invalid ssh key entry - empty key")
@@ -70,30 +103,14 @@
        if user == "" {
                return "", "", errors.New("Invalid ssh key entry - user 
missing")
        }
-       fields := strings.SplitN(key, " ", 4)
-       if len(fields) == 3 && fields[2] == "google-ssh" {
-               // expiring key without expiration format.
-               return "", "", errors.New("Invalid ssh key entry - expiration 
missing")
-       }
-       if len(fields) > 3 {
-               lkey := sshKeyData{}
-               if err := json.Unmarshal([]byte(fields[3]), &lkey); err != nil {
-                       // invalid expiration format.
-                       return "", "", err
-               }
-               expired, err := CheckExpired(lkey.ExpireOn)
-               if err != nil {
-                       return "", "", err
-               }
-               if expired {
-                       return "", "", errors.New("Invalid ssh key entry - 
expired key")
-               }
+       if err := CheckExpiredKey(key[idx+1:]); err != nil {
+               return "", "", err
        }
 
        return user, key[idx+1:], nil
 }
 
-//SerialPort is a type for writing to a named serial port.
+// SerialPort is a type for writing to a named serial port.
 type SerialPort struct {
        Port string
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/guest-agent-20220713.00/utils/main_test.go 
new/guest-agent-20220824.00/utils/main_test.go
--- old/guest-agent-20220713.00/utils/main_test.go      2022-06-22 
23:00:27.000000000 +0200
+++ new/guest-agent-20220824.00/utils/main_test.go      2022-08-24 
03:13:05.000000000 +0200
@@ -59,3 +59,27 @@
                }
        }
 }
+
+func TestCheckExpiredKey(t *testing.T) {
+       table := []struct {
+               key     string
+               expired bool
+       }{
+               {`usera:ssh-rsa AAAA1234 google-ssh 
{"userName":"us...@example.com","expireOn":"2095-04-23T12:34:56+0000"}`, false},
+               {`usera:ssh-rsa AAAA1234 google-ssh 
{"userName":"us...@example.com","expireOn":"2021-04-23T12:34:56+0000"}`, true},
+               {`usera:ssh-rsa AAAA1234 google-ssh 
{"userName":"us...@example.com","expireOn":"Apri 4, 2056"}`, true},
+               {`usera:ssh-rsa AAAA1234 google-ssh`, true},
+               {"    ", true},
+               {"ssh-rsa AAAA1234", false},
+               {":ssh-rsa AAAA1234", false},
+               {"usera:ssh-rsa AAAA1234", false},
+       }
+
+       for _, tt := range table {
+               err := CheckExpiredKey(tt.key)
+               isExpired := err != nil
+               if isExpired != tt.expired {
+                       t.Errorf("CheckExpiredKey(%s) incorrect return: 
expired: %t - want expired: %t", tt.key, isExpired, tt.expired)
+               }
+       }
+}

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

Reply via email to