mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-06 12:19:37 -06:00
feat: add CSP and other security related headers in the oCIS proxy service (#8777)
* feat: add CSP and other security related headers in the oCIS proxy service * fix: consolidate security related headers - drop middleware.Secure * fix: use github.com/DeepDiver1975/secure * fix: acceptance tests * feat: support env var replacements in csp.yaml
This commit is contained in:
116
vendor/github.com/unrolled/secure/cspbuilder/builder.go
generated
vendored
Normal file
116
vendor/github.com/unrolled/secure/cspbuilder/builder.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
package cspbuilder
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// Fetch Directives.
|
||||
ChildSrc = "child-src"
|
||||
ConnectSrc = "connect-src"
|
||||
DefaultSrc = "default-src"
|
||||
FontSrc = "font-src"
|
||||
FrameSrc = "frame-src"
|
||||
ImgSrc = "img-src"
|
||||
ManifestSrc = "manifest-src"
|
||||
MediaSrc = "media-src"
|
||||
ObjectSrc = "object-src"
|
||||
PrefetchSrc = "prefetch-src"
|
||||
ScriptSrc = "script-src"
|
||||
ScriptSrcAttr = "script-src-attr"
|
||||
ScriptSrcElem = "script-src-elem"
|
||||
StyleSrc = "style-src"
|
||||
StyleSrcAttr = "style-src-attr"
|
||||
StyleSrcElem = "style-src-elem"
|
||||
WorkerSrc = "worker-src"
|
||||
|
||||
// Document Directives.
|
||||
BaseURI = "base-uri"
|
||||
Sandbox = "sandbox"
|
||||
|
||||
// Navigation directives.
|
||||
FormAction = "form-action"
|
||||
FrameAncestors = "frame-ancestors"
|
||||
NavigateTo = "navigate-to"
|
||||
|
||||
// Reporting directives.
|
||||
ReportURI = "report-uri"
|
||||
ReportTo = "report-to"
|
||||
|
||||
// Other directives.
|
||||
RequireTrustedTypesFor = "require-trusted-types-for"
|
||||
TrustedTypes = "trusted-types"
|
||||
UpgradeInsecureRequests = "upgrade-insecure-requests"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
Directives map[string]([]string)
|
||||
}
|
||||
|
||||
// MustBuild is like Build but panics if an error occurs.
|
||||
func (builder *Builder) MustBuild() string {
|
||||
policy, err := builder.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return policy
|
||||
}
|
||||
|
||||
// Build creates a content security policy string from the specified directives.
|
||||
// If any directive contains invalid values, an error is returned instead.
|
||||
func (builder *Builder) Build() (string, error) {
|
||||
var sb strings.Builder
|
||||
var keys []string
|
||||
for k := range builder.Directives {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, directive := range keys {
|
||||
if sb.Len() > 0 {
|
||||
sb.WriteString("; ")
|
||||
}
|
||||
|
||||
switch directive {
|
||||
case Sandbox:
|
||||
err := buildDirectiveSandbox(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case FrameAncestors:
|
||||
err := buildDirectiveFrameAncestors(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case ReportTo:
|
||||
err := buildDirectiveReportTo(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case RequireTrustedTypesFor:
|
||||
err := buildDirectiveRequireTrustedTypesFor(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case TrustedTypes:
|
||||
err := buildDirectiveTrustedTypes(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case UpgradeInsecureRequests:
|
||||
err := buildDirectiveUpgradeInsecureRequests(&sb, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
default:
|
||||
// no special handling of directive values needed
|
||||
err := buildDirectiveDefault(&sb, directive, builder.Directives[directive])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
||||
154
vendor/github.com/unrolled/secure/cspbuilder/directive_builder.go
generated
vendored
Normal file
154
vendor/github.com/unrolled/secure/cspbuilder/directive_builder.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
package cspbuilder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func buildDirectiveSandbox(sb *strings.Builder, values []string) error {
|
||||
if len(values) == 0 {
|
||||
sb.WriteString(Sandbox)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(values) > 1 {
|
||||
return fmt.Errorf("too many values set for directive %s", Sandbox)
|
||||
}
|
||||
|
||||
sandboxVal := values[0]
|
||||
|
||||
switch sandboxVal {
|
||||
case "allow-downloads-without-user-activation":
|
||||
case "allow-downloads":
|
||||
case "allow-forms":
|
||||
case "allow-modals":
|
||||
case "allow-orientation-lock":
|
||||
case "allow-pointer-lock":
|
||||
case "allow-popups-to-escape-sandbox":
|
||||
case "allow-popups":
|
||||
case "allow-presentation":
|
||||
case "allow-same-origin":
|
||||
case "allow-scripts":
|
||||
case "allow-storage-access-by-user-activation":
|
||||
case "allow-top-navigation-by-user-activation":
|
||||
case "allow-top-navigation-to-custom-protocols":
|
||||
case "allow-top-navigation":
|
||||
default:
|
||||
return fmt.Errorf("unallowed value %s for directive %s", sandboxVal, Sandbox)
|
||||
}
|
||||
|
||||
sb.WriteString(Sandbox)
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(sandboxVal)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveFrameAncestors(sb *strings.Builder, values []string) error {
|
||||
if len(values) == 0 {
|
||||
return fmt.Errorf("no values set for directive %s", FrameAncestors)
|
||||
}
|
||||
|
||||
sb.WriteString(FrameAncestors)
|
||||
|
||||
for _, val := range values {
|
||||
if strings.HasPrefix(val, "'") && strings.HasSuffix(val, "'") {
|
||||
switch val {
|
||||
case "'self'":
|
||||
case "'none'":
|
||||
default:
|
||||
return fmt.Errorf("unallowed value %s for directive %s", val, FrameAncestors)
|
||||
}
|
||||
}
|
||||
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(val)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveReportTo(sb *strings.Builder, values []string) error {
|
||||
if len(values) == 0 {
|
||||
return fmt.Errorf("no values set for directive %s", ReportTo)
|
||||
}
|
||||
|
||||
if len(values) > 1 {
|
||||
return fmt.Errorf("too many values set for directive %s", ReportTo)
|
||||
}
|
||||
|
||||
sb.WriteString(ReportTo)
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(values[0])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveRequireTrustedTypesFor(sb *strings.Builder, values []string) error {
|
||||
const allowedValue = "'script'"
|
||||
if len(values) != 1 || values[0] != allowedValue {
|
||||
return fmt.Errorf("value for directive %s must be %s", RequireTrustedTypesFor, allowedValue)
|
||||
}
|
||||
|
||||
sb.WriteString(RequireTrustedTypesFor)
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(values[0])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveTrustedTypes(sb *strings.Builder, values []string) error {
|
||||
sb.WriteString(TrustedTypes)
|
||||
|
||||
for _, val := range values {
|
||||
sb.WriteString(" ")
|
||||
|
||||
switch val {
|
||||
case "'none'":
|
||||
if len(values) != 1 {
|
||||
return fmt.Errorf("'none' must be only value for directive %s", TrustedTypes)
|
||||
}
|
||||
case "'allow-duplicates'":
|
||||
// nothing to do
|
||||
case "*":
|
||||
// nothing to do
|
||||
default:
|
||||
// value is policy name
|
||||
regex := regexp.MustCompile(`^[A-Za-z0-9\-#=_/@\.%]*$`)
|
||||
if !regex.MatchString(val) {
|
||||
return fmt.Errorf("unallowed value %s for directive %s", val, TrustedTypes)
|
||||
}
|
||||
}
|
||||
|
||||
sb.WriteString(val)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveUpgradeInsecureRequests(sb *strings.Builder, values []string) error {
|
||||
if len(values) != 0 {
|
||||
return fmt.Errorf("directive %s must not contain values", UpgradeInsecureRequests)
|
||||
}
|
||||
|
||||
sb.WriteString(UpgradeInsecureRequests)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildDirectiveDefault(sb *strings.Builder, directive string, values []string) error {
|
||||
if len(values) == 0 {
|
||||
return fmt.Errorf("no values set for directive %s", directive)
|
||||
}
|
||||
|
||||
sb.WriteString(directive)
|
||||
|
||||
for i := range values {
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(values[i])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user