diff --git a/cmd/ftl/main.go b/cmd/ftl/main.go index a734f86c71..e22d58f44d 100644 --- a/cmd/ftl/main.go +++ b/cmd/ftl/main.go @@ -30,6 +30,7 @@ type CLI struct { ConfigFlag string `name:"config" short:"C" help:"Path to FTL project configuration file." env:"FTL_CONFIG" placeholder:"FILE"` Authenticators map[string]string `help:"Authenticators to use for FTL endpoints." mapsep:"," env:"FTL_AUTHENTICATORS" placeholder:"HOST=EXE,…"` + Insecure bool `help:"Skip TLS certificate verification. Caution: susceptible to machine-in-the-middle attacks."` Ping pingCmd `cmd:"" help:"Ping the FTL cluster."` Status statusCmd `cmd:"" help:"Show FTL status."` @@ -74,7 +75,7 @@ func main() { }, ) - rpc.InitialiseClients(cli.Authenticators) + rpc.InitialiseClients(cli.Authenticators, cli.Insecure) // Set some envars for child processes. os.Setenv("LOG_LEVEL", cli.LogConfig.Level.String()) @@ -84,6 +85,10 @@ func main() { logger := log.Configure(os.Stderr, cli.LogConfig) ctx = log.ContextWithLogger(ctx, logger) + if cli.Insecure { + logger.Warnf("--insecure skips TLS certificate verification") + } + configPath := cli.ConfigFlag if configPath == "" { var ok bool diff --git a/internal/rpc/rpc.go b/internal/rpc/rpc.go index 2b30ea25cb..bc2d49d38d 100644 --- a/internal/rpc/rpc.go +++ b/internal/rpc/rpc.go @@ -23,12 +23,17 @@ import ( // // "authenticators" are authenticator executables to use for each endpoint. The key is the URL of the endpoint, the // value is the path to the authenticator executable. -func InitialiseClients(authenticators map[string]string) { +// +// "allowInsecure" skips certificate verification, making TLS susceptible to machine-in-the-middle attacks. +func InitialiseClients(authenticators map[string]string, allowInsecure bool) { // We can't have a client-wide timeout because it also applies to // streaming RPCs, timing them out. h2cClient = &http.Client{ Transport: authn.Transport(&http2.Transport{ AllowHTTP: true, + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: allowInsecure, // #nosec G402 + }, DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { conn, err := dialer.Dial(network, addr) return conn, err @@ -37,6 +42,9 @@ func InitialiseClients(authenticators map[string]string) { } tlsClient = &http.Client{ Transport: authn.Transport(&http2.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: allowInsecure, // #nosec G402 + }, DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) { tlsDialer := tls.Dialer{Config: config, NetDialer: dialer} conn, err := tlsDialer.DialContext(ctx, network, addr) @@ -47,7 +55,7 @@ func InitialiseClients(authenticators map[string]string) { } func init() { - InitialiseClients(map[string]string{}) + InitialiseClients(map[string]string{}, false) } var (