aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2024-06-12 11:26:23 +0200
committerMartin Polden <mpolden@mpolden.no>2024-06-12 11:26:23 +0200
commit17f9406eb10982c8201ace9de673c0d53af98ed0 (patch)
treef5239da97b2bdc4708b792173a06907c46759741
parent15cb97dd996b2e1addd999f5db967e9008339047 (diff)
Refactor reading of credentials
-rw-r--r--client/go/internal/cli/cmd/config.go85
-rw-r--r--client/go/internal/cli/cmd/config_test.go17
-rw-r--r--client/go/internal/cli/cmd/feed.go2
-rw-r--r--client/go/internal/vespa/target.go11
4 files changed, 76 insertions, 39 deletions
diff --git a/client/go/internal/cli/cmd/config.go b/client/go/internal/cli/cmd/config.go
index 77ca2cf8c12..032abfd598a 100644
--- a/client/go/internal/cli/cmd/config.go
+++ b/client/go/internal/cli/cmd/config.go
@@ -429,51 +429,76 @@ func (c *Config) privateKeyPath(app vespa.ApplicationID, targetType string) (cre
return c.credentialsFile(app, targetType, false)
}
-func (c *Config) readTLSOptions(app vespa.ApplicationID, targetType string) (vespa.TLSOptions, error) {
- _, trustAll := c.environment["VESPA_CLI_DATA_PLANE_TRUST_ALL"]
- cert, certOk := c.environment["VESPA_CLI_DATA_PLANE_CERT"]
- key, keyOk := c.environment["VESPA_CLI_DATA_PLANE_KEY"]
- caCertText, caCertOk := c.environment["VESPA_CLI_DATA_PLANE_CA_CERT"]
- options := vespa.TLSOptions{TrustAll: trustAll}
- // CA certificate
+func (c *Config) caCertificatePEM() ([]byte, string, error) {
+ envVar := "VESPA_CLI_DATA_PLANE_CA_CERT"
+ caCertText, caCertOk := c.environment[envVar]
if caCertOk {
- options.CACertificate = []byte(caCertText)
- } else if caCertFile := c.caCertificatePath(); caCertFile != "" {
+ return []byte(caCertText), envVar, nil
+ }
+ if caCertFile := c.caCertificatePath(); caCertFile != "" {
b, err := os.ReadFile(caCertFile)
if err != nil {
- return options, err
+ return nil, "", err
+ }
+ return b, caCertFile, nil
+ }
+ return nil, "", nil
+}
+
+func (c *Config) credentialsPEM(envVar string, credentialsFile credentialsFile) ([]byte, string, error) {
+ if pem, ok := c.environment[envVar]; ok {
+ return []byte(pem), envVar, nil
+ }
+ pem, err := os.ReadFile(credentialsFile.path)
+ if err != nil {
+ if os.IsNotExist(err) && credentialsFile.optional {
+ return nil, "", nil
}
- options.CACertificate = b
- options.CACertificateFile = caCertFile
+ return nil, "", err
}
- // Certificate and private key
- if certOk && keyOk {
- kp, err := tls.X509KeyPair([]byte(cert), []byte(key))
+ return []byte(pem), credentialsFile.path, nil
+}
+
+func (c *Config) readTLSOptions(app vespa.ApplicationID, targetType string) (vespa.TLSOptions, error) {
+ var options vespa.TLSOptions
+ // Certificate
+ if certPath, err := c.certificatePath(app, targetType); err == nil {
+ certPEM, certFile, err := c.credentialsPEM("VESPA_CLI_DATA_PLANE_CERT", certPath)
if err != nil {
return vespa.TLSOptions{}, err
}
- options.KeyPair = []tls.Certificate{kp}
+ options.CertificatePEM = certPEM
+ options.CertificateFile = certFile
} else {
- keyFile, err := c.privateKeyPath(app, targetType)
+ return vespa.TLSOptions{}, err
+ }
+ // Private key
+ if keyPath, err := c.privateKeyPath(app, targetType); err == nil {
+ keyPEM, keyFile, err := c.credentialsPEM("VESPA_CLI_DATA_PLANE_KEY", keyPath)
if err != nil {
return vespa.TLSOptions{}, err
}
- certFile, err := c.certificatePath(app, targetType)
+ options.PrivateKeyPEM = keyPEM
+ options.PrivateKeyFile = keyFile
+ } else {
+ return vespa.TLSOptions{}, err
+
+ }
+ // CA certificate
+ _, options.TrustAll = c.environment["VESPA_CLI_DATA_PLANE_TRUST_ALL"]
+ caCertificate, caCertificateFile, err := c.caCertificatePEM()
+ if err != nil {
+ return vespa.TLSOptions{}, err
+ }
+ options.CACertificatePEM = caCertificate
+ options.CACertificateFile = caCertificateFile
+ // Key pair
+ if len(options.CertificatePEM) > 0 && len(options.PrivateKeyPEM) > 0 {
+ kp, err := tls.X509KeyPair(options.CertificatePEM, options.PrivateKeyPEM)
if err != nil {
return vespa.TLSOptions{}, err
}
- 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.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 {
+ options.KeyPair = []tls.Certificate{kp}
cert, err := x509.ParseCertificate(options.KeyPair[0].Certificate[0])
if err != nil {
return vespa.TLSOptions{}, err
diff --git a/client/go/internal/cli/cmd/config_test.go b/client/go/internal/cli/cmd/config_test.go
index a70766ff931..6c9321b3219 100644
--- a/client/go/internal/cli/cmd/config_test.go
+++ b/client/go/internal/cli/cmd/config_test.go
@@ -209,9 +209,14 @@ func TestConfigReadTLSOptions(t *testing.T) {
assertTLSOptions(t, homeDir, app,
vespa.TargetLocal,
vespa.TLSOptions{
- TrustAll: true,
- CACertificate: []byte("cacert"),
- KeyPair: []tls.Certificate{keyPair},
+ TrustAll: true,
+ KeyPair: []tls.Certificate{keyPair},
+ CACertificatePEM: []byte("cacert"),
+ CertificatePEM: pemCert,
+ PrivateKeyPEM: pemKey,
+ CACertificateFile: "VESPA_CLI_DATA_PLANE_CA_CERT",
+ CertificateFile: "VESPA_CLI_DATA_PLANE_CERT",
+ PrivateKeyFile: "VESPA_CLI_DATA_PLANE_KEY",
},
"VESPA_CLI_DATA_PLANE_TRUST_ALL=true",
"VESPA_CLI_DATA_PLANE_CA_CERT=cacert",
@@ -230,7 +235,9 @@ func TestConfigReadTLSOptions(t *testing.T) {
vespa.TargetLocal,
vespa.TLSOptions{
KeyPair: []tls.Certificate{keyPair},
- CACertificate: []byte("cacert"),
+ CACertificatePEM: []byte("cacert"),
+ CertificatePEM: pemCert,
+ PrivateKeyPEM: pemKey,
CACertificateFile: caCertFile,
CertificateFile: certFile,
PrivateKeyFile: keyFile,
@@ -249,6 +256,8 @@ func TestConfigReadTLSOptions(t *testing.T) {
vespa.TargetLocal,
vespa.TLSOptions{
KeyPair: []tls.Certificate{keyPair},
+ CertificatePEM: pemCert,
+ PrivateKeyPEM: pemKey,
CertificateFile: defaultCertFile,
PrivateKeyFile: defaultKeyFile,
},
diff --git a/client/go/internal/cli/cmd/feed.go b/client/go/internal/cli/cmd/feed.go
index f69de6b3038..e696333a3f1 100644
--- a/client/go/internal/cli/cmd/feed.go
+++ b/client/go/internal/cli/cmd/feed.go
@@ -143,7 +143,7 @@ func createServices(n int, timeout time.Duration, cli *CLI, waiter *Waiter) ([]h
// Create a separate HTTP client for each service
client := cli.httpClientFactory(timeout)
// Feeding should always use HTTP/2
- httputil.ForceHTTP2(client, service.TLSOptions.KeyPair, service.TLSOptions.CACertificate, service.TLSOptions.TrustAll)
+ httputil.ForceHTTP2(client, service.TLSOptions.KeyPair, service.TLSOptions.CACertificatePEM, service.TLSOptions.TrustAll)
service.SetClient(client)
services = append(services, service)
}
diff --git a/client/go/internal/vespa/target.go b/client/go/internal/vespa/target.go
index 960917b75d6..5270b5669f9 100644
--- a/client/go/internal/vespa/target.go
+++ b/client/go/internal/vespa/target.go
@@ -126,9 +126,12 @@ type Target interface {
// TLSOptions holds the client certificate to use for cloud API or service requests.
type TLSOptions struct {
- CACertificate []byte
- KeyPair []tls.Certificate
- TrustAll bool
+ KeyPair []tls.Certificate
+ TrustAll bool
+
+ CACertificatePEM []byte
+ CertificatePEM []byte
+ PrivateKeyPEM []byte
CACertificateFile string
CertificateFile string
@@ -149,7 +152,7 @@ type LogOptions struct {
func (s *Service) Do(request *http.Request, timeout time.Duration) (*http.Response, error) {
if !s.customClient {
// Do not override TLS config if a custom client has been configured
- httputil.ConfigureTLS(s.httpClient, s.TLSOptions.KeyPair, s.TLSOptions.CACertificate, s.TLSOptions.TrustAll)
+ httputil.ConfigureTLS(s.httpClient, s.TLSOptions.KeyPair, s.TLSOptions.CACertificatePEM, s.TLSOptions.TrustAll)
}
if s.auth != nil {
if err := s.auth.Authenticate(request); err != nil {