asset integrity
This commit is contained in:
@@ -32,12 +32,14 @@ func NewTemplates() *Templates {
|
|||||||
type Page struct {
|
type Page struct {
|
||||||
Boxes []boxes.Box
|
Boxes []boxes.Box
|
||||||
BuildNumber string
|
BuildNumber string
|
||||||
|
Integrity *util.AssetIntegrity
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPage(boxes []boxes.Box) Page {
|
func newPage(boxes []boxes.Box) Page {
|
||||||
return Page{
|
return Page{
|
||||||
Boxes: boxes,
|
Boxes: boxes,
|
||||||
BuildNumber: util.GetBuildNumber(),
|
BuildNumber: util.GetBuildNumber(),
|
||||||
|
Integrity: util.CalculateAssetIntegrities(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +60,7 @@ func main() {
|
|||||||
e.GET("/health", func(c echo.Context) error {
|
e.GET("/health", func(c echo.Context) error {
|
||||||
return c.Render(200, "health", Page{
|
return c.Render(200, "health", Page{
|
||||||
BuildNumber: util.GetBuildNumber(),
|
BuildNumber: util.GetBuildNumber(),
|
||||||
|
Integrity: util.CalculateAssetIntegrities(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,3 +15,52 @@ func GetBuildNumber() string {
|
|||||||
func IsProd() bool {
|
func IsProd() bool {
|
||||||
return len(GetBuildNumber()) > 0
|
return len(GetBuildNumber()) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalculateFileIntegrity calculates SHA256 hash for SRI
|
||||||
|
func CalculateFileIntegrity(filePath string) (string, error) {
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
hasher := sha256.New()
|
||||||
|
if _, err := io.Copy(hasher, file); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := hasher.Sum(nil)
|
||||||
|
return fmt.Sprintf("sha256-%s", base64.StdEncoding.EncodeToString(hash)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetIntegrity holds file integrity information
|
||||||
|
type AssetIntegrity struct {
|
||||||
|
CSS map[string]string
|
||||||
|
JS map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculateAssetIntegrities calculates hashes for all assets
|
||||||
|
func CalculateAssetIntegrities() *AssetIntegrity {
|
||||||
|
integrity := &AssetIntegrity{
|
||||||
|
CSS: make(map[string]string),
|
||||||
|
JS: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS files
|
||||||
|
cssFiles := []string{"main.css", "boxes.css"}
|
||||||
|
for _, file := range cssFiles {
|
||||||
|
if hash, err := CalculateFileIntegrity("css/" + file); err == nil {
|
||||||
|
integrity.CSS[file] = hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JS files
|
||||||
|
jsFiles := []string{"ws.js", "boxes.js", "draw.js"}
|
||||||
|
for _, file := range jsFiles {
|
||||||
|
if hash, err := CalculateFileIntegrity("js/" + file); err == nil {
|
||||||
|
integrity.JS[file] = hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return integrity
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{{block "boxes" .}}
|
{{block "boxes" .}}
|
||||||
<link rel="stylesheet" href="/css/boxes.css?v={{.BuildNumber}}" />
|
<link rel="stylesheet" href="/css/boxes.css?v={{.BuildNumber}}" integrity="{{index .Integrity.CSS "boxes.css"}}" crossorigin="anonymous" />
|
||||||
|
|
||||||
|
|
||||||
<div class="counter-label">Currently Online: <span id="counter"></span></div>
|
<div class="counter-label">Currently Online: <span id="counter"></span></div>
|
||||||
@@ -21,6 +21,6 @@
|
|||||||
<div id="users" class="users-container"></div>
|
<div id="users" class="users-container"></div>
|
||||||
|
|
||||||
|
|
||||||
<script src="js/ws.js?v={{.BuildNumber}}"></script>
|
<script src="js/ws.js?v={{.BuildNumber}}" integrity="{{index .Integrity.JS "ws.js"}}" crossorigin="anonymous"></script>
|
||||||
<script src="js/boxes.js?v={{.BuildNumber}}"></script>
|
<script src="js/boxes.js?v={{.BuildNumber}}" integrity="{{index .Integrity.JS "boxes.js"}}" crossorigin="anonymous"></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" href="/css/main.css?v={{.BuildNumber}}" />
|
<link rel="stylesheet" href="/css/main.css?v={{.BuildNumber}}" integrity="{{index .Integrity.CSS "main.css" }}" crossorigin="anonymous" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||||
<link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
Reference in New Issue
Block a user