diff --git a/api/v1beta1/gitrepository_types.go b/api/v1beta1/gitrepository_types.go
index 8bc69ff24..3596e034a 100644
--- a/api/v1beta1/gitrepository_types.go
+++ b/api/v1beta1/gitrepository_types.go
@@ -80,6 +80,11 @@ type GitRepositorySpec struct {
// +kubebuilder:default:=go-git
// +optional
GitImplementation string `json:"gitImplementation,omitempty"`
+
+ // CertSecretRef
+ //
+ // +optional
+ CertSecretRef *meta.LocalObjectReference `json:"certSecretRef,omitempty"`
}
// GitRepositoryRef defines the Git ref used for pull and checkout operations.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 24e929f38..fd8c18acd 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -263,6 +263,11 @@ func (in *GitRepositorySpec) DeepCopyInto(out *GitRepositorySpec) {
*out = new(string)
**out = **in
}
+ if in.CertSecretRef != nil {
+ in, out := &in.CertSecretRef, &out.CertSecretRef
+ *out = new(meta.LocalObjectReference)
+ **out = **in
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepositorySpec.
diff --git a/config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml b/config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml
index 75e8f1614..a74cea203 100644
--- a/config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml
+++ b/config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml
@@ -49,6 +49,15 @@ spec:
spec:
description: GitRepositorySpec defines the desired state of a Git repository.
properties:
+ certSecretRef:
+ description: CertSecretRef
+ properties:
+ name:
+ description: Name of the referent
+ type: string
+ required:
+ - name
+ type: object
gitImplementation:
default: go-git
description: Determines which git client library to use. Defaults
diff --git a/controllers/gitrepository_controller.go b/controllers/gitrepository_controller.go
index ccad45e90..4c55c51a8 100644
--- a/controllers/gitrepository_controller.go
+++ b/controllers/gitrepository_controller.go
@@ -179,25 +179,41 @@ func (r *GitRepositoryReconciler) reconcile(ctx context.Context, repository sour
// determine auth method
auth := &common.Auth{}
- if repository.Spec.SecretRef != nil {
+ if repository.Spec.SecretRef != nil || repository.Spec.CertSecretRef != nil {
authStrategy, err := git.AuthSecretStrategyForURL(repository.Spec.URL, repository.Spec.GitImplementation)
if err != nil {
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
}
- name := types.NamespacedName{
- Namespace: repository.GetNamespace(),
- Name: repository.Spec.SecretRef.Name,
+ var secret *corev1.Secret
+ if repository.Spec.SecretRef != nil {
+ secret = &corev1.Secret{}
+ name := types.NamespacedName{
+ Namespace: repository.GetNamespace(),
+ Name: repository.Spec.SecretRef.Name,
+ }
+
+ err = r.Client.Get(ctx, name, secret)
+ if err != nil {
+ err = fmt.Errorf("auth secret error: %w", err)
+ return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
+ }
}
- var secret corev1.Secret
- err = r.Client.Get(ctx, name, &secret)
- if err != nil {
- err = fmt.Errorf("auth secret error: %w", err)
- return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
+ var certSecret *corev1.Secret
+ if repository.Spec.CertSecretRef != nil {
+ certSecret = &corev1.Secret{}
+ name := types.NamespacedName{
+ Namespace: repository.GetNamespace(),
+ Name: repository.Spec.CertSecretRef.Name,
+ }
+ err = r.Client.Get(ctx, name, certSecret)
+ if err != nil {
+ return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
+ }
}
- auth, err = authStrategy.Method(secret)
+ auth, err = authStrategy.Method(secret, certSecret)
if err != nil {
err = fmt.Errorf("auth error: %w", err)
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
diff --git a/controllers/gitrepository_controller_test.go b/controllers/gitrepository_controller_test.go
index f5596ca94..5fce938f5 100644
--- a/controllers/gitrepository_controller_test.go
+++ b/controllers/gitrepository_controller_test.go
@@ -18,7 +18,9 @@ package controllers
import (
"context"
+ "crypto/tls"
"fmt"
+ "net/http"
"net/url"
"os"
"path"
@@ -30,6 +32,8 @@ import (
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
+ "github.com/go-git/go-git/v5/plumbing/transport/client"
+ httptransport "github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/storage/memory"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
@@ -38,6 +42,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
+ "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/gittestserver"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
@@ -65,6 +70,18 @@ var _ = Describe("GitRepositoryReconciler", func() {
err = k8sClient.Create(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
+ cert := corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "cert",
+ Namespace: namespace.Name,
+ },
+ Data: map[string][]byte{
+ "caFile": exampleCA,
+ },
+ }
+ err = k8sClient.Create(context.Background(), &cert)
+ Expect(err).NotTo(HaveOccurred())
+
gitServer, err = gittestserver.NewTempGitServer()
Expect(err).NotTo(HaveOccurred())
gitServer.AutoCreate()
@@ -88,6 +105,7 @@ var _ = Describe("GitRepositoryReconciler", func() {
expectRevision string
gitImplementation string
+ certSecretRef *meta.LocalObjectReference
}
DescribeTable("Git references tests", func(t refTestCase) {
@@ -274,6 +292,55 @@ var _ = Describe("GitRepositoryReconciler", func() {
Expect(err).NotTo(HaveOccurred())
u.Path = path.Join(u.Path, fmt.Sprintf("repository-%s.git", randStringRunes(5)))
+ var transport = httptransport.NewClient(&http.Client{
+ Transport: &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ },
+ })
+ client.InstallProtocol("https", transport)
+
+ fs := memfs.New()
+ gitrepo, err := git.Init(memory.NewStorage(), fs)
+ Expect(err).NotTo(HaveOccurred())
+
+ wt, err := gitrepo.Worktree()
+ Expect(err).NotTo(HaveOccurred())
+
+ ff, _ := fs.Create("fixture")
+ _ = ff.Close()
+ _, err = wt.Add(fs.Join("fixture"))
+ Expect(err).NotTo(HaveOccurred())
+
+ commit, err := wt.Commit("Sample", &git.CommitOptions{Author: &object.Signature{
+ Name: "John Doe",
+ Email: "john@example.com",
+ When: time.Now(),
+ }})
+ Expect(err).NotTo(HaveOccurred())
+
+ gitrepo.Worktree()
+
+ for _, ref := range t.createRefs {
+ hRef := plumbing.NewHashReference(plumbing.ReferenceName(ref), commit)
+ err = gitrepo.Storer.SetReference(hRef)
+ Expect(err).NotTo(HaveOccurred())
+ }
+
+ remote, err := gitrepo.CreateRemote(&config.RemoteConfig{
+ Name: "origin",
+ URLs: []string{u.String()},
+ })
+ Expect(err).NotTo(HaveOccurred())
+
+ err = remote.Push(&git.PushOptions{
+ RefSpecs: []config.RefSpec{"refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"},
+ })
+ Expect(err).NotTo(HaveOccurred())
+
+ t.reference.Commit = strings.Replace(t.reference.Commit, "", commit.String(), 1)
+
+ client.InstallProtocol("https", httptransport.DefaultClient)
+
key := types.NamespacedName{
Name: fmt.Sprintf("git-ref-test-%s", randStringRunes(5)),
Namespace: namespace.Name,
@@ -288,6 +355,8 @@ var _ = Describe("GitRepositoryReconciler", func() {
Interval: metav1.Duration{Duration: indexInterval},
Reference: t.reference,
GitImplementation: t.gitImplementation,
+ SecretRef: nil,
+ CertSecretRef: t.certSecretRef,
},
}
Expect(k8sClient.Create(context.Background(), created)).Should(Succeed())
@@ -316,13 +385,22 @@ var _ = Describe("GitRepositoryReconciler", func() {
expectStatus: metav1.ConditionFalse,
expectMessage: "x509: certificate signed by unknown authority",
}),
- Entry("self signed v2", refTestCase{
+ Entry("self signed v2 without CA", refTestCase{
reference: &sourcev1.GitRepositoryRef{Branch: "main"},
waitForReason: sourcev1.GitOperationFailedReason,
expectStatus: metav1.ConditionFalse,
expectMessage: "error: user rejected certificate",
gitImplementation: sourcev1.LibGit2Implementation,
}),
+ Entry("self signed v2 with CA", refTestCase{
+ reference: &sourcev1.GitRepositoryRef{Branch: "some-branch"},
+ createRefs: []string{"refs/heads/some-branch"},
+ waitForReason: sourcev1.GitOperationSucceedReason,
+ expectStatus: metav1.ConditionTrue,
+ expectRevision: "some-branch",
+ certSecretRef: &meta.LocalObjectReference{Name: "cert"},
+ gitImplementation: sourcev1.LibGit2Implementation,
+ }),
)
})
})
diff --git a/docs/api/source.md b/docs/api/source.md
index c0de25e90..e50eb728c 100644
--- a/docs/api/source.md
+++ b/docs/api/source.md
@@ -400,6 +400,20 @@ string
Defaults to go-git, valid values are (‘go-git’, ‘libgit2’).
+
+
+certSecretRef
+
+
+github.com/fluxcd/pkg/apis/meta.LocalObjectReference
+
+
+ |
+
+(Optional)
+ CertSecretRef
+ |
+
@@ -1246,6 +1260,20 @@ string
Defaults to go-git, valid values are (‘go-git’, ‘libgit2’).
+
+
+certSecretRef
+
+
+github.com/fluxcd/pkg/apis/meta.LocalObjectReference
+
+
+ |
+
+(Optional)
+ CertSecretRef
+ |
+
diff --git a/go.mod b/go.mod
index c8dccd194..2f60fa109 100644
--- a/go.mod
+++ b/go.mod
@@ -20,12 +20,12 @@ require (
github.com/go-git/go-billy/v5 v5.0.0
github.com/go-git/go-git/v5 v5.2.0
github.com/go-logr/logr v0.3.0
- github.com/libgit2/git2go/v31 v31.3.0
+ github.com/libgit2/git2go/v31 v31.4.7
github.com/minio/minio-go/v7 v7.0.5
github.com/onsi/ginkgo v1.14.1
github.com/onsi/gomega v1.10.2
github.com/spf13/pflag v1.0.5
- golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
+ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
helm.sh/helm/v3 v3.5.0
k8s.io/api v0.20.2
diff --git a/go.sum b/go.sum
index 311fe6918..3bbc6502b 100644
--- a/go.sum
+++ b/go.sum
@@ -427,6 +427,8 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
@@ -553,8 +555,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/libgit2/git2go/v31 v31.3.0 h1:d8ciyYVKir+gKwra3KuNxTyVvbgGKn4admdt1PNNAOg=
-github.com/libgit2/git2go/v31 v31.3.0/go.mod h1:mnc0hPGPs0nDi9INrurTpioeRzje9DvSXqON/+JEhwY=
+github.com/libgit2/git2go/v31 v31.4.7 h1:P85qB5at5un4qPqUcvOZbAom7P0G4KAG/OLVyD29kQ0=
+github.com/libgit2/git2go/v31 v31.4.7/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
@@ -903,6 +905,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
+golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1032,6 +1036,10 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/pkg/git/common/common.go b/pkg/git/common/common.go
index 3b949fbb3..9ec4d602a 100644
--- a/pkg/git/common/common.go
+++ b/pkg/git/common/common.go
@@ -46,5 +46,5 @@ type Auth struct {
}
type AuthSecretStrategy interface {
- Method(secret corev1.Secret) (*Auth, error)
+ Method(secret *corev1.Secret, certSecret *corev1.Secret) (*Auth, error)
}
diff --git a/pkg/git/v1/transport.go b/pkg/git/v1/transport.go
index f8f64f5ae..554f55a43 100644
--- a/pkg/git/v1/transport.go
+++ b/pkg/git/v1/transport.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1
import (
+ "errors"
"fmt"
"net/url"
@@ -46,7 +47,11 @@ func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
type BasicAuth struct{}
-func (s *BasicAuth) Method(secret corev1.Secret) (*common.Auth, error) {
+func (s *BasicAuth) Method(secret *corev1.Secret, certSecret *corev1.Secret) (*common.Auth, error) {
+ if certSecret != nil {
+ return nil, errors.New("git2go HTTP transport does not support custom certificates.")
+ }
+
auth := &http.BasicAuth{}
if username, ok := secret.Data["username"]; ok {
auth.Username = string(username)
@@ -64,7 +69,11 @@ type PublicKeyAuth struct {
user string
}
-func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
+func (s *PublicKeyAuth) Method(secret *corev1.Secret, certSecret *corev1.Secret) (*common.Auth, error) {
+ if certSecret != nil {
+ return nil, errors.New("git2go SSH transport does not support custom certificates.")
+ }
+
identity := secret.Data["identity"]
knownHosts := secret.Data["known_hosts"]
if len(identity) == 0 || len(knownHosts) == 0 {
diff --git a/pkg/git/v1/transport_test.go b/pkg/git/v1/transport_test.go
index 8e27033e5..07f889739 100644
--- a/pkg/git/v1/transport_test.go
+++ b/pkg/git/v1/transport_test.go
@@ -112,7 +112,7 @@ func TestBasicAuthStrategy_Method(t *testing.T) {
tt.modify(secret)
}
s := &BasicAuth{}
- got, err := s.Method(*secret)
+ got, err := s.Method(secret, nil)
if (err != nil) != tt.wantErr {
t.Errorf("Method() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -145,7 +145,7 @@ func TestPublicKeyStrategy_Method(t *testing.T) {
tt.modify(secret)
}
s := &PublicKeyAuth{}
- _, err := s.Method(*secret)
+ _, err := s.Method(secret, nil)
if (err != nil) != tt.wantErr {
t.Errorf("Method() error = %v, wantErr %v", err, tt.wantErr)
return
diff --git a/pkg/git/v2/transport.go b/pkg/git/v2/transport.go
index 992e4d94a..03362d6f0 100644
--- a/pkg/git/v2/transport.go
+++ b/pkg/git/v2/transport.go
@@ -20,16 +20,23 @@ import (
"bufio"
"bytes"
"crypto/sha1"
+ "crypto/x509"
+ "errors"
"fmt"
- "golang.org/x/crypto/ssh"
"net/url"
"strings"
+ "golang.org/x/crypto/ssh"
+
"github.com/fluxcd/source-controller/pkg/git/common"
git2go "github.com/libgit2/git2go/v31"
corev1 "k8s.io/api/core/v1"
)
+const (
+ CACert = "caFile"
+)
+
func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
u, err := url.Parse(URL)
if err != nil {
@@ -48,35 +55,66 @@ func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
type BasicAuth struct{}
-func (s *BasicAuth) Method(secret corev1.Secret) (*common.Auth, error) {
- var username string
- if d, ok := secret.Data["username"]; ok {
- username = string(d)
- }
- var password string
- if d, ok := secret.Data["password"]; ok {
- password = string(d)
- }
- if username == "" || password == "" {
- return nil, fmt.Errorf("invalid '%s' secret data: required fields 'username' and 'password'", secret.Name)
+func (s *BasicAuth) Method(secret *corev1.Secret, certSecret *corev1.Secret) (*common.Auth, error) {
+ var credCallback git2go.CredentialsCallback = nil
+ if secret != nil {
+ var username string
+ if d, ok := secret.Data["username"]; ok {
+ username = string(d)
+ }
+ var password string
+ if d, ok := secret.Data["password"]; ok {
+ password = string(d)
+ }
+ if username == "" || password == "" {
+ return nil, fmt.Errorf("invalid '%s' secret data: required fields 'username' and 'password'", secret.Name)
+ }
+ credCallback = func(url string, username_from_url string, allowed_types git2go.CredType) (*git2go.Cred, error) {
+ cred, err := git2go.NewCredUserpassPlaintext(username, password)
+ if err != nil {
+ return nil, err
+ }
+ return cred, nil
+ }
}
- credCallback := func(url string, username_from_url string, allowed_types git2go.CredType) (*git2go.Cred, error) {
- cred, err := git2go.NewCredUserpassPlaintext(username, password)
- if err != nil {
- return nil, err
+ var certCallback git2go.CertificateCheckCallback = nil
+ if certSecret != nil {
+ caCert, ok := certSecret.Data[CACert]
+ if !ok {
+ return nil, fmt.Errorf("invalid '%s' cert secret data: required field '%s'", secret.Name, CACert)
+ }
+
+ certCallback = func(cert *git2go.Certificate, valid bool, hostname string) git2go.ErrorCode {
+ roots := x509.NewCertPool()
+ ok := roots.AppendCertsFromPEM(caCert)
+ if !ok {
+ return git2go.ErrCertificate
+ }
+
+ opts := x509.VerifyOptions{
+ Roots: roots,
+ }
+ _, err := cert.X509.Verify(opts)
+ if err != nil {
+ return git2go.ErrCertificate
+ }
+ return git2go.ErrOk
}
- return cred, nil
}
- return &common.Auth{CredCallback: credCallback, CertCallback: nil}, nil
+ return &common.Auth{CredCallback: credCallback, CertCallback: certCallback}, nil
}
type PublicKeyAuth struct {
user string
}
-func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
+func (s *PublicKeyAuth) Method(secret *corev1.Secret, cert *corev1.Secret) (*common.Auth, error) {
+ if cert != nil {
+ return nil, errors.New("libgit2 SSH transport does not support custom certificates.")
+ }
+
identity := secret.Data["identity"]
knownHosts := secret.Data["known_hosts"]
if len(identity) == 0 || len(knownHosts) == 0 {
diff --git a/pkg/git/v2/transport_test.go b/pkg/git/v2/transport_test.go
index 8428229ea..e9069fd6e 100644
--- a/pkg/git/v2/transport_test.go
+++ b/pkg/git/v2/transport_test.go
@@ -110,7 +110,7 @@ func TestBasicAuthStrategy_Method(t *testing.T) {
tt.modify(secret)
}
s := &BasicAuth{}
- got, err := s.Method(*secret)
+ got, err := s.Method(secret, nil)
if (err != nil) != tt.wantErr {
t.Errorf("Method() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -143,7 +143,7 @@ func TestPublicKeyStrategy_Method(t *testing.T) {
tt.modify(secret)
}
s := &PublicKeyAuth{}
- _, err := s.Method(*secret)
+ _, err := s.Method(secret, nil)
if (err != nil) != tt.wantErr {
t.Errorf("Method() error = %v, wantErr %v", err, tt.wantErr)
return