Add flag to 'tunnel create' subcommand to specify a base64-encoded secret

This commit is contained in:
Jeremy Teale 2021-09-29 18:56:38 -05:00
parent cbdf88ea28
commit 1239006e96
3 changed files with 27 additions and 7 deletions

View File

@ -181,7 +181,8 @@ func Init(ver string, gracefulShutdown chan struct{}) {
func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath string) error { func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath string) error {
tunnel, ok, err := sc.tunnelActive(name) tunnel, ok, err := sc.tunnelActive(name)
if err != nil || !ok { if err != nil || !ok {
tunnel, err = sc.create(name, credentialsOutputPath) // pass empty string as secret to generate one
tunnel, err = sc.create(name, credentialsOutputPath, "")
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create tunnel") return errors.Wrap(err, "failed to create tunnel")
} }

View File

@ -1,6 +1,7 @@
package tunnel package tunnel
import ( import (
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
@ -148,15 +149,27 @@ func (sc *subcommandContext) readTunnelCredentials(credFinder CredFinder) (conne
return credentials, nil return credentials, nil
} }
func (sc *subcommandContext) create(name string, credentialsFilePath string) (*tunnelstore.Tunnel, error) { func (sc *subcommandContext) create(name string, credentialsFilePath string, secret string) (*tunnelstore.Tunnel, error) {
client, err := sc.client() client, err := sc.client()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "couldn't create client to talk to Cloudflare Tunnel backend") return nil, errors.Wrap(err, "couldn't create client to talk to Cloudflare Tunnel backend")
} }
tunnelSecret, err := generateTunnelSecret() var tunnelSecret []byte
if err != nil { if secret == "" {
return nil, errors.Wrap(err, "couldn't generate the secret for your new tunnel") tunnelSecret, err = generateTunnelSecret()
if err != nil {
return nil, errors.Wrap(err, "couldn't generate the secret for your new tunnel")
}
} else {
decodedSecret, err := base64.StdEncoding.DecodeString(secret)
if err != nil {
return nil, errors.Wrap(err, "Couldn't decode tunnel secret from base64")
}
tunnelSecret = []byte(decodedSecret)
if len(tunnelSecret) < 32 {
return nil, errors.New("Decoded tunnel secret must be at least 32 bytes long")
}
} }
tunnel, err := client.CreateTunnel(name, tunnelSecret) tunnel, err := client.CreateTunnel(name, tunnelSecret)

View File

@ -156,6 +156,12 @@ var (
Usage: `Overwrites existing DNS records with this hostname`, Usage: `Overwrites existing DNS records with this hostname`,
EnvVars: []string{"TUNNEL_FORCE_PROVISIONING_DNS"}, EnvVars: []string{"TUNNEL_FORCE_PROVISIONING_DNS"},
} }
createSecretFlag = &cli.StringFlag{
Name: "secret",
Aliases: []string{"s"},
Usage: "Base64 encoded secret to set for the tunnel. The decoded secret must be at least 32 bytes long. If not specified, a random 32-byte secret will be generated.",
EnvVars: []string{"TUNNEL_CREATE_SECRET"},
}
) )
func buildCreateCommand() *cli.Command { func buildCreateCommand() *cli.Command {
@ -170,7 +176,7 @@ func buildCreateCommand() *cli.Command {
For example, to create a tunnel named 'my-tunnel' run: For example, to create a tunnel named 'my-tunnel' run:
$ cloudflared tunnel create my-tunnel`, $ cloudflared tunnel create my-tunnel`,
Flags: []cli.Flag{outputFormatFlag, credentialsFileFlagCLIOnly}, Flags: []cli.Flag{outputFormatFlag, credentialsFileFlagCLIOnly, createSecretFlag},
CustomHelpTemplate: commandHelpTemplate(), CustomHelpTemplate: commandHelpTemplate(),
} }
} }
@ -196,7 +202,7 @@ func createCommand(c *cli.Context) error {
warningChecker := updater.StartWarningCheck(c) warningChecker := updater.StartWarningCheck(c)
defer warningChecker.LogWarningIfAny(sc.log) defer warningChecker.LogWarningIfAny(sc.log)
_, err = sc.create(name, c.String(CredFileFlag)) _, err = sc.create(name, c.String(CredFileFlag), c.String(createSecretFlag.Name))
return errors.Wrap(err, "failed to create tunnel") return errors.Wrap(err, "failed to create tunnel")
} }