TUN-1012: Normalize config filename for Linux services

This commit is contained in:
Nick Vollmar 2018-10-03 15:05:30 -05:00
parent 2f5ac3b556
commit f7b1f7cb22
6 changed files with 47 additions and 39 deletions

View File

@ -10,13 +10,16 @@ import (
) )
var ( var (
defaultConfigFiles = []string{"config.yml", "config.yaml"} // File names from which we attempt to read configuration.
DefaultConfigFiles = []string{"config.yml", "config.yaml"}
// Launchd doesn't set root env variables, so there is default // Launchd doesn't set root env variables, so there is default
// Windows default config dir was ~/cloudflare-warp in documentation; let's keep it compatible // Windows default config dir was ~/cloudflare-warp in documentation; let's keep it compatible
DefaultConfigDirs = []string{"~/.cloudflared", "~/.cloudflare-warp", "~/cloudflare-warp", "/usr/local/etc/cloudflared", "/etc/cloudflared"} DefaultConfigDirs = []string{"~/.cloudflared", "~/.cloudflare-warp", "~/cloudflare-warp", "/usr/local/etc/cloudflared", "/etc/cloudflared"}
) )
const DefaultCredentialFile = "cert.pem"
// FileExists checks to see if a file exist at the provided path. // FileExists checks to see if a file exist at the provided path.
func FileExists(path string) (bool, error) { func FileExists(path string) (bool, error) {
f, err := os.Open(path) f, err := os.Open(path)
@ -40,11 +43,11 @@ func FindInputSourceContext(context *cli.Context) (altsrc.InputSourceContext, er
} }
// FindDefaultConfigPath returns the first path that contains a config file. // FindDefaultConfigPath returns the first path that contains a config file.
// If none of the combination of defaultConfigDirs (differs by OS for legacy reasons) // If none of the combination of DefaultConfigDirs and DefaultConfigFiles
// and defaultConfigFiles contains a config file, return empty string. // contains a config file, return empty string.
func FindDefaultConfigPath() string { func FindDefaultConfigPath() string {
for _, configDir := range DefaultConfigDirs { for _, configDir := range DefaultConfigDirs {
for _, configFile := range defaultConfigFiles { for _, configFile := range DefaultConfigFiles {
dirPath, err := homedir.Expand(configDir) dirPath, err := homedir.Expand(configDir)
if err != nil { if err != nil {
continue continue

View File

@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
cli "gopkg.in/urfave/cli.v2" cli "gopkg.in/urfave/cli.v2"
) )
@ -30,12 +31,14 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
app.Run(os.Args) app.Run(os.Args)
} }
// The directory and files that are used by the service.
// These are hard-coded in the templates below.
const ( const (
serviceConfigDir = "/etc/cloudflared" serviceConfigDir = "/etc/cloudflared"
defaultCredentialFile = "cert.pem" serviceConfigFile = "config.yml"
serviceCredentialFile = "cert.pem"
) )
var defaultConfigFiles = []string{"config.yml", "config.yaml"}
var systemdTemplates = []ServiceTemplate{ var systemdTemplates = []ServiceTemplate{
{ {
Path: "/etc/systemd/system/cloudflared.service", Path: "/etc/systemd/system/cloudflared.service",
@ -178,6 +181,23 @@ func isSystemd() bool {
return false return false
} }
func copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile string) error {
if err := ensureConfigDirExists(serviceConfigDir); err != nil {
return err
}
srcCredentialPath := filepath.Join(userConfigDir, userCredentialFile)
destCredentialPath := filepath.Join(serviceConfigDir, serviceCredentialFile)
if err := copyCredential(srcCredentialPath, destCredentialPath); err != nil {
return err
}
srcConfigPath := filepath.Join(userConfigDir, userConfigFile)
destConfigPath := filepath.Join(serviceConfigDir, serviceConfigFile)
if err := copyConfig(srcConfigPath, destConfigPath); err != nil {
return err
}
return nil
}
func installLinuxService(c *cli.Context) error { func installLinuxService(c *cli.Context) error {
etPath, err := os.Executable() etPath, err := os.Executable()
if err != nil { if err != nil {
@ -185,11 +205,12 @@ func installLinuxService(c *cli.Context) error {
} }
templateArgs := ServiceTemplateArgs{Path: etPath} templateArgs := ServiceTemplateArgs{Path: etPath}
defaultConfigDir := filepath.Dir(c.String("config")) userConfigDir := filepath.Dir(c.String("config"))
defaultConfigFile := filepath.Base(c.String("config")) userConfigFile := filepath.Base(c.String("config"))
if err = copyCredentials(serviceConfigDir, defaultConfigDir, defaultConfigFile, defaultCredentialFile); err != nil { userCredentialFile := config.DefaultCredentialFile
if err = copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile); err != nil {
logger.WithError(err).Infof("Failed to copy user configuration. Before running the service, ensure that %s contains two files, %s and %s", logger.WithError(err).Infof("Failed to copy user configuration. Before running the service, ensure that %s contains two files, %s and %s",
serviceConfigDir, defaultCredentialFile, defaultConfigFiles[0]) serviceConfigDir, serviceCredentialFile, serviceConfigFile)
return err return err
} }

View File

@ -8,7 +8,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"text/template" "text/template"
"github.com/cloudflare/cloudflared/cmd/cloudflared/config" "github.com/cloudflare/cloudflared/cmd/cloudflared/config"
@ -120,8 +119,7 @@ func openFile(path string, create bool) (file *os.File, exists bool, err error)
return file, false, err return file, false, err
} }
func copyCertificate(srcConfigDir, destConfigDir, credentialFile string) error { func copyCredential(srcCredentialPath, destCredentialPath string) error {
destCredentialPath := filepath.Join(destConfigDir, credentialFile)
destFile, exists, err := openFile(destCredentialPath, true) destFile, exists, err := openFile(destCredentialPath, true)
if err != nil { if err != nil {
return err return err
@ -131,7 +129,6 @@ func copyCertificate(srcConfigDir, destConfigDir, credentialFile string) error {
} }
defer destFile.Close() defer destFile.Close()
srcCredentialPath := filepath.Join(srcConfigDir, credentialFile)
srcFile, _, err := openFile(srcCredentialPath, false) srcFile, _, err := openFile(srcCredentialPath, false)
if err != nil { if err != nil {
return err return err
@ -147,17 +144,8 @@ func copyCertificate(srcConfigDir, destConfigDir, credentialFile string) error {
return nil return nil
} }
func copyCredentials(serviceConfigDir, defaultConfigDir, defaultConfigFile, defaultCredentialFile string) error { func copyConfig(srcConfigPath, destConfigPath string) error {
if err := ensureConfigDirExists(serviceConfigDir); err != nil {
return err
}
if err := copyCertificate(defaultConfigDir, serviceConfigDir, defaultCredentialFile); err != nil {
return err
}
// Copy or create config // Copy or create config
destConfigPath := filepath.Join(serviceConfigDir, defaultConfigFile)
destFile, exists, err := openFile(destConfigPath, true) destFile, exists, err := openFile(destConfigPath, true)
if err != nil { if err != nil {
logger.WithError(err).Infof("cannot open %s", destConfigPath) logger.WithError(err).Infof("cannot open %s", destConfigPath)
@ -168,7 +156,6 @@ func copyCredentials(serviceConfigDir, defaultConfigDir, defaultConfigFile, defa
} }
defer destFile.Close() defer destFile.Close()
srcConfigPath := filepath.Join(defaultConfigDir, defaultConfigFile)
srcFile, _, err := openFile(srcConfigPath, false) srcFile, _, err := openFile(srcConfigPath, false)
if err != nil { if err != nil {
fmt.Println("Your service needs a config file that at least specifies the hostname option.") fmt.Println("Your service needs a config file that at least specifies the hostname option.")

View File

@ -123,7 +123,7 @@ func Commands() []*cli.Command {
}, },
Before: func(c *cli.Context) error { Before: func(c *cli.Context) error {
if c.String("config") == "" { if c.String("config") == "" {
logger.Warnf("Cannot determine default configuration path. No file %v in %v", defaultConfigFiles, config.DefaultConfigDirs) logger.Warnf("Cannot determine default configuration path. No file %v in %v", config.DefaultConfigFiles, config.DefaultConfigDirs)
} }
inputSource, err := config.FindInputSourceContext(c) inputSource, err := config.FindInputSourceContext(c)
if err != nil { if err != nil {
@ -211,7 +211,7 @@ func StartServer(c *cli.Context, version string, shutdownC, graceShutdownC chan
dnsReadySignal := make(chan struct{}) dnsReadySignal := make(chan struct{})
if c.String("config") == "" { if c.String("config") == "" {
logger.Warnf("Cannot determine default configuration path. No file %v in %v", defaultConfigFiles, config.DefaultConfigDirs) logger.Warnf("Cannot determine default configuration path. No file %v in %v", config.DefaultConfigFiles, config.DefaultConfigDirs)
} }
if err := configMainLogger(c); err != nil { if err := configMainLogger(c); err != nil {

View File

@ -30,20 +30,17 @@ import (
) )
var ( var (
defaultConfigFiles = []string{"config.yml", "config.yaml"} developerPortal = "https://developers.cloudflare.com/argo-tunnel"
developerPortal = "https://developers.cloudflare.com/argo-tunnel" quickStartUrl = developerPortal + "/quickstart/quickstart/"
quickStartUrl = developerPortal + "/quickstart/quickstart/" serviceUrl = developerPortal + "/reference/service/"
serviceUrl = developerPortal + "/reference/service/" argumentsUrl = developerPortal + "/reference/arguments/"
argumentsUrl = developerPortal + "/reference/arguments/"
) )
const defaultCredentialFile = "cert.pem" // returns the first path that contains a cert.pem file. If none of the DefaultConfigDirs
// contains a cert.pem file, return empty string
// returns the first path that contains a cert.pem file. If none of the defaultConfigDirs
// (differs by OS for legacy reasons) contains a cert.pem file, return empty string
func findDefaultOriginCertPath() string { func findDefaultOriginCertPath() string {
for _, defaultConfigDir := range config.DefaultConfigDirs { for _, defaultConfigDir := range config.DefaultConfigDirs {
originCertPath, _ := homedir.Expand(filepath.Join(defaultConfigDir, defaultCredentialFile)) originCertPath, _ := homedir.Expand(filepath.Join(defaultConfigDir, config.DefaultCredentialFile))
if ok, _ := config.FileExists(originCertPath); ok { if ok, _ := config.FileExists(originCertPath); ok {
return originCertPath return originCertPath
} }
@ -111,7 +108,7 @@ func dnsProxyStandAlone(c *cli.Context) bool {
func getOriginCert(c *cli.Context) ([]byte, error) { func getOriginCert(c *cli.Context) ([]byte, error) {
if c.String("origincert") == "" { if c.String("origincert") == "" {
logger.Warnf("Cannot determine default origin certificate path. No file %s in %v", defaultCredentialFile, config.DefaultConfigDirs) logger.Warnf("Cannot determine default origin certificate path. No file %s in %v", config.DefaultCredentialFile, config.DefaultConfigDirs)
if isRunningFromTerminal() { if isRunningFromTerminal() {
logger.Errorf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl) logger.Errorf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl)
return nil, fmt.Errorf("Client didn't specify origincert path when running from terminal") return nil, fmt.Errorf("Client didn't specify origincert path when running from terminal")

View File

@ -56,7 +56,7 @@ func checkForExistingCert() (string, bool, error) {
if err != nil { if err != nil {
return "", false, err return "", false, err
} }
path := filepath.Join(configPath, defaultCredentialFile) path := filepath.Join(configPath, config.DefaultCredentialFile)
fileInfo, err := os.Stat(path) fileInfo, err := os.Stat(path)
if err == nil && fileInfo.Size() > 0 { if err == nil && fileInfo.Size() > 0 {
return path, true, nil return path, true, nil