Skip to content

Commit 06b7a47

Browse files
CR-9195 validate git source token (#244)
* validate git source token * wip * removed option for different repo for git source added PAT flag * change strings in wizard * modify strings * modified token type to personal * bump * lint error bug fixed * lint err * handle prompt errors better * docs update * small fix * removed security fix from release notes * bump * handle prompt errors * added initializeGitSourceCloneOpts * removed recognizing ^C error * taking values from variable and not flag
1 parent d955f72 commit 06b7a47

File tree

7 files changed

+95
-68
lines changed

7 files changed

+95
-68
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION=v0.0.226
1+
VERSION=v0.0.227
22

33
OUT_DIR=dist
44
YEAR?=$(shell date +"%Y")

cmd/commands/common.go

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ func askUserIfToInstallDemoResources(cmd *cobra.Command, sampleInstall *bool) er
105105

106106
_, result, err := prompt.Run()
107107
if err != nil {
108-
return fmt.Errorf("Prompt error: %w", err)
108+
return err
109109
}
110110

111111
if result == "No" {
112112
*sampleInstall = false
113113
}
114114
}
115+
115116
return nil
116117
}
117118

@@ -152,9 +153,11 @@ func getRepoFromUserInput(cmd *cobra.Command) error {
152153
}
153154
repoInput, err := repoPrompt.Run()
154155
if err != nil {
155-
return fmt.Errorf("Prompt error: %w", err)
156+
return err
156157
}
158+
157159
die(cmd.Flags().Set("repo", repoInput))
160+
158161
return nil
159162
}
160163

@@ -179,11 +182,14 @@ func getRuntimeNameFromUserInput(runtimeName *string) error {
179182
Default: "codefresh",
180183
Pointer: promptui.PipeCursor,
181184
}
185+
182186
runtimeNameInput, err := runtimeNamePrompt.Run()
183187
if err != nil {
184-
return fmt.Errorf("Prompt error: %w", err)
188+
return err
185189
}
190+
186191
*runtimeName = runtimeNameInput
192+
187193
return nil
188194
}
189195

@@ -218,7 +224,7 @@ func getRuntimeNameFromUserSelect(ctx context.Context, runtimeName *string) erro
218224

219225
_, result, err := prompt.Run()
220226
if err != nil {
221-
return fmt.Errorf("Prompt error: %w", err)
227+
return err
222228
}
223229

