TUN-3451: Cloudflared tunnel ingress command
This commit is contained in:
parent
407c9550d7
commit
86a7af3dc4
|
@ -182,8 +182,7 @@ func Commands() []*cli.Command {
|
||||||
subcommands = append(subcommands, buildRunCommand())
|
subcommands = append(subcommands, buildRunCommand())
|
||||||
subcommands = append(subcommands, buildCleanupCommand())
|
subcommands = append(subcommands, buildCleanupCommand())
|
||||||
subcommands = append(subcommands, buildRouteCommand())
|
subcommands = append(subcommands, buildRouteCommand())
|
||||||
subcommands = append(subcommands, buildValidateCommand())
|
subcommands = append(subcommands, buildIngressSubcommand())
|
||||||
subcommands = append(subcommands, buildRuleCommand())
|
|
||||||
|
|
||||||
cmds = append(cmds, buildTunnelCommand(subcommands))
|
cmds = append(cmds, buildTunnelCommand(subcommands))
|
||||||
|
|
||||||
|
@ -221,6 +220,38 @@ func buildTunnelCommand(subcommands []*cli.Command) *cli.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildIngressSubcommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "ingress",
|
||||||
|
Category: "Tunnel",
|
||||||
|
Usage: "Validate and test cloudflared tunnel's ingress configuration",
|
||||||
|
Hidden: true,
|
||||||
|
Description: `
|
||||||
|
Cloudflared lets you route traffic from the internet to multiple different addresses on your
|
||||||
|
origin. Multiple-origin routing is configured by a set of rules. Each rule matches traffic
|
||||||
|
by its hostname or path, and routes it to an address. These rules are configured under the
|
||||||
|
'ingress' key of your config.yaml, for example:
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
- hostname: www.example.com
|
||||||
|
service: https://localhost:8000
|
||||||
|
- hostname: *.example.xyz
|
||||||
|
path: /[a-zA-Z]+.html
|
||||||
|
service: https://localhost:8001
|
||||||
|
- hostname: *
|
||||||
|
service: https://localhost:8002
|
||||||
|
|
||||||
|
To ensure cloudflared can route all incoming requests, the last rule must be a catch-all
|
||||||
|
rule that matches all traffic. You can validate these rules with the 'ingress validate'
|
||||||
|
command, and test which rule matches a particular URL with 'ingress rule <URL>'.
|
||||||
|
|
||||||
|
Multiple-origin routing is incompatible with the --url flag.
|
||||||
|
`,
|
||||||
|
Subcommands: []*cli.Command{buildValidateCommand(), buildRuleCommand()},
|
||||||
|
Flags: tunnelFlags(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TunnelCommand(c *cli.Context) error {
|
func TunnelCommand(c *cli.Context) error {
|
||||||
if name := c.String("name"); name != "" { // Start a named tunnel
|
if name := c.String("name"); name != "" { // Start a named tunnel
|
||||||
return adhocNamedTunnel(c, name)
|
return adhocNamedTunnel(c, name)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||||
"github.com/cloudflare/cloudflared/logger"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
@ -91,6 +90,9 @@ func (ing ingress) validate() ([]rule, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if service.Scheme == "" || service.Hostname() == "" {
|
||||||
|
return nil, fmt.Errorf("The service %s must have a scheme and a hostname", r.Service)
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that there are no wildcards anywhere except the first character
|
// Ensure that there are no wildcards anywhere except the first character
|
||||||
// of the hostname.
|
// of the hostname.
|
||||||
|
@ -148,32 +150,28 @@ func parseIngress(rawYAML []byte) ([]rule, error) {
|
||||||
return ing.validate()
|
return ing.validate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ingressContext(c *cli.Context) ([]rule, *logger.OutputWriter, error) {
|
func ingressContext(c *cli.Context) ([]rule, error) {
|
||||||
log, err := createLogger(c, false, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
configFilePath := c.String("config")
|
configFilePath := c.String("config")
|
||||||
if configFilePath == "" {
|
if configFilePath == "" {
|
||||||
return nil, nil, config.ErrNoConfigFile
|
return nil, config.ErrNoConfigFile
|
||||||
}
|
}
|
||||||
log.Infof("Validating %s", configFilePath)
|
fmt.Printf("Reading from config file %s\n", configFilePath)
|
||||||
configBytes, err := ioutil.ReadFile(configFilePath)
|
configBytes, err := ioutil.ReadFile(configFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rules, err := parseIngress(configBytes)
|
rules, err := parseIngress(configBytes)
|
||||||
return rules, log, err
|
return rules, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates the ingress rules in the cloudflared config file
|
// Validates the ingress rules in the cloudflared config file
|
||||||
func validateCommand(c *cli.Context) error {
|
func validateCommand(c *cli.Context) error {
|
||||||
_, log, err := ingressContext(c)
|
_, err := ingressContext(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err.Error())
|
fmt.Println(err.Error())
|
||||||
return errors.New("Validation failed")
|
return errors.New("Validation failed")
|
||||||
}
|
}
|
||||||
log.Infof("OK")
|
fmt.Println("OK")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +187,7 @@ func buildValidateCommand() *cli.Command {
|
||||||
|
|
||||||
// Checks which ingress rule matches the given URL.
|
// Checks which ingress rule matches the given URL.
|
||||||
func ruleCommand(c *cli.Context) error {
|
func ruleCommand(c *cli.Context) error {
|
||||||
rules, log, err := ingressContext(c)
|
rules, err := ingressContext(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -206,7 +204,7 @@ func ruleCommand(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
for i, r := range rules {
|
for i, r := range rules {
|
||||||
if r.matches(requestURL) {
|
if r.matches(requestURL) {
|
||||||
log.Infof("Matched rule #%d", i+1)
|
fmt.Printf("Matched rule #%d\n", i+1)
|
||||||
fmt.Println(r.String())
|
fmt.Println(r.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,14 @@ ingress:
|
||||||
service: https://localhost:8000
|
service: https://localhost:8000
|
||||||
path: "*/subpath2"
|
path: "*/subpath2"
|
||||||
- service: https://localhost:8001
|
- service: https://localhost:8001
|
||||||
|
`},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service must have a scheme",
|
||||||
|
args: args{rawYAML: `
|
||||||
|
ingress:
|
||||||
|
- service: localhost:8000
|
||||||
`},
|
`},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue