Skip to content

Commit 41e7b24

Browse files
committed
Issue 1880: Adds the ability to disable the certificate validation in the
client interacting with the git server performing actions related to the use of the pipeline resource of type pullrequest. To disable, user specifies sslVerify parameter in their resource with value set to "false". Value is true by default.
1 parent 5e7f2ac commit 41e7b24

File tree

6 files changed

+126
-44
lines changed

6 files changed

+126
-44
lines changed

cmd/pullrequest-init/main.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ import (
1919
"context"
2020
"flag"
2121
"fmt"
22-
"os"
23-
2422
"github.com/tektoncd/pipeline/pkg/pullrequest"
2523
"go.uber.org/zap"
2624
"knative.dev/pkg/logging"
25+
"os"
2726
)
2827

2928
var (
30-
prURL = flag.String("url", "", "The url of the pull request to initialize.")
31-
path = flag.String("path", "", "Path of directory under which PR will be copied")
32-
mode = flag.String("mode", "download", "Whether to operate in download or upload mode")
33-
provider = flag.String("provider", "", "The SCM provider to use. Optional")
29+
prURL = flag.String("url", "", "The url of the pull request to initialize.")
30+
path = flag.String("path", "", "Path of directory under which PR will be copied")
31+
mode = flag.String("mode", "download", "Whether to operate in download or upload mode")
32+
provider = flag.String("provider", "", "The SCM provider to use. Optional")
33+
sslVerify = flag.Bool("sslVerify", true, "Enable/Disable SSL verification in the git client. Defaults to true")
3434
)
3535

