From aa6fefcdac595779dab6983d37768499306d690a Mon Sep 17 00:00:00 2001 From: Debayan De Date: Tue, 18 Jun 2024 19:21:55 +0100 Subject: [PATCH] Allow upterm host to allowlist users on self-hosted versions of VCSes --- cmd/upterm/command/host.go | 8 ++++---- host/authorizedkeys.go | 33 ++++++++++++++++++++++----------- utils/utils.go | 7 +++++++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/cmd/upterm/command/host.go b/cmd/upterm/command/host.go index b5c8438b1..8002cca30 100644 --- a/cmd/upterm/command/host.go +++ b/cmd/upterm/command/host.go @@ -74,10 +74,10 @@ private key. To authorize client connections, specify a authorized_key file with cmd.PersistentFlags().StringSliceVarP(&flagPrivateKeys, "private-key", "i", defaultPrivateKeys(homeDir), "Specify private key files for public key authentication with the upterm server (required).") cmd.PersistentFlags().StringVarP(&flagKnownHostsFilename, "known-hosts", "", defaultKnownHost(homeDir), "Specify a file containing known keys for remote hosts (required).") cmd.PersistentFlags().StringVar(&flagAuthorizedKeys, "authorized-keys", "", "Specify a authorize_keys file listing authorized public keys for connection.") - cmd.PersistentFlags().StringSliceVar(&flagCodebergUsers, "codeberg-user", nil, "Authorize specified Codeberg users by allowing their public keys to connect.") - cmd.PersistentFlags().StringSliceVar(&flagGitHubUsers, "github-user", nil, "Authorize specified GitHub users by allowing their public keys to connect. Configure GitHub CLI environment variables as needed; see https://cli.github.com/manual/gh_help_environment for details.") - cmd.PersistentFlags().StringSliceVar(&flagGitLabUsers, "gitlab-user", nil, "Authorize specified GitLab users by allowing their public keys to connect.") - cmd.PersistentFlags().StringSliceVar(&flagSourceHutUsers, "srht-user", nil, "Authorize specified SourceHut users by allowing their public keys to connect.") + cmd.PersistentFlags().StringSliceVar(&flagCodebergUsers, "codeberg-user", nil, "Authorize specified Codeberg users by allowing their public keys to connect. For self-hosted installations, set CODEBERG_HOST, along with the protocol prefix (e.g., https://git.example.com).") + cmd.PersistentFlags().StringSliceVar(&flagGitHubUsers, "github-user", nil, "Authorize specified GitHub users by allowing their public keys to connect. Configure GitHub CLI environment variables as needed; see https://cli.github.com/manual/gh_help_environment for details. For self-hosted installations, set GITHUB_HOST, along with the protocol prefix (e.g., https://git.example.com).") + cmd.PersistentFlags().StringSliceVar(&flagGitLabUsers, "gitlab-user", nil, "Authorize specified GitLab users by allowing their public keys to connect. For self-hosted installations, set GITLAB_HOST, along with the protocol prefix (e.g., https://git.example.com).") + cmd.PersistentFlags().StringSliceVar(&flagSourceHutUsers, "srht-user", nil, "Authorize specified SourceHut users by allowing their public keys to connect. For self-hosted installations, set SOURCEHUT_HOST, along with the protocol prefix (e.g., https://git.example.com).") cmd.PersistentFlags().BoolVar(&flagAccept, "accept", false, "Automatically accept client connections without prompts.") cmd.PersistentFlags().BoolVarP(&flagReadOnly, "read-only", "r", false, "Host a read-only session, preventing client interaction.") diff --git a/host/authorizedkeys.go b/host/authorizedkeys.go index 906daac6b..a99800b38 100644 --- a/host/authorizedkeys.go +++ b/host/authorizedkeys.go @@ -10,22 +10,33 @@ import ( "time" "github.com/cli/go-gh/v2/pkg/api" + "github.com/owenthereal/upterm/utils" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" ) -const ( - codebergKeysUrlFmt = "https://codeberg.org/%s" - gitHubKeysUrlFmt = "https://github.com/%s" - gitLabKeysUrlFmt = "https://gitlab.com/%s" - sourceHutKeysUrlFmt = "https://meta.sr.ht/~%s" -) - type AuthorizedKey struct { PublicKeys []ssh.PublicKey Comment string } +func GetUrlFmt(service string) string { + serviceAttrsMap := map[string][]string{ + "Codeberg": {"CODEBERG_HOST", "https://codeberg.org"}, + "GitHub": {"GITHUB_HOST", "https://github.com"}, + "GitLab": {"GITLAB_HOST", "https://gitlab.com"}, + "SourceHut": {"SOURCEHUT_HOST", "https://meta.sr.ht"}, + } + + serviceUrl := utils.GetEnvWithDefault(serviceAttrsMap[service][0], serviceAttrsMap[service][1]) + + if service == "SourceHut" { + return (serviceUrl + "/~%s") + } + + return (serviceUrl + "/%s") +} + func AuthorizedKeysFromFile(file string) (*AuthorizedKey, error) { authorizedKeysBytes, err := os.ReadFile(file) if err != nil { @@ -36,7 +47,7 @@ func AuthorizedKeysFromFile(file string) (*AuthorizedKey, error) { } func CodebergUserAuthorizedKeys(usernames []string) ([]*AuthorizedKey, error) { - return usersPublicKeys(codebergKeysUrlFmt, usernames) + return usersPublicKeys(GetUrlFmt("Codeberg"), usernames) } func GitHubUserAuthorizedKeys(usernames []string, logger *logrus.Logger) ([]*AuthorizedKey, error) { @@ -66,11 +77,11 @@ func GitHubUserAuthorizedKeys(usernames []string, logger *logrus.Logger) ([]*Aut } func GitLabUserAuthorizedKeys(usernames []string) ([]*AuthorizedKey, error) { - return usersPublicKeys(gitLabKeysUrlFmt, usernames) + return usersPublicKeys(GetUrlFmt("GitLab"), usernames) } func SourceHutUserAuthorizedKeys(usernames []string) ([]*AuthorizedKey, error) { - return usersPublicKeys(sourceHutKeysUrlFmt, usernames) + return usersPublicKeys(GetUrlFmt("SourceHut"), usernames) } func parseAuthorizedKeys(keysBytes []byte, comment string) (*AuthorizedKey, error) { @@ -97,7 +108,7 @@ func githubUserPublicKeys(username string, logger *logrus.Logger) ([]byte, error if strings.Contains(err.Error(), "authentication token not found for host") { // fallback to use the public GH API logger.WithError(err).Warn("no GitHub token found, falling back to public API") - return userPublicKeys(gitHubKeysUrlFmt, username) + return userPublicKeys(GetUrlFmt("GitHub"), username) } return nil, err diff --git a/utils/utils.go b/utils/utils.go index 47dbcd883..70f93026a 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -27,6 +27,13 @@ func UptermDir() (string, error) { return filepath.Join(homedir, ".upterm"), nil } +func GetEnvWithDefault(envVar, defaultValue string) string { + if v, ok := os.LookupEnv(envVar); ok && len(v) > 0 { + return v + } + return defaultValue +} + func CreateUptermDir() (string, error) { dir, err := UptermDir() if err != nil {