func updateSSHKeys()

in cmd/core_plugin/metadatasshkey/metadatasshkey_linux.go [90:161]


func updateSSHKeys(ctx context.Context, user *accounts.User, keys []string) error {
	gComment := "# Added by Google"

	if user.HomeDir == "" {
		return fmt.Errorf("user %s has no homedir set", user.Username)
	}
	if user.Shell == "/sbin/nologin" {
		return nil
	}

	galog.V(2).Debugf("Updating keys for user %s to %v", user.Username, keys)

	sshPath := filepath.Join(user.HomeDir, ".ssh")
	if !file.Exists(sshPath, file.TypeDir) {
		if err := os.Mkdir(sshPath, 0700); err != nil {
			return err
		}
		if err := os.Chown(sshPath, user.UnixUID(), user.UnixGID()); err != nil {
			return err
		}
	}
	authorizedKeysPath := filepath.Join(sshPath, "authorized_keys")
	// Remove empty file.
	if len(keys) == 0 {
		os.Remove(authorizedKeysPath)
		return nil
	}

	authorizedKeysContents, err := os.ReadFile(authorizedKeysPath)
	if err != nil && !os.IsNotExist(err) {
		return err
	}

	var isGoogle bool
	var userKeys []string
	for _, key := range strings.Split(string(authorizedKeysContents), "\n") {
		if key == "" {
			continue
		}
		if isGoogle {
			isGoogle = false
			continue
		}
		if key == gComment {
			isGoogle = true
			continue
		}
		userKeys = append(userKeys, key)
	}

	authorizedKeysOutput := strings.Join(userKeys, "\n")
	if len(userKeys) > 0 {
		authorizedKeysOutput += "\n"
	}
	for _, k := range keys {
		authorizedKeysOutput += fmt.Sprintf("%s\n%s\n", gComment, k)
	}

	writeOpts := file.Options{
		Perm: 0600,
		Owner: &file.GUID{
			UID: user.UnixUID(),
			GID: user.UnixGID(),
		},
	}

	if err := file.SaferWriteFile(ctx, []byte(authorizedKeysOutput), authorizedKeysPath, writeOpts); err != nil {
		return fmt.Errorf("failed to write authorized_keys file: %w", err)
	}

	return selinuxRestoreCon(ctx, authorizedKeysPath)
}