✨ Add Helmet & Watermark
All checks were successful
release-nightly / build-docker (push) Successful in 2m37s
All checks were successful
release-nightly / build-docker (push) Successful in 2m37s
This commit is contained in:
parent
ef10fab47d
commit
09c4800143
@ -28,4 +28,5 @@ host = ["localhost:8000"]
|
|||||||
path = ["/"]
|
path = ["/"]
|
||||||
[[locations.destinations]]
|
[[locations.destinations]]
|
||||||
id = "example-destination"
|
id = "example-destination"
|
||||||
uri = "http://protocol.smartsheep.studio:20004"
|
uri = "https://example.com"
|
||||||
|
helmet = { x_frame_options = "SAMEORIGIN" }
|
@ -1,7 +1,6 @@
|
|||||||
package hypertext
|
package hypertext
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -105,22 +104,6 @@ func makeResponse(c *fiber.Ctx, region *navi.Region, location *navi.Location, de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add reserve proxy headers
|
|
||||||
ip := c.IP()
|
|
||||||
scheme := c.Protocol()
|
|
||||||
protocol := string(c.Request().Header.Protocol())
|
|
||||||
c.Request().Header.Set(fiber.HeaderXForwardedFor, ip)
|
|
||||||
c.Request().Header.Set(fiber.HeaderXForwardedHost, ip)
|
|
||||||
c.Request().Header.Set(fiber.HeaderXForwardedProto, scheme)
|
|
||||||
c.Request().Header.Set(
|
|
||||||
fiber.HeaderVia,
|
|
||||||
fmt.Sprintf("%s %s", protocol, viper.GetString("central")),
|
|
||||||
)
|
|
||||||
c.Request().Header.Set(
|
|
||||||
fiber.HeaderForwarded,
|
|
||||||
fmt.Sprintf("by=%s; for=%s; host=%s; proto=%s", c.IP(), c.IP(), c.Get(fiber.HeaderHost), scheme),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Forward
|
// Forward
|
||||||
err := navi.R.Forward(c, dest)
|
err := navi.R.Forward(c, dest)
|
||||||
|
|
||||||
|
89
pkg/navi/helmet.go
Normal file
89
pkg/navi/helmet.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package navi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HelmetConfig struct {
|
||||||
|
XSSProtection string `json:"xss_protection" toml:"xss_protection"`
|
||||||
|
ContentTypeNosniff string `json:"content_type_nosniff" toml:"content_type_nosniff"`
|
||||||
|
XFrameOptions string `json:"x_frame_options" toml:"x_frame_options"`
|
||||||
|
HSTSMaxAge int `json:"hsts_max_age" toml:"hsts_max_age"`
|
||||||
|
HSTSExcludeSubdomains bool `json:"hsts_exclude_subdomains" toml:"hsts_exclude_subdomains"`
|
||||||
|
ContentSecurityPolicy string `json:"content_security_policy" toml:"content_security_policy"`
|
||||||
|
CSPReportOnly bool `json:"csp_report_only" toml:"csp_report_only"`
|
||||||
|
HSTSPreloadEnabled bool `json:"hsts_preload_enabled" toml:"hsts_preload_enabled"`
|
||||||
|
ReferrerPolicy string `json:"referrer_policy" toml:"referrer_policy"`
|
||||||
|
PermissionPolicy string `json:"permission_policy" toml:"permission_policy"`
|
||||||
|
CrossOriginEmbedderPolicy string `json:"cross_origin_embedder_policy" toml:"cross_origin_embedder_policy"`
|
||||||
|
CrossOriginOpenerPolicy string `json:"cross_origin_opener_policy" toml:"cross_origin_opener_policy"`
|
||||||
|
CrossOriginResourcePolicy string `json:"cross_origin_resource_policy" toml:"cross_origin_resource_policy"`
|
||||||
|
OriginAgentCluster string `json:"origin_agent_cluster" toml:"origin_agent_cluster"`
|
||||||
|
XDNSPrefetchControl string `json:"xdns_prefetch_control" toml:"xdns_prefetch_control"`
|
||||||
|
XDownloadOptions string `json:"x_download_options" toml:"x_download_options"`
|
||||||
|
XPermittedCrossDomain string `json:"x_permitted_cross_domain" toml:"x_permitted_cross_domain"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg HelmetConfig) Apply(c *fiber.Ctx) {
|
||||||
|
// Apply other headers
|
||||||
|
if cfg.XSSProtection != "" {
|
||||||
|
c.Set(fiber.HeaderXXSSProtection, cfg.XSSProtection)
|
||||||
|
}
|
||||||
|
if cfg.ContentTypeNosniff != "" {
|
||||||
|
c.Set(fiber.HeaderXContentTypeOptions, cfg.ContentTypeNosniff)
|
||||||
|
}
|
||||||
|
if cfg.XFrameOptions != "" {
|
||||||
|
c.Set(fiber.HeaderXFrameOptions, cfg.XFrameOptions)
|
||||||
|
}
|
||||||
|
if cfg.CrossOriginEmbedderPolicy != "" {
|
||||||
|
c.Set("Cross-Origin-Embedder-Policy", cfg.CrossOriginEmbedderPolicy)
|
||||||
|
}
|
||||||
|
if cfg.CrossOriginOpenerPolicy != "" {
|
||||||
|
c.Set("Cross-Origin-Opener-Policy", cfg.CrossOriginOpenerPolicy)
|
||||||
|
}
|
||||||
|
if cfg.CrossOriginResourcePolicy != "" {
|
||||||
|
c.Set("Cross-Origin-Resource-Policy", cfg.CrossOriginResourcePolicy)
|
||||||
|
}
|
||||||
|
if cfg.OriginAgentCluster != "" {
|
||||||
|
c.Set("Origin-Agent-Cluster", cfg.OriginAgentCluster)
|
||||||
|
}
|
||||||
|
if cfg.ReferrerPolicy != "" {
|
||||||
|
c.Set("Referrer-Policy", cfg.ReferrerPolicy)
|
||||||
|
}
|
||||||
|
if cfg.XDNSPrefetchControl != "" {
|
||||||
|
c.Set("X-DNS-Prefetch-Control", cfg.XDNSPrefetchControl)
|
||||||
|
}
|
||||||
|
if cfg.XDownloadOptions != "" {
|
||||||
|
c.Set("X-Download-Options", cfg.XDownloadOptions)
|
||||||
|
}
|
||||||
|
if cfg.XPermittedCrossDomain != "" {
|
||||||
|
c.Set("X-Permitted-Cross-Domain-Policies", cfg.XPermittedCrossDomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle HSTS headers
|
||||||
|
if c.Protocol() == "https" && cfg.HSTSMaxAge != 0 {
|
||||||
|
subdomains := ""
|
||||||
|
if !cfg.HSTSExcludeSubdomains {
|
||||||
|
subdomains = "; includeSubDomains"
|
||||||
|
}
|
||||||
|
if cfg.HSTSPreloadEnabled {
|
||||||
|
subdomains = fmt.Sprintf("%s; preload", subdomains)
|
||||||
|
}
|
||||||
|
c.Set(fiber.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", cfg.HSTSMaxAge, subdomains))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Content-Security-Policy headers
|
||||||
|
if cfg.ContentSecurityPolicy != "" {
|
||||||
|
if cfg.CSPReportOnly {
|
||||||
|
c.Set(fiber.HeaderContentSecurityPolicyReportOnly, cfg.ContentSecurityPolicy)
|
||||||
|
} else {
|
||||||
|
c.Set(fiber.HeaderContentSecurityPolicy, cfg.ContentSecurityPolicy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Permissions-Policy headers
|
||||||
|
if cfg.PermissionPolicy != "" {
|
||||||
|
c.Set(fiber.HeaderPermissionsPolicy, cfg.PermissionPolicy)
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
package navi
|
package navi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
roadsign "code.smartsheep.studio/goatworks/roadsign/pkg"
|
||||||
"code.smartsheep.studio/goatworks/roadsign/pkg/navi/transformers"
|
"code.smartsheep.studio/goatworks/roadsign/pkg/navi/transformers"
|
||||||
|
"fmt"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
@ -11,15 +14,44 @@ type RoadApp struct {
|
|||||||
Traces []RoadTrace `json:"traces"`
|
Traces []RoadTrace `json:"traces"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *RoadApp) Forward(ctx *fiber.Ctx, dest *Destination) error {
|
func (v *RoadApp) Forward(c *fiber.Ctx, dest *Destination) error {
|
||||||
|
// Add reserve proxy headers
|
||||||
|
ip := c.IP()
|
||||||
|
scheme := c.Protocol()
|
||||||
|
protocol := string(c.Request().Header.Protocol())
|
||||||
|
c.Request().Header.Set(fiber.HeaderXForwardedFor, ip)
|
||||||
|
c.Request().Header.Set(fiber.HeaderXForwardedHost, ip)
|
||||||
|
c.Request().Header.Set(fiber.HeaderXForwardedProto, scheme)
|
||||||
|
c.Request().Header.Set(
|
||||||
|
fiber.HeaderVia,
|
||||||
|
fmt.Sprintf("%s %s", protocol, viper.GetString("central")),
|
||||||
|
)
|
||||||
|
c.Request().Header.Set(
|
||||||
|
fiber.HeaderForwarded,
|
||||||
|
fmt.Sprintf("by=%s; for=%s; host=%s; proto=%s", c.IP(), c.IP(), c.Get(fiber.HeaderHost), scheme),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Response body
|
||||||
|
var err error
|
||||||
switch dest.GetType() {
|
switch dest.GetType() {
|
||||||
case DestinationHypertext:
|
case DestinationHypertext:
|
||||||
return makeUnifiedResponse(ctx, dest)
|
err = makeUnifiedResponse(c, dest)
|
||||||
case DestinationStaticFile:
|
case DestinationStaticFile:
|
||||||
return makeFileResponse(ctx, dest)
|
err = makeFileResponse(c, dest)
|
||||||
default:
|
default:
|
||||||
return fiber.ErrBadGateway
|
err = fiber.ErrBadGateway
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply helmet
|
||||||
|
if dest.Helmet != nil {
|
||||||
|
dest.Helmet.Apply(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply watermark
|
||||||
|
c.Response().Header.Set(fiber.HeaderServer, "RoadSign")
|
||||||
|
c.Response().Header.Set(fiber.HeaderXPoweredBy, fmt.Sprintf("RoadSign %s", roadsign.AppVersion))
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type RequestTransformerConfig = transformers.TransformerConfig
|
type RequestTransformerConfig = transformers.TransformerConfig
|
||||||
|
@ -38,6 +38,7 @@ const (
|
|||||||
type Destination struct {
|
type Destination struct {
|
||||||
ID string `json:"id" toml:"id"`
|
ID string `json:"id" toml:"id"`
|
||||||
Uri string `json:"uri" toml:"uri"`
|
Uri string `json:"uri" toml:"uri"`
|
||||||
|
Helmet *HelmetConfig `json:"helmet" toml:"helmet"`
|
||||||
Transformers []transformers.TransformerConfig `json:"transformers" toml:"transformers"`
|
Transformers []transformers.TransformerConfig `json:"transformers" toml:"transformers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user