cloudflare/cloudflared

Public

mirrored fromhttps://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2020.6.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

dbconnect/cmd.go

165lines · modecode

1package dbconnect
2
3import (
4 "context"
5 "log"
6 "net"
7 "strconv"
8
9 "gopkg.in/urfave/cli.v2"
10 "gopkg.in/urfave/cli.v2/altsrc"
11)
12
13// Cmd is the entrypoint command for dbconnect.
14//
15// The tunnel package is responsible for appending this to tunnel.Commands().
16func Cmd() *cli.Command {
17 return &cli.Command{
18 Category: "Database Connect (ALPHA) - Deprecated",
19 Name: "db-connect",
20 Usage: "deprecated: Access your SQL database from Cloudflare Workers or the browser",
21 ArgsUsage: " ",
22 Description: `
23 This feature has been deprecated.
24 Please see:
25
26 cloudflared access tcp --help
27
28 for setting up database connections to the cloudflare edge.
29
30
31 Creates a connection between your database and the Cloudflare edge.
32 Now you can execute SQL commands anywhere you can send HTTPS requests.
33
34 Connect your database with any of the following commands, you can also try the "playground" without a database:
35
36 cloudflared db-connect --hostname sql.mysite.com --url postgres://user:pass@localhost?sslmode=disable \
37 --auth-domain mysite.cloudflareaccess.com --application-aud my-access-policy-tag
38 cloudflared db-connect --hostname sql-dev.mysite.com --url mysql://localhost --insecure
39 cloudflared db-connect --playground
40
41 Requests should be authenticated using Cloudflare Access, learn more about how to enable it here:
42
43 https://developers.cloudflare.com/access/service-auth/service-token/
44 `,
45 Flags: []cli.Flag{
46 altsrc.NewStringFlag(&cli.StringFlag{
47 Name: "url",
48 Usage: "URL to the database (eg. postgres://user:pass@localhost?sslmode=disable)",
49 EnvVars: []string{"TUNNEL_URL"},
50 }),
51 altsrc.NewStringFlag(&cli.StringFlag{
52 Name: "hostname",
53 Usage: "Hostname to accept commands over HTTPS (eg. sql.mysite.com)",
54 EnvVars: []string{"TUNNEL_HOSTNAME"},
55 }),
56 altsrc.NewStringFlag(&cli.StringFlag{
57 Name: "auth-domain",
58 Usage: "Cloudflare Access authentication domain for your account (eg. mysite.cloudflareaccess.com)",
59 EnvVars: []string{"TUNNEL_ACCESS_AUTH_DOMAIN"},
60 }),
61 altsrc.NewStringFlag(&cli.StringFlag{
62 Name: "application-aud",
63 Usage: "Cloudflare Access application \"AUD\" to verify JWTs from requests",
64 EnvVars: []string{"TUNNEL_ACCESS_APPLICATION_AUD"},
65 }),
66 altsrc.NewBoolFlag(&cli.BoolFlag{
67 Name: "insecure",
68 Usage: "Disable authentication, the database will be open to the Internet",
69 Value: false,
70 EnvVars: []string{"TUNNEL_ACCESS_INSECURE"},
71 }),
72 altsrc.NewBoolFlag(&cli.BoolFlag{
73 Name: "playground",
74 Usage: "Run a temporary, in-memory SQLite3 database for testing",
75 Value: false,
76 EnvVars: []string{"TUNNEL_HELLO_WORLD"},
77 }),
78 altsrc.NewStringFlag(&cli.StringFlag{
79 Name: "loglevel",
80 Value: "debug", // Make it more verbose than the tunnel default 'info'.
81 EnvVars: []string{"TUNNEL_LOGLEVEL"},
82 Hidden: true,
83 }),
84 },
85 Before: CmdBefore,
86 Action: CmdAction,
87 Hidden: true,
88 }
89}
90
91// CmdBefore runs some validation checks before running the command.
92func CmdBefore(c *cli.Context) error {
93 // Show the help text is no flags are specified.
94 if c.NumFlags() == 0 {
95 return cli.ShowSubcommandHelp(c)
96 }
97
98 // Hello-world and playground are synonymous with each other,
99 // unset hello-world to prevent tunnel from initializing the hello package.
100 if c.IsSet("hello-world") {
101 c.Set("playground", "true")
102 c.Set("hello-world", "false")
103 }
104
105 // Unix-socket database urls are supported, but the logic is the same as url.
106 if c.IsSet("unix-socket") {
107 c.Set("url", c.String("unix-socket"))
108 c.Set("unix-socket", "")
109 }
110
111 // When playground mode is enabled, run with an in-memory database.
112 if c.IsSet("playground") {
113 c.Set("url", "sqlite3::memory:?cache=shared")
114 c.Set("insecure", strconv.FormatBool(!c.IsSet("auth-domain") && !c.IsSet("application-aud")))
115 }
116
117 // At this point, insecure configurations are valid.
118 if c.Bool("insecure") {
119 return nil
120 }
121
122 // Ensure that secure configurations specify a hostname, domain, and tag for JWT validation.
123 if !c.IsSet("hostname") || !c.IsSet("auth-domain") || !c.IsSet("application-aud") {
124 log.Fatal("must specify --hostname, --auth-domain, and --application-aud unless you want to run in --insecure mode")
125 }
126
127 return nil
128}
129
130// CmdAction starts the Proxy and sets the url in cli.Context to point to the Proxy address.
131func CmdAction(c *cli.Context) error {
132 // STOR-612: sync with context in tunnel daemon.
133 ctx := context.Background()
134
135 var proxy *Proxy
136 var err error
137 if c.Bool("insecure") {
138 proxy, err = NewInsecureProxy(ctx, c.String("url"))
139 } else {
140 proxy, err = NewSecureProxy(ctx, c.String("url"), c.String("auth-domain"), c.String("application-aud"))
141 }
142
143 if err != nil {
144 log.Fatal(err)
145 return err
146 }
147
148 listenerC := make(chan net.Listener)
149 defer close(listenerC)
150
151 // Since the Proxy should only talk to the tunnel daemon, find the next available
152 // localhost port and start to listen to requests.
153 go func() {
154 err := proxy.Start(ctx, "127.0.0.1:", listenerC)
155 if err != nil {
156 log.Fatal(err)
157 }
158 }()
159
160 // Block until the the Proxy is online, retreive its address, and change the url to point to it.
161 // This is effectively "handing over" control to the tunnel package so it can run the tunnel daemon.
162 c.Set("url", "https://"+(<-listenerC).Addr().String())
163
164 return nil
165}
166