Skip to content

Commit

Permalink
feat: add nonce placeholder option to cli insert command (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyubisation authored Aug 30, 2024
1 parent 12e7ac5 commit b7aab37
Show file tree
Hide file tree
Showing 10 changed files with 1,652 additions and 1,960 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,12 @@ given directory. Directory defaults to current working directory.

Usage: ngssc insert [options] [directory]

| Options | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `--recursive, -r` | Recursively searches for ngssc.json files and applies the contained configuration. |
| `--nginx` | Applies default configuration for ngssc insert to work with nginx. Sets working directory to /usr/share/nginx/html/ and recursive to true. |
| `--dry` | Perform the insert without actually inserting the variables. |
| Options | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `--recursive, -r` | Recursively searches for ngssc.json files and applies the contained configuration. |
| `--nginx` | Applies default configuration for ngssc insert to work with nginx. Sets working directory to /usr/share/nginx/html/ and recursive to true. |
| `--dry` | Perform the insert without actually inserting the variables. |
| `--nonce="example"` | Generates a nonce in the script tag with the given placeholder. |

#### ngssc substitute

Expand Down
6 changes: 4 additions & 2 deletions cli/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
func InsertCommand(c *cli.Context) error {
// Init Flags
nginxFlag := c.Bool("nginx")
noncePlaceholder := c.String("nonce")
dryRunFlag := c.Bool("dry")
recursive := c.Bool("recursive")
if !recursive && nginxFlag {
Expand Down Expand Up @@ -50,8 +51,9 @@ func InsertCommand(c *cli.Context) error {
}

task := InsertionTask{
path: workingDirectory,
dryRun: dryRunFlag,
path: workingDirectory,
noncePlaceholder: noncePlaceholder,
dryRun: dryRunFlag,
}
if recursive {
return task.Recursive()
Expand Down
11 changes: 11 additions & 0 deletions cli/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,17 @@ func TestNgsscProcessWithNgsw(t *testing.T) {
"Expected ngsw.json to be updated:\n "+result.Stdout())
}

func TestNonce(t *testing.T) {
context := newTestDir(t)
context.CreateFile("index.html", configHTMLTemplate)
context.CreateFile("ngssc.json", `{"variant":"process","environmentVariables":["TEST_VALUE"]}`)

result := runWithArgs("insert", context.path, "--nonce=CSP_NONCE")
assertSuccess(t, result)
expect := `<script nonce="CSP_NONCE">(function(self){self.process={"env":{"TEST_VALUE":null}};})(window)</script>`
assertContains(t, context.ReadFile("index.html"), expect, "Expected html to contain iife.")
}

var configHTMLTemplate = `<!DOCTYPE html>
<html lang="en">
Expand Down
24 changes: 16 additions & 8 deletions cli/insertion_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"crypto/sha1"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
Expand All @@ -12,20 +11,29 @@ import (

// InsertionTarget represents an html file target
type InsertionTarget struct {
filePath string
ngsscConfig NgsscConfig
filePath string
noncePlaceholder string
ngsscConfig NgsscConfig
}

// Insert the environment variables into the targeted file
func (target InsertionTarget) Insert() error {
htmlBytes, err := ioutil.ReadFile(target.filePath)
htmlBytes, err := os.ReadFile(target.filePath)
if err != nil {
return fmt.Errorf("failed to read %v\n%v", target.filePath, err)
}

nonce := ""
if target.noncePlaceholder != "" {
nonce = fmt.Sprintf(
" nonce=\"%v\"",
target.noncePlaceholder)
}

html := string(htmlBytes)
iifeScript := fmt.Sprintf(
"<!--ngssc--><script>%v</script><!--/ngssc-->",
"<!--ngssc--><script%v>%v</script><!--/ngssc-->",
nonce,
target.ngsscConfig.BuildIifeScriptContent())
var newHTML string
ngsscRegex := regexp.MustCompile(`<!--ngssc-->[\w\W]*<!--/ngssc-->`)
Expand All @@ -41,7 +49,7 @@ func (target InsertionTarget) Insert() error {
}

newHTMLBytes := []byte(newHTML)
err = ioutil.WriteFile(target.filePath, newHTMLBytes, 0644)
err = os.WriteFile(target.filePath, newHTMLBytes, 0644)
if err != nil {
return fmt.Errorf("failed to update %v\n%v", target.filePath, err)
}
Expand All @@ -58,7 +66,7 @@ func replaceIndexHashInNgsw(target InsertionTarget, originalHash []byte, replace
return
}

ngswBytes, err := ioutil.ReadFile(filePath)
ngswBytes, err := os.ReadFile(filePath)
if err != nil {
fmt.Printf("Detected ngsw.json, but failed to read it at %v\n", filePath)
return
Expand All @@ -73,7 +81,7 @@ func replaceIndexHashInNgsw(target InsertionTarget, originalHash []byte, replace

replacedWrappedHexHash := createQuotedHash(replacedHash)
replacedNgswContent := strings.Replace(ngswContent, wrappedHexHash, replacedWrappedHexHash, 1)
err = ioutil.WriteFile(filePath, []byte(replacedNgswContent), info.Mode())
err = os.WriteFile(filePath, []byte(replacedNgswContent), info.Mode())
if err != nil {
fmt.Printf("Detected ngsw.json, but failed to update it at %v\n", filePath)
return
Expand Down
10 changes: 6 additions & 4 deletions cli/insertion_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (

// InsertionTask represents an insertion task
type InsertionTask struct {
path string
dryRun bool
path string
noncePlaceholder string
dryRun bool
}

// Single will perform the insertion for a single ngssc.json
Expand Down Expand Up @@ -53,8 +54,9 @@ func (task InsertionTask) insertWithNgssc(ngsscConfig NgsscConfig) error {
if !task.dryRun {
for _, insertionFile := range files {
target := InsertionTarget{
filePath: insertionFile,
ngsscConfig: ngsscConfig,
filePath: insertionFile,
noncePlaceholder: task.noncePlaceholder,
ngsscConfig: ngsscConfig,
}
target.Insert()
}
Expand Down
4 changes: 4 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func run(args []string) error {
Name: "dry",
Usage: "Perform the insert without actually inserting the variables.",
},
cli.StringFlag{
Name: "nonce",
Usage: "Generates a nonce in the script tag with the given placeholder.",
},
},
Action: InsertCommand,
},
Expand Down
50 changes: 25 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,35 @@
"homepage": "https://github.com/kyubisation/angular-server-side-configuration#readme",
"private": true,
"dependencies": {
"@angular/animations": "^18.0.6",
"@angular/common": "^18.0.6",
"@angular/compiler": "^18.0.6",
"@angular/core": "^18.0.6",
"@angular/forms": "^18.0.6",
"@angular/platform-browser": "^18.0.6",
"@angular/platform-browser-dynamic": "^18.0.6",
"@angular/platform-server": "^18.0.6",
"@angular/router": "^18.0.6",
"@angular/ssr": "^18.0.7",
"@angular/animations": "^18.2.2",
"@angular/common": "^18.2.2",
"@angular/compiler": "^18.2.2",
"@angular/core": "^18.2.2",
"@angular/forms": "^18.2.2",
"@angular/platform-browser": "^18.2.2",
"@angular/platform-browser-dynamic": "^18.2.2",
"@angular/platform-server": "^18.2.2",
"@angular/router": "^18.2.2",
"@angular/ssr": "^18.2.2",
"rxjs": "7.8.1",
"tslib": "^2.6.3",
"zone.js": "~0.14.6"
"zone.js": "~0.14.10"
},
"devDependencies": {
"@angular-devkit/architect": "^0.1800.7",
"@angular-devkit/build-angular": "^18.0.7",
"@angular-devkit/core": "^18.0.7",
"@angular-devkit/schematics": "^18.0.7",
"@angular-eslint/builder": "18.1.0",
"@angular-eslint/eslint-plugin": "18.1.0",
"@angular-eslint/eslint-plugin-template": "18.1.0",
"@angular-eslint/schematics": "18.1.0",
"@angular-eslint/template-parser": "18.1.0",
"@angular/build": "^18.0.7",
"@angular/cli": "^18.0.7",
"@angular/compiler-cli": "^18.0.6",
"@angular/localize": "18.0.6",
"@schematics/angular": "^18.0.7",
"@angular-devkit/architect": "^0.1802.2",
"@angular-devkit/build-angular": "^18.2.2",
"@angular-devkit/core": "^18.2.2",
"@angular-devkit/schematics": "^18.2.2",
"@angular-eslint/builder": "18.3.0",
"@angular-eslint/eslint-plugin": "18.3.0",
"@angular-eslint/eslint-plugin-template": "18.3.0",
"@angular-eslint/schematics": "18.3.0",
"@angular-eslint/template-parser": "18.3.0",
"@angular/build": "^18.2.2",
"@angular/cli": "^18.2.2",
"@angular/compiler-cli": "^18.2.2",
"@angular/localize": "18.2.2",
"@schematics/angular": "^18.2.2",
"@types/jasmine": "~5.1.4",
"@types/node": "^20.12.12",
"@typescript-eslint/eslint-plugin": "^7.16.0",
Expand Down
Loading

0 comments on commit b7aab37

Please sign in to comment.