Skip to content

Commit

Permalink
replace --insecure with --git-server-crt
Browse files Browse the repository at this point in the history
Signed-off-by: Noam Gal <[email protected]>
  • Loading branch information
ATGardner committed Nov 18, 2022
1 parent 387cf2d commit 8c18d31
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 39 deletions.
2 changes: 1 addition & 1 deletion cmd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func RunAppCreate(ctx context.Context, opts *AppCreateOptions) error {
if opts.AppsCloneOpts.Auth.Password == "" {
opts.AppsCloneOpts.Auth.Username = opts.CloneOpts.Auth.Username
opts.AppsCloneOpts.Auth.Password = opts.CloneOpts.Auth.Password
opts.AppsCloneOpts.Auth.Insecure = opts.CloneOpts.Auth.Insecure
opts.AppsCloneOpts.Auth.CertFile = opts.CloneOpts.Auth.CertFile
opts.AppsCloneOpts.Provider = opts.CloneOpts.Provider
}

Expand Down
50 changes: 46 additions & 4 deletions pkg/git/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package git
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"sort"
)

Expand All @@ -28,7 +30,7 @@ type (
Auth struct {
Username string
Password string
Insecure bool
CertFile string
}

// ProviderOptions for a new git provider
Expand Down Expand Up @@ -89,8 +91,48 @@ func Providers() []string {
return res
}

func DefaultTransportWithInsecure() *http.Transport {
func DefaultTransportWithCa(certFile string) (*http.Transport, error) {
rootCAs, err := getRootCas(certFile)
if err != nil {
return nil, err
}

transport := http.DefaultTransport.(*http.Transport).Clone()
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
return transport
transport.TLSClientConfig = &tls.Config{RootCAs: rootCAs}
return transport, nil
}

func getRootCas(certFile string) (*x509.CertPool, error) {
rootCAs, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("failed getting system certificates: %w", err)
}

if rootCAs == nil {
rootCAs = x509.NewCertPool()
}

if certFile == "" {
return rootCAs, nil
}

certs, err := os.ReadFile(certFile)
if err != nil {
return nil, fmt.Errorf("failed reading certificate from %s: %w", certFile, err)
}

// Append our cert to the system pool
if ok := rootCAs.AppendCertsFromPEM(certs); !ok {
return nil, fmt.Errorf("failed adding certificate to rootCAs")
}

return rootCAs, nil
}

func (a *Auth) getCertificate() ([]byte, error) {
if a.CertFile == "" {
return nil, nil
}

return os.ReadFile(a.CertFile)
}
7 changes: 4 additions & 3 deletions pkg/git/provider_ado.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package git

import (
"context"
"crypto/tls"
"fmt"
"net/url"
"strings"
Expand Down Expand Up @@ -48,10 +47,12 @@ func newAdo(opts *ProviderOptions) (Provider, error) {
}

connection := azuredevops.NewPatConnection(adoUrl.loginUrl, opts.Auth.Password)
if opts.Auth.Insecure {
connection.TlsConfig = &tls.Config{InsecureSkipVerify: true}
rootCAs, err := getRootCas(opts.Auth.CertFile)
if err != nil {
return nil, err
}

connection.TlsConfig.RootCAs = rootCAs
ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
defer cancel()
// FYI: ado also has a "core" client that can be used to update project, teams, and other ADO constructs
Expand Down
5 changes: 3 additions & 2 deletions pkg/git/provider_bitbucket-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ func newBitbucketServer(opts *ProviderOptions) (Provider, error) {
}

httpClient := &http.Client{}
if opts.Auth.Insecure {
httpClient.Transport = DefaultTransportWithInsecure()
httpClient.Transport, err = DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

g := &bitbucketServer{
Expand Down
6 changes: 4 additions & 2 deletions pkg/git/provider_bitbucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ type (
)

func newBitbucket(opts *ProviderOptions) (Provider, error) {
var err error
c := bb.NewBasicAuth(opts.Auth.Username, opts.Auth.Password)
if c == nil {
return nil, errors.New("Authentication info is invalid")
}

if opts.Auth.Insecure {
c.HttpClient.Transport = DefaultTransportWithInsecure()
c.HttpClient.Transport, err = DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

g := &bitbucket{
Expand Down
11 changes: 7 additions & 4 deletions pkg/git/provider_gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ func newGitea(opts *ProviderOptions) (Provider, error) {
return nil, err
}

if opts.Auth.Insecure {
c.SetHTTPClient(&http.Client{
Transport: DefaultTransportWithInsecure(),
})
transport, err := DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

c.SetHTTPClient(&http.Client{
Transport: transport,
})

g := &gitea{
client: c,
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/git/provider_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ func newGithub(opts *ProviderOptions) (Provider, error) {

hc := &http.Client{}
if opts.Auth != nil {
underlyingTransport, err := DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

transport := &gh.BasicAuthTransport{
Username: opts.Auth.Username,
Password: opts.Auth.Password,
Transport: underlyingTransport,
}

if opts.Auth.Insecure {
transport.Transport = DefaultTransportWithInsecure()
}


hc.Transport = transport
}

Expand Down
18 changes: 10 additions & 8 deletions pkg/git/provider_gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ type (

func newGitlab(opts *ProviderOptions) (Provider, error) {
host, _, _, _, _, _, _ := util.ParseGitUrl(opts.RepoURL)
clientOptions := []gl.ClientOptionFunc{
gl.WithBaseURL(host),
}
if opts.Auth.Insecure {
clientOptions = append(clientOptions, gl.WithHTTPClient(&http.Client{
Transport: DefaultTransportWithInsecure(),
}))
transport, err := DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

c, err := gl.NewClient(opts.Auth.Password, clientOptions...)
c, err := gl.NewClient(
opts.Auth.Password,
gl.WithBaseURL(host),
gl.WithHTTPClient(&http.Client{
Transport: transport,
}),
)
if err != nil {
return nil, err
}
Expand Down
30 changes: 20 additions & 10 deletions pkg/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ func AddFlags(cmd *cobra.Command, opts *AddFlagsOptions) *CloneOptions {
envPrefix := strings.ReplaceAll(strings.ToUpper(opts.Prefix), "-", "_")
cmd.PersistentFlags().StringVar(&co.Auth.Password, opts.Prefix+"git-token", "", fmt.Sprintf("Your git provider api token [%sGIT_TOKEN]", envPrefix))
cmd.PersistentFlags().StringVar(&co.Auth.Username, opts.Prefix+"git-user", "", fmt.Sprintf("Your git provider user name [%sGIT_USER] (not required in GitHub)", envPrefix))
cmd.PersistentFlags().BoolVar(&co.Auth.Insecure, opts.Prefix+"insecure-git-server", false, fmt.Sprint("Disable repository server certificate validation", envPrefix))
cmd.PersistentFlags().StringVar(&co.Auth.CertFile, opts.Prefix+"git-server-crt", "", fmt.Sprint("Git Server certificate file", envPrefix))
cmd.PersistentFlags().StringVar(&co.Repo, opts.Prefix+"repo", "", fmt.Sprintf("Repository URL [%sGIT_REPO]", envPrefix))

util.Die(viper.BindEnv(opts.Prefix+"git-token", envPrefix+"GIT_TOKEN"))
util.Die(viper.BindEnv(opts.Prefix+"git-user", envPrefix+"GIT_USER"))
util.Die(viper.BindEnv(opts.Prefix+"repo", envPrefix+"GIT_REPO"))
util.Die(cmd.PersistentFlags().MarkHidden(opts.Prefix + "insecure-git-server"))
util.Die(cmd.PersistentFlags().MarkHidden(opts.Prefix + "git-server-crt"))

if opts.Prefix == "" {
cmd.Flag("git-token").Shorthand = "t"
Expand Down Expand Up @@ -275,16 +275,21 @@ func (r *repo) Persist(ctx context.Context, opts *PushOptions) (string, error) {
progress = r.progress
}

cert, err := r.auth.getCertificate()
if err != nil {
return "", fmt.Errorf("failed reading git certificate file: %w", err)
}

h, err := r.commit(ctx, opts)
if err != nil {
return "", err
}

for try := 0; try < pushRetries; try++ {
err = r.PushContext(ctx, &gg.PushOptions{
Auth: getAuth(r.auth),
Progress: progress,
InsecureSkipTLS: r.auth.Insecure,
Auth: getAuth(r.auth),
Progress: progress,
CABundle: cert,
})
if err == nil || !errors.Is(err, transport.ErrRepositoryNotFound) {
break
Expand Down Expand Up @@ -406,12 +411,17 @@ var clone = func(ctx context.Context, opts *CloneOptions) (*repo, error) {
progress = os.Stderr
}

cert, err := opts.Auth.getCertificate()
if err != nil {
return nil, fmt.Errorf("failed reading git certificate file: %w", err)
}

cloneOpts := &gg.CloneOptions{
URL: opts.url,
Auth: getAuth(opts.Auth),
Depth: 1,
Progress: progress,
InsecureSkipTLS: opts.Auth.Insecure,
URL: opts.url,
Auth: getAuth(opts.Auth),
Depth: 1,
Progress: progress,
CABundle: cert,
}

log.G(ctx).WithField("url", opts.url).Debug("cloning git repo")
Expand Down

0 comments on commit 8c18d31

Please sign in to comment.