Skip to content

Commit

Permalink
feat(appset): Add support for self-signed TLS / Certificates for Gitl…
Browse files Browse the repository at this point in the history
…ab Scm Provider (#14348)

* Add support for self-signed TLS / Certificates for Gitlab Scm Provider

Signed-off-by: ishitasequeira <[email protected]>

* Add support for self-signed TLS / Certificates for Gitlab Pull Request

Signed-off-by: ishitasequeira <[email protected]>

* Add TLS configuration for SCM and Pull request Gitlab Provider

Signed-off-by: ishitasequeira <[email protected]>

* rebase with master

Signed-off-by: ishitasequeira <[email protected]>

* add params to argocd-cmd-params-cm and docs

Signed-off-by: ishitasequeira <[email protected]>

* fix generated manifests

Signed-off-by: ishitasequeira <[email protected]>

* Address comments for docs

Signed-off-by: ishitasequeira <[email protected]>

* Add test cases to validate insecure mode and ca cert combinations

Signed-off-by: ishitasequeira <[email protected]>

* simplify (#24)

Signed-off-by: Michael Crenshaw <[email protected]>

---------

Signed-off-by: ishitasequeira <[email protected]>
Signed-off-by: Michael Crenshaw <[email protected]>
Co-authored-by: Michael Crenshaw <[email protected]>
  • Loading branch information
ishitasequeira and crenshaw-dev authored Jul 11, 2023
1 parent 6a9f4c4 commit 6fb238c
Show file tree
Hide file tree
Showing 34 changed files with 1,060 additions and 701 deletions.
1 change: 1 addition & 0 deletions applicationset/controllers/applicationset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type ApplicationSetReconciler struct {
ArgoCDNamespace string
ApplicationSetNamespaces []string
EnableProgressiveSyncs bool
SCMRootCAPath string
}

// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets,verbs=get;list;watch;create;update;patch;delete
Expand Down
5 changes: 3 additions & 2 deletions applicationset/controllers/applicationset_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"

"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync/common"

"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"

"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
"github.com/argoproj/argo-cd/v2/util/collections"
Expand Down
11 changes: 6 additions & 5 deletions applicationset/controllers/requeue_after_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import (
"testing"
"time"

"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand All @@ -17,6 +14,10 @@ import (
kubefake "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)

func TestRequeueAfter(t *testing.T) {
Expand Down Expand Up @@ -59,9 +60,9 @@ func TestRequeueAfter(t *testing.T) {
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(k8sClient, ctx, appClientset, "argocd"),
"Git": generators.NewGitGenerator(mockServer),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build(), generators.SCMAuthProviders{}),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build(), generators.SCMAuthProviders{}, ""),
"ClusterDecisionResource": generators.NewDuckTypeGenerator(ctx, fakeDynClient, appClientset, "argocd"),
"PullRequest": generators.NewPullRequestGenerator(k8sClient, generators.SCMAuthProviders{}),
"PullRequest": generators.NewPullRequestGenerator(k8sClient, generators.SCMAuthProviders{}, ""),
}

nestedGenerators := map[string]generators.Generator{
Expand Down
3 changes: 1 addition & 2 deletions applicationset/generators/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
return &appSetGenerator.Clusters.Template
}

func (g *ClusterGenerator) GenerateParams(
appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet) ([]map[string]interface{}, error) {

if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
Expand Down
3 changes: 1 addition & 2 deletions applicationset/generators/duck_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package generators
import (
"context"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
Expand All @@ -15,8 +16,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"

"testing"
)

const resourceApiVersion = "mallard.io/v1"
Expand Down
3 changes: 2 additions & 1 deletion applicationset/generators/generator_spec_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"fmt"
"reflect"

"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/jeremywohl/flatten"

"github.com/argoproj/argo-cd/v2/applicationset/utils"

"k8s.io/apimachinery/pkg/labels"

argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
Expand Down
3 changes: 2 additions & 1 deletion applicationset/generators/generator_spec_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"context"
"testing"

"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"

argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"

"github.com/stretchr/testify/mock"
Expand Down
3 changes: 2 additions & 1 deletion applicationset/generators/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import (
"fmt"
"time"

argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"sigs.k8s.io/yaml"

argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)

var _ Generator = (*ListGenerator)(nil)
Expand Down
10 changes: 6 additions & 4 deletions applicationset/generators/pull_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ type PullRequestGenerator struct {
client client.Client
selectServiceProviderFunc func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error)
auth SCMAuthProviders
scmRootCAPath string
}

func NewPullRequestGenerator(client client.Client, auth SCMAuthProviders) Generator {
func NewPullRequestGenerator(client client.Client, auth SCMAuthProviders, scmRootCAPath string) Generator {
g := &PullRequestGenerator{
client: client,
auth: auth,
client: client,
auth: auth,
scmRootCAPath: scmRootCAPath,
}
g.selectServiceProviderFunc = g.selectServiceProvider
return g
Expand Down Expand Up @@ -126,7 +128,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %v", err)
}
return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState)
return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState, g.scmRootCAPath, providerConfig.Insecure)
}
if generatorConfig.Gitea != nil {
providerConfig := generatorConfig.Gitea
Expand Down
6 changes: 4 additions & 2 deletions applicationset/generators/scm_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ type SCMProviderGenerator struct {
// Testing hooks.
overrideProvider scm_provider.SCMProviderService
SCMAuthProviders
scmRootCAPath string
}

type SCMAuthProviders struct {
GitHubApps github_app_auth.Credentials
}

func NewSCMProviderGenerator(client client.Client, providers SCMAuthProviders) Generator {
func NewSCMProviderGenerator(client client.Client, providers SCMAuthProviders, scmRootCAPath string) Generator {
return &SCMProviderGenerator{
client: client,
SCMAuthProviders: providers,
scmRootCAPath: scmRootCAPath,
}
}

Expand Down Expand Up @@ -85,7 +87,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if err != nil {
return nil, fmt.Errorf("error fetching Gitlab token: %v", err)
}
provider, err = scm_provider.NewGitlabProvider(ctx, providerConfig.Gitlab.Group, token, providerConfig.Gitlab.API, providerConfig.Gitlab.AllBranches, providerConfig.Gitlab.IncludeSubgroups)
provider, err = scm_provider.NewGitlabProvider(ctx, providerConfig.Gitlab.Group, token, providerConfig.Gitlab.API, providerConfig.Gitlab.AllBranches, providerConfig.Gitlab.IncludeSubgroups, providerConfig.Gitlab.Insecure, g.scmRootCAPath)
if err != nil {
return nil, fmt.Errorf("error initializing Gitlab service: %v", err)
}
Expand Down
13 changes: 12 additions & 1 deletion applicationset/services/pull_request/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package pull_request
import (
"context"
"fmt"
"net/http"
"os"

"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
gitlab "github.com/xanzy/go-gitlab"
)

Expand All @@ -17,7 +20,7 @@ type GitLabService struct {

var _ PullRequestService = (*GitLabService)(nil)

func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string) (PullRequestService, error) {
func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string, scmRootCAPath string, insecure bool) (PullRequestService, error) {
var clientOptionFns []gitlab.ClientOptionFunc

// Set a custom Gitlab base URL if one is provided
Expand All @@ -29,6 +32,14 @@ func NewGitLabService(ctx context.Context, token, url, project string, labels []
token = os.Getenv("GITLAB_TOKEN")
}

tr := &http.Transport{
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
}
retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr

clientOptionFns = append(clientOptionFns, gitlab.WithHTTPClient(retryClient.HTTPClient))

client, err := gitlab.NewClient(token, clientOptionFns...)
if err != nil {
return nil, fmt.Errorf("error creating Gitlab client: %v", err)
Expand Down
10 changes: 5 additions & 5 deletions applicationset/services/pull_request/gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestGitLabServiceCustomBaseURL(t *testing.T) {
writeMRListResponse(t, w)
})

svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", nil, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", nil, "", "", false)
assert.NoError(t, err)

_, err = svc.List(context.Background())
Expand All @@ -53,7 +53,7 @@ func TestGitLabServiceToken(t *testing.T) {
writeMRListResponse(t, w)
})

svc, err := NewGitLabService(context.Background(), "token-123", server.URL, "278964", nil, "")
svc, err := NewGitLabService(context.Background(), "token-123", server.URL, "278964", nil, "", "", false)
assert.NoError(t, err)

_, err = svc.List(context.Background())
Expand All @@ -72,7 +72,7 @@ func TestList(t *testing.T) {
writeMRListResponse(t, w)
})

svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "", "", false)
assert.NoError(t, err)

prs, err := svc.List(context.Background())
Expand All @@ -96,7 +96,7 @@ func TestListWithLabels(t *testing.T) {
writeMRListResponse(t, w)
})

svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{"feature", "ready"}, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{"feature", "ready"}, "", "", false)
assert.NoError(t, err)

_, err = svc.List(context.Background())
Expand All @@ -115,7 +115,7 @@ func TestListWithState(t *testing.T) {
writeMRListResponse(t, w)
})

svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "opened")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "opened", "", false)
assert.NoError(t, err)

_, err = svc.List(context.Background())
Expand Down
15 changes: 12 additions & 3 deletions applicationset/services/scm_provider/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"os"
pathpkg "path"

"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
"github.com/xanzy/go-gitlab"
)

Expand All @@ -19,21 +21,28 @@ type GitlabProvider struct {

var _ SCMProviderService = &GitlabProvider{}

func NewGitlabProvider(ctx context.Context, organization string, token string, url string, allBranches, includeSubgroups bool) (*GitlabProvider, error) {
func NewGitlabProvider(ctx context.Context, organization string, token string, url string, allBranches, includeSubgroups, insecure bool, scmRootCAPath string) (*GitlabProvider, error) {
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
if token == "" {
token = os.Getenv("GITLAB_TOKEN")
}
var client *gitlab.Client

tr := &http.Transport{
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
}
retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr

if url == "" {
var err error
client, err = gitlab.NewClient(token)
client, err = gitlab.NewClient(token, gitlab.WithHTTPClient(retryClient.HTTPClient))
if err != nil {
return nil, err
}
} else {
var err error
client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url))
client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url), gitlab.WithHTTPClient(retryClient.HTTPClient))
if err != nil {
return nil, err
}
Expand Down
14 changes: 7 additions & 7 deletions applicationset/services/scm_provider/gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ func gitlabMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
}
func TestGitlabListRepos(t *testing.T) {
cases := []struct {
name, proto, url string
hasError, allBranches, includeSubgroups bool
branches []string
filters []v1alpha1.SCMProviderGeneratorFilter
name, proto, url string
hasError, allBranches, includeSubgroups, insecure bool
branches []string
filters []v1alpha1.SCMProviderGeneratorFilter
}{
{
name: "blank protocol",
Expand Down Expand Up @@ -323,7 +323,7 @@ func TestGitlabListRepos(t *testing.T) {
}))
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
provider, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups)
provider, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups, c.insecure, "")
rawRepos, err := ListRepos(context.Background(), provider, c.filters, c.proto)
if c.hasError {
assert.NotNil(t, err)
Expand Down Expand Up @@ -352,7 +352,7 @@ func TestGitlabHasPath(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gitlabMockHandler(t)(w, r)
}))
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true)
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true, false, "")
repo := &Repository{
Organization: "test-argocd-proton",
Repository: "argocd",
Expand Down Expand Up @@ -398,7 +398,7 @@ func TestGitlabGetBranches(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gitlabMockHandler(t)(w, r)
}))
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true)
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true, false, "")

