mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-24 12:13:28 +00:00
Add public paths inventory test
This commit is contained in:
@@ -205,6 +205,7 @@ var publicRouteAllowlist = []string{
|
||||
"/api/health",
|
||||
"/api/version",
|
||||
"/api/agent/version",
|
||||
"/api/agent/ws",
|
||||
"/api/server/info",
|
||||
"/api/security/status",
|
||||
"/api/security/validate-bootstrap-token",
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRouterPublicPathsInventory(t *testing.T) {
|
||||
literalPaths, dynamicPaths := parsePublicPaths(t)
|
||||
|
||||
expectedLiterals := sliceToSet(t, publicPathsAllowlist, "public paths allowlist")
|
||||
expectedDynamics := sliceToSet(t, publicPathsDynamicAllowlist, "public dynamic allowlist")
|
||||
expectedPublic := sliceToSet(t, publicRouteAllowlist, "public route allowlist")
|
||||
|
||||
actualLiterals := sliceToSet(t, literalPaths, "router public paths")
|
||||
actualDynamics := sliceToSet(t, dynamicPaths, "router public dynamic paths")
|
||||
|
||||
if missing := setDifference(actualLiterals, expectedLiterals); len(missing) > 0 {
|
||||
t.Fatalf("public paths missing from allowlist: %s", strings.Join(sortedKeys(missing), ", "))
|
||||
}
|
||||
if stale := setDifference(expectedLiterals, actualLiterals); len(stale) > 0 {
|
||||
t.Fatalf("public allowlist contains paths not in router.go: %s", strings.Join(sortedKeys(stale), ", "))
|
||||
}
|
||||
if missing := setDifference(actualDynamics, expectedDynamics); len(missing) > 0 {
|
||||
t.Fatalf("public dynamic paths missing from allowlist: %s", strings.Join(sortedKeys(missing), ", "))
|
||||
}
|
||||
if stale := setDifference(expectedDynamics, actualDynamics); len(stale) > 0 {
|
||||
t.Fatalf("public dynamic allowlist contains paths not in router.go: %s", strings.Join(sortedKeys(stale), ", "))
|
||||
}
|
||||
if missing := setDifference(expectedLiterals, expectedPublic); len(missing) > 0 {
|
||||
t.Fatalf("publicPaths entries missing from public route allowlist: %s", strings.Join(sortedKeys(missing), ", "))
|
||||
}
|
||||
}
|
||||
|
||||
func parsePublicPaths(t *testing.T) ([]string, []string) {
|
||||
t.Helper()
|
||||
|
||||
_, file, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatalf("failed to locate test file path")
|
||||
}
|
||||
routerPath := filepath.Join(filepath.Dir(file), "router.go")
|
||||
|
||||
fset := token.NewFileSet()
|
||||
fileAST, err := parser.ParseFile(fset, routerPath, nil, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("parse router.go: %v", err)
|
||||
}
|
||||
|
||||
var literalPaths []string
|
||||
var dynamicPaths []string
|
||||
var found bool
|
||||
|
||||
ast.Inspect(fileAST, func(node ast.Node) bool {
|
||||
assign, ok := node.(*ast.AssignStmt)
|
||||
if !ok || len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {
|
||||
return true
|
||||
}
|
||||
ident, ok := assign.Lhs[0].(*ast.Ident)
|
||||
if !ok || ident.Name != "publicPaths" {
|
||||
return true
|
||||
}
|
||||
comp, ok := assign.Rhs[0].(*ast.CompositeLit)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
found = true
|
||||
for _, elt := range comp.Elts {
|
||||
switch v := elt.(type) {
|
||||
case *ast.BasicLit:
|
||||
if v.Kind != token.STRING {
|
||||
continue
|
||||
}
|
||||
unquoted, err := strconv.Unquote(v.Value)
|
||||
if err != nil {
|
||||
unquoted = strings.Trim(v.Value, "`\"'")
|
||||
}
|
||||
literalPaths = append(literalPaths, unquoted)
|
||||
case *ast.Ident:
|
||||
dynamicPaths = append(dynamicPaths, v.Name)
|
||||
case *ast.SelectorExpr:
|
||||
dynamicPaths = append(dynamicPaths, selectorName(v))
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if !found {
|
||||
t.Fatalf("publicPaths slice not found in router.go")
|
||||
}
|
||||
|
||||
return literalPaths, dynamicPaths
|
||||
}
|
||||
|
||||
var publicPathsDynamicAllowlist = []string{
|
||||
"config.DefaultOIDCCallbackPath",
|
||||
}
|
||||
|
||||
var publicPathsAllowlist = []string{
|
||||
"/api/health",
|
||||
"/api/security/status",
|
||||
"/api/security/validate-bootstrap-token",
|
||||
"/api/security/quick-setup",
|
||||
"/api/version",
|
||||
"/api/login",
|
||||
"/api/oidc/login",
|
||||
"/install-docker-agent.sh",
|
||||
"/install-container-agent.sh",
|
||||
"/download/pulse-docker-agent",
|
||||
"/install-host-agent.sh",
|
||||
"/install-host-agent.ps1",
|
||||
"/uninstall-host-agent.sh",
|
||||
"/uninstall-host-agent.ps1",
|
||||
"/download/pulse-host-agent",
|
||||
"/install.sh",
|
||||
"/install.ps1",
|
||||
"/download/pulse-agent",
|
||||
"/api/agent/version",
|
||||
"/api/agent/ws",
|
||||
"/api/server/info",
|
||||
"/api/install/install-docker.sh",
|
||||
"/api/ai/oauth/callback",
|
||||
}
|
||||
Reference in New Issue
Block a user