Skip to content

Commit

Permalink
Allow insecure git server (#392)
Browse files Browse the repository at this point in the history
* added support for --git-server-crt
* add certificate to argocd cm

Signed-off-by: Noam Gal <[email protected]>
  • Loading branch information
ATGardner authored Nov 18, 2022
1 parent 8d2f516 commit 5415ff1
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 7 deletions.
1 change: 1 addition & 0 deletions cmd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +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.CertFile = opts.CloneOpts.Auth.CertFile
opts.AppsCloneOpts.Provider = opts.CloneOpts.Provider
}

Expand Down
33 changes: 29 additions & 4 deletions cmd/commands/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -235,7 +236,7 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error {

log.G(ctx).Infof("using revision: \"%s\", installation path: \"%s\"", opts.CloneOptions.Revision(), opts.CloneOptions.Path())
err = validateRepo(repofs, opts.Recover)
if err != nil{
if err != nil {
return err
}

Expand Down Expand Up @@ -624,7 +625,7 @@ func buildBootstrapManifests(namespace, appSpecifier string, cloneOpts *git.Clon
return nil, err
}

k, err := createBootstrapKustomization(namespace, cloneOpts.URL(), appSpecifier)
k, err := createBootstrapKustomization(namespace, appSpecifier, cloneOpts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -691,8 +692,8 @@ func writeManifestsToRepo(repoFS fs.FS, manifests *bootstrapManifests, installat
return fsutils.BulkWrite(repoFS, bulkWrites...)
}

func createBootstrapKustomization(namespace, repoURL, appSpecifier string) (*kusttypes.Kustomization, error) {
credsYAML, err := createCreds(repoURL)
func createBootstrapKustomization(namespace, appSpecifier string, cloneOpts *git.CloneOptions) (*kusttypes.Kustomization, error) {
credsYAML, err := createCreds(cloneOpts.URL())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -721,6 +722,30 @@ func createBootstrapKustomization(namespace, repoURL, appSpecifier string) (*kus
Namespace: namespace,
}

cert, err := cloneOpts.Auth.GetCertificate()
if err != nil {
return nil, err
}

if cert != nil {
u, err := url.Parse(cloneOpts.URL())
if err != nil {
return nil, err
}

k.ConfigMapGenerator = append(k.ConfigMapGenerator, kusttypes.ConfigMapArgs{
GeneratorArgs: kusttypes.GeneratorArgs{
Name: "argocd-tls-certs-cm",
Behavior: kusttypes.BehaviorMerge.String(),
KvPairSources: kusttypes.KvPairSources{
LiteralSources: []string{
u.Host + "=" + string(cert),
},
},
},
})
}

k.FixKustomizationPostUnmarshalling()
errs := k.EnforceFields()
if len(errs) > 0 {
Expand Down
51 changes: 51 additions & 0 deletions pkg/git/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package git

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"sort"
)

Expand All @@ -26,6 +30,7 @@ type (
Auth struct {
Username string
Password string
CertFile string
}

// ProviderOptions for a new git provider
Expand Down Expand Up @@ -85,3 +90,49 @@ func Providers() []string {
sort.Strings(res) // must sort the providers by name, otherwise the codegen is not deterministic
return res
}

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{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)
}
6 changes: 6 additions & 0 deletions pkg/git/provider_ado.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ func newAdo(opts *ProviderOptions) (Provider, error) {
}

connection := azuredevops.NewPatConnection(adoUrl.loginUrl, opts.Auth.Password)
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: 5 additions & 0 deletions pkg/git/provider_bitbucket-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ func newBitbucketServer(opts *ProviderOptions) (Provider, error) {
}

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

g := &bitbucketServer{
baseURL: baseURL,
c: httpClient,
Expand Down
8 changes: 7 additions & 1 deletion pkg/git/provider_bitbucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,24 @@ 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")
}

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

g := &bitbucket{
opts: opts,
Repository: c.Repositories.Repository,
User: c.User,
}

return g, nil

}

func (g *bitbucket) CreateRepository(ctx context.Context, orgRepo string) (defaultBranch string, err error) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/git/provider_gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package git
import (
"context"
"fmt"
"net/http"

gt "code.gitea.io/sdk/gitea"
)
Expand All @@ -28,6 +29,15 @@ func newGitea(opts *ProviderOptions) (Provider, error) {
return nil, err
}

transport, err := DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

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

g := &gitea{
client: c,
}
Expand Down
10 changes: 9 additions & 1 deletion pkg/git/provider_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ func newGithub(opts *ProviderOptions) (Provider, error) {

hc := &http.Client{}
if opts.Auth != nil {
hc.Transport = &gh.BasicAuthTransport{
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,
}

hc.Transport = transport
}

host, _, _, _, _, _, _ := util.ParseGitUrl(opts.RepoURL)
Expand Down
14 changes: 13 additions & 1 deletion pkg/git/provider_gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package git
import (
"context"
"fmt"
"net/http"

"github.com/argoproj-labs/argocd-autopilot/pkg/util"
gl "github.com/xanzy/go-gitlab"
Expand Down Expand Up @@ -32,7 +33,18 @@ type (

func newGitlab(opts *ProviderOptions) (Provider, error) {
host, _, _, _, _, _, _ := util.ParseGitUrl(opts.RepoURL)
c, err := gl.NewClient(opts.Auth.Password, gl.WithBaseURL(host))
transport, err := DefaultTransportWithCa(opts.Auth.CertFile)
if err != nil {
return nil, err
}

c, err := gl.NewClient(
opts.Auth.Password,
gl.WithBaseURL(host),
gl.WithHTTPClient(&http.Client{
Transport: transport,
}),
)
if err != nil {
return nil, err
}
Expand Down
14 changes: 14 additions & 0 deletions pkg/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +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().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 + "git-server-crt"))

if opts.Prefix == "" {
cmd.Flag("git-token").Shorthand = "t"
Expand Down Expand Up @@ -273,6 +275,11 @@ 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
Expand All @@ -282,6 +289,7 @@ func (r *repo) Persist(ctx context.Context, opts *PushOptions) (string, error) {
err = r.PushContext(ctx, &gg.PushOptions{
Auth: getAuth(r.auth),
Progress: progress,
CABundle: cert,
})
if err == nil || !errors.Is(err, transport.ErrRepositoryNotFound) {
break
Expand Down Expand Up @@ -403,11 +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,
CABundle: cert,
}

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

0 comments on commit 5415ff1

Please sign in to comment.