Path: blob/main/components/gitpod-cli/cmd/git-token-validator.go
2498 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package cmd56import (7"context"8"fmt"9"io"10"os"11"os/exec"12"strings"13"time"1415log "github.com/sirupsen/logrus"16"github.com/spf13/cobra"17"google.golang.org/grpc"18"google.golang.org/grpc/credentials/insecure"1920"github.com/gitpod-io/gitpod/common-go/util"21"github.com/gitpod-io/gitpod/gitpod-cli/pkg/utils"22serverapi "github.com/gitpod-io/gitpod/gitpod-protocol"23supervisor "github.com/gitpod-io/gitpod/supervisor/api"24)2526var gitTokenValidatorOpts struct {27User string28Token string29TokenScopes string30Host string31RepoURL string32GitCommand string33}3435var gitTokenValidator = &cobra.Command{36Use: "git-token-validator",37Short: "Gitpod's Git token validator",38Long: "Tries to guess the scopes needed for a git operation and requests an appropriate token.",39Args: cobra.ExactArgs(0),40Hidden: true,41RunE: func(cmd *cobra.Command, args []string) error {42// ignore trace43utils.TrackCommandUsageEvent.Command = nil4445log.SetOutput(io.Discard)46f, err := os.OpenFile(os.TempDir()+"/gitpod-git-credential-helper.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)47if err == nil {48defer f.Close()49log.SetOutput(f)50}5152log.Infof("gp git-token-validator")5354ctx, cancel := context.WithTimeout(cmd.Context(), 1*time.Minute)55defer cancel()5657supervisorConn, err := grpc.Dial(util.GetSupervisorAddress(), grpc.WithTransportCredentials(insecure.NewCredentials()))58if err != nil {59log.WithError(err).Fatal("error connecting to supervisor")60}61wsinfo, err := supervisor.NewInfoServiceClient(supervisorConn).WorkspaceInfo(ctx, &supervisor.WorkspaceInfoRequest{})62if err != nil {63log.WithError(err).Fatal("error getting workspace info from supervisor")64}65clientToken, err := supervisor.NewTokenServiceClient(supervisorConn).GetToken(ctx, &supervisor.GetTokenRequest{66Host: wsinfo.GitpodApi.Host,67Kind: "gitpod",68Scope: []string{69"function:guessGitTokenScopes",70},71})72if err != nil {73log.WithError(err).Fatal("error getting token from supervisor")74}75client, err := serverapi.ConnectToServer(wsinfo.GitpodApi.Endpoint, serverapi.ConnectToServerOpts{76Token: clientToken.Token,77Context: ctx,78Log: log.NewEntry(log.StandardLogger()),79})80if err != nil {81log.WithError(err).Fatal("error connecting to server")82}83defer client.Close()8485params := &serverapi.GuessGitTokenScopesParams{86Host: gitTokenValidatorOpts.Host,87RepoURL: gitTokenValidatorOpts.RepoURL,88GitCommand: gitTokenValidatorOpts.GitCommand,89CurrentToken: &serverapi.GitToken{90Token: gitTokenValidatorOpts.Token,91Scopes: strings.Split(gitTokenValidatorOpts.TokenScopes, ","),92User: gitTokenValidatorOpts.User,93},94}95log.WithField("host", gitTokenValidatorOpts.Host).96WithField("repoURL", gitTokenValidatorOpts.RepoURL).97WithField("command", gitTokenValidatorOpts.GitCommand).98WithField("user", gitTokenValidatorOpts.User).99WithField("tokenScopes", gitTokenValidatorOpts.TokenScopes).100Info("guessing required token scopes")101guessedTokenScopes, err := client.GuessGitTokenScopes(ctx, params)102if err != nil {103log.WithError(err).Fatal("error guessing token scopes on server")104}105if guessedTokenScopes.Message != "" {106message := fmt.Sprintf("%s Please grant the necessary permissions.", guessedTokenScopes.Message)107log.WithField("guessedTokenScopes", guessedTokenScopes.Scopes).Info("insufficient permissions")108result, err := supervisor.NewNotificationServiceClient(supervisorConn).Notify(ctx,109&supervisor.NotifyRequest{110Level: supervisor.NotifyRequest_INFO,111Message: message,112Actions: []string{"Open Access Control"},113})114if err != nil {115log.WithError(err).Fatalf("error notifying client: '%s'", message)116}117if result.Action == "Open Access Control" {118cmd := exec.Command("/proc/self/exe", "preview", "--external", wsinfo.GetGitpodHost()+"/access-control")119err := cmd.Run()120if err != nil {121log.WithError(err).Fatalf("error opening access-control: '%s'", message)122}123}124return nil125}126if len(guessedTokenScopes.Scopes) > 0 {127_, err = supervisor.NewTokenServiceClient(supervisorConn).GetToken(ctx,128&supervisor.GetTokenRequest{129Host: gitTokenValidatorOpts.Host,130Scope: guessedTokenScopes.Scopes,131Description: "",132Kind: "git",133})134if err != nil {135log.WithError(err).Fatal("error getting new token from token service")136return nil137}138}139return nil140},141}142143func init() {144rootCmd.AddCommand(gitTokenValidator)145gitTokenValidator.Flags().StringVarP(&gitTokenValidatorOpts.User, "user", "u", "", "Git user")146gitTokenValidator.Flags().StringVarP(&gitTokenValidatorOpts.Token, "token", "t", "", "The Git token to be validated")147gitTokenValidator.Flags().StringVarP(&gitTokenValidatorOpts.TokenScopes, "scopes", "s", "", "A comma spearated list of the scopes of given token")148gitTokenValidator.Flags().StringVar(&gitTokenValidatorOpts.Host, "host", "", "The Git host")149gitTokenValidator.Flags().StringVarP(&gitTokenValidatorOpts.RepoURL, "repoURL", "r", "", "The URL of the Git repository")150gitTokenValidator.Flags().StringVarP(&gitTokenValidatorOpts.GitCommand, "gitCommand", "c", "", "The Git command to be performed")151gitTokenValidator.MarkFlagRequired("user")152gitTokenValidator.MarkFlagRequired("token")153gitTokenValidator.MarkFlagRequired("scopes")154gitTokenValidator.MarkFlagRequired("host")155gitTokenValidator.MarkFlagRequired("repoURL")156gitTokenValidator.MarkFlagRequired("gitCommand")157}158159160