Michael Pratt submitted this change.
4 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:
```
The name of the file: influx/main.go
Insertions: 6, Deletions: 3.
@@ -31,14 +31,17 @@
"golang.org/x/build/internal/https"
)
-const influxURL = "http://localhost:8086"
+const (
+ influxListen = "localhost:8086"
+ influxURL = "http://"+influxListen
+)
func main() {
https.RegisterFlags(flag.CommandLine)
flag.Parse()
if err := run(); err != nil {
- log.Printf("Error completing setup: %v", err)
+ log.Printf("Error starting and running influx: %v", err)
os.Exit(1)
}
}
@@ -52,7 +55,7 @@
//
// Once we verify setup is complete, or perform setup ourselves, we
// will start a reverse proxy to forward external traffic to Influx.
- cmd, err := startInflux("localhost:8086")
+ cmd, err := startInflux(influxListen)
if err != nil {
return fmt.Errorf("error starting influx: %w", err)
}
```
influx: put influx behind a reverse proxy
When started for the first time, Influx allows any unauthenticated user
to perform initial database setup. An instance that is reachable from
the public internet thus has a race window for initial setup.
Close the window by starting Influx listening only on localhost,
performing setup, and only then running a reverse proxy on the external
interface to forward external traffic to influx. We must do this on
every startup just to see if this instance has already been set up or
not.
For golang/go#48803.
Change-Id: Iea41b01f61199101eb59686f1e6a3e9dab059a0e
Reviewed-on: https://go-review.googlesource.com/c/build/+/394357
Reviewed-by: Heschi Kreinick <hes...@google.com>
Trust: Michael Pratt <mpr...@google.com>
Run-TryBot: Michael Pratt <mpr...@google.com>
TryBot-Result: Gopher Robot <go...@golang.org>
---
M influx/Dockerfile
M influx/main.go
2 files changed, 100 insertions(+), 27 deletions(-)
diff --git a/influx/Dockerfile b/influx/Dockerfile
index 3f44eea..115e423 100644
--- a/influx/Dockerfile
+++ b/influx/Dockerfile
@@ -19,14 +19,5 @@
COPY --from=build /app/run-influx /run-influx
-# For now, generate a self-signed cert to use. Not for production use!
-RUN openssl req -x509 -nodes -newkey rsa:2048 \
- -keyout /etc/ssl/influxdb-selfsigned.key \
- -out /etc/ssl/influxdb-selfsigned.crt \
- -days 30 \
- -subj '/CN=localhost'
-
-# Run our setup application in the background and the parent Influx entrypoint
-# in the foreground.
ENTRYPOINT ["/bin/sh"]
-CMD ["-c", "/run-influx & /docker-entrypoint.sh influxd --tls-cert=/etc/ssl/influxdb-selfsigned.crt --tls-key=/etc/ssl/influxdb-selfsigned.key --http-bind-address=:443"]
+CMD ["-c", "/run-influx -listen-http=:80"]
diff --git a/influx/main.go b/influx/main.go
index caf83a1..bf6f598 100644
--- a/influx/main.go
+++ b/influx/main.go
@@ -12,11 +12,15 @@
"crypto/rand"
"crypto/tls"
"encoding/json"
+ "flag"
"fmt"
"log"
"math/big"
"net/http"
+ "net/http/httputil"
+ "net/url"
"os"
+ "os/exec"
"time"
"github.com/influxdata/influxdb-client-go/v2"
@@ -24,13 +28,20 @@
"cloud.google.com/go/compute/metadata"
secretmanager "cloud.google.com/go/secretmanager/apiv1"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
+ "golang.org/x/build/internal/https"
)
-const influxURL = "https://localhost:443"
+const (
+ influxListen = "localhost:8086"
+ influxURL = "http://"+influxListen
+)
func main() {
+ https.RegisterFlags(flag.CommandLine)
+ flag.Parse()
+
if err := run(); err != nil {
- log.Printf("Error completing setup: %v", err)
+ log.Printf("Error starting and running influx: %v", err)
os.Exit(1)
}
}
@@ -38,24 +49,46 @@
func run() error {
ctx := context.Background()
- // Connecting via localhost with self-signed certs, so no cert checks.
- options := influxdb2.DefaultOptions()
- options.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
- client := influxdb2.NewClientWithOptions(influxURL, "", options)
- defer client.Close()
+ // Start Influx, bound to listen on localhost only. The DB may not be
+ // set up yet, in which case any unauthenticated user could perform
+ // setup, so we must ensure that only we can reach the server.
+ //
+ // Once we verify setup is complete, or perform setup ourselves, we
+ // will start a reverse proxy to forward external traffic to Influx.
+ cmd, err := startInflux(influxListen)
+ if err != nil {
+ return fmt.Errorf("error starting influx: %w", err)
+ }
+ go func() {
+ err := cmd.Wait()
+ log.Fatalf("Influx exited unexpectedly: %v", err)
+ }()
- log.Printf("Waiting for influx to start...")
- for {
- _, err := client.Ready(ctx)
- if err != nil {
- log.Printf("Influx not ready: %v", err)
- time.Sleep(1 * time.Second)
- continue
- }
- break
+ if err := checkAndSetupInflux(ctx); err != nil {
+ return fmt.Errorf("error setting up influx: %w", err)
}
- log.Printf("Influx ready!")
+ u, err := url.Parse(influxURL)
+ if err != nil {
+ return fmt.Errorf("error parsing influxURL: %w", err)
+ }
+
+ log.Printf("Starting reverse HTTP proxy...")
+ return https.ListenAndServe(ctx, httputil.NewSingleHostReverseProxy(u))
+}
+
+func startInflux(bindAddr string) (*exec.Cmd, error) {
+ cmd := exec.Command("/docker-entrypoint.sh", "influxd", "--http-bind-address", bindAddr)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ log.Printf("Running %v", cmd.Args)
+ return cmd, cmd.Start()
+}
+
+// checkAndSetupInflux determines if influx is already set up, and sets it up if not.
+func checkAndSetupInflux(ctx context.Context) (err error) {
+ client := newInfluxClient(ctx)
+ defer client.Close()
allowed, err := setupAllowed(ctx)
if err != nil {
@@ -79,6 +112,29 @@
return nil
}
+// newInfluxClient creates and influx Client and waits for the database to
+// finish starting up.
+func newInfluxClient(ctx context.Context) influxdb2.Client {
+ // We used a self-signed certificate.
+ options := influxdb2.DefaultOptions()
+ options.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
+ client := influxdb2.NewClientWithOptions(influxURL, "", options)
+
+ log.Printf("Waiting for influx to start...")
+ for {
+ _, err := client.Ready(ctx)
+ if err != nil {
+ log.Printf("Influx not ready: %v", err)
+ time.Sleep(1 * time.Second)
+ continue
+ }
+ break
+ }
+
+ log.Printf("Influx ready!")
+ return client
+}
+
// Setup is the response to Influx GET /api/v2/setup.
type Setup struct {
Allowed bool `json:"allowed"`
To view, visit change 394357. To unsubscribe, or for help writing mail filters, visit settings.