From 9099ad3d8ba3a15c1d254f16e5f3439e859e7165 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 9 Jun 2020 12:25:33 +0200 Subject: [PATCH] Split cmd SSH/auth functions --- cmd/tk/create_source_git.go | 145 +++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 53 deletions(-) diff --git a/cmd/tk/create_source_git.go b/cmd/tk/create_source_git.go index f017cac2..9f112af9 100644 --- a/cmd/tk/create_source_git.go +++ b/cmd/tk/create_source_git.go @@ -116,18 +116,70 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() + kubeClient, err := utils.kubeClient(kubeconfig) + if err != nil { + return err + } + withAuth := false + // TODO(hidde): move all auth prep to separate func? if u.Scheme == "ssh" { + logAction("generating deploy key pair") + pair, err := generateKeyPair(ctx) + if err != nil { + return err + } + + fmt.Printf("%s", pair.PublicKey) + prompt := promptui.Prompt{ + Label: "Have you added the deploy key to your repository", + IsConfirm: true, + } + if _, err := prompt.Run(); err != nil { + return fmt.Errorf("aborting") + } + + logAction("collecting preferred public key from SSH server") host := u.Host if u.Port() == "" { host = host + ":22" } - if err := generateSSH(ctx, name, host); err != nil { + hostKey, err := scanHostKey(ctx, host) + if err != nil { + return err + } + logSuccess("collected public key from SSH server:") + fmt.Printf("%s", hostKey) + + logAction("applying secret with keys") + secret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + StringData: map[string]string{ + "identity": string(pair.PrivateKey), + "identity.pub": string(pair.PublicKey), + "known_hosts": string(hostKey), + }, + } + if err := upsertSecret(ctx, kubeClient, secret); err != nil { return err } withAuth = true } else if sourceGitUsername != "" && sourceGitPassword != "" { - if err := generateBasicAuth(ctx, name); err != nil { + logAction("applying secret with basic auth credentials") + secret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + StringData: map[string]string{ + "username": sourceGitUsername, + "password": sourceGitPassword, + }, + } + if err := upsertSecret(ctx, kubeClient, secret); err != nil { return err } withAuth = true @@ -167,11 +219,6 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { gitRepository.Spec.Reference.Branch = sourceGitBranch } - kubeClient, err := utils.kubeClient(kubeconfig) - if err != nil { - return err - } - logAction("applying source") if err := upsertGitRepository(ctx, kubeClient, gitRepository); err != nil { return err @@ -203,50 +250,55 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { return nil } -func generateBasicAuth(ctx context.Context, name string) error { - logAction("saving credentials") - credentials := fmt.Sprintf("--from-literal=username='%s' --from-literal=password='%s'", - sourceGitUsername, sourceGitPassword) - secret := fmt.Sprintf("kubectl -n %s create secret generic %s %s --dry-run=client -oyaml | kubectl apply -f-", - namespace, name, credentials) - if _, err := utils.execCommand(ctx, ModeOS, secret); err != nil { - return fmt.Errorf("kubectl create secret failed") +func generateKeyPair(ctx context.Context) (*ssh.KeyPair, error) { + var keyGen ssh.KeyPairGenerator + switch sourceGitKeyAlgorithm.String() { + case "rsa": + keyGen = ssh.NewRSAGenerator(int(sourceGitRSABits)) + case "ecdsa": + keyGen = ssh.NewECDSAGenerator(sourceGitECDSACurve.Curve) + case "ed25519": + keyGen = ssh.NewEd25519Generator() + default: + return nil, fmt.Errorf("unsupported public key algorithm '%s'", sourceGitKeyAlgorithm.String()) } - return nil + pair, err := keyGen.Generate() + if err != nil { + return nil, fmt.Errorf("key pair generation failed: %w", err) + } + return pair, nil } -func generateSSH(ctx context.Context, name, host string) error { - gen := getKeyPairGenerator() - logGenerate("generating deploy key pair") - pair, err := gen.Generate() +func scanHostKey(ctx context.Context, host string) ([]byte, error) { + hostKey, err := ssh.ScanHostKey(host, 30*time.Second) if err != nil { - return fmt.Errorf("key pair generation failed: %w", err) + return nil, fmt.Errorf("SSH key scan for host '%s' failed: %w", host, err) } - fmt.Printf("%s", pair.PublicKey) + return hostKey, nil +} - prompt := promptui.Prompt{ - Label: "Have you added the deploy key to your repository", - IsConfirm: true, - } - if _, err := prompt.Run(); err != nil { - return fmt.Errorf("aborting") +func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.Secret) error { + namespacedName := types.NamespacedName{ + Namespace: secret.GetNamespace(), + Name: secret.GetName(), } - logAction("collecting preferred public key from SSH server") - hostKey, err := ssh.ScanHostKey(host, 30*time.Second) + var existing corev1.Secret + err := kubeClient.Get(ctx, namespacedName, &existing) if err != nil { + if errors.IsNotFound(err) { + if err := kubeClient.Create(ctx, &existing); err != nil { + return err + } else { + return nil + } + } return err } - logSuccess("collected public key from SSH server:") - fmt.Printf("%s", hostKey) - - logAction("saving keys") - files := fmt.Sprintf("--from-literal=identity=\"%s\" --from-literal=identity.pub=\"%s\" --from-literal=known_hosts=\"%s\"", - pair.PrivateKey, pair.PublicKey, hostKey) - secret := fmt.Sprintf("kubectl -n %s create secret generic %s %s --dry-run=client -oyaml | kubectl apply -f-", - namespace, name, files) - if _, err := utils.execCommand(ctx, ModeOS, secret); err != nil { - return fmt.Errorf("failed to create secret") + + existing.StringData = secret.StringData + if err := kubeClient.Update(ctx, &existing); err != nil { + return err } return nil } @@ -305,16 +357,3 @@ func isGitRepositoryReady(ctx context.Context, kubeClient client.Client, name, n return false, nil } } - -func getKeyPairGenerator() ssh.KeyPairGenerator { - var keyGen ssh.KeyPairGenerator - switch sourceGitKeyAlgorithm.String() { - case "rsa": - keyGen = ssh.NewRSAGenerator(int(sourceGitRSABits)) - case "ecdsa": - keyGen = ssh.NewECDSAGenerator(sourceGitECDSACurve.Curve) - case "ed25519": - keyGen = ssh.NewEd25519Generator() - } - return keyGen -}