Skip to content

Commit

Permalink
add support for defining a custom list of ssh key exchange algorithms.
Browse files Browse the repository at this point in the history
Fixes argoproj#17634

Signed-off-by: Enno Boland <g@s01.de>
  • Loading branch information
Gottox committed Apr 30, 2024
1 parent a63068d commit 0bc4f28
Show file tree
Hide file tree
Showing 13 changed files with 759 additions and 688 deletions.
4 changes: 4 additions & 0 deletions assets/swagger.json
Expand Up @@ -8150,6 +8150,10 @@
"type": "string",
"title": "Repo contains the URL to the remote repository"
},
"sshKexAlgorithms": {
"description": "KexAlgorithms specifies the key exchange algorithms to use for SSH connections. Whitespace seperated list.",
"type": "string"
},
"sshPrivateKey": {
"description": "SSHPrivateKey contains the PEM data for authenticating at the repo server. Only used with Git repos.",
"type": "string"
Expand Down
2 changes: 2 additions & 0 deletions cmd/util/repo.go
Expand Up @@ -24,6 +24,7 @@ type RepoOptions struct {
Proxy string
GCPServiceAccountKeyPath string
ForceHttpBasicAuth bool
SshKexAlgorithms string
}

func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
Expand All @@ -46,4 +47,5 @@ func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
command.Flags().StringVar(&opts.Proxy, "proxy", "", "use proxy to access repository")
command.Flags().StringVar(&opts.GCPServiceAccountKeyPath, "gcp-service-account-key-path", "", "service account key for the Google Cloud Platform")
command.Flags().BoolVar(&opts.ForceHttpBasicAuth, "force-http-basic-auth", false, "whether to force use of basic auth when connecting repository via HTTP")
command.Flags().StringVar(&opts.SshKexAlgorithms, "ssh-kex-algorithms", "", "space-separated list of key exchange algorithms to use for SSH connections")
}
Expand Up @@ -54,6 +54,7 @@ argocd admin repo generate-spec REPOURL [flags]
--password string password to the repository
--project string project of the repository
--proxy string use proxy to access repository
--ssh-kex-algorithms string space-separated list of key exchange algorithms to use for SSH connections
--ssh-private-key-path string path to the private ssh key (e.g. ~/.ssh/id_rsa)
--tls-client-cert-key-path string path to the TLS client cert's key path (must be PEM format)
--tls-client-cert-path string path to the TLS client cert (must be PEM format)
Expand Down
1 change: 1 addition & 0 deletions docs/user-guide/commands/argocd_repo_add.md
Expand Up @@ -67,6 +67,7 @@ argocd repo add REPOURL [flags]
--password string password to the repository
--project string project of the repository
--proxy string use proxy to access repository
--ssh-kex-algorithms string space-separated list of key exchange algorithms to use for SSH connections
--ssh-private-key-path string path to the private ssh key (e.g. ~/.ssh/id_rsa)
--tls-client-cert-key-path string path to the TLS client cert's key path (must be PEM format)
--tls-client-cert-path string path to the TLS client cert (must be PEM format)
Expand Down
1,405 changes: 724 additions & 681 deletions pkg/apis/application/v1alpha1/generated.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions pkg/apis/application/v1alpha1/generated.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/apis/application/v1alpha1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion pkg/apis/application/v1alpha1/repository_types.go
Expand Up @@ -93,6 +93,8 @@ type Repository struct {
GCPServiceAccountKey string `json:"gcpServiceAccountKey,omitempty" protobuf:"bytes,21,opt,name=gcpServiceAccountKey"`
// ForceHttpBasicAuth specifies whether Argo CD should attempt to force basic auth for HTTP connections
ForceHttpBasicAuth bool `json:"forceHttpBasicAuth,omitempty" protobuf:"bytes,22,opt,name=forceHttpBasicAuth"`
// KexAlgorithms specifies the key exchange algorithms to use for SSH connections. Whitespace seperated list.
SSHKexAlgorithms string `json:"sshKexAlgorithms,omitempty" protobuf:"bytes,23,opt,name=sshKexAlgorithms"`
}

