From 240fb94f82b8a59e70135deee6bc870e8ced2673 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Wed, 25 Aug 2021 14:41:24 +0200 Subject: Implement vespa cert --- client/go/cmd/cert.go | 70 ++++++++++++++++++++++++++++++++++++++++++ client/go/cmd/config.go | 6 ++-- client/go/util/print.go | 8 +++++ client/go/vespa/crypto_test.go | 2 +- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 client/go/cmd/cert.go (limited to 'client') diff --git a/client/go/cmd/cert.go b/client/go/cmd/cert.go new file mode 100644 index 00000000000..8b75ad2a509 --- /dev/null +++ b/client/go/cmd/cert.go @@ -0,0 +1,70 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa cert command +// Author: mpolden +package cmd + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "github.com/vespa-engine/vespa/util" + "github.com/vespa-engine/vespa/vespa" +) + +var overwriteCertificate bool + +func init() { + certCmd.Flags().BoolVarP(&overwriteCertificate, "force", "f", false, "Force overwrite of existing certificate and private key") + rootCmd.AddCommand(certCmd) +} + +var certCmd = &cobra.Command{ + Use: "cert", + Short: "Creates a new private key and self-signed certificate", + Long: `Applications in Vespa Cloud are required to secure their data plane with mutual TLS. ` + + `This command creates a self-signed certificate suitable for development purposes. ` + + `See https://cloud.vespa.ai/en/security-model for more information on the Vespa Cloud security model.`, + Run: func(cmd *cobra.Command, args []string) { + var path string + if len(args) > 0 { + path = args[0] + } else { + var err error + path, err = os.Getwd() + util.FatalIfErr(err) + } + + pkg, err := vespa.FindApplicationPackage(path) + util.FatalIfErr(err) + if pkg.HasCertificate() { + util.Print("Certificate already exists") + return + } + + // TODO: Consider writing key pair inside ~/.vespa// instead so that vespa document commands can easily + // locate key pair + securityDir := filepath.Join(pkg.Path, "security") + privateKeyFile := filepath.Join(path, "data-plane-private-key.pem") + certificateFile := filepath.Join(path, "data-plane-public-cert.pem") + pkgCertificateFile := filepath.Join(securityDir, "clients.pem") + + keyPair, err := vespa.CreateKeyPair() + util.FatalIfErr(err) + + err = os.MkdirAll(securityDir, 0755) + util.FatalIfErr(err) + err = keyPair.WriteCertificateFile(pkgCertificateFile, overwriteCertificate) + util.FatalIfErr(err) + err = keyPair.WriteCertificateFile(certificateFile, overwriteCertificate) + util.FatalIfErr(err) + err = keyPair.WritePrivateKeyFile(privateKeyFile, overwriteCertificate) + util.FatalIfErr(err) + + // TODO: Just use log package, which has Printf + util.Print(fmt.Sprintf("Certificate written to %s", pkgCertificateFile)) + util.Print(fmt.Sprintf("Certificate written to %s", certificateFile)) + util.Print(fmt.Sprintf("Private key written to %s", privateKeyFile)) + }, +} diff --git a/client/go/cmd/config.go b/client/go/cmd/config.go index 6d25f33d07c..9435a97d999 100644 --- a/client/go/cmd/config.go +++ b/client/go/cmd/config.go @@ -5,11 +5,12 @@ package cmd import ( + "os" + "path/filepath" + "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/vespa-engine/vespa/util" - "os" - "path/filepath" ) func init() { @@ -25,6 +26,7 @@ var configCmd = &cobra.Command{ } func readConfig() { + // TODO: Make ~/.vespa a directory so that we can put other files there as well home, err := os.UserHomeDir() configName := ".vespa" configType := "yaml" diff --git a/client/go/util/print.go b/client/go/util/print.go index 6f6e40be07f..ed3a3a1d18a 100644 --- a/client/go/util/print.go +++ b/client/go/util/print.go @@ -29,6 +29,14 @@ func Error(messages ...string) { print("\033[31m", messages) } +// FatalIfError prints error and exists if given err is non-nill. +func FatalIfErr(err error) { + if err != nil { + Error(err.Error()) + os.Exit(1) + } +} + // Prints in a color appropriate for success messages func Success(messages ...string) { print("\033[32m", messages) diff --git a/client/go/vespa/crypto_test.go b/client/go/vespa/crypto_test.go index 5ac8464e4b0..6a6d1d6a10a 100644 --- a/client/go/vespa/crypto_test.go +++ b/client/go/vespa/crypto_test.go @@ -1,8 +1,8 @@ package vespa import ( - "testing" "github.com/stretchr/testify/assert" + "testing" ) func TestCreateKeyPair(t *testing.T) { -- cgit v1.2.3