3636
func main() {
@@ -45,7 +45,7 @@ func main() {
4545
ctx := context.Background()
4646

4747
token := os.Getenv("AUTH_TOKEN")
48-
client, err := pullrequest.NewSCMHandler(logger, *prURL, *provider, token)
48+
client, err := pullrequest.NewSCMHandler(logger, *prURL, *provider, token, *sslVerify)
4949
if err != nil {
5050
logger.Fatalf("error creating GitHub client: %v", err)
5151
}

docs/resources.md

+4
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ Params that can be added are the following:
439439
1. `url`: represents the location of the pull request to fetch.
440440
1. `provider`: represents the SCM provider to use. This will be "guessed" based
441441
on the url if not set. Valid values are `github` or `gitlab` today.
442+
1. `sslVerify`: represents whether or not the client should verify certificates
443+
from the git server. Valid values are `"true"` or `"false"`, the default being
444+
`"true"`.
442445

443446
#### Statuses
444447

@@ -456,6 +459,7 @@ URLs should be of the form: https://github.com/tektoncd/pipeline/pull/1
456459

457460
The PullRequest resource works with self hosted or enterprise GitHub/GitLab
458461
instances. Simply provide the pull request URL and set the `provider` parameter.
462+
If you need to skip certificate validation set the `sslVerify` parameter to `"false"`.
459463

460464
```yaml
461465
apiVersion: tekton.dev/v1alpha1

pkg/apis/pipeline/v1alpha1/pull_request_resource.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package v1alpha1
1818

1919
import (
2020
"fmt"
21+
"strconv"
2122
"strings"
2223

2324
"github.com/tektoncd/pipeline/pkg/apis/pipeline"
@@ -46,25 +47,34 @@ type PullRequestResource struct {
4647
// Secrets holds a struct to indicate a field name and corresponding secret name to populate it.
4748
Secrets []SecretParam `json:"secrets"`
4849

49-
PRImage string `json:"-"`
50+
PRImage string `json:"-"`
51+
SSLVerify bool `json:"sslVerify"`
5052
}
5153

5254
// NewPullRequestResource create a new git resource to pass to a Task
5355
func NewPullRequestResource(prImage string, r *PipelineResource) (*PullRequestResource, error) {
5456
if r.Spec.Type != PipelineResourceTypePullRequest {
55-
return nil, fmt.Errorf("PipelineResource: Cannot create a PR resource from a %s Pipeline Resource", r.Spec.Type)
57+
return nil, fmt.Errorf("cannot create a PR resource from a %s Pipeline Resource", r.Spec.Type)
5658
}
5759
prResource := PullRequestResource{
58-
Name: r.Name,
59-
Type: r.Spec.Type,
60-
Secrets: r.Spec.SecretParams,
61-
PRImage: prImage,
60+
Name: r.Name,
61+
Type: r.Spec.Type,
62+
Secrets: r.Spec.SecretParams,
63+
PRImage: prImage,
64+
SSLVerify: true,
6265
}
6366
for _, param := range r.Spec.Params {
64-
if strings.EqualFold(param.Name, "URL") {
67+
switch {
68+
case strings.EqualFold(param.Name, "URL"):
6569
prResource.URL = param.Value
66-
} else if strings.EqualFold(param.Name, "Provider") {
70+
case strings.EqualFold(param.Name, "Provider"):
6771
prResource.Provider = param.Value
72+
case strings.EqualFold(param.Name, "SSLVerify"):
73+
verify, err := strconv.ParseBool(param.Value)
74+
if err != nil {
75+
return nil, fmt.Errorf("error occurred converting %q to boolean in Pipeline Resource %s", param.Value, r.Name)
76+
}
77+
prResource.SSLVerify = verify
6878
}
6979
}
7080

@@ -89,10 +99,11 @@ func (s *PullRequestResource) GetURL() string {
8999
// Replacements is used for template replacement on a PullRequestResource inside of a Taskrun.
90100
func (s *PullRequestResource) Replacements() map[string]string {
91101
return map[string]string{
92-
"name": s.Name,
93-
"type": string(s.Type),
94-
"url": s.URL,
95-
"provider": s.Provider,
102+
"name": s.Name,
103+
"type": string(s.Type),
104+
"url": s.URL,
105+
"provider": s.Provider,
106+
"sslVerify": strconv.FormatBool(s.SSLVerify),
96107
}
97108
}
98109

@@ -115,6 +126,9 @@ func (s *PullRequestResource) getSteps(mode string, sourcePath string) []Step {
115126
if s.Provider != "" {
116127
args = append(args, []string{"-provider", s.Provider}...)
117128
}
129+
if !s.SSLVerify {
130+
args = append(args, "-sslVerify=false")
131+
}
118132

119133
evs := []corev1.EnvVar{}
120134
for _, sec := range s.Secrets {

pkg/apis/pipeline/v1alpha1/pull_request_resource_test.go

+29-11
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ func TestPullRequest_NewResource(t *testing.T) {
4141
}
4242

4343
want := &v1alpha1.PullRequestResource{
44-
Name: pr.Name,
45-
Type: v1alpha1.PipelineResourceTypePullRequest,
46-
URL: url,
47-
Provider: "github",
48-
Secrets: pr.Spec.SecretParams,
49-
PRImage: "override-with-pr:latest",
44+
Name: pr.Name,
45+
Type: v1alpha1.PipelineResourceTypePullRequest,
46+
URL: url,
47+
Provider: "github",
48+
Secrets: pr.Spec.SecretParams,
49+
PRImage: "override-with-pr:latest",
50+
SSLVerify: true,
5051
}
5152
if diff := cmp.Diff(want, got); diff != "" {
5253
t.Error(diff)
@@ -70,9 +71,10 @@ const workspace = "/workspace"
7071
func containerTestCases(mode string) []testcase {
7172
return []testcase{{
7273
in: &v1alpha1.PullRequestResource{
73-
Name: "nocreds",
74-
URL: "https://example.com",
75-
PRImage: "override-with-pr:latest",
74+
Name: "nocreds",
75+
URL: "https://example.com",
76+
PRImage: "override-with-pr:latest",
77+
SSLVerify: true,
7678
},
7779
out: []v1alpha1.Step{{Container: corev1.Container{
7880
Name: "pr-source-nocreds-9l9zj",
@@ -84,8 +86,9 @@ func containerTestCases(mode string) []testcase {
8486
}}},
8587
}, {
8688
in: &v1alpha1.PullRequestResource{
87-
Name: "creds",
88-
URL: "https://example.com",
89+
Name: "creds",
90+
URL: "https://example.com",
91+
SSLVerify: true,
8992
Secrets: []v1alpha1.SecretParam{{
9093
FieldName: "authToken",
9194
SecretName: "github-creds",
@@ -112,6 +115,21 @@ func containerTestCases(mode string) []testcase {
112115
},
113116
}},
114117
}}},
118+
}, {
119+
in: &v1alpha1.PullRequestResource{
120+
Name: "nocreds",
121+
URL: "https://example.com",
122+
PRImage: "override-with-pr:latest",
123+
SSLVerify: false,
124+
},
125+
out: []v1alpha1.Step{{Container: corev1.Container{
126+
Name: "pr-source-nocreds-mssqb",
127+
Image: "override-with-pr:latest",
128+
WorkingDir: pipeline.WorkspaceDir,
129+
Command: []string{"/ko-app/pullrequest-init"},
130+
Args: []string{"-url", "https://example.com", "-path", workspace, "-mode", mode, "-sslVerify=false"},
131+
Env: []corev1.EnvVar{},
132+
}}},
115133
}}
116134
}
117135

pkg/pullrequest/scm.go

+40-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package pullrequest
1818

1919
import (
20-
"context"
2120
"fmt"
2221
"net/http"
2322
"net/url"
@@ -26,12 +25,14 @@ import (
2625

2726
"golang.org/x/oauth2"
2827

28+
"crypto/tls"
29+
2930
"github.com/jenkins-x/go-scm/scm/driver/github"
3031
"github.com/jenkins-x/go-scm/scm/driver/gitlab"
3132
"go.uber.org/zap"
3233
)
3334

34-
func NewSCMHandler(logger *zap.SugaredLogger, raw, provider, token string) (*Handler, error) {
35+
func NewSCMHandler(logger *zap.SugaredLogger, raw, provider, token string, sslVerify bool) (*Handler, error) {
3536
u, err := url.Parse(raw)
3637
if err != nil {
3738
return nil, err
@@ -49,16 +50,16 @@ func NewSCMHandler(logger *zap.SugaredLogger, raw, provider, token string) (*Han
4950
var handler *Handler
5051
switch provider {
5152
case "github":
52-
handler, err = githubHandlerFromURL(u, token, logger)
53+
handler, err = githubHandlerFromURL(u, token, sslVerify, logger)
5354
case "gitlab":
54-
handler, err = gitlabHandlerFromURL(u, token, logger)
55+
handler, err = gitlabHandlerFromURL(u, token, sslVerify, logger)
5556
default:
5657
return nil, fmt.Errorf("unsupported pr url: %s", raw)
5758
}
5859
return handler, err
5960
}
6061

61-
func githubHandlerFromURL(u *url.URL, token string, logger *zap.SugaredLogger) (*Handler, error) {
62+
func githubHandlerFromURL(u *url.URL, token string, sslVerify bool, logger *zap.SugaredLogger) (*Handler, error) {
6263
split := strings.Split(u.Path, "/")
6364
if len(split) < 5 {
6465
return nil, fmt.Errorf("could not determine PR from URL: %v", u)
@@ -83,17 +84,34 @@ func githubHandlerFromURL(u *url.URL, token string, logger *zap.SugaredLogger) (
8384
}
8485
}
8586
ownerRepo := fmt.Sprintf("%s/%s", owner, repo)
86-
h := NewHandler(logger, client, ownerRepo, prNumber)
87+
8788
if token != "" {
8889
ts := oauth2.StaticTokenSource(
8990
&oauth2.Token{AccessToken: token},
9091
)
91-
h.client.Client = oauth2.NewClient(context.Background(), ts)
92+
client.Client = &http.Client{
93+
Transport: &oauth2.Transport{
94+
Source: ts,
95+
Base: &http.Transport{
96+
/* #nosec G402 */
97+
TLSClientConfig: &tls.Config{InsecureSkipVerify: !sslVerify},
98+
},
99+
},
100+
}
101+
} else {
102+
client.Client = &http.Client{
103+
Transport: &http.Transport{
104+
/* #nosec G402 */
105+
TLSClientConfig: &tls.Config{InsecureSkipVerify: !sslVerify},
106+
},
107+
}
92108
}
109+
110+
h := NewHandler(logger, client, ownerRepo, prNumber)
93111
return h, nil
94112
}
95113

96-
func gitlabHandlerFromURL(u *url.URL, token string, logger *zap.SugaredLogger) (*Handler, error) {
114+
func gitlabHandlerFromURL(u *url.URL, token string, sslVerify bool, logger *zap.SugaredLogger) (*Handler, error) {
97115
// The project name can be multiple /'s deep, so split on / and work from right to left.
98116
split := strings.Split(u.Path, "/")
99117

@@ -124,14 +142,26 @@ func gitlabHandlerFromURL(u *url.URL, token string, logger *zap.SugaredLogger) (
124142
return nil, fmt.Errorf("error creating client: %w", err)
125143
}
126144
}
145+
127146
if token != "" {
128147
client.Client = &http.Client{
129148
Transport: &gitlabClient{
130-
token: token,
131-
transport: http.DefaultTransport,
149+
token: token,
150+
transport: &http.Transport{
151+
/* #nosec G402 */
152+
TLSClientConfig: &tls.Config{InsecureSkipVerify: !sslVerify},
153+
},
154+
},
155+
}
156+
} else {
157+
client.Client = &http.Client{
158+
Transport: &http.Transport{
159+
/* #nosec G402 */
160+
TLSClientConfig: &tls.Config{InsecureSkipVerify: !sslVerify},
132161
},
133162
}
134163
}
164+
135165
return NewHandler(logger, client, project, prInt), nil
136166
}
137167

pkg/pullrequest/scm_test.go

+20-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ limitations under the License.
1717
package pullrequest
1818

1919
import (
20+
"net/http"
2021
"net/url"
22+
"strconv"
2123
"testing"
2224

2325
"go.uber.org/zap"
@@ -28,6 +30,7 @@ func TestNewSCMHandler(t *testing.T) {
2830
tests := []struct {
2931
name string
3032
raw string
33+
sslVerify bool
3134
wantBaseURL string
3235
wantRepo string
3336
wantNum int
@@ -36,6 +39,7 @@ func TestNewSCMHandler(t *testing.T) {
3639
{
3740
name: "github",
3841
raw: "https://github.com/foo/bar/pull/1",
42+
sslVerify: true,
3943
wantBaseURL: "https://api.github.com/",
4044
wantRepo: "foo/bar",
4145
wantNum: 1,
@@ -44,6 +48,7 @@ func TestNewSCMHandler(t *testing.T) {
4448
{
4549
name: "custom github",
4650
raw: "https://github.tekton.dev/foo/baz/pull/2",
51+
sslVerify: true,
4752
wantBaseURL: "https://github.tekton.dev/api/v3/",
4853
wantRepo: "foo/baz",
4954
wantNum: 2,
@@ -52,6 +57,7 @@ func TestNewSCMHandler(t *testing.T) {
5257
{
5358
name: "gitlab",
5459
raw: "https://gitlab.com/foo/bar/merge_requests/3",
60+
sslVerify: true,
5561
wantBaseURL: "https://gitlab.com/",
5662
wantRepo: "foo/bar",
5763
wantNum: 3,
@@ -60,22 +66,24 @@ func TestNewSCMHandler(t *testing.T) {
6066
{
6167
name: "gitlab multi-level",
6268
raw: "https://gitlab.com/foo/bar/baz/merge_requests/3",
69+
sslVerify: false,
6370
wantBaseURL: "https://gitlab.com/",
6471
wantRepo: "foo/bar/baz",
6572
wantNum: 3,
6673
wantErr: false,
6774
},
6875
{
69-
name: "unsupported",
70-
raw: "https://unsupported.com/foo/baz/merge_requests/3",
71-
wantErr: true,
76+
name: "unsupported",
77+
raw: "https://unsupported.com/foo/baz/merge_requests/3",
78+
sslVerify: false,
79+
wantErr: true,
7280
},
7381
}
7482
for _, tt := range tests {
7583
t.Run(tt.name, func(t *testing.T) {
7684
observer, _ := observer.New(zap.InfoLevel)
7785
logger := zap.New(observer).Sugar()
78-
got, err := NewSCMHandler(logger, tt.raw, "", "")
86+
got, err := NewSCMHandler(logger, tt.raw, "", "", tt.sslVerify)
7987
if err != nil {
8088
if !tt.wantErr {
8189
t.Errorf("NewSCMHandler() error = %v, wantErr %v", err, tt.wantErr)
@@ -91,6 +99,14 @@ func TestNewSCMHandler(t *testing.T) {
9199
if baseURL := got.client.BaseURL.String(); baseURL != tt.wantBaseURL {
92100
t.Errorf("NewSCMHandler() [base url] = %v, want %v", baseURL, tt.wantBaseURL)
93101
}
102+
switch transport := got.client.Client.Transport.(type) {
103+
case *http.Transport:
104+
if transport.TLSClientConfig.InsecureSkipVerify != !tt.sslVerify {
105+
t.Errorf("NewSCMHandler() [InsecureSkipVerify] = %v, want %v", strconv.FormatBool(transport.TLSClientConfig.InsecureSkipVerify), !tt.sslVerify)
106+
}
107+
default:
108+
t.Errorf("NewSCMHandler() client.Client.Transport was not of type http.Transport")
109+
}
94110
})
95111
}
96112
}

0 commit comments

Comments
 (0)