diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-07-17 14:45:27 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-07-17 15:10:53 +0200 |
commit | f48dbf9e3938b938a21a9246dc50b3a19c020d18 (patch) | |
tree | 2719249a06c1e93c9bb05389931b4e4b10ef214c /client | |
parent | 96a788f1ec06d341479a603b3819eacfc98316ea (diff) |
Require certificate files specified in environment
Diffstat (limited to 'client')
-rw-r--r-- | client/go/internal/cli/cmd/cert.go | 16 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/config.go | 70 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/config_test.go | 6 |
3 files changed, 58 insertions, 34 deletions
diff --git a/client/go/internal/cli/cmd/cert.go b/client/go/internal/cli/cmd/cert.go index ccfce5eb7bb..f7320e37626 100644 --- a/client/go/internal/cli/cmd/cert.go +++ b/client/go/internal/cli/cmd/cert.go @@ -114,11 +114,11 @@ func doCert(cli *CLI, overwriteCertificate, skipApplicationPackage bool, args [] if !overwriteCertificate { hint := "Use -f flag to force overwriting" - if util.PathExists(privateKeyFile) { - return errHint(fmt.Errorf("private key %s already exists", color.CyanString(privateKeyFile)), hint) + if util.PathExists(privateKeyFile.path) { + return errHint(fmt.Errorf("private key %s already exists", color.CyanString(privateKeyFile.path)), hint) } - if util.PathExists(certificateFile) { - return errHint(fmt.Errorf("certificate %s already exists", color.CyanString(certificateFile)), hint) + if util.PathExists(certificateFile.path) { + return errHint(fmt.Errorf("certificate %s already exists", color.CyanString(certificateFile.path)), hint) } } @@ -126,14 +126,14 @@ func doCert(cli *CLI, overwriteCertificate, skipApplicationPackage bool, args [] if err != nil { return err } - if err := keyPair.WriteCertificateFile(certificateFile, overwriteCertificate); err != nil { + if err := keyPair.WriteCertificateFile(certificateFile.path, overwriteCertificate); err != nil { return fmt.Errorf("could not write certificate: %w", err) } - if err := keyPair.WritePrivateKeyFile(privateKeyFile, overwriteCertificate); err != nil { + if err := keyPair.WritePrivateKeyFile(privateKeyFile.path, overwriteCertificate); err != nil { return fmt.Errorf("could not write private key: %w", err) } - cli.printSuccess("Certificate written to ", color.CyanString(certificateFile)) - cli.printSuccess("Private key written to ", color.CyanString(privateKeyFile)) + cli.printSuccess("Certificate written to ", color.CyanString(certificateFile.path)) + cli.printSuccess("Private key written to ", color.CyanString(privateKeyFile.path)) if !skipApplicationPackage { return doCertAdd(cli, overwriteCertificate, args) } diff --git a/client/go/internal/cli/cmd/config.go b/client/go/internal/cli/cmd/config.go index eb79a2004c4..0a03686dd33 100644 --- a/client/go/internal/cli/cmd/config.go +++ b/client/go/internal/cli/cmd/config.go @@ -384,24 +384,43 @@ func (c *Config) caCertificatePath() string { return c.environment["VESPA_CLI_DATA_PLANE_CA_CERT_FILE"] } -func (c *Config) certificatePath(app vespa.ApplicationID, targetType string) (string, error) { - if override, ok := c.environment["VESPA_CLI_DATA_PLANE_CERT_FILE"]; ok { - return override, nil - } - if targetType == vespa.TargetHosted { - return athenzPath("cert") - } - return c.applicationFilePath(app, "data-plane-public-cert.pem") +type credentialsFile struct { + path string + optional bool } -func (c *Config) privateKeyPath(app vespa.ApplicationID, targetType string) (string, error) { - if override, ok := c.environment["VESPA_CLI_DATA_PLANE_KEY_FILE"]; ok { - return override, nil +func (c *Config) credentialsFile(app vespa.ApplicationID, targetType string, cert bool) (credentialsFile, error) { + envVar := "VESPA_CLI_DATA_PLANE_CERT_FILE" + athenzFile := "cert" + applicationFile := "data-plane-public-cert.pem" + if !cert { + envVar = "VESPA_CLI_DATA_PLANE_KEY_FILE" + athenzFile = "key" + applicationFile = "data-plane-private-key.pem" + } + if override, ok := c.environment[envVar]; ok { + return credentialsFile{override, false}, nil } if targetType == vespa.TargetHosted { - return athenzPath("key") + path, err := athenzPath(athenzFile) + if err != nil { + return credentialsFile{}, err + } + return credentialsFile{path, false}, nil } - return c.applicationFilePath(app, "data-plane-private-key.pem") + path, err := c.applicationFilePath(app, applicationFile) + if err != nil { + return credentialsFile{}, err + } + return credentialsFile{path, true}, nil +} + +func (c *Config) certificatePath(app vespa.ApplicationID, targetType string) (credentialsFile, error) { + return c.credentialsFile(app, targetType, true) +} + +func (c *Config) privateKeyPath(app vespa.ApplicationID, targetType string) (credentialsFile, error) { + return c.credentialsFile(app, targetType, false) } func (c *Config) readTLSOptions(app vespa.ApplicationID, targetType string) (vespa.TLSOptions, error) { @@ -413,16 +432,13 @@ func (c *Config) readTLSOptions(app vespa.ApplicationID, targetType string) (ves // CA certificate if caCertOk { options.CACertificate = []byte(caCertText) - } else { - caCertFile := c.caCertificatePath() - if caCertFile != "" { - b, err := os.ReadFile(caCertFile) - if err != nil { - return options, err - } - options.CACertificate = b - options.CACertificateFile = caCertFile + } else if caCertFile := c.caCertificatePath(); caCertFile != "" { + b, err := os.ReadFile(caCertFile) + if err != nil { + return options, err } + options.CACertificate = b + options.CACertificateFile = caCertFile } // Certificate and private key if certOk && keyOk { @@ -440,15 +456,17 @@ func (c *Config) readTLSOptions(app vespa.ApplicationID, targetType string) (ves if err != nil { return vespa.TLSOptions{}, err } - kp, err := tls.LoadX509KeyPair(certFile, keyFile) + kp, err := tls.LoadX509KeyPair(certFile.path, keyFile.path) + allowMissing := os.IsNotExist(err) && keyFile.optional && certFile.optional if err == nil { options.KeyPair = []tls.Certificate{kp} - options.PrivateKeyFile = keyFile - options.CertificateFile = certFile - } else if err != nil && !os.IsNotExist(err) { + options.PrivateKeyFile = keyFile.path + options.CertificateFile = certFile.path + } else if err != nil && !allowMissing { return vespa.TLSOptions{}, err } } + // If we found a key pair, parse it and check expiry if options.KeyPair != nil { cert, err := x509.ParseCertificate(options.KeyPair[0].Certificate[0]) if err != nil { diff --git a/client/go/internal/cli/cmd/config_test.go b/client/go/internal/cli/cmd/config_test.go index 14a3cf7cbbc..b00be38d021 100644 --- a/client/go/internal/cli/cmd/config_test.go +++ b/client/go/internal/cli/cmd/config_test.go @@ -253,6 +253,12 @@ func TestConfigReadTLSOptions(t *testing.T) { PrivateKeyFile: defaultKeyFile, }, ) + + // Key pair files specified through environment are required + nonExistentFile := filepath.Join(homeDir, "non-existent-file") + cli, _, _ := newTestCLI(t, "VESPA_CLI_DATA_PLANE_CERT_FILE="+nonExistentFile, "VESPA_CLI_DATA_PLANE_KEY_FILE="+nonExistentFile) + _, err := cli.config.readTLSOptions(app, vespa.TargetLocal) + assert.True(t, os.IsNotExist(err)) } func TestConfigTargetResolving(t *testing.T) { |