Write tunnel token to EnvironmentFile, resolve #802

This commit is contained in:
iBug 2023-07-18 01:02:22 +08:00
parent 9b8a533435
commit faa43cde1c
3 changed files with 68 additions and 21 deletions

View File

@ -8,23 +8,25 @@ import (
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel" "github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
) )
func buildArgsForToken(c *cli.Context, log *zerolog.Logger) ([]string, error) { type buildArgsFunc = func(c *cli.Context, log *zerolog.Logger) ([]string, map[string]string, error)
func buildArgsForToken(c *cli.Context, log *zerolog.Logger) ([]string, map[string]string, error) {
token := c.Args().First() token := c.Args().First()
if _, err := tunnel.ParseToken(token); err != nil { if _, err := tunnel.ParseToken(token); err != nil {
return nil, cliutil.UsageError("Provided tunnel token is not valid (%s).", err) return nil, nil, cliutil.UsageError("Provided tunnel token is not valid (%s).", err)
} }
return []string{ return []string{"tunnel", "run"},
"tunnel", "run", "--token", token, map[string]string{"TUNNEL_TOKEN": token},
}, nil nil
} }
func getServiceExtraArgsFromCliArgs(c *cli.Context, log *zerolog.Logger) ([]string, error) { func getServiceExtraArgsFromCliArgs(c *cli.Context, log *zerolog.Logger) ([]string, map[string]string, error) {
if c.NArg() > 0 { if c.NArg() > 0 {
// currently, we only support extra args for token // currently, we only support extra args for token
return buildArgsForToken(c, log) return buildArgsForToken(c, log)
} else { } else {
// empty extra args // empty extra args
return make([]string, 0), nil return make([]string, 0), nil, nil
} }
} }

View File

