Add user support to git2go implementation
Signed-off-by: Philip Laine <philip.laine@gmail.com>
This commit is contained in:
parent
934f5df668
commit
5ff65d7ae7
|
|
@ -182,8 +182,12 @@ func (r *GitRepositoryReconciler) reconcile(ctx context.Context, repository sour
|
||||||
|
|
||||||
// determine auth method
|
// determine auth method
|
||||||
auth := &common.Auth{}
|
auth := &common.Auth{}
|
||||||
authStrategy := git.AuthSecretStrategyForURL(repository.Spec.URL, repository.Spec.GitProtocolV2Compatibility)
|
if repository.Spec.SecretRef != nil {
|
||||||
if repository.Spec.SecretRef != nil && authStrategy != nil {
|
authStrategy, err := git.AuthSecretStrategyForURL(repository.Spec.URL, repository.Spec.GitProtocolV2Compatibility)
|
||||||
|
if err != nil {
|
||||||
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
|
}
|
||||||
|
|
||||||
name := types.NamespacedName{
|
name := types.NamespacedName{
|
||||||
Namespace: repository.GetNamespace(),
|
Namespace: repository.GetNamespace(),
|
||||||
Name: repository.Spec.SecretRef.Name,
|
Name: repository.Spec.SecretRef.Name,
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
const (
|
const (
|
||||||
DefaultOrigin = "origin"
|
DefaultOrigin = "origin"
|
||||||
DefaultBranch = "master"
|
DefaultBranch = "master"
|
||||||
|
DefaultPublicKeyAuthUser = "git"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Commit interface {
|
type Commit interface {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func CheckoutStrategyForRef(ref *sourcev1.GitRepositoryRef, useGitV2 bool) commo
|
||||||
return gitv1.CheckoutStrategyForRef(ref)
|
return gitv1.CheckoutStrategyForRef(ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AuthSecretStrategyForURL(url string, useGitV2 bool) common.AuthSecretStrategy {
|
func AuthSecretStrategyForURL(url string, useGitV2 bool) (common.AuthSecretStrategy, error) {
|
||||||
if useGitV2 {
|
if useGitV2 {
|
||||||
return gitv2.AuthSecretStrategyForURL(url)
|
return gitv2.AuthSecretStrategyForURL(url)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ import (
|
||||||
"github.com/fluxcd/source-controller/pkg/git/common"
|
"github.com/fluxcd/source-controller/pkg/git/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultPublicKeyAuthUser = "git"
|
|
||||||
|
|
||||||
func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
|
func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
|
||||||
u, err := url.Parse(URL)
|
u, err := url.Parse(URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -75,7 +73,7 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
|
||||||
|
|
||||||
user := s.user
|
user := s.user
|
||||||
if user == "" {
|
if user == "" {
|
||||||
user = defaultPublicKeyAuthUser
|
user = common.DefaultPublicKeyAuthUser
|
||||||
}
|
}
|
||||||
|
|
||||||
pk, err := ssh.NewPublicKeys(user, identity, "")
|
pk, err := ssh.NewPublicKeys(user, identity, "")
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fluxcd/source-controller/pkg/git/common"
|
"github.com/fluxcd/source-controller/pkg/git/common"
|
||||||
|
|
@ -29,14 +30,20 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AuthSecretStrategyForURL(url string) common.AuthSecretStrategy {
|
func AuthSecretStrategyForURL(URL string) (common.AuthSecretStrategy, error) {
|
||||||
switch {
|
u, err := url.Parse(URL)
|
||||||
case strings.HasPrefix(url, "http"):
|
if err != nil {
|
||||||
return &BasicAuth{}
|
return nil, fmt.Errorf("failed to parse URL to determine auth strategy: %w", err)
|
||||||
case strings.HasPrefix(url, "ssh"):
|
}
|
||||||
return &PublicKeyAuth{}
|
|
||||||
|
switch {
|
||||||
|
case u.Scheme == "http", u.Scheme == "https":
|
||||||
|
return &BasicAuth{}, nil
|
||||||
|
case u.Scheme == "ssh":
|
||||||
|
return &PublicKeyAuth{user: u.User.Username()}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("no auth secret strategy for scheme %s", u.Scheme)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BasicAuth struct{}
|
type BasicAuth struct{}
|
||||||
|
|
@ -65,7 +72,9 @@ func (s *BasicAuth) Method(secret corev1.Secret) (*common.Auth, error) {
|
||||||
return &common.Auth{CredCallback: credCallback, CertCallback: nil}, nil
|
return &common.Auth{CredCallback: credCallback, CertCallback: nil}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PublicKeyAuth struct{}
|
type PublicKeyAuth struct {
|
||||||
|
user string
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
|
func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
|
||||||
identity := secret.Data["identity"]
|
identity := secret.Data["identity"]
|
||||||
|
|
@ -79,14 +88,20 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*common.Auth, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to validate private key
|
// Need to validate private key as it is not
|
||||||
|
// done by git2go when loading the key
|
||||||
_, err = ssh.ParsePrivateKey(identity)
|
_, err = ssh.ParsePrivateKey(identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user := s.user
|
||||||
|
if user == "" {
|
||||||
|
user = common.DefaultPublicKeyAuthUser
|
||||||
|
}
|
||||||
|
|
||||||
credCallback := func(url string, username_from_url string, allowed_types git2go.CredType) (*git2go.Cred, error) {
|
credCallback := func(url string, username_from_url string, allowed_types git2go.CredType) (*git2go.Cred, error) {
|
||||||
cred, err := git2go.NewCredSshKeyFromMemory("git", "", string(identity), "")
|
cred, err := git2go.NewCredSshKeyFromMemory(user, "", string(identity), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,16 +69,22 @@ func TestAuthSecretStrategyForURL(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
url string
|
url string
|
||||||
want common.AuthSecretStrategy
|
want common.AuthSecretStrategy
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"HTTP", "http://git.example.com/org/repo.git", &BasicAuth{}},
|
{"HTTP", "http://git.example.com/org/repo.git", &BasicAuth{}, false},
|
||||||
{"HTTPS", "https://git.example.com/org/repo.git", &BasicAuth{}},
|
{"HTTPS", "https://git.example.com/org/repo.git", &BasicAuth{}, false},
|
||||||
{"SSH", "ssh://git.example.com:2222/org/repo.git", &PublicKeyAuth{}},
|
{"SSH", "ssh://git.example.com:2222/org/repo.git", &PublicKeyAuth{}, false},
|
||||||
{"unsupported", "protocol://example.com", nil},
|
{"SSH with username", "ssh://example@git.example.com:2222/org/repo.git", &PublicKeyAuth{user: "example"}, false},
|
||||||
|
{"unsupported", "protocol://example.com", nil, true},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got := AuthSecretStrategyForURL(tt.url)
|
got, err := AuthSecretStrategyForURL(tt.url)
|
||||||
if reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("AuthSecretStrategyForURL() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("AuthSecretStrategyForURL() got = %v, want %v", got, tt.want)
|
t.Errorf("AuthSecretStrategyForURL() got = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue