1
0
Fork 0
mirror of https://github.com/Luzifer/go_helpers.git synced 2024-12-25 13:31:21 +00:00
go_helpers/http/csp.go
Knut Ahlers fe36f52937
Add CSP helper
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2023-06-17 14:37:18 +02:00

93 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, ";")
}