Add git.CheckoutStrategy auth tests
Adds tests for git.CheckoutStrategy to check if both the git implementations work with all the authentication methods. Signed-off-by: Sunny <darkowlzz@protonmail.com>
This commit is contained in:
parent
942c310195
commit
8c581ddfbc
2
go.mod
2
go.mod
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.0
|
||||
github.com/fluxcd/pkg/gittestserver v0.3.0
|
||||
github.com/fluxcd/pkg/gittestserver v0.4.0
|
||||
github.com/fluxcd/pkg/gitutil v0.1.0
|
||||
github.com/fluxcd/pkg/helmtestserver v0.2.0
|
||||
github.com/fluxcd/pkg/lockedfile v0.1.0
|
||||
|
|
|
|||
5
go.sum
5
go.sum
|
|
@ -266,8 +266,8 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
|||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSLjG2rlE=
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE=
|
||||
github.com/fluxcd/pkg/gittestserver v0.3.0 h1:6aa30mybecBwBWaJ2IEk7pQzefWnjWjxkTSrHMHawvg=
|
||||
github.com/fluxcd/pkg/gittestserver v0.3.0/go.mod h1:8j36Z6B0BuKNZZ6exAWoyDEpyQoFcjz1IX3WBT7PZNg=
|
||||
github.com/fluxcd/pkg/gittestserver v0.4.0 h1:VQzQ5TcHzohxbYGWpnQ/79w7/rnS2SQGC7FSDtbIsCA=
|
||||
github.com/fluxcd/pkg/gittestserver v0.4.0/go.mod h1:hUPx21fe/6oox336Wih/XF1fnmzLmptNMOvATbTZXNY=
|
||||
github.com/fluxcd/pkg/gitutil v0.1.0 h1:VO3kJY/CKOCO4ysDNqfdpTg04icAKBOSb3lbR5uE/IE=
|
||||
github.com/fluxcd/pkg/gitutil v0.1.0/go.mod h1:Ybz50Ck5gkcnvF0TagaMwtlRy3X3wXuiri1HVsK5id4=
|
||||
github.com/fluxcd/pkg/helmtestserver v0.2.0 h1:cE7YHDmrWI0hr9QpaaeQ0vQ16Z0IiqZKiINDpqdY610=
|
||||
|
|
@ -984,7 +984,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/pkg/gittestserver"
|
||||
"github.com/fluxcd/pkg/ssh"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/fluxcd/source-controller/pkg/git"
|
||||
"github.com/fluxcd/source-controller/pkg/git/gogit"
|
||||
"github.com/fluxcd/source-controller/pkg/git/libgit2"
|
||||
)
|
||||
|
||||
func TestCheckoutStrategyForImplementation_Auth(t *testing.T) {
|
||||
gitImpls := []git.Implementation{gogit.Implementation, libgit2.Implementation}
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
transport git.TransportType
|
||||
getRepoURL func(g *WithT, srv *gittestserver.GitServer, repoPath string) string
|
||||
getAuthOpts func(g *WithT, u *url.URL, user string, pswd string, ca []byte) *git.AuthOptions
|
||||
wantFunc func(g *WithT, cs git.CheckoutStrategy, dir string, repoURL string, authOpts *git.AuthOptions)
|
||||
}
|
||||
|
||||
cases := []testCase{
|
||||
{
|
||||
name: "http cloning",
|
||||
transport: git.HTTP,
|
||||
getRepoURL: func(g *WithT, srv *gittestserver.GitServer, repoPath string) string {
|
||||
return srv.HTTPAddressWithCredentials() + "/" + repoPath
|
||||
},
|
||||
getAuthOpts: func(g *WithT, u *url.URL, user string, pswd string, ca []byte) *git.AuthOptions {
|
||||
return &git.AuthOptions{
|
||||
Transport: git.HTTP,
|
||||
Username: user,
|
||||
Password: pswd,
|
||||
}
|
||||
},
|
||||
wantFunc: func(g *WithT, cs git.CheckoutStrategy, dir string, repoURL string, authOpts *git.AuthOptions) {
|
||||
_, err := cs.Checkout(context.TODO(), dir, repoURL, authOpts)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "https cloning",
|
||||
transport: git.HTTPS,
|
||||
getRepoURL: func(g *WithT, srv *gittestserver.GitServer, repoPath string) string {
|
||||
return srv.HTTPAddress() + "/" + repoPath
|
||||
},
|
||||
getAuthOpts: func(g *WithT, u *url.URL, user, pswd string, ca []byte) *git.AuthOptions {
|
||||
return &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: user,
|
||||
Password: pswd,
|
||||
CAFile: ca,
|
||||
}
|
||||
},
|
||||
wantFunc: func(g *WithT, cs git.CheckoutStrategy, dir, repoURL string, authOpts *git.AuthOptions) {
|
||||
_, err := cs.Checkout(context.TODO(), dir, repoURL, authOpts)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ssh cloning",
|
||||
transport: git.SSH,
|
||||
getRepoURL: func(g *WithT, srv *gittestserver.GitServer, repoPath string) string {
|
||||
return getSSHRepoURL(srv.SSHAddress(), repoPath)
|
||||
},
|
||||
getAuthOpts: func(g *WithT, u *url.URL, user, pswd string, ca []byte) *git.AuthOptions {
|
||||
knownhosts, err := ssh.ScanHostKey(u.Host, 5*time.Second)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
keygen := ssh.NewRSAGenerator(2048)
|
||||
pair, err := keygen.Generate()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
return &git.AuthOptions{
|
||||
Host: u.Host, // Without this libgit2 returns error "user cancelled hostkey check".
|
||||
Transport: git.SSH,
|
||||
Username: "git", // Without this libgit2 returns error "username does not match previous request".
|
||||
Identity: pair.PrivateKey,
|
||||
KnownHosts: knownhosts,
|
||||
}
|
||||
},
|
||||
wantFunc: func(g *WithT, cs git.CheckoutStrategy, dir, repoURL string, authOpts *git.AuthOptions) {
|
||||
_, err := cs.Checkout(context.TODO(), dir, repoURL, authOpts)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testFunc := func(tt testCase, impl git.Implementation) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
var examplePublicKey, examplePrivateKey, exampleCA []byte
|
||||
|
||||
gitServer, err := gittestserver.NewTempGitServer()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(gitServer.Root())
|
||||
|
||||
username := "test-user"
|
||||
password := "test-password"
|
||||
gitServer.Auth(username, password)
|
||||
gitServer.KeyDir(gitServer.Root())
|
||||
|
||||
// Start the HTTP/HTTPS server.
|
||||
if tt.transport == git.HTTPS {
|
||||
var err error
|
||||
examplePublicKey, err = os.ReadFile("testdata/certs/server.pem")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
examplePrivateKey, err = os.ReadFile("testdata/certs/server-key.pem")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
exampleCA, err = os.ReadFile("testdata/certs/ca.pem")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
err = gitServer.StartHTTPS(examplePublicKey, examplePrivateKey, exampleCA, "example.com")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
} else {
|
||||
g.Expect(gitServer.StartHTTP()).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
defer gitServer.StopHTTP()
|
||||
|
||||
// Start the SSH server.
|
||||
if tt.transport == git.SSH {
|
||||
g.Expect(gitServer.ListenSSH()).ToNot(HaveOccurred())
|
||||
go func() {
|
||||
gitServer.StartSSH()
|
||||
}()
|
||||
defer func() {
|
||||
g.Expect(gitServer.StopSSH()).To(Succeed())
|
||||
}()
|
||||
}
|
||||
|
||||
// Initialize a git repo.
|
||||
// TODO: Fix pkg/gittestserver InitRepo() bug to enable creating
|
||||
// custom branch.
|
||||
// branch := "main"
|
||||
branch := "master"
|
||||
repoPath := "bar/test-reponame"
|
||||
err = gitServer.InitRepo("testdata/repo1", branch, repoPath)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
repoURL := tt.getRepoURL(g, gitServer, repoPath)
|
||||
u, err := url.Parse(repoURL)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
authOpts := tt.getAuthOpts(g, u, username, password, exampleCA)
|
||||
|
||||
// Get the checkout strategy.
|
||||
checkoutOpts := git.CheckoutOptions{
|
||||
Branch: branch,
|
||||
}
|
||||
checkoutStrategy, err := CheckoutStrategyForImplementation(context.TODO(), impl, checkoutOpts)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "test-checkout")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
tt.wantFunc(g, checkoutStrategy, tmpDir, repoURL, authOpts)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test cases against the git implementations.
|
||||
for _, gitImpl := range gitImpls {
|
||||
for _, tt := range cases {
|
||||
t.Run(string(gitImpl)+"_"+tt.name, testFunc(tt, gitImpl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getSSHRepoURL(sshAddress, repoPath string) string {
|
||||
// This is expected to use 127.0.0.1, but host key
|
||||
// checking usually wants a hostname, so use
|
||||
// "localhost".
|
||||
sshURL := strings.Replace(sshAddress, "127.0.0.1", "localhost", 1)
|
||||
return sshURL + "/" + repoPath
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# Copyright 2021 The Flux authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
all: server-key.pem
|
||||
|
||||
ca-key.pem: ca-csr.json
|
||||
cfssl gencert -initca ca-csr.json | cfssljson -bare ca –
|
||||
ca.pem: ca-key.pem
|
||||
ca.csr: ca-key.pem
|
||||
|
||||
server-key.pem: server-csr.json ca-config.json ca-key.pem
|
||||
cfssl gencert \
|
||||
-ca=ca.pem \
|
||||
-ca-key=ca-key.pem \
|
||||
-config=ca-config.json \
|
||||
-profile=web-servers \
|
||||
server-csr.json | cfssljson -bare server
|
||||
sever.pem: server-key.pem
|
||||
server.csr: server-key.pem
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"expiry": "87600h"
|
||||
},
|
||||
"profiles": {
|
||||
"web-servers": {
|
||||
"usages": [
|
||||
"signing",
|
||||
"key encipherment",
|
||||
"server auth",
|
||||
"client auth"
|
||||
],
|
||||
"expiry": "87600h"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"CN": "example.com CA",
|
||||
"hosts": [
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"example.com",
|
||||
"www.example.com"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOH/u9dMcpVcZ0+X9Fc78dCTj8SHuXawhLjhu/ej64WToAoGCCqGSM49
|
||||
AwEHoUQDQgAEruH/kPxtX3cyYR2G7TYmxLq6AHyzo/NGXc9XjGzdJutE2SQzn37H
|
||||
dvSJbH+Lvqo9ik0uiJVRVdCYD1j7gNszGA==
|
||||
-----END EC PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBIDCBxgIBADAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxigSzBJBgkqhkiG9w0BCQ4x
|
||||
PDA6MDgGA1UdEQQxMC+CCWxvY2FsaG9zdIILZXhhbXBsZS5jb22CD3d3dy5leGFt
|
||||
cGxlLmNvbYcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAkw85nyLhJssyCYsaFvRU
|
||||
EErhu66xHPJug/nG50uV5OoCIQCUorrflOSxfChPeCe4xfwcPv7FpcCYbKVYtGzz
|
||||
b34Wow==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw
|
||||
NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE
|
||||
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ
|
||||
4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O
|
||||
1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb
|
||||
OD8EjjCMY69RMO0=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"CN": "example.com",
|
||||
"hosts": [
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"example.com",
|
||||
"www.example.com"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIKQbEXV6nljOHMmPrWVWQ+JrAE5wsbE9iMhfY7wlJgXOoAoGCCqGSM49
|
||||
AwEHoUQDQgAE+53oBGlrvVUTelSGYji8GNHVhVg8jOs1PeeLuXCIZjQmctHLFEq3
|
||||
fE+mGxCL93MtpYzlwIWBf0m7pEGQre6bzg==
|
||||
-----END EC PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBHDCBwwIBADAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEG
|
||||
CCqGSM49AwEHA0IABPud6ARpa71VE3pUhmI4vBjR1YVYPIzrNT3ni7lwiGY0JnLR
|
||||
yxRKt3xPphsQi/dzLaWM5cCFgX9Ju6RBkK3um86gSzBJBgkqhkiG9w0BCQ4xPDA6
|
||||
MDgGA1UdEQQxMC+CCWxvY2FsaG9zdIILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxl
|
||||
LmNvbYcEfwAAATAKBggqhkjOPQQDAgNIADBFAiB5A6wvQ5x6g/zhiyn+wLzXsOaB
|
||||
Gb/F25p/zTHHQqZbkwIhAPUgWzy/2bs6eZEi97bSlaRdmrqHwqT842t5sEwGyXNV
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7TCCAZKgAwIBAgIUB+17B8PU05wVTzRHLeG+S+ybZK4wCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMzAw
|
||||
NDE1MDgxODAwWjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEG
|
||||
CCqGSM49AwEHA0IABPud6ARpa71VE3pUhmI4vBjR1YVYPIzrNT3ni7lwiGY0JnLR
|
||||
yxRKt3xPphsQi/dzLaWM5cCFgX9Ju6RBkK3um86jgbowgbcwDgYDVR0PAQH/BAQD
|
||||
AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA
|
||||
MB0GA1UdDgQWBBTM8HS5EIlVMBYv/300jN8PEArUgDAfBgNVHSMEGDAWgBQGyUiU
|
||||
1QEZiMAqjsnIYTwZ4yp5wzA4BgNVHREEMTAvgglsb2NhbGhvc3SCC2V4YW1wbGUu
|
||||
Y29tgg93d3cuZXhhbXBsZS5jb22HBH8AAAEwCgYIKoZIzj0EAwIDSQAwRgIhAOgB
|
||||
5W82FEgiTTOmsNRekkK5jUPbj4D4eHtb2/BI7ph4AiEA2AxHASIFBdv5b7Qf5prb
|
||||
bdNmUCzAvVuCAKuMjg2OPrE=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1 @@
|
|||
test file
|
||||
Loading…
Reference in New Issue