diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 3ea343f8a5..94b285e79a 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -12,8 +12,8 @@ on: # Stable release tags - v[0-9]+.[0-9]+.[0-9]+ paths: - - 'docs/**' - - 'mkdocs.yml' + - "docs/**" + - "mkdocs.yml" workflow_dispatch: jobs: diff --git a/config-example.yaml b/config-example.yaml index b083091ffb..33e4a1949f 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -40,6 +40,13 @@ grpc_listen_addr: 127.0.0.1:50443 # are doing. grpc_allow_insecure: false +# The Access-Control-Allow-Origin header specifies which origins are allowed to access resources. +# Options: +# - "*" to allow access from any origin (not recommended for sensitive data). +# - "http://example.com" to only allow access from a specific origin. +# - "" to disable Cross-Origin Resource Sharing (CORS). +Access-Control-Allow-Origin: "" + # The Noise section includes specific configuration for the # TS2021 Noise protocol noise: diff --git a/hscontrol/app.go b/hscontrol/app.go index 1651b8f211..11ae193314 100644 --- a/hscontrol/app.go +++ b/hscontrol/app.go @@ -440,10 +440,21 @@ func (h *Headscale) ensureUnixSocketIsAbsent() error { return os.Remove(h.cfg.UnixSocket) } +func (h *Headscale) corsHeadersMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", h.cfg.AccessControlAllowOrigins) + next.ServeHTTP(w, r) + }) +} + func (h *Headscale) createRouter(grpcMux *grpcRuntime.ServeMux) *mux.Router { router := mux.NewRouter() router.Use(prometheusMiddleware) + if h.cfg.AccessControlAllowOrigins != "" { + router.Use(h.corsHeadersMiddleware) + } + router.HandleFunc(ts2021UpgradePath, h.NoiseUpgradeHandler).Methods(http.MethodPost, http.MethodGet) router.HandleFunc("/health", h.HealthHandler).Methods(http.MethodGet) diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index 2af3989646..0d5f1d9363 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -63,6 +63,8 @@ type Config struct { Log LogConfig DisableUpdateCheck bool + AccessControlAllowOrigins string + Database DatabaseConfig DERP DERPConfig @@ -292,6 +294,8 @@ func LoadConfig(path string, isFile bool) error { viper.SetDefault("tuning.batch_change_delay", "800ms") viper.SetDefault("tuning.node_mapsession_buffered_chan_size", 30) + viper.SetDefault("Access-Control-Allow-Origin", "") + viper.SetDefault("prefixes.allocation", string(IPAllocationStrategySequential)) if err := viper.ReadInConfig(); err != nil { @@ -852,6 +856,8 @@ func LoadServerConfig() (*Config, error) { GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"), DisableUpdateCheck: false, + AccessControlAllowOrigins: viper.GetString("Access-Control-Allow-Origin"), + PrefixV4: prefix4, PrefixV6: prefix6, IPAllocation: IPAllocationStrategy(alloc),