// IsInsecure returns true if the repository has been configured to skip server verification
Expand Down Expand Up @@ -196,7 +198,7 @@ func (repo *Repository) GetGitCreds(store git.CredsStore) git.Creds {
return git.NewHTTPSCreds(repo.Username, repo.Password, repo.TLSClientCertData, repo.TLSClientCertKey, repo.IsInsecure(), repo.Proxy, store, repo.ForceHttpBasicAuth)
}
if repo.SSHPrivateKey != "" {
return git.NewSSHCreds(repo.SSHPrivateKey, getCAPath(repo.Repo), repo.IsInsecure(), store, repo.Proxy)
return git.NewSSHCreds(repo.SSHPrivateKey, getCAPath(repo.Repo), repo.IsInsecure(), store, repo.Proxy, repo.SSHKexAlgorithms)
}
if repo.GithubAppPrivateKey != "" && repo.GithubAppId != 0 && repo.GithubAppInstallationId != 0 {
return git.NewGitHubAppCreds(repo.GithubAppId, repo.GithubAppInstallationId, repo.GithubAppPrivateKey, repo.GitHubAppEnterpriseBaseURL, repo.Repo, repo.TLSClientCertData, repo.TLSClientCertKey, repo.IsInsecure(), repo.Proxy, store)
Expand Down
7 changes: 6 additions & 1 deletion ui/src/app/settings/components/repos-list/repos-list.tsx
Expand Up @@ -17,6 +17,7 @@ interface NewSSHRepoParams {
name: string;
url: string;
sshPrivateKey: string;
sshKexAlgorithms: string;
insecure: boolean;
enableLfs: boolean;
proxy: string;
Expand Down Expand Up @@ -67,6 +68,7 @@ interface NewGoogleCloudSourceRepoParams {
interface NewSSHRepoCredsParams {
url: string;
sshPrivateKey: string;
sshKexAlgorithms: string;
}

interface NewHTTPSRepoCredsParams {
Expand Down Expand Up @@ -435,6 +437,9 @@ export class ReposList extends React.Component<
<div className='argo-form-row'>
<FormField formApi={formApi} label='SSH private key data' field='sshPrivateKey' component={TextArea} />
</div>
<div className='argo-form-row'>
<FormField formApi={formApi} label='SSH key exchange algorithms (white space seperated list)' field='sshKexAlgorithms' component={TextArea} />
</div>
<div className='argo-form-row'>
<FormField formApi={formApi} label='Skip server verification' field='insecure' component={CheckboxField} />
<HelpIcon title='This setting is ignored when creating as credential template.' />
Expand Down Expand Up @@ -674,7 +679,7 @@ export class ReposList extends React.Component<
// Connect a new repository or create a repository credentials for SSH repositories
private async connectSSHRepo(params: NewSSHRepoParams) {
if (this.credsTemplate) {
this.createSSHCreds({url: params.url, sshPrivateKey: params.sshPrivateKey});
this.createSSHCreds({url: params.url, sshPrivateKey: params.sshPrivateKey, sshKexAlgorithms: params.sshKexAlgorithms});
} else {
this.setState({connecting: true});
try {
Expand Down
1 change: 1 addition & 0 deletions util/db/repository_secrets.go
Expand Up @@ -314,6 +314,7 @@ func secretToRepository(secret *corev1.Secret) (*appsv1.Repository, error) {
Proxy: string(secret.Data["proxy"]),
Project: string(secret.Data["project"]),
GCPServiceAccountKey: string(secret.Data["gcpServiceAccountKey"]),
SSHKexAlgorithms: string(secret.Data["sshKexAlgorithms"]),
}

insecureIgnoreHostKey, err := boolOrFalse(secret, "insecureIgnoreHostKey")
Expand Down
1 change: 1 addition & 0 deletions util/git/client.go
Expand Up @@ -267,6 +267,7 @@ func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
auth := &PublicKeysWithOptions{}
auth.User = sshUser
auth.Signer = signer
auth.KexAlgorithms = strings.Fields(creds.kexAlgorithms)
if creds.insecure {
auth.HostKeyCallback = ssh.InsecureIgnoreHostKey()
} else {
Expand Down
5 changes: 3 additions & 2 deletions util/git/creds.go
Expand Up @@ -243,10 +243,11 @@ type SSHCreds struct {
insecure bool
store CredsStore
proxy string
kexAlgorithms string
}

func NewSSHCreds(sshPrivateKey string, caPath string, insecureIgnoreHostKey bool, store CredsStore, proxy string) SSHCreds {
return SSHCreds{sshPrivateKey, caPath, insecureIgnoreHostKey, store, proxy}
func NewSSHCreds(sshPrivateKey string, caPath string, insecureIgnoreHostKey bool, store CredsStore, proxy string, kexAlgorithms string) SSHCreds {
return SSHCreds{sshPrivateKey, caPath, insecureIgnoreHostKey, store, proxy, kexAlgorithms}
}

type sshPrivateKeyFile string
Expand Down
6 changes: 3 additions & 3 deletions util/git/creds_test.go
Expand Up @@ -206,7 +206,7 @@ func Test_SSHCreds_Environ(t *testing.T) {
caFile := path.Join(tempDir, "caFile")
err := os.WriteFile(caFile, []byte(""), os.FileMode(0600))
require.NoError(t, err)
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "")
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "", "")
closer, env, err := creds.Environ()
require.NoError(t, err)
require.Len(t, env, 2)
Expand Down Expand Up @@ -239,7 +239,7 @@ func Test_SSHCreds_Environ_WithProxy(t *testing.T) {
caFile := path.Join(tempDir, "caFile")
err := os.WriteFile(caFile, []byte(""), os.FileMode(0600))
require.NoError(t, err)
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "socks5://127.0.0.1:1080")
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "socks5://127.0.0.1:1080", "")
closer, env, err := creds.Environ()
require.NoError(t, err)
require.Len(t, env, 2)
Expand Down Expand Up @@ -273,7 +273,7 @@ func Test_SSHCreds_Environ_WithProxyUserNamePassword(t *testing.T) {
caFile := path.Join(tempDir, "caFile")
err := os.WriteFile(caFile, []byte(""), os.FileMode(0600))
require.NoError(t, err)
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "socks5://user:password@127.0.0.1:1080")
creds := NewSSHCreds("sshPrivateKey", caFile, insecureIgnoreHostKey, &NoopCredsStore{}, "socks5://user:password@127.0.0.1:1080", "")
closer, env, err := creds.Environ()
require.NoError(t, err)
require.Len(t, env, 4)
Expand Down

0 comments on commit 0bc4f28

Please sign in to comment.