From 3a8151bcc0411db1c50ef8c8d21deb08d68a904a Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Mon, 8 Jun 2020 20:05:25 +0200 Subject: [PATCH] Add various custom flags --- cmd/tk/create_source_git.go | 24 ++++----- cmd/tk/flags.go | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 cmd/tk/flags.go diff --git a/cmd/tk/create_source_git.go b/cmd/tk/create_source_git.go index 929f39f3..8121a19f 100644 --- a/cmd/tk/create_source_git.go +++ b/cmd/tk/create_source_git.go @@ -2,12 +2,10 @@ package main import ( "context" - "crypto/elliptic" "fmt" "io/ioutil" "net/url" "os" - "strings" sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1" "github.com/manifoldco/promptui" @@ -65,8 +63,9 @@ var ( sourceGitSemver string sourceGitUsername string sourceGitPassword string - sourceGitKeyAlgorithm string - sourceGitRSABits int + sourceGitKeyAlgorithm PublicKeyAlgorithm + sourceGitRSABits RSAKeyBits + sourceGitECDSACurve ECDSACurve ) func init() { @@ -76,8 +75,9 @@ func init() { createSourceGitCmd.Flags().StringVar(&sourceGitSemver, "tag-semver", "", "git tag semver range") createSourceGitCmd.Flags().StringVarP(&sourceGitUsername, "username", "u", "", "basic authentication username") createSourceGitCmd.Flags().StringVarP(&sourceGitPassword, "password", "p", "", "basic authentication password") - createSourceGitCmd.Flags().StringVarP(&sourceGitKeyAlgorithm, "ssh-algorithm", "", "rsa", "SSH public key algorithm") - createSourceGitCmd.Flags().IntVarP(&sourceGitRSABits, "ssh-rsa-bits", "", 2048, "SSH RSA public key bit size") + createSourceGitCmd.Flags().Var(&sourceGitKeyAlgorithm, "ssh-algorithm", "SSH public key algorithm") + createSourceGitCmd.Flags().Var(&sourceGitRSABits, "ssh-rsa-bits", "SSH RSA public key bit size") + createSourceGitCmd.Flags().Var(&sourceGitECDSACurve, "ssh-ecdsa-curve", "SSH ECDSA public key curve") createSourceCmd.AddCommand(createSourceGitCmd) } @@ -109,12 +109,11 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { withAuth := false if u.Scheme == "ssh" { var keyGen ssh.KeyPairGenerator - switch strings.ToLower(sourceGitKeyAlgorithm) { + switch sourceGitKeyAlgorithm.String() { case "rsa": - keyGen = ssh.NewRSAGenerator(sourceGitRSABits) + keyGen = ssh.NewRSAGenerator(int(sourceGitRSABits)) case "ecdsa": - // TODO(hidde): make curve configurable by flag - keyGen = ssh.NewECDSAGenerator(elliptic.P521()) + keyGen = ssh.NewECDSAGenerator(sourceGitECDSACurve.Curve) } host := u.Host if u.Port() == "" { @@ -230,15 +229,16 @@ func generateSSH(ctx context.Context, generator ssh.KeyPairGenerator, name, host } logAction("collecting SSH server public key for generated public key algorithm") - serverKey, err := ssh.ScanHostKey(host, user, kp) + hostKey, err := ssh.ScanHostKey(host, user, kp) if err != 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\"", - kp.PublicKey, kp.PrivateKey, serverKey) + kp.PublicKey, kp.PrivateKey, 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 { diff --git a/cmd/tk/flags.go b/cmd/tk/flags.go new file mode 100644 index 00000000..f91e729c --- /dev/null +++ b/cmd/tk/flags.go @@ -0,0 +1,101 @@ +package main + +import ( + "crypto/elliptic" + "fmt" + "strconv" + "strings" +) + +var supportedPublicKeyAlgorithms = []string{"rsa", "ecdsa"} + +type PublicKeyAlgorithm string + +func (a *PublicKeyAlgorithm) String() string { + return string(*a) +} + +func (a *PublicKeyAlgorithm) Set(str string) error { + if strings.TrimSpace(str) == "" { + *a = PublicKeyAlgorithm(supportedPublicKeyAlgorithms[0]) + return nil + } + for _, v := range supportedPublicKeyAlgorithms { + if str == v { + *a = PublicKeyAlgorithm(str) + return nil + } + } + return fmt.Errorf( + "unsupported public key algorithm '%s', must be one of: %s", + str, + strings.Join(supportedPublicKeyAlgorithms, ", "), + ) +} + +func (a *PublicKeyAlgorithm) Type() string { + return "publicKeyAlgorithm" +} + +var defaultRSAKeyBits = 2048 + +type RSAKeyBits int + +func (b *RSAKeyBits) String() string { + return strconv.Itoa(int(*b)) +} + +func (b *RSAKeyBits) Set(str string) error { + if strings.TrimSpace(str) == "" { + *b = RSAKeyBits(defaultRSAKeyBits) + return nil + } + bits, err := strconv.Atoi(str) + if err != nil { + return err + } + if bits%8 != 0 { + return fmt.Errorf("RSA key bit size should be a multiples of 8") + } + *b = RSAKeyBits(bits) + return nil +} + +func (b *RSAKeyBits) Type() string { + return "rsaKeyBits" +} + +type ECDSACurve struct { + elliptic.Curve +} + +var supportedECDSACurves = map[string]elliptic.Curve{ + "P-256": elliptic.P256(), + "P-384": elliptic.P384(), + "P-521": elliptic.P521(), +} + +func (c *ECDSACurve) String() string { + if c == nil || c.Curve == nil { + return "" + } + return c.Curve.Params().Name +} + +func (c *ECDSACurve) Set(str string) error { + if strings.TrimSpace(str) == "" { + *c = ECDSACurve{supportedECDSACurves["P-384"]} + return nil + } + for k, v := range supportedECDSACurves { + if k == str { + *c = ECDSACurve{v} + return nil + } + } + return fmt.Errorf("unsupported curve '%s', should be one of: P-256, P-384, P-521", str) +} + +func (c *ECDSACurve) Type() string { + return "ecdsaCurve" +}