feat: Warn on coderd startup if access URL is localhost (#2248)

This commit is contained in:
David Wahler
2022-06-10 13:35:51 -05:00
committed by GitHub
parent f79ab7f87e
commit 71fd19631a
2 changed files with 72 additions and 0 deletions
+43
View File
@@ -203,6 +203,28 @@ func server() *cobra.Command {
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
}
// Warn the user if the access URL appears to be a loopback address.
isLocal, err := isLocalURL(cmd.Context(), accessURL)
if isLocal || err != nil {
var reason string
if isLocal {
reason = "appears to be a loopback address"
} else {
reason = "could not be resolved"
}
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), cliui.Styles.Wrap.Render(
cliui.Styles.Warn.Render("Warning:")+" The current access URL:")+"\n\n")
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), " "+cliui.Styles.Field.Render(accessURL)+"\n\n")
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), cliui.Styles.Wrap.Render(
reason+". Provisioned workspaces are unlikely to be able to "+
"connect to Coder. Please consider changing your "+
"access URL using the --access-url option, or directly "+
"specifying access URLs on templates.",
)+"\n\n")
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "For more information, see "+
"https://github.com/coder/coder/issues/1528\n\n")
}
validator, err := idtoken.NewValidator(cmd.Context(), option.WithoutAuthentication())
if err != nil {
return err
@@ -803,3 +825,24 @@ func serveHandler(ctx context.Context, logger slog.Logger, handler http.Handler,
return func() { _ = srv.Close() }
}
// isLocalURL returns true if the hostname of the provided URL appears to
// resolve to a loopback address.
func isLocalURL(ctx context.Context, urlString string) (bool, error) {
parsedURL, err := url.Parse(urlString)
if err != nil {
return false, err
}
resolver := &net.Resolver{}
ips, err := resolver.LookupIPAddr(ctx, parsedURL.Hostname())
if err != nil {
return false, err
}
for _, ip := range ips {
if ip.IP.IsLoopback() {
return true, nil
}
}
return false, nil
}
+29
View File
@@ -118,6 +118,9 @@ func TestServer(t *testing.T) {
} else {
t.Error("expected password line output; got no match")
}
// Verify that we warned the user about the default access URL possibly not being what they want.
assert.Contains(t, buf.String(), "coder/coder/issues/1528")
})
// Duplicated test from "Development" above to test setting email/password via env.
@@ -163,6 +166,32 @@ func TestServer(t *testing.T) {
assert.Contains(t, buf.String(), fmt.Sprintf("password: %s", wantPassword), "expected output %q; got no match", wantPassword)
})
t.Run("NoWarningWithRemoteAccessURL", func(t *testing.T) {
t.Parallel()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
root, cfg := clitest.New(t, "server", "--dev", "--tunnel=false", "--address", ":0", "--access-url", "http://1.2.3.4:3000/")
var buf strings.Builder
errC := make(chan error)
root.SetOutput(&buf)
go func() {
errC <- root.ExecuteContext(ctx)
}()
// Just wait for startup
require.Eventually(t, func() bool {
var err error
_, err = cfg.URL().Read()
return err == nil
}, 15*time.Second, 25*time.Millisecond)
cancelFunc()
require.ErrorIs(t, <-errC, context.Canceled)
assert.NotContains(t, buf.String(), "coder/coder/issues/1528")
})
t.Run("TLSBadVersion", func(t *testing.T) {
t.Parallel()
ctx, cancelFunc := context.WithCancel(context.Background())