in google_guest_agent/non_windows_accounts.go [416:503]
func updateAuthorizedKeysFile(ctx context.Context, user string, keys []string) error {
gcomment := "# Added by Google"
passwd, err := getPasswd(user)
if err != nil {
return err
}
if passwd.HomeDir == "" {
return fmt.Errorf("user %s has no homedir set", user)
}
if passwd.Shell == "/sbin/nologin" {
return nil
}
sshpath := path.Join(passwd.HomeDir, ".ssh")
if _, err := os.Stat(sshpath); err != nil {
if os.IsNotExist(err) {
if err = os.Mkdir(sshpath, 0700); err != nil {
return err
}
if err = os.Chown(sshpath, passwd.UID, passwd.GID); err != nil {
return err
}
} else {
return err
}
}
akpath := path.Join(sshpath, "authorized_keys")
// Remove empty file.
if len(keys) == 0 {
os.Remove(akpath)
return nil
}
tempPath := akpath + ".google"
akcontents, err := os.ReadFile(akpath)
if err != nil && !os.IsNotExist(err) {
return err
}
var isgoogle bool
var userKeys []string
for _, key := range strings.Split(string(akcontents), "\n") {
if key == "" {
continue
}
if isgoogle {
isgoogle = false
continue
}
if key == gcomment {
isgoogle = true
continue
}
userKeys = append(userKeys, key)
}
newfile, err := os.OpenFile(tempPath, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
defer newfile.Close()
for _, key := range userKeys {
fmt.Fprintf(newfile, "%s\n", key)
}
for _, key := range keys {
fmt.Fprintf(newfile, "%s\n%s\n", gcomment, key)
}
err = os.Chown(tempPath, passwd.UID, passwd.GID)
if err != nil {
// Existence of temp file will block further updates for this user.
// Don't catch remove error, nothing we can do. Return the
// chown error which caused the issue.
os.Remove(tempPath)
return fmt.Errorf("error setting ownership of new keys file: %v", err)
}
_, err = exec.LookPath("restorecon")
if err == nil {
if err := run.Quiet(ctx, "restorecon", tempPath); err != nil {
return fmt.Errorf("error setting selinux context: %+v", err)
}
}
return os.Rename(tempPath, akpath)
}