From baa791e797cace58f79d73c05a3419a2042db064 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sun, 25 Feb 2018 18:57:20 -0700 Subject: [PATCH] Move config dir and credential file constants to warp package and export --- cmd/cloudflare-warp/main.go | 8 ++- cmd/cloudflare-warp/service_template.go | 7 +-- tlsconfig/tlsconfig.go | 2 + warp/login.go | 67 ++++++++++++++++--------- warp/server.go | 1 + 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/cmd/cloudflare-warp/main.go b/cmd/cloudflare-warp/main.go index 0fd0a2f4..48a7c065 100644 --- a/cmd/cloudflare-warp/main.go +++ b/cmd/cloudflare-warp/main.go @@ -29,8 +29,6 @@ import ( ) const sentryDSN = "https://56a9c9fa5c364ab28f34b14f35ea0f1b:3e8827f6f9f740738eb11138f7bebb68@sentry.io/189878" -const defaultConfigDir = "~/.cloudflare-warp" -const credentialFile = "cert.pem" const configFile = "config.yml" var listeners = gracenet.Net{} @@ -112,7 +110,7 @@ WARNING: Name: "origincert", Usage: "Path to the certificate generated for your origin when you run cloudflare-warp login.", EnvVars: []string{"TUNNEL_ORIGIN_CERT"}, - Value: filepath.Join(defaultConfigDir, credentialFile), + Value: filepath.Join(warp.DefaultConfigDir, warp.DefaultCredentialFilename), }), altsrc.NewStringFlag(&cli.StringFlag{ Name: "url", @@ -462,7 +460,7 @@ func WaitForSignal(errC chan error, shutdownC chan struct{}) error { } func login(c *cli.Context) error { - err := warp.Login(defaultConfigDir, credentialFile, c.String("url")) + err := warp.Login(warp.DefaultConfigDir, warp.DefaultCredentialFilename, c.String("url")) if err != nil { fmt.Println(err) } @@ -531,7 +529,7 @@ func findInputSourceContext(context *cli.Context) (altsrc.InputSourceContext, er if context.IsSet("config") { return altsrc.NewYamlSourceFromFile(context.String("config")) } - dirPath, err := homedir.Expand(defaultConfigDir) + dirPath, err := homedir.Expand(warp.DefaultConfigDir) if err != nil { return nil, nil } diff --git a/cmd/cloudflare-warp/service_template.go b/cmd/cloudflare-warp/service_template.go index 871b01ff..72e6e2f6 100644 --- a/cmd/cloudflare-warp/service_template.go +++ b/cmd/cloudflare-warp/service_template.go @@ -11,6 +11,7 @@ import ( "path/filepath" "text/template" + "github.com/cloudflare/cloudflare-warp/warp" homedir "github.com/mitchellh/go-homedir" ) @@ -118,7 +119,7 @@ func openFile(path string, create bool) (file *os.File, exists bool, err error) func copyCertificate(configDir string) error { // Copy certificate - destCredentialPath := filepath.Join(configDir, credentialFile) + destCredentialPath := filepath.Join(configDir, warp.DefaultCredentialFilename) destFile, exists, err := openFile(destCredentialPath, true) if err != nil { return err @@ -128,7 +129,7 @@ func copyCertificate(configDir string) error { } defer destFile.Close() - srcCredentialPath := filepath.Join(defaultConfigDir, credentialFile) + srcCredentialPath := filepath.Join(warp.DefaultConfigDir, warp.DefaultCredentialFilename) srcFile, _, err := openFile(srcCredentialPath, false) if err != nil { return err @@ -163,7 +164,7 @@ func copyCredentials(configDir string) error { } defer destFile.Close() - srcConfigPath := filepath.Join(defaultConfigDir, configFile) + srcConfigPath := filepath.Join(warp.DefaultConfigDir, configFile) srcFile, _, err := openFile(srcConfigPath, false) if err != nil { fmt.Println("Your service needs a config file that at least specifies the hostname option.") diff --git a/tlsconfig/tlsconfig.go b/tlsconfig/tlsconfig.go index b48ec8e7..28fda885 100644 --- a/tlsconfig/tlsconfig.go +++ b/tlsconfig/tlsconfig.go @@ -90,6 +90,8 @@ func LoadOriginCertsPool() *x509.CertPool { return certPool } +// CreateTunnelConfig creates a TLS configuration for a tunnel based on tlsConfig. +// If tlsConfig is nil, one will be created. func CreateTunnelConfig(tlsConfig *tls.Config, addrs []string) *tls.Config { if tlsConfig == nil { tlsConfig = new(tls.Config) diff --git a/warp/login.go b/warp/login.go index 82e4a206..afd366fc 100644 --- a/warp/login.go +++ b/warp/login.go @@ -17,35 +17,18 @@ import ( homedir "github.com/mitchellh/go-homedir" ) -const baseLoginURL = "https://www.cloudflare.com/a/warp" -const baseCertStoreURL = "https://login.cloudflarewarp.com" -const clientTimeout = time.Minute * 20 - // Login obtains credentials from Cloudflare to enable // the creation of tunnels with the Warp service. // baseURL is the base URL from which to login to warp; // leave empty to use default. func Login(configDir, credentialFile, baseURL string) error { - configPath, err := homedir.Expand(configDir) - if err != nil { - return err - } - ok, err := fileExists(configPath) - if !ok && err == nil { - // create config directory if doesn't already exist - err = os.Mkdir(configPath, 0700) - } - if err != nil { - return err - } - path := filepath.Join(configPath, credentialFile) - fileInfo, err := os.Stat(path) - if err == nil && fileInfo.Size() > 0 { + credPath := filepath.Join(configDir, credentialFile) + + if ok, err := HasExistingCertificate(configDir, credentialFile); ok && err == nil { return fmt.Errorf(`You have an existing certificate at %s which login would overwrite. If this is intentional, please move or delete that file then run this command again. -`, path) - } - if err != nil && err.(*os.PathError).Err != syscall.ENOENT { +`, credPath) + } else if err != nil && err.(*os.PathError).Err != syscall.ENOENT { return err } @@ -80,11 +63,11 @@ If the browser failed to open, open it yourself and visit the URL above. `, loginURL.String()) } - if ok, err := download(certURL, path); ok && err == nil { + if ok, err := download(certURL, credPath); ok && err == nil { fmt.Fprintf(os.Stderr, `You have successfully logged in. If you wish to copy your credentials to a server, they have been saved to: %s -`, path) +`, credPath) } else { fmt.Fprintf(os.Stderr, `Failed to write the certificate due to the following error: %v @@ -94,11 +77,31 @@ copy it to the following path: %s -`, err, path) +`, err, credPath) } return nil } +// HasExistingCertificate returns true if a certificate in configDir +// exists with name credentialFile. +func HasExistingCertificate(configDir, credentialFile string) (bool, error) { + configPath, err := homedir.Expand(configDir) + if err != nil { + return false, err + } + ok, err := fileExists(configPath) + if !ok && err == nil { + // create config directory if doesn't already exist + err = os.Mkdir(configPath, 0700) + } + if err != nil { + return false, err + } + path := filepath.Join(configPath, credentialFile) + fileInfo, err := os.Stat(path) + return err == nil && fileInfo.Size() > 0, nil +} + // generateRandomPath generates a random URL to associate with the certificate. func generateRandomPath() string { randomBytes := make([]byte, 40) @@ -195,3 +198,17 @@ func putSuccess(client *http.Client, certURL string) error { } return nil } + +const ( + // The default directory in which to store configuration/credentials. + DefaultConfigDir = "~/.cloudflare-warp" + + // The default credential filename. + DefaultCredentialFilename = "cert.pem" +) + +const ( + baseLoginURL = "https://www.cloudflare.com/a/warp" + baseCertStoreURL = "https://login.cloudflarewarp.com" + clientTimeout = 20 * time.Minute +) diff --git a/warp/server.go b/warp/server.go index 8ee60e25..60d42545 100644 --- a/warp/server.go +++ b/warp/server.go @@ -171,6 +171,7 @@ type ServerConfig struct { IsAutoupdated bool // is-autoupdated // The TLS client config used when making the tunnel. + // If not set, a sane default config will be created. TLSConfig *tls.Config // The version of the client to report