224230
*runtimeName = result
@@ -241,7 +247,7 @@ func getIngressClassFromUserSelect(ctx context.Context, ingressClassNames []stri
241247

242248
_, result, err := prompt.Run()
243249
if err != nil {
244-
return fmt.Errorf("Prompt error: %w", err)
250+
return err
245251
}
246252

247253
*ingressClass = result
@@ -271,7 +277,7 @@ func ensureGitToken(cmd *cobra.Command, cloneOpts *git.CloneOptions, verify bool
271277
}
272278

273279
if verify {
274-
err := cfgit.VerifyToken(cmd.Context(), cloneOpts.Provider, cloneOpts.Auth.Password)
280+
err := cfgit.VerifyToken(cmd.Context(), cloneOpts.Provider, cloneOpts.Auth.Password, cfgit.RuntimeToken)
275281
if err != nil {
276282
return fmt.Errorf("failed to verify git token: %w", err)
277283
}
@@ -282,23 +288,35 @@ func ensureGitToken(cmd *cobra.Command, cloneOpts *git.CloneOptions, verify bool
282288

283289
func ensureGitPAT(cmd *cobra.Command, opts *RuntimeInstallOptions) error {
284290
var err error
285-
if !store.Get().Silent {
286-
return getGitPATFromUserInput(cmd, opts)
291+
tokenFromFlag := opts.GitIntegrationRegistrationOpts.Token
292+
293+
if tokenFromFlag == "" {
294+
if !store.Get().Silent {
295+
err = getGitPATFromUserInput(cmd, opts)
296+
if err != nil {
297+
return err
298+
}
299+
} else {
300+
log.G(cmd.Context()).Info("Using runtime token as personal user token")
301+
opts.GitIntegrationRegistrationOpts.Token = opts.InsCloneOpts.Auth.Password
302+
if err != nil {
303+
return err
304+
}
305+
}
287306
}
288307

289-
opts.GitIntegrationRegistrationOpts.Token, err = cmd.Flags().GetString("git-token")
290-
return err
308+
return cfgit.VerifyToken(cmd.Context(), opts.InsCloneOpts.Provider, opts.GitIntegrationRegistrationOpts.Token, cfgit.PersonalToken)
291309
}
292310

293311
func getGitPATFromUserInput(cmd *cobra.Command, opts *RuntimeInstallOptions) error {
294312
gitPATPrompt := promptui.Prompt{
295-
Label: "Enter your Personal Git Access Token (leave blank to use runtime token. Can be changed later)",
313+
Label: "Personal git token for your user (skip to use runtime token)",
296314
Mask: '*',
297315
}
298316

299317
gitPAT, err := gitPATPrompt.Run()
300318
if err != nil {
301-
return fmt.Errorf("prompt error: %w", err)
319+
return err
302320
}
303321

304322
if gitPAT == "" {
@@ -314,14 +332,16 @@ func getGitPATFromUserInput(cmd *cobra.Command, opts *RuntimeInstallOptions) err
314332

315333
func getGitTokenFromUserInput(cmd *cobra.Command) error {
316334
gitTokenPrompt := promptui.Prompt{
317-
Label: "Git provider api token",
335+
Label: "Runtime git api token",
318336
Mask: '*',
319337
}
320338
gitTokenInput, err := gitTokenPrompt.Run()
321339
if err != nil {
322-
return fmt.Errorf("Prompt error: %w", err)
340+
return err
323341
}
342+
324343
die(cmd.Flags().Set("git-token", gitTokenInput))
344+
325345
return nil
326346
}
327347

@@ -361,7 +381,7 @@ func promptSummaryToUser(ctx context.Context, finalParameters map[string]string,
361381

362382
_, result, err := prompt.Run()
363383
if err != nil {
364-
return false, fmt.Errorf("Prompt error: %w", err)
384+
return false, err
365385
}
366386

367387
if result == "Yes" {
@@ -409,7 +429,7 @@ func getKubeContextNameFromUserSelect(cmd *cobra.Command, kubeContextName *strin
409429

410430
index, _, err := prompt.Run()
411431
if err != nil {
412-
return fmt.Errorf("Prompt error: %w", err)
432+
return err
413433
}
414434

415435
result := contextsIndex[index]
@@ -429,7 +449,7 @@ func getIngressHostFromUserInput(ctx context.Context, opts *RuntimeInstallOption
429449

430450
ingressHostInput, err := ingressHostPrompt.Run()
431451
if err != nil {
432-
return fmt.Errorf("Prompt error: %w", err)
452+
return err
433453
}
434454

435455
opts.IngressHost = ingressHostInput
@@ -471,7 +491,7 @@ func setIngressHost(ctx context.Context, opts *RuntimeInstallOptions) error {
471491
}
472492
}
473493

474-
if opts.IngressController == "" {
494+
if opts.IngressHost == "" {
475495
return fmt.Errorf("please provide an ingress host via --ingress-host or installation wizard")
476496
}
477497

@@ -558,7 +578,7 @@ func askUserIfToProceedWithInsecure(ctx context.Context) error {
558578

559579
_, result, err := prompt.Run()
560580
if err != nil {
561-
return fmt.Errorf("Prompt error: %w", err)
581+
return err
562582
}
563583

564584
if result == "Yes" {

cmd/commands/runtime.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ func NewRuntimeInstallCommand() *cobra.Command {
215215

216216
cmd.Flags().StringVar(&installationOpts.IngressHost, "ingress-host", "", "The ingress host")
217217
cmd.Flags().StringVar(&installationOpts.IngressClass, "ingress-class", "", "The ingress class name")
218+
cmd.Flags().StringVar(&installationOpts.GitIntegrationRegistrationOpts.Token, "personal-git-token", "", "The Personal git token for your user")
218219
cmd.Flags().StringVar(&installationOpts.versionStr, "version", "", "The runtime version to install (default: latest)")
219220
cmd.Flags().BoolVar(&installationOpts.InstallDemoResources, "demo-resources", true, "Installs demo resources (default: true)")
220221
cmd.Flags().DurationVar(&store.Get().WaitTimeout, "wait-timeout", store.Get().WaitTimeout, "How long to wait for the runtime components to be ready")
@@ -224,11 +225,12 @@ func NewRuntimeInstallCommand() *cobra.Command {
224225
installationOpts.InsCloneOpts = apu.AddCloneFlags(cmd, &apu.CloneFlagsOptions{
225226
CreateIfNotExist: true,
226227
})
227-
installationOpts.GsCloneOpts = apu.AddCloneFlags(cmd, &apu.CloneFlagsOptions{
228-
Prefix: "git-src",
229-
Optional: true,
228+
229+
installationOpts.GsCloneOpts = &git.CloneOptions{
230+
FS: fs.Create(memfs.New()),
230231
CreateIfNotExist: true,
231-
})
232+
}
233+
232234
installationOpts.KubeFactory = kube.AddFlags(cmd.Flags())
233235

234236
util.Die(cmd.Flags().MarkHidden("bypass-ingress-class-check"))
@@ -307,22 +309,7 @@ func runtimeInstallCommandPreRunHandler(cmd *cobra.Command, opts *RuntimeInstall
307309
return err
308310
}
309311

310-
if opts.GsCloneOpts.Auth.Username == "" {
311-
opts.GsCloneOpts.Auth.Username = opts.InsCloneOpts.Auth.Username
312-
}
313-
314-
if opts.GsCloneOpts.Auth.Password == "" {
315-
opts.GsCloneOpts.Auth.Password = opts.InsCloneOpts.Auth.Password
316-
}
317-
318-
if opts.GsCloneOpts.Repo == "" {
319-
host, orgRepo, _, _, _, suffix, _ := aputil.ParseGitUrl(opts.InsCloneOpts.Repo)
320-
opts.GsCloneOpts.Repo = host + orgRepo + "_git-source" + suffix + "/resources" + "_" + opts.RuntimeName
321-
}
322-
323-
if opts.GsCloneOpts.Provider == "" {
324-
opts.GsCloneOpts.Provider = opts.InsCloneOpts.Provider
325-
}
312+
initializeGitSourceCloneOpts(opts)
326313

327314
opts.InsCloneOpts.Parse()
328315
opts.GsCloneOpts.Parse()
@@ -1864,3 +1851,11 @@ func getVersionIfExists(opts *RuntimeInstallOptions) error {
18641851
}
18651852
return nil
18661853
}
1854+
1855+
func initializeGitSourceCloneOpts(opts *RuntimeInstallOptions) {
1856+
opts.GsCloneOpts.Provider = opts.InsCloneOpts.Provider
1857+
opts.GsCloneOpts.Auth = opts.InsCloneOpts.Auth
1858+
opts.GsCloneOpts.Progress = opts.InsCloneOpts.Progress
1859+
host, orgRepo, _, _, _, suffix, _ := aputil.ParseGitUrl(opts.InsCloneOpts.Repo)
1860+
opts.GsCloneOpts.Repo = host + orgRepo + "_git-source" + suffix + "/resources" + "_" + opts.RuntimeName
1861+
}

docs/commands/cli-v2_runtime_install.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,21 @@ cli-v2 runtime install [runtime_name] [flags]
2828
### Options
2929

3030
```
31-
--context string The name of the kubeconfig context to use
32-
--demo-resources Installs demo resources (default: true) (default true)
33-
--git-src-git-token string Your git provider api token [GIT_SRC_GIT_TOKEN]
34-
--git-src-git-user string Your git provider user name [GIT_SRC_GIT_USER] (not required in GitHub)
35-
--git-src-provider string The git provider, one of: gitea|github|gitlab
36-
--git-src-repo string Repository URL [GIT_SRC_GIT_REPO]
37-
-t, --git-token string Your git provider api token [GIT_TOKEN]
38-
-u, --git-user string Your git provider user name [GIT_USER] (not required in GitHub)
39-
-h, --help help for install
40-
--ingress-class string The ingress class name
41-
--ingress-host string The ingress host
42-
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
43-
-n, --namespace string If present, the namespace scope for this CLI request
44-
--provider string The git provider, one of: gitea|github|gitlab
45-
--provider-api-url string Git provider API url
46-
--repo string Repository URL [GIT_REPO]
47-
--version string The runtime version to install (default: latest)
48-
--wait-timeout duration How long to wait for the runtime components to be ready (default 8m0s)
31+
--context string The name of the kubeconfig context to use
32+
--demo-resources Installs demo resources (default: true) (default true)
33+
-t, --git-token string Your git provider api token [GIT_TOKEN]
34+
-u, --git-user string Your git provider user name [GIT_USER] (not required in GitHub)
35+
-h, --help help for install
36+
--ingress-class string The ingress class name
37+
--ingress-host string The ingress host
38+
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
39+
-n, --namespace string If present, the namespace scope for this CLI request
40+
--personal-git-token string The Personal git token for your user
41+
--provider string The git provider, one of: gitea|github|gitlab
42+
--provider-api-url string Git provider API url
43+
--repo string Repository URL [GIT_REPO]
44+
--version string The runtime version to install (default: latest)
45+
--wait-timeout duration How long to wait for the runtime components to be ready (default 8m0s)
4946
```
5047

5148
### Options inherited from parent commands

docs/releases/release_notes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cf version
2323

2424
```bash
2525
# download and extract the binary
26-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.226/cf-linux-amd64.tar.gz | tar zx
26+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.227/cf-linux-amd64.tar.gz | tar zx
2727

2828
# move the binary to your $PATH
2929
mv ./cf-linux-amd64 /usr/local/bin/cf
@@ -36,7 +36,7 @@ cf version
3636

3737
```bash
3838
# download and extract the binary
39-
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.226/cf-darwin-amd64.tar.gz | tar zx
39+
curl -L --output - https://github.com/codefresh-io/cli-v2/releases/download/v0.0.227/cf-darwin-amd64.tar.gz | tar zx
4040

4141
# move the binary to your $PATH
4242
mv ./cf-darwin-amd64 /usr/local/bin/cf

manifests/runtime.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ metadata:
55
namespace: "{{ namespace }}"
66
spec:
77
defVersion: 1.0.0
8-
version: 0.0.226
8+
version: 0.0.227
99
bootstrapSpecifier: github.com/codefresh-io/cli-v2/manifests/argo-cd
1010
components:
1111
- name: events

pkg/git/git.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,27 @@ import (
2323
"github.com/codefresh-io/cli-v2/pkg/log"
2424
)
2525

26+
type TokenTypes string
27+
28+
const (
29+
RuntimeToken TokenTypes = "runtime token"
30+
PersonalToken TokenTypes = "personal token"
31+
)
2632

2733
var (
28-
requiredGitHubScopes = []string{ "repo", "admin:repo_hook" }
34+
requiredGitHubRuntimeScopes = []string{ "repo", "admin:repo_hook" }
35+
requiredGitHubGitSourceScopes = []string{ "repo" }
36+
37+
typeToGitHubScopes = map[TokenTypes][]string {
38+
RuntimeToken: requiredGitHubRuntimeScopes,
39+
PersonalToken: requiredGitHubGitSourceScopes,
40+
}
2941
)
3042

3143

32-
func VerifyToken(ctx context.Context, provider string, token string) error {
33-
providerToVerifier := map[string]func(context.Context, string)error {
44+
45+
func VerifyToken(ctx context.Context, provider string, token string, tokenType TokenTypes) error {
46+
providerToVerifier := map[string]func(context.Context, string, TokenTypes)error {
3447
"github": verifyGitHubTokenScope,
3548
}
3649

@@ -39,11 +52,11 @@ func VerifyToken(ctx context.Context, provider string, token string) error {
3952
return verifyTokenScopeFallback(ctx, provider)
4053
}
4154

42-
return verifier(ctx, token)
55+
return verifier(ctx, token, tokenType)
4356
}
4457

45-
func verifyGitHubTokenScope(ctx context.Context, token string) error {
46-
errMessage := "the provided git token is missing one or more of the required scopes:" + strings.Join(requiredGitHubScopes, ", ")
58+
func verifyGitHubTokenScope(ctx context.Context, token string, tokenType TokenTypes) error {
59+
errMessage := fmt.Sprintf("the provided %s is missing one or more of the required scopes: %s", tokenType, strings.Join(typeToGitHubScopes[tokenType], ", "))
4760

4861
req, err := http.NewRequestWithContext(ctx, "HEAD", "https://api.github.com/", nil)
4962
if err != nil {
@@ -65,7 +78,7 @@ func verifyGitHubTokenScope(ctx context.Context, token string) error {
6578
scopes = strings.Split(rawScopes[0], ", ")
6679
}
6780

68-
for _, rs := range requiredGitHubScopes {
81+
for _, rs := range typeToGitHubScopes[tokenType] {
6982
var contained bool
7083
for _, scope := range scopes {
7184
if scope == rs {
@@ -79,6 +92,8 @@ func verifyGitHubTokenScope(ctx context.Context, token string) error {
7992
}
8093
}
8194

95+
log.G(ctx).Info("Token verified")
96+
8297
return nil
8398
}
8499

0 commit comments

Comments
 (0)