From c1d6ee5df9c1c8f30dcc196f882b6f579c38e22c Mon Sep 17 00:00:00 2001 From: Duane Appleby Date: Mon, 16 Dec 2019 10:19:47 +0000 Subject: [PATCH] Issue 1182: Add sslVerify flag to pipelineresource type git Enables the disabling in git config of http.sslVerify such that the git fetch can succeed against local gitlab installs with self signed certificates. --- cmd/git-init/main.go | 1 + docs/resources.md | 3 + go.mod | 3 +- pkg/apis/pipeline/v1alpha1/git_resource.go | 24 ++++-- .../pipeline/v1alpha1/git_resource_test.go | 81 ++++++++++++++++--- pkg/git/git.go | 14 +++- .../taskrun/resources/input_resource_test.go | 54 +++++++++++++ 7 files changed, 157 insertions(+), 23 deletions(-) diff --git a/cmd/git-init/main.go b/cmd/git-init/main.go index bbee75d1228..0cd389d4f89 100644 --- a/cmd/git-init/main.go +++ b/cmd/git-init/main.go @@ -34,6 +34,7 @@ func init() { flag.StringVar(&fetchSpec.URL, "url", "", "Git origin URL to fetch") flag.StringVar(&fetchSpec.Revision, "revision", "", "The Git revision to make the repository HEAD") flag.StringVar(&fetchSpec.Path, "path", "", "Path of directory under which Git repository will be copied") + flag.BoolVar(&fetchSpec.SSLVerify, "sslVerify", true, "Enable/Disable SSL verification in the git config") flag.BoolVar(&submodules, "submodules", true, "Initialize and fetch Git submodules") flag.UintVar(&fetchSpec.Depth, "depth", 1, "Perform a shallow clone to this depth") flag.StringVar(&terminationMessagePath, "terminationMessagePath", "/dev/termination-log", "Location of file containing termination message") diff --git a/docs/resources.md b/docs/resources.md index ab9e8e5dfd7..56965cbbebd 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -289,9 +289,12 @@ Params that can be added are the following: 1. `depth`: performs a [shallow clone][git-depth] where only the most recent commit(s) will be fetched. If set to `'0'`, all commits will be fetched. _If not specified, the default depth is 1._ +1. `sslVerify`: defines if [http.sslVerify][git-http.sslVerify] should be set to `true` or `false` + in the global git config. _Defaults to `true` if omitted._ [git-rev]: https://git-scm.com/docs/gitrevisions#_specifying_revisions [git-depth]: https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt +[git-http.sslVerify]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpsslVerify When used as an input, the Git resource includes the exact commit fetched in the `resourceResults` section of the `taskRun`'s status object: diff --git a/go.mod b/go.mod index 89f844da90a..4f447cee593 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( cloud.google.com/go v0.47.0 // indirect + cloud.google.com/go/storage v1.0.0 contrib.go.opencensus.io/exporter/prometheus v0.1.0 // indirect contrib.go.opencensus.io/exporter/stackdriver v0.12.8 // indirect github.com/Azure/azure-sdk-for-go v36.1.0+incompatible // indirect @@ -50,7 +51,7 @@ require ( golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - google.golang.org/api v0.10.0 // indirect + google.golang.org/api v0.10.0 google.golang.org/appengine v1.6.5 // indirect google.golang.org/grpc v1.24.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/pkg/apis/pipeline/v1alpha1/git_resource.go b/pkg/apis/pipeline/v1alpha1/git_resource.go index 745cdbe9ed3..47af13028a9 100644 --- a/pkg/apis/pipeline/v1alpha1/git_resource.go +++ b/pkg/apis/pipeline/v1alpha1/git_resource.go @@ -42,9 +42,9 @@ type GitResource struct { Revision string `json:"revision"` Submodules bool `json:"submodules"` - Depth uint `json:"depth"` - - GitImage string `json:"-"` + Depth uint `json:"depth"` + SSLVerify bool `json:"sslVerify"` + GitImage string `json:"-"` } // NewGitResource creates a new git resource to pass to a Task @@ -58,6 +58,7 @@ func NewGitResource(gitImage string, r *PipelineResource) (*GitResource, error) GitImage: gitImage, Submodules: true, Depth: 1, + SSLVerify: true, } for _, param := range r.Spec.Params { switch { @@ -69,6 +70,8 @@ func NewGitResource(gitImage string, r *PipelineResource) (*GitResource, error) gitResource.Submodules = toBool(param.Value, true) case strings.EqualFold(param.Name, "Depth"): gitResource.Depth = toUint(param.Value, 1) + case strings.EqualFold(param.Name, "SSLVerify"): + gitResource.SSLVerify = toBool(param.Value, true) } } // default revision to master if nothing is provided @@ -115,11 +118,12 @@ func (s *GitResource) GetURL() string { // Replacements is used for template replacement on a GitResource inside of a Taskrun. func (s *GitResource) Replacements() map[string]string { return map[string]string{ - "name": s.Name, - "type": string(s.Type), - "url": s.URL, - "revision": s.Revision, - "depth": strconv.FormatUint(uint64(s.Depth), 10), + "name": s.Name, + "type": string(s.Type), + "url": s.URL, + "revision": s.Revision, + "depth": strconv.FormatUint(uint64(s.Depth), 10), + "sslVerify": strconv.FormatBool(s.SSLVerify), } } @@ -137,6 +141,9 @@ func (s *GitResource) GetInputTaskModifier(_ *TaskSpec, path string) (TaskModifi if s.Depth != 1 { args = append(args, "-depth", strconv.FormatUint(uint64(s.Depth), 10)) } + if !s.SSLVerify { + args = append(args, "-sslVerify=false") + } step := Step{ Container: corev1.Container{ @@ -152,6 +159,7 @@ func (s *GitResource) GetInputTaskModifier(_ *TaskSpec, path string) (TaskModifi }}, }, } + return &InternalTaskModifier{ StepsToPrepend: []Step{step}, }, nil diff --git a/pkg/apis/pipeline/v1alpha1/git_resource_test.go b/pkg/apis/pipeline/v1alpha1/git_resource_test.go index 03ed36156b5..c7534b12834 100644 --- a/pkg/apis/pipeline/v1alpha1/git_resource_test.go +++ b/pkg/apis/pipeline/v1alpha1/git_resource_test.go @@ -53,6 +53,7 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 1, + SSLVerify: true, }, }, { desc: "Without Revision", @@ -69,6 +70,7 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 1, + SSLVerify: true, }, }, { desc: "With Submodules", @@ -86,6 +88,7 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 1, + SSLVerify: true, }, }, { desc: "Without Submodules", @@ -104,6 +107,7 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: false, Depth: 1, + SSLVerify: true, }, }, { desc: "With positive depth", @@ -122,6 +126,7 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 8, + SSLVerify: true, }, }, { desc: "With zero depth", @@ -140,6 +145,27 @@ func Test_Valid_NewGitResource(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 0, + SSLVerify: true, + }, + }, { + desc: "Without SSLVerify", + pipelineResource: tb.PipelineResource("git-resource", "default", + tb.PipelineResourceSpec(v1alpha1.PipelineResourceTypeGit, + tb.PipelineResourceSpecParam("URL", "git@github.com:test/test.git"), + tb.PipelineResourceSpecParam("Revision", "test"), + tb.PipelineResourceSpecParam("Depth", "0"), + tb.PipelineResourceSpecParam("SSLVerify", "false"), + ), + ), + want: &v1alpha1.GitResource{ + Name: "git-resource", + Type: v1alpha1.PipelineResourceTypeGit, + URL: "git@github.com:test/test.git", + Revision: "test", + GitImage: "override-with-git:latest", + Submodules: true, + Depth: 0, + SSLVerify: false, }, }} { t.Run(tc.desc, func(t *testing.T) { @@ -157,19 +183,21 @@ func Test_Valid_NewGitResource(t *testing.T) { func Test_GitResource_Replacements(t *testing.T) { r := &v1alpha1.GitResource{ - Name: "git-resource", - Type: v1alpha1.PipelineResourceTypeGit, - URL: "git@github.com:test/test.git", - Revision: "master", - Depth: 16, + Name: "git-resource", + Type: v1alpha1.PipelineResourceTypeGit, + URL: "git@github.com:test/test.git", + Revision: "master", + Depth: 16, + SSLVerify: false, } want := map[string]string{ - "name": "git-resource", - "type": string(v1alpha1.PipelineResourceTypeGit), - "url": "git@github.com:test/test.git", - "revision": "master", - "depth": "16", + "name": "git-resource", + "type": string(v1alpha1.PipelineResourceTypeGit), + "url": "git@github.com:test/test.git", + "revision": "master", + "depth": "16", + "sslVerify": "false", } got := r.Replacements() @@ -196,6 +224,7 @@ func Test_GitResource_GetDownloadTaskModifier(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 1, + SSLVerify: true, }, want: corev1.Container{ Name: "git-source-git-resource-9l9zj", @@ -222,6 +251,7 @@ func Test_GitResource_GetDownloadTaskModifier(t *testing.T) { GitImage: "override-with-git:latest", Submodules: false, Depth: 1, + SSLVerify: true, }, want: corev1.Container{ Name: "git-source-git-resource-mz4c7", @@ -250,6 +280,7 @@ func Test_GitResource_GetDownloadTaskModifier(t *testing.T) { GitImage: "override-with-git:latest", Submodules: true, Depth: 8, + SSLVerify: true, }, want: corev1.Container{ Name: "git-source-git-resource-mssqb", @@ -268,6 +299,36 @@ func Test_GitResource_GetDownloadTaskModifier(t *testing.T) { WorkingDir: "/workspace", Env: []corev1.EnvVar{{Name: "TEKTON_RESOURCE_NAME", Value: "git-resource"}}, }, + }, { + desc: "Without sslVerify", + gitResource: &v1alpha1.GitResource{ + Name: "git-resource", + Type: v1alpha1.PipelineResourceTypeGit, + URL: "git@github.com:test/test.git", + Revision: "master", + GitImage: "override-with-git:latest", + Submodules: false, + Depth: 1, + SSLVerify: false, + }, + want: corev1.Container{ + Name: "git-source-git-resource-78c5n", + Image: "override-with-git:latest", + Command: []string{"/ko-app/git-init"}, + Args: []string{ + "-url", + "git@github.com:test/test.git", + "-revision", + "master", + "-path", + "/test/test", + "-submodules", + "false", + "-sslVerify=false", + }, + WorkingDir: "/workspace", + Env: []corev1.EnvVar{{Name: "TEKTON_RESOURCE_NAME", Value: "git-resource"}}, + }, }} { t.Run(tc.desc, func(t *testing.T) { ts := v1alpha1.TaskSpec{} diff --git a/pkg/git/git.go b/pkg/git/git.go index c8af78670d0..77364fe07e8 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "os/exec" + "strconv" "strings" homedir "github.com/mitchellh/go-homedir" @@ -45,10 +46,11 @@ func run(logger *zap.SugaredLogger, dir string, args ...string) (string, error) // FetchSpec describes how to initialize and fetch from a Git repository. type FetchSpec struct { - URL string - Revision string - Path string - Depth uint + URL string + Revision string + Path string + Depth uint + SSLVerify bool } // Fetch fetches the specified git repository at the revision into path. @@ -74,6 +76,10 @@ func Fetch(logger *zap.SugaredLogger, spec FetchSpec) error { if _, err := run(logger, "", "remote", "add", "origin", trimmedURL); err != nil { return err } + if _, err := run(logger, "", "config", "--global", "http.sslVerify", strconv.FormatBool(spec.SSLVerify)); err != nil { + logger.Warnf("Failed to set http.sslVerify in git config: %s", err) + return err + } fetchArgs := []string{"fetch", "--recurse-submodules=yes"} if spec.Depth > 0 { diff --git a/pkg/reconciler/taskrun/resources/input_resource_test.go b/pkg/reconciler/taskrun/resources/input_resource_test.go index f982b90e7ab..af25dc0471d 100644 --- a/pkg/reconciler/taskrun/resources/input_resource_test.go +++ b/pkg/reconciler/taskrun/resources/input_resource_test.go @@ -145,6 +145,24 @@ func setUp() { Value: "branch", }}, }, + }, { + ObjectMeta: metav1.ObjectMeta{ + Name: "the-git-with-sslVerify-false", + Namespace: "marshmallow", + }, + Spec: v1alpha1.PipelineResourceSpec{ + Type: "git", + Params: []v1alpha1.ResourceParam{{ + Name: "Url", + Value: "https://github.com/grafeas/kritis", + }, { + Name: "Revision", + Value: "branch", + }, { + Name: "SSLVerify", + Value: "false", + }}, + }, }, { ObjectMeta: metav1.ObjectMeta{ Name: "cluster2", @@ -554,6 +572,42 @@ func TestAddResourceToTask(t *testing.T) { }, }}, }, + }, { + desc: "simple with sslVerify false", + task: task, + taskRun: &v1alpha1.TaskRun{ + ObjectMeta: metav1.ObjectMeta{ + Name: "build-from-repo-run", + Namespace: "marshmallow", + }, + Spec: v1alpha1.TaskRunSpec{ + TaskRef: &v1alpha1.TaskRef{ + Name: "simpleTask", + }, + Inputs: v1alpha1.TaskRunInputs{ + Resources: []v1alpha1.TaskResourceBinding{{ + PipelineResourceBinding: v1alpha1.PipelineResourceBinding{ + ResourceRef: &v1alpha1.PipelineResourceRef{ + Name: "the-git-with-sslVerify-false", + }, + Name: "gitspace", + }, + }}, + }, + }, + }, + wantErr: false, + want: &v1alpha1.TaskSpec{ + Inputs: gitInputs, + Steps: []v1alpha1.Step{{Container: corev1.Container{ + Name: "git-source-the-git-with-sslVerify-false-9l9zj", + Image: "override-with-git:latest", + Command: []string{"/ko-app/git-init"}, + Args: []string{"-url", "https://github.com/grafeas/kritis", "-revision", "branch", "-path", "/workspace/gitspace", "-sslVerify=false"}, + WorkingDir: "/workspace", + Env: []corev1.EnvVar{{Name: "TEKTON_RESOURCE_NAME", Value: "the-git-with-sslVerify-false"}}, + }}}, + }, }, { desc: "storage resource as input with target path", task: taskWithTargetPath,