@ -43,6 +43,7 @@ const (
serviceConfigFile = "config.yml" serviceConfigFile = "config.yml"
serviceCredentialFile = "cert.pem" serviceCredentialFile = "cert.pem"
serviceConfigPath = serviceConfigDir + "/" + serviceConfigFile serviceConfigPath = serviceConfigDir + "/" + serviceConfigFile
serviceEnvFile = "/etc/default/cloudflared"
cloudflaredService = "cloudflared.service" cloudflaredService = "cloudflared.service"
) )
@ -56,6 +57,8 @@ After=network.target
[Service] [Service]
TimeoutStartSec=0 TimeoutStartSec=0
Type=notify Type=notify
{{- if ne .EnvFile "" }}
EnvironmentFile=-{{ .EnvFile }}{{ end }}
ExecStart={{ .Path }} --no-autoupdate{{ range .ExtraArgs }} {{ . }}{{ end }} ExecStart={{ .Path }} --no-autoupdate{{ range .ExtraArgs }} {{ . }}{{ end }}
Restart=on-failure Restart=on-failure
RestartSec=5s RestartSec=5s
@ -196,19 +199,23 @@ func installLinuxService(c *cli.Context) error {
Path: etPath, Path: etPath,
} }
var extraArgsFunc func(c *cli.Context, log *zerolog.Logger) ([]string, error) var extraArgsFunc buildArgsFunc
if c.NArg() == 0 { if c.NArg() == 0 {
extraArgsFunc = buildArgsForConfig extraArgsFunc = buildArgsForConfig
} else { } else {
extraArgsFunc = buildArgsForToken extraArgsFunc = buildArgsForToken
} }
extraArgs, err := extraArgsFunc(c, log) extraArgs, extraEnv, err := extraArgsFunc(c, log)
if err != nil { if err != nil {
return err return err
} }
templateArgs.ExtraArgs = extraArgs templateArgs.ExtraArgs = extraArgs
templateArgs.Env = extraEnv
if len(extraEnv) > 0 {
templateArgs.EnvFile = serviceEnvFile
}
switch { switch {
case isSystemd(): case isSystemd():
@ -225,14 +232,14 @@ func installLinuxService(c *cli.Context) error {
return err return err
} }
func buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, error) { func buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, map[string]string, error) {
if err := ensureConfigDirExists(serviceConfigDir); err != nil { if err := ensureConfigDirExists(serviceConfigDir); err != nil {
return nil, err return nil, nil, err
} }
src, _, err := config.ReadConfigFile(c, log) src, _, err := config.ReadConfigFile(c, log)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
// can't use context because this command doesn't define "credentials-file" flag // can't use context because this command doesn't define "credentials-file" flag
@ -241,24 +248,24 @@ func buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, error) {
return err == nil && val != "" return err == nil && val != ""
} }
if src.TunnelID == "" || !configPresent(tunnel.CredFileFlag) { if src.TunnelID == "" || !configPresent(tunnel.CredFileFlag) {
return nil, fmt.Errorf(`Configuration file %s must contain entries for the tunnel to run and its associated credentials: return nil, nil, fmt.Errorf(`Configuration file %s must contain entries for the tunnel to run and its associated credentials:
tunnel: TUNNEL-UUID tunnel: TUNNEL-UUID
credentials-file: CREDENTIALS-FILE credentials-file: CREDENTIALS-FILE
`, src.Source()) `, src.Source())
} }
if src.Source() != serviceConfigPath { if src.Source() != serviceConfigPath {
if exists, err := config.FileExists(serviceConfigPath); err != nil || exists { if exists, err := config.FileExists(serviceConfigPath); err != nil || exists {
return nil, fmt.Errorf("Possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`", src.Source(), serviceConfigPath) return nil, nil, fmt.Errorf("Possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`", src.Source(), serviceConfigPath)
} }
if err := copyFile(src.Source(), serviceConfigPath); err != nil { if err := copyFile(src.Source(), serviceConfigPath); err != nil {
return nil, fmt.Errorf("failed to copy %s to %s: %w", src.Source(), serviceConfigPath, err) return nil, nil, fmt.Errorf("failed to copy %s to %s: %w", src.Source(), serviceConfigPath, err)
} }
} }
return []string{ return []string{
"--config", "/etc/cloudflared/config.yml", "tunnel", "run", "--config", "/etc/cloudflared/config.yml", "tunnel", "run",
}, nil }, nil, nil
} }
func installSystemd(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error { func installSystemd(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error {

View File

@ -25,14 +25,48 @@ type ServiceTemplate struct {
type ServiceTemplateArgs struct { type ServiceTemplateArgs struct {
Path string Path string
ExtraArgs []string ExtraArgs []string
EnvFile string
Env map[string]string
}
func resolvePath(s string) (string, error) {
resolvedPath, err := homedir.Expand(s)
if err != nil {
return "", fmt.Errorf("error resolving path %s: %v", s, err)
}
return resolvedPath, nil
} }
func (st *ServiceTemplate) ResolvePath() (string, error) { func (st *ServiceTemplate) ResolvePath() (string, error) {
resolvedPath, err := homedir.Expand(st.Path) return resolvePath(st.Path)
if err != nil { }
return "", fmt.Errorf("error resolving path %s: %v", st.Path, err)
func (st *ServiceTemplate) GenerateEnvFile(args *ServiceTemplateArgs) error {
if args.EnvFile == "" {
return nil
} }
return resolvedPath, nil filePath, err := resolvePath(args.EnvFile)
if err != nil {
return err
}
if _, err = os.Stat(filePath); err == nil {
return fmt.Errorf("%s", serviceAlreadyExistsWarn(filePath))
}
fileMode := os.FileMode(0o640)
if st.FileMode != 0 {
fileMode &= st.FileMode
}
buf := new(bytes.Buffer)
for k, v := range args.Env {
if _, err = fmt.Fprintf(buf, "%s=%s\n", k, v); err != nil {
return fmt.Errorf("error writing internal buffer: %v", err)
}
}
if err = os.WriteFile(filePath, buf.Bytes(), fileMode); err != nil {
_ = os.Remove(filePath)
return fmt.Errorf("error writing %s: %v", filePath, err)
}
return nil
} }
func (st *ServiceTemplate) Generate(args *ServiceTemplateArgs) error { func (st *ServiceTemplate) Generate(args *ServiceTemplateArgs) error {
@ -45,7 +79,11 @@ func (st *ServiceTemplate) Generate(args *ServiceTemplateArgs) error {
return err return err
} }
if _, err = os.Stat(resolvedPath); err == nil { if _, err = os.Stat(resolvedPath); err == nil {
return fmt.Errorf(serviceAlreadyExistsWarn(resolvedPath)) return fmt.Errorf("%s", serviceAlreadyExistsWarn(resolvedPath))
}
if err = st.GenerateEnvFile(args); err != nil {
return err
} }
var buffer bytes.Buffer var buffer bytes.Buffer