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