repo := &Repository{
RepositoryId: 27084533,
Expand Down
38 changes: 38 additions & 0 deletions applicationset/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package utils

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"os"
"reflect"
"regexp"
"sort"
Expand Down Expand Up @@ -406,3 +409,38 @@ func SanitizeName(name string) string {

return strings.Trim(name, "-.")
}

func getTlsConfigWithCACert(scmRootCAPath string) *tls.Config {

tlsConfig := &tls.Config{}

if scmRootCAPath != "" {
_, err := os.Stat(scmRootCAPath)
if os.IsNotExist(err) {
log.Errorf("scmRootCAPath '%s' specified does not exist: %s", scmRootCAPath, err)
return tlsConfig
}
rootCA, err := os.ReadFile(scmRootCAPath)
if err != nil {
log.Errorf("error reading certificate from file '%s', proceeding without custom rootCA : %s", scmRootCAPath, err)
return tlsConfig
}
certPool := x509.NewCertPool()
ok := certPool.AppendCertsFromPEM([]byte(rootCA))
if !ok {
log.Errorf("failed to append certificates from PEM: proceeding without custom rootCA")
} else {
tlsConfig.RootCAs = certPool
}
}
return tlsConfig
}

func GetTlsConfig(scmRootCAPath string, insecure bool) *tls.Config {
tlsConfig := getTlsConfigWithCACert(scmRootCAPath)

if insecure {
tlsConfig.InsecureSkipVerify = true
}
return tlsConfig
}
Loading

0 comments on commit 6fb238c

Please sign in to comment.