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"
)
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()
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{
"tunnel", "run", "--token", token,
}, nil
return []string{"tunnel", "run"},
map[string]string{"TUNNEL_TOKEN": token},
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 {
// currently, we only support extra args for token
return buildArgsForToken(c, log)
} else {
// empty extra args
return make([]string, 0), nil
return make([]string, 0), nil, nil
}
}

View File

@ -43,6 +43,7 @@ const (
serviceConfigFile = "config.yml"
serviceCredentialFile = "cert.pem"
serviceConfigPath = serviceConfigDir + "/" + serviceConfigFile
serviceEnvFile = "/etc/default/cloudflared"
cloudflaredService = "cloudflared.service"
)
@ -56,6 +57,8 @@ After=network.target
[Service]
TimeoutStartSec=0
Type=notify
{{- if ne .EnvFile "" }}
EnvironmentFile=-{{ .EnvFile }}{{ end }}
ExecStart={{ .Path }} --no-autoupdate{{ range .ExtraArgs }} {{ . }}{{ end }}
Restart=on-failure
RestartSec=5s
@ -196,19 +199,23 @@ func installLinuxService(c *cli.Context) error {
Path: etPath,
}
var extraArgsFunc func(c *cli.Context, log *zerolog.Logger) ([]string, error)
var extraArgsFunc buildArgsFunc
if c.NArg() == 0 {
extraArgsFunc = buildArgsForConfig
} else {
extraArgsFunc = buildArgsForToken
}
extraArgs, err := extraArgsFunc(c, log)
extraArgs, extraEnv, err := extraArgsFunc(c, log)
if err != nil {
return err
}
templateArgs.ExtraArgs = extraArgs
templateArgs.Env = extraEnv
if len(extraEnv) > 0 {
templateArgs.EnvFile = serviceEnvFile
}
switch {
case isSystemd():
@ -225,14 +232,14 @@ func installLinuxService(c *cli.Context) error {
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 {
return nil, err
return nil, nil, err
}
src, _, err := config.ReadConfigFile(c, log)
if err != nil {
return nil, err
return nil, nil, err
}
// 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 != ""
}
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
credentials-file: CREDENTIALS-FILE
`, src.Source())
}
if src.Source() != serviceConfigPath {
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 {
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{
"--config", "/etc/cloudflared/config.yml", "tunnel", "run",
}, nil
}, nil, nil
}
func installSystemd(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error {

View File

@ -25,14 +25,48 @@ type ServiceTemplate struct {
type ServiceTemplateArgs struct {
Path 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) {
resolvedPath, err := homedir.Expand(st.Path)
if err != nil {
return "", fmt.Errorf("error resolving path %s: %v", st.Path, err)
return resolvePath(st.Path)
}
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 {
@ -45,7 +79,11 @@ func (st *ServiceTemplate) Generate(args *ServiceTemplateArgs) error {
return err
}
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