Fix and enhance end-to-end testing for SSH repositories (#2101)

* Fix and enhance end-to-end testing for SSH repositories
This commit is contained in:
jannfis 2019-08-07 19:53:00 +02:00 committed by Alexander Matyushentsev
parent 3f312a9e92
commit de4fbcdf5b
13 changed files with 184 additions and 142 deletions

1
Gopkg.lock generated
View file

@ -1646,6 +1646,7 @@
"github.com/yuin/gopher-lua",
"golang.org/x/crypto/bcrypt",
"golang.org/x/crypto/ssh",
"golang.org/x/crypto/ssh/knownhosts",
"golang.org/x/crypto/ssh/terminal",
"golang.org/x/net/context",
"golang.org/x/oauth2",

View file

@ -2,6 +2,6 @@ controller: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/a
api-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-server/main.go --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --staticassets ui/dist/app"
dex: sh -c "go run ./cmd/argocd-util/main.go gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml quay.io/dexidp/dex:v2.14.0 serve /dex.yaml"
redis: docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:5.0.3-alpine --save "" --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}
repo-server: sh -c "FORCE_LOG_COLORS=1 go run ./cmd/argocd-repo-server/main.go --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
repo-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-repo-server/main.go --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
git-server: test/fixture/testrepos/start-git.sh
git-server: test/fixture/testrepos/start-git.sh

View file

