mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
chore: CORs option for yarn dev server (#7630)
* chore: Yarn dev servers require CORs headers for external proxies Adds a flag to set CORs headers to `*` for yarn dev servers
This commit is contained in:
3
coderd/apidoc/docs.go
generated
3
coderd/apidoc/docs.go
generated
@ -7252,6 +7252,9 @@ const docTemplate = `{
|
||||
"codersdk.DangerousConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow_all_cors": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"allow_path_app_sharing": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
3
coderd/apidoc/swagger.json
generated
3
coderd/apidoc/swagger.json
generated
@ -6454,6 +6454,9 @@
|
||||
"codersdk.DangerousConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow_all_cors": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"allow_path_app_sharing": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
@ -393,8 +393,10 @@ func New(options *Options) *API {
|
||||
|
||||
derpHandler := derphttp.Handler(api.DERPServer)
|
||||
derpHandler, api.derpCloseFunc = tailnet.WithWebsocketSupport(api.DERPServer, derpHandler)
|
||||
cors := httpmw.Cors(options.DeploymentValues.Dangerous.AllowAllCors.Value())
|
||||
|
||||
r.Use(
|
||||
cors,
|
||||
httpmw.Recover(api.Logger),
|
||||
tracing.StatusWriterMiddleware,
|
||||
tracing.Middleware(api.TracerProvider),
|
||||
@ -799,6 +801,10 @@ func New(options *Options) *API {
|
||||
// Add CSP headers to all static assets and pages. CSP headers only affect
|
||||
// browsers, so these don't make sense on api routes.
|
||||
cspMW := httpmw.CSPHeaders(func() []string {
|
||||
if api.DeploymentValues.Dangerous.AllowAllCors {
|
||||
// In this mode, allow all external requests
|
||||
return []string{"*"}
|
||||
}
|
||||
if f := api.WorkspaceProxyHostsFn.Load(); f != nil {
|
||||
return (*f)()
|
||||
}
|
||||
@ -813,7 +819,7 @@ func New(options *Options) *API {
|
||||
// This is the only route we add before all the middleware.
|
||||
// We want to time the latency of the request, so any middleware will
|
||||
// interfere with that timing.
|
||||
rootRouter.Get("/latency-check", LatencyCheck(api.AccessURL))
|
||||
rootRouter.Get("/latency-check", cors(LatencyCheck(options.DeploymentValues.Dangerous.AllowAllCors.Value(), api.AccessURL)).ServeHTTP)
|
||||
rootRouter.Mount("/", r)
|
||||
api.RootHandler = rootRouter
|
||||
|
||||
|
27
coderd/httpmw/cors.go
Normal file
27
coderd/httpmw/cors.go
Normal file
@ -0,0 +1,27 @@
|
||||
package httpmw
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/cors"
|
||||
)
|
||||
|
||||
//nolint:revive
|
||||
func Cors(allowAll bool, origins ...string) func(next http.Handler) http.Handler {
|
||||
if len(origins) == 0 {
|
||||
// The default behavior is '*', so putting the empty string defaults to
|
||||
// the secure behavior of blocking CORs requests.
|
||||
origins = []string{""}
|
||||
}
|
||||
if allowAll {
|
||||
origins = []string{"*"}
|
||||
}
|
||||
return cors.Handler(cors.Options{
|
||||
AllowedOrigins: origins,
|
||||
// We only need GET for latency requests
|
||||
AllowedMethods: []string{http.MethodOptions, http.MethodGet},
|
||||
AllowedHeaders: []string{"Accept", "Content-Type", "X-LATENCY-CHECK", "X-CSRF-TOKEN"},
|
||||
// Do not send any cookies
|
||||
AllowCredentials: false,
|
||||
})
|
||||
}
|
@ -103,6 +103,11 @@ func CSPHeaders(websocketHosts func() []string) func(next http.Handler) http.Han
|
||||
extraConnect := websocketHosts()
|
||||
if len(extraConnect) > 0 {
|
||||
for _, extraHost := range extraConnect {
|
||||
if extraHost == "*" {
|
||||
// '*' means all
|
||||
cspSrcs.Append(cspDirectiveConnectSrc, "*")
|
||||
continue
|
||||
}
|
||||
cspSrcs.Append(cspDirectiveConnectSrc, fmt.Sprintf("wss://%[1]s ws://%[1]s", extraHost))
|
||||
// We also require this to make http/https requests to the workspace proxy for latency checking.
|
||||
cspSrcs.Append(cspDirectiveConnectSrc, fmt.Sprintf("https://%[1]s http://%[1]s", extraHost))
|
||||
|
@ -6,7 +6,12 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func LatencyCheck(allowedOrigins ...*url.URL) http.HandlerFunc {
|
||||
// LatencyCheck is an endpoint for the web ui to measure latency with.
|
||||
// allowAll allows any Origin to get timing information. The allowAll should
|
||||
// only be set in dev modes.
|
||||
//
|
||||
//nolint:revive
|
||||
func LatencyCheck(allowAll bool, allowedOrigins ...*url.URL) http.HandlerFunc {
|
||||
allowed := make([]string, 0, len(allowedOrigins))
|
||||
for _, origin := range allowedOrigins {
|
||||
// Allow the origin without a path
|
||||
@ -14,6 +19,9 @@ func LatencyCheck(allowedOrigins ...*url.URL) http.HandlerFunc {
|
||||
tmp.Path = ""
|
||||
allowed = append(allowed, strings.TrimSuffix(origin.String(), "/"))
|
||||
}
|
||||
if allowAll {
|
||||
allowed = append(allowed, "*")
|
||||
}
|
||||
origins := strings.Join(allowed, ",")
|
||||
return func(rw http.ResponseWriter, r *http.Request) {
|
||||
// Allowing timing information to be shared. This allows the browser
|
||||
|
Reference in New Issue
Block a user