mirror of
https://github.com/Luzifer/go_helpers.git
synced 2024-12-26 14:01:20 +00:00
94 lines
2.8 KiB
Go
94 lines
2.8 KiB
Go
|
package http
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
"fmt"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
// CSP is a non-concurrency-safe map to hold a Content-Security-Policy
|
||
|
// and manipulate it afterwards to eventually render it into its
|
||
|
// header-representation
|
||
|
CSP map[string][]CSPSourceValue
|
||
|
// CSPHashAlgo defines the available hash algorithms
|
||
|
CSPHashAlgo string
|
||
|
// CSPSourceValue represents an value in the map for a given directive
|
||
|
CSPSourceValue string
|
||
|
)
|
||
|
|
||
|
// Collection of pre-defined values. For documentation see
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources
|
||
|
const (
|
||
|
CSPHashSHA256 CSPHashAlgo = "sha256"
|
||
|
CSPHashSHA384 CSPHashAlgo = "sha384"
|
||
|
CSPHashSHA512 CSPHashAlgo = "sha512"
|
||
|
|
||
|
CSPSrcNone CSPSourceValue = "'none'"
|
||
|
CSPSrcReportSample CSPSourceValue = "'report-sample'"
|
||
|
CSPSrcSelf CSPSourceValue = "'self'"
|
||
|
CSPSrcStrictDynamic CSPSourceValue = "'strict-dynamic'"
|
||
|
CSPSrcUnsafeEval CSPSourceValue = "'unsafe-eval'"
|
||
|
CSPSrcUnsafeHashes CSPSourceValue = "'unsafe-hashes'"
|
||
|
CSPSrcUnsafeInline CSPSourceValue = "'unsafe-inline'"
|
||
|
CSPSrcWASMUnsafeEval CSPSourceValue = "'wasm-unsafe-eval'"
|
||
|
|
||
|
CSPSrcSchemeData CSPSourceValue = "data:"
|
||
|
CSPSrcSchemeMediastream CSPSourceValue = "mediastream:"
|
||
|
CSPSrcSchemeBlob CSPSourceValue = "blob:"
|
||
|
CSPSrcSchemeFilesystem CSPSourceValue = "filesystem:"
|
||
|
)
|
||
|
|
||
|
// CSPSrcHash takes an algo (sha256, sha384 or sha512) and the sum
|
||
|
// value and converts it into the right representation for the header
|
||
|
func CSPSrcHash(algo CSPHashAlgo, sum []byte) CSPSourceValue {
|
||
|
return CSPSourceValue(fmt.Sprintf("'%s-%s'", algo, base64.StdEncoding.EncodeToString(sum)))
|
||
|
}
|
||
|
|
||
|
// CSPSrcNonce takes a base64 encoded nonce value and converts it
|
||
|
// into the right representation for the header
|
||
|
func CSPSrcNonce(b64Value string) CSPSourceValue {
|
||
|
return CSPSourceValue(fmt.Sprintf("'nonce-%s'", b64Value))
|
||
|
}
|
||
|
|
||
|
// Add adds a single CSPSourceValue to the given directive
|
||
|
func (c CSP) Add(directive string, value CSPSourceValue) {
|
||
|
c[directive] = append(c[directive], value)
|
||
|
}
|
||
|
|
||
|
// Clone copies the CSP into a new one for manipulation
|
||
|
func (c CSP) Clone() CSP {
|
||
|
n := make(CSP)
|
||
|
for dir, vals := range c {
|
||
|
n[dir] = append([]CSPSourceValue{}, vals...)
|
||
|
}
|
||
|
return n
|
||
|
}
|
||
|
|
||
|
// Set replaces all present values for the given directive
|
||
|
func (c CSP) Set(directive string, value CSPSourceValue) {
|
||
|
c[directive] = []CSPSourceValue{value}
|
||
|
}
|
||
|
|
||
|
// ToHeaderValue encodes the policy into the format expected in the
|
||
|
// `Content-Security-Policy` header.
|
||
|
func (c CSP) ToHeaderValue() string {
|
||
|
var keys []string
|
||
|
for k := range c {
|
||
|
keys = append(keys, k)
|
||
|
}
|
||
|
sort.Strings(keys)
|
||
|
|
||
|
var parts []string
|
||
|
for _, k := range keys {
|
||
|
lst := []string{k}
|
||
|
for _, v := range c[k] {
|
||
|
lst = append(lst, string(v))
|
||
|
}
|
||
|
parts = append(parts, strings.Join(lst, " "))
|
||
|
}
|
||
|
|
||
|
return strings.Join(parts, ";")
|
||
|
}
|