@ -49,7 +49,7 @@
"ApplicationService"
],
"summary": "List returns list of applications",
"operationId": "ListMixin6",
"operationId": "ListMixin1",
"parameters": [
{
"type": "string",
@ -89,7 +89,7 @@
"ApplicationService"
],
"summary": "Create creates an application",
"operationId": "CreateMixin6",
"operationId": "CreateMixin1",
"parameters": [
{
"name": "body",
@ -116,7 +116,7 @@
"ApplicationService"
],
"summary": "Update updates an application",
"operationId": "UpdateMixin6",
"operationId": "UpdateMixin1",
"parameters": [
{
"type": "string",
@ -197,7 +197,7 @@
"ApplicationService"
],
"summary": "Get returns an application by name",
"operationId": "GetMixin6",
"operationId": "Get",
"parameters": [
{
"type": "string",
@ -238,7 +238,7 @@
"ApplicationService"
],
"summary": "Delete deletes an application",
"operationId": "DeleteMixin6",
"operationId": "DeleteMixin1",
"parameters": [
{
"type": "string",
@ -852,7 +852,7 @@
"ClusterService"
],
"summary": "List returns list of clusters",
"operationId": "List",
"operationId": "ListMixin3",
"parameters": [
{
"type": "string",
@ -874,7 +874,7 @@
"ClusterService"
],
"summary": "Create creates a cluster",
"operationId": "Create",
"operationId": "CreateMixin3",
"parameters": [
{
"name": "body",
@ -901,7 +901,7 @@
"ClusterService"
],
"summary": "Update updates a cluster",
"operationId": "Update",
"operationId": "UpdateMixin3",
"parameters": [
{
"type": "string",
@ -934,7 +934,7 @@
"ClusterService"
],
"summary": "Get returns a cluster by server address",
"operationId": "GetMixin1",
"operationId": "GetMixin3",
"parameters": [
{
"type": "string",
@ -957,7 +957,7 @@
"ClusterService"
],
"summary": "Delete deletes a cluster",
"operationId": "Delete",
"operationId": "DeleteMixin3",
"parameters": [
{
"type": "string",
@ -1239,7 +1239,7 @@
"RepositoryService"
],
"summary": "List returns list of repos",
"operationId": "ListMixin2",
"operationId": "List",
"parameters": [
{
"type": "string",
@ -1261,7 +1261,7 @@
"RepositoryService"
],
"summary": "Create creates a repo",
"operationId": "CreateMixin2",
"operationId": "Create",
"parameters": [
{
"name": "body",
@ -1288,7 +1288,7 @@
"RepositoryService"
],
"summary": "Update updates a repo",
"operationId": "UpdateMixin2",
"operationId": "Update",
"parameters": [
{
"type": "string",
@ -1321,7 +1321,7 @@
"RepositoryService"
],
"summary": "Delete deletes a repo",
"operationId": "DeleteMixin2",
"operationId": "Delete",
"parameters": [
{
"type": "string",
@ -1500,7 +1500,7 @@
"SettingsService"
],
"summary": "Get returns Argo CD settings",
"operationId": "Get",
"operationId": "GetMixin5",
"responses": {
"200": {
"description": "(empty)",

View file

@ -43,6 +43,11 @@ func (c *Context) CustomCACertAdded() *Context {
return c
}
func (c *Context) CustomSSHKnownHostsAdded() *Context {
certs.AddCustomSSHKnownHostsKeys()
return c
}
func (c *Context) HTTPSRepoURLAdded() *Context {
repos.AddHTTPSRepo(false)
return c

View file

@ -1,12 +1,15 @@
package certs
import (
"io/ioutil"
"path/filepath"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/test/e2e/fixture"
)
// Add a custom CA certificate to the test and also create the certificate file
// on the file system, so argocd-server and argocd-repo-server can use it.
func AddCustomCACert() {
caCertPath, err := filepath.Abs("../fixture/certs/argocd-test-ca.crt")
errors.CheckError(err)
@ -14,4 +17,23 @@ func AddCustomCACert() {
errors.FailOnErr(fixture.RunCli(args...))
args = []string{"cert", "add-tls", "127.0.0.1", "--from", caCertPath}
errors.FailOnErr(fixture.RunCli(args...))
certData, err := ioutil.ReadFile(caCertPath)
errors.CheckError(err)
err = ioutil.WriteFile(fixture.TmpDir+"/app/config/tls/localhost", certData, 0644)
errors.CheckError(err)
err = ioutil.WriteFile(fixture.TmpDir+"/app/config/tls/127.0.0.1", certData, 0644)
errors.CheckError(err)
}
func AddCustomSSHKnownHostsKeys() {
knownHostsPath, err := filepath.Abs("../fixture/certs/ssh_known_hosts")
errors.CheckError(err)
args := []string{"cert", "add-ssh", "--batch", "--from", knownHostsPath}
errors.FailOnErr(fixture.RunCli(args...))
knownHostsData, err := ioutil.ReadFile(knownHostsPath)
errors.CheckError(err)
err = ioutil.WriteFile(fixture.TmpDir+"/app/config/ssh/ssh_known_hosts", knownHostsData, 0644)
errors.CheckError(err)
}

View file

@ -40,7 +40,7 @@ const (
ArgoCDNamespace = "argocd-e2e"
// ensure all repos are in one directory tree, so we can easily clean them up
tmpDir = "/tmp/argo-e2e"
TmpDir = "/tmp/argo-e2e"
repoDir = "testdata.git"
GuestbookPath = "guestbook"
@ -127,7 +127,7 @@ func Name() string {
}
func repoDirectory() string {
return path.Join(tmpDir, repoDir)
return path.Join(TmpDir, repoDir)
}
func RepoURL(urlType RepoURLType) string {
@ -336,7 +336,7 @@ func EnsureCleanState(t *testing.T) {
SetTLSCerts()
// remove tmp dir
CheckError(os.RemoveAll(tmpDir))
CheckError(os.RemoveAll(TmpDir))
// name based on test name
name = dnsFriendly(t.Name())
@ -344,11 +344,11 @@ func EnsureCleanState(t *testing.T) {
id = name + "-" + strings.ToLower(rand.RandString(5))
// create tmp dir
FailOnErr(Run("", "mkdir", "-p", tmpDir))
FailOnErr(Run("", "mkdir", "-p", TmpDir))
// create TLS and SSH certificate directories
FailOnErr(Run("", "mkdir", "-p", tmpDir+"/app/config/tls"))
FailOnErr(Run("", "mkdir", "-p", tmpDir+"/app/config/ssh"))
FailOnErr(Run("", "mkdir", "-p", TmpDir+"/app/config/tls"))
FailOnErr(Run("", "mkdir", "-p", TmpDir+"/app/config/ssh"))
// set-up tmp repo, must have unique name
FailOnErr(Run("", "cp", "-Rf", "testdata", repoDirectory()))

View file

@ -9,7 +9,7 @@ import (
. "github.com/argoproj/argo-cd/test/e2e/fixture/app"
)
func TestCanAccessSSHRepo(t *testing.T) {
func TestCanAccessInsecureSSHRepo(t *testing.T) {
Given(t).
SSHInsecureRepoURLAdded().
RepoURLType(fixture.RepoURLTypeSSH).
@ -20,3 +20,16 @@ func TestCanAccessSSHRepo(t *testing.T) {
Then().
Expect(OperationPhaseIs(OperationSucceeded))
}
func TestCanAccessSSHRepo(t *testing.T) {
Given(t).
CustomSSHKnownHostsAdded().
SSHRepoURLAdded().
RepoURLType(fixture.RepoURLTypeSSH).
Path("config-map").
When().
Create().
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded))
}

View file

@ -0,0 +1,3 @@
[localhost]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLle3IiLWy+Cwz6/JT3K8PSGAEZAJnaxiWk0u9wkAvbZ9wHTffctg25coBa8J4Oo1l5GTIkezib2C4PjCE01BZM=
[localhost]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhRWyu6rg0Kd0ugLxNGZ8gzUjasF4Z0oT16RUC/L9EkJWATAu4TkkoozZ5AcejlS29jUZXTkKt0La4dmIooeMDNd8b5vg1dWzSDDHwxd8Wa/4XZsUlL6zkUFrnqOPaFc/7EwM3I30064zT/Gt0BVvQUxKoT/TTea2KhQqeLmlWh4cVWJBuhZ8YODUf2VD4TSYfvpcqW/jVw2oG8Pj3WIaaG2+Bcp4Q4sJS2K+2kkiqmZ/hiPK1X/UbMRN2zWQBp5UPWFY2ctuC9B8yhLwAyMkHzuWLfB39dNEdn1jTjDsOUWbC3kDsWHsY5gtBxN30NizBWC+83NpaWbrzAlGb0JV1
[localhost]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2t7Tcavp5oUqbbSwEKRaGwEq94b8BFK16AEBbgRCTp

View file

@ -2,11 +2,14 @@ package db
import (
"fmt"
"regexp"
"strings"
"golang.org/x/crypto/ssh"
"golang.org/x/net/context"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/common"
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
certutil "github.com/argoproj/argo-cd/util/cert"
@ -169,9 +172,24 @@ func (db *db) CreateRepoCertificate(ctx context.Context, certificates *appsv1.Re
// Each request can contain multiple certificates of different types, so we
// make sure to handle each request accordingly.
for _, certificate := range certificates.Items {
// Ensure valid repo server name was given
if !certutil.IsValidHostname(certificate.ServerName, false) {
// Ensure valid repo server name was given only for https certificates.
// For SSH known host entries, we let Go's ssh library do the validation
// later on.
if certificate.CertType == "https" && !certutil.IsValidHostname(certificate.ServerName, false) {
return nil, fmt.Errorf("Invalid hostname in request: %s", certificate.ServerName)
} else if certificate.CertType == "ssh" {
// Matches "[hostname]:port" format
reExtract := regexp.MustCompile(`^\[(.*)\]\:[0-9]+$`)
matches := reExtract.FindStringSubmatch(certificate.ServerName)
var hostnameToCheck string
if len(matches) == 0 {
hostnameToCheck = certificate.ServerName
} else {
hostnameToCheck = matches[1]
}
if !certutil.IsValidHostname(hostnameToCheck, false) {
return nil, fmt.Errorf("Invalid hostname in request: %s", hostnameToCheck)
}
}
if certificate.CertType == "ssh" {
@ -201,14 +219,18 @@ func (db *db) CreateRepoCertificate(ctx context.Context, certificates *appsv1.Re
}
// Make sure that we received a valid public host key by parsing it
_, _, rawKeyData, _, _, err := ssh.ParseKnownHosts([]byte(fmt.Sprintf("%s %s %s", certificate.ServerName, certificate.CertSubType, certificate.CertData)))
_, hostnames, rawKeyData, _, _, err := ssh.ParseKnownHosts([]byte(fmt.Sprintf("%s %s %s", certificate.ServerName, certificate.CertSubType, certificate.CertData)))
if err != nil {
return nil, err
}
if len(hostnames) == 0 {
log.Errorf("Could not parse hostname for key from token %s", certificate.ServerName)
}
if newEntry {
sshKnownHostsList = append(sshKnownHostsList, &SSHKnownHostsEntry{
Host: certificate.ServerName,
Host: hostnames[0],
Data: string(certificate.CertData),
SubType: certificate.CertSubType,
})

View file

@ -292,9 +292,9 @@ func Test_ListCertificate(t *testing.T) {
HostNamePattern: "*",
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, len(certList.Items), Test_NumSSHKnownHostsExpected)
assert.Len(t, certList.Items, Test_NumSSHKnownHostsExpected)
for idx, entry := range certList.Items {
assert.Equal(t, entry.ServerName, Test_SSH_Hostname_Entries[idx])
assert.Equal(t, entry.CertSubType, Test_SSH_Subtypes[idx])
@ -306,9 +306,9 @@ func Test_ListCertificate(t *testing.T) {
HostNamePattern: "*",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected)
assert.Len(t, certList.Items, Test_NumTLSCertificatesExpected)
// List all certificates using selector
// Expected: List of 10 entries
@ -316,16 +316,16 @@ func Test_ListCertificate(t *testing.T) {
HostNamePattern: "*",
CertType: "*",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
assert.Len(t, certList.Items, Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
// List all certificates using nil selector
// Expected: List of 10 entries
certList, err = db.ListRepoCertificates(context.Background(), nil)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
assert.Len(t, certList.Items, Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
// List all certificates matching a host name pattern
// Expected: List of 4 entries, all with servername gitlab.com
@ -333,9 +333,9 @@ func Test_ListCertificate(t *testing.T) {
HostNamePattern: "gitlab.com",
CertType: "*",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 4, len(certList.Items))
assert.Len(t, certList.Items, 4)
for _, entry := range certList.Items {
assert.Equal(t, "gitlab.com", entry.ServerName)
}
@ -345,9 +345,9 @@ func Test_ListCertificate(t *testing.T) {
HostNamePattern: "gitlab.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
assert.Equal(t, "gitlab.com", certList.Items[0].ServerName)
assert.Equal(t, "https", certList.Items[0].CertType)
}
@ -367,9 +367,23 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Valid known hosts entry
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
Items: []v1alpha1.RepositoryCertificate{
{
ServerName: "[foo.example.com]:2222",
CertType: "ssh",
CertData: []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
},
},
}, false)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Len(t, certList.Items, 1)
// Invalid hostname
// Result: Error
@ -382,7 +396,7 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Check if it really was added
@ -391,9 +405,9 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
HostNamePattern: "foo.example.com",
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Existing cert, same data, no upsert
// Result: no error, should return 0 added certificates
@ -406,9 +420,9 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
// Existing cert, different data, no upsert
// Result: Error
@ -421,7 +435,7 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Existing cert, different data, upsert
@ -434,9 +448,9 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, true)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Invalid known hosts entry, case 1: key sub type missing
// Result: Error
@ -449,7 +463,7 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Invalid known hosts entry, case 2: invalid base64 data
@ -463,7 +477,7 @@ func Test_CreateSSHKnownHostEntries(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
}
@ -483,9 +497,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Invalid hostname
// Result: Error
@ -498,7 +512,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Check if it really was added
@ -507,9 +521,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
HostNamePattern: "foo.example.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Valid TLS certificates, multiple PEMs in data
// Expected: List of 2 entry
@ -522,9 +536,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 2, len(certList.Items))
assert.Len(t, certList.Items, 2)
// Check if it really was added
// Result: Return new certificate
@ -532,9 +546,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
HostNamePattern: "bar.example.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 2, len(certList.Items))
assert.Len(t, certList.Items, 2)
// Valid TLS certificate, existing cert, same data, no upsert
// Expected: List of 0 entry
@ -547,9 +561,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
// Valid TLS certificate, existing cert, different data, no upsert
// Expected: Error
@ -562,7 +576,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Valid TLS certificate, existing cert, different data, upsert
@ -576,9 +590,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, true)
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 2, len(certList.Items))
assert.Len(t, certList.Items, 2)
// Check if upsert was successful
// Expected: List of 2 entries, matching hostnames & cert types
@ -586,9 +600,9 @@ func Test_CreateTLSCertificates(t *testing.T) {
HostNamePattern: "foo.example.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 2, len(certList.Items))
assert.Len(t, certList.Items, 2)
for _, entry := range certList.Items {
assert.Equal(t, "foo.example.com", entry.ServerName)
assert.Equal(t, "https", entry.CertType)
@ -605,7 +619,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Valid PEM data, new cert, but invalid certificate
@ -619,7 +633,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, false)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Invalid PEM data, existing cert, upsert
@ -633,7 +647,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, true)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
// Valid PEM data, existing cert, but invalid certificate, upsert
@ -647,7 +661,7 @@ func Test_CreateTLSCertificates(t *testing.T) {
},
},
}, true)
assert.NotNil(t, err)
assert.Error(t, err)
assert.Nil(t, certList)
}
@ -663,9 +677,9 @@ func Test_RemoveSSHKnownHosts(t *testing.T) {
HostNamePattern: "github.com",
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Check whether entry was really removed
// Expected: List of 0 entries
@ -673,9 +687,9 @@ func Test_RemoveSSHKnownHosts(t *testing.T) {
HostNamePattern: "github.com",
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
// Remove single SSH known hosts entry by sub type
// Expected: List of 1 entry
@ -683,9 +697,9 @@ func Test_RemoveSSHKnownHosts(t *testing.T) {
CertType: "ssh",
CertSubType: "ssh-ed25519",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Check whether entry was really removed
// Expected: List of 0 entries
@ -693,27 +707,27 @@ func Test_RemoveSSHKnownHosts(t *testing.T) {
CertType: "ssh",
CertSubType: "ssh-ed25519",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
// Remove all remaining SSH known hosts entries
// Expected: List of 5 entry
certList, err = db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 5, len(certList.Items))
assert.Len(t, certList.Items, 5)
// Check whether the entries were really removed
// Expected: List of 0 entries
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
CertType: "ssh",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
}
func Test_RemoveTLSCertificates(t *testing.T) {
@ -727,9 +741,9 @@ func Test_RemoveTLSCertificates(t *testing.T) {
HostNamePattern: "gitlab.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 1, len(certList.Items))
assert.Len(t, certList.Items, 1)
// Check whether entry was really removed
// Expected: List of 0 entries
@ -737,9 +751,9 @@ func Test_RemoveTLSCertificates(t *testing.T) {
HostNamePattern: "gitlab.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
// Remove all TLS certificate entry for hostname
// Expected: List of 2 entry
@ -747,9 +761,9 @@ func Test_RemoveTLSCertificates(t *testing.T) {
HostNamePattern: "test.example.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 2, len(certList.Items))
assert.Len(t, certList.Items, 2)
// Check whether entries were really removed
// Expected: List of 0 entries
@ -757,8 +771,8 @@ func Test_RemoveTLSCertificates(t *testing.T) {
HostNamePattern: "test.example.com",
CertType: "https",
})
assert.Nil(t, err)
assert.NoError(t, err)
assert.NotNil(t, certList)
assert.Equal(t, 0, len(certList.Items))
assert.Len(t, certList.Items, 0)
}

View file

@ -14,6 +14,7 @@ import (
argoexec "github.com/argoproj/pkg/exec"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/knownhosts"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/plumbing"
@ -195,6 +196,13 @@ func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
auth := &ssh2.PublicKeys{User: sshUser, Signer: signer}
if creds.insecure {
auth.HostKeyCallback = ssh.InsecureIgnoreHostKey()
} else {
// Set up validation of SSH known hosts for using our ssh_known_hosts
// file.
auth.HostKeyCallback, err = knownhosts.New(certutil.GetSSHKnownHostsDataPath())
if err != nil {
log.Errorf("Could not set-up SSH known hosts callback: %v", err)
}
}
return auth, nil
case HTTPSCreds:

View file

@ -10,6 +10,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/util"
certutil "github.com/argoproj/argo-cd/util/cert"
)
type Creds interface {
@ -171,6 +172,9 @@ func (c SSHCreds) Environ() (io.Closer, []string, error) {
// StrictHostKeyChecking will add the host to the knownhosts file, we don't want that - a security issue really,
// UserKnownHostsFile=/dev/null is therefore used so we write the new insecure host to /dev/null
args = append(args, "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null")
} else {
knownHostsFile := certutil.GetSSHKnownHostsDataPath()
args = append(args, "-o", "StrictHostKeyChecking=yes", "-o", fmt.Sprintf("UserKnownHostsFile=%s", knownHostsFile))
}
env = append(env, []string{fmt.Sprintf("GIT_SSH_COMMAND=%s", strings.Join(args, " "))}...)
return sshPrivateKeyFile(file.Name()), env, nil

View file

@ -7,7 +7,6 @@ import (
"crypto/x509"
"encoding/base64"
"fmt"
"io/ioutil"
"os"
"strings"
"sync"
@ -28,7 +27,6 @@ import (
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
certutil "github.com/argoproj/argo-cd/util/cert"
"github.com/argoproj/argo-cd/util/password"
tlsutil "github.com/argoproj/argo-cd/util/tls"
)
@ -689,18 +687,6 @@ func (mgr *SettingsManager) SaveSSHKnownHostsData(ctx context.Context, knownHost
return err
}
// If we are running outside a K8S cluster, the ConfigMap mount will not
// automatically write out the SSH known hosts data. We need this mechanism
// for running E2E tests.
if os.Getenv(common.EnvVarFakeInClusterConfig) == "true" {
knownHostsPath := certutil.GetSSHKnownHostsDataPath()
err := ioutil.WriteFile(knownHostsPath, []byte(sshKnownHostsData), 0644)
// We don't return error, but let the user know through log
if err != nil {
log.Errorf("Could not write SSH known hosts data: %v", err)
}
}
return mgr.ResyncInformers()
}
@ -721,42 +707,6 @@ func (mgr *SettingsManager) SaveTLSCertificateData(ctx context.Context, tlsCerti
return err
}
// If we are running outside a K8S cluster, the ConfigMap mount will not
// automatically write out the TLS certificate data. We need this mechanism
// for running E2E tests.
//
// The paradigm here is, that we first remove all files in the TLS data
// directory (there should be only TLS certs in it), and then recreate each
// single cert that is still in the tlsCertificates data map.
if os.Getenv(common.EnvVarFakeInClusterConfig) == "true" {
tlsDataPath := certutil.GetTLSCertificateDataPath()
// First throw way everything
tlsFiles, err := ioutil.ReadDir(tlsDataPath)
if err != nil {
log.Errorf("Could not open TLS certificate dir %s: %v", tlsDataPath, err)
} else {
for _, file := range tlsFiles {
tlsCertPath := fmt.Sprintf("%s/%s", tlsDataPath, file.Name())
log.Debugf("Deleting TLS certificate file %s", tlsCertPath)
err := os.Remove(tlsCertPath)
if err != nil {
log.Errorf("Could not delete TLS cert file %s: %v", tlsCertPath, err)
}
}
}
// Recreate configured TLS certificates
for hostName, certData := range tlsCertificates {
certPath := fmt.Sprintf("%s/%s", tlsDataPath, hostName)
log.Debugf("Writing TLS Certificate data to %s", certPath)
err := ioutil.WriteFile(certPath, []byte(certData), 0644)
if err != nil {
log.Errorf("Could not write PEM data to %s: %v", certPath, err)
}
}
}
return mgr.ResyncInformers()
}