docker: include default snippets onto Dockerfile, allow multiple snippets folders, closes #8

This commit is contained in:
WeebDataHoarder
2025-04-25 18:09:25 +02:00
parent d665036d98
commit bca5b25f28
4 changed files with 57 additions and 41 deletions

View File

@@ -32,6 +32,7 @@ RUN test -e "${GOBIN}/go-away"
FROM --platform=$TARGETPLATFORM ${from}
COPY --from=build /go/bin/go-away /bin/go-away
COPY examples/snippets/ /snippets/
ENV TZ UTC
@@ -65,7 +66,7 @@ ENV JWT_PRIVATE_KEY_SEED="${GOAWAY_JWT_PRIVATE_KEY_SEED}"
ENTRYPOINT /bin/go-away --bind "${GOAWAY_BIND}" --bind-network "${GOAWAY_BIND_NETWORK}" --socket-mode "${GOAWAY_SOCKET_MODE}" \
--metrics-bind "${GOAWAY_METRICS_BIND}" --debug-bind "${GOAWAY_DEBUG_BIND}" \
--config "${GOAWAY_CONFIG}" \
--policy "${GOAWAY_POLICY}" --policy-snippets "${GOAWAY_POLICY_SNIPPETS}" \
--policy "${GOAWAY_POLICY}" --policy-snippets "/snippets" --policy-snippets "${GOAWAY_POLICY_SNIPPETS}" \
--client-ip-header "${GOAWAY_CLIENT_IP_HEADER}" --backend-ip-header "${GOAWAY_BACKEND_IP_HEADER}" \
--cache "${GOAWAY_CACHE}" \
--challenge-template "${GOAWAY_CHALLENGE_TEMPLATE}" --challenge-template-theme "${GOAWAY_CHALLENGE_TEMPLATE_THEME}" \

View File

@@ -373,7 +373,7 @@ services:
volumes:
- "goaway_cache:/cache"
- "./examples/forgejo.yml:/policy.yml:ro"
- "./examples/snippets/:/policy/snippets/:ro"
#- "./your/snippets/:/policy/snippets/:ro"
environment:
#GOAWAY_BIND: ":8080"
# Supported tcp, unix, and proxy (for enabling PROXY module for request unwrapping)
@@ -418,7 +418,9 @@ services:
GOAWAY_POLICY: "/policy.yml"
GOAWAY_POLICY_SNIPPETS: "/policy/snippets"
# Include extra snippets to load from this path.
# Note that the default snippets from example/snippets/ are included by default
#GOAWAY_POLICY_SNIPPETS: "/policy/snippets"
# Template, and theme for the template to pick. defaults to an anubis-like one
# An file path can be specified. See embed/templates for a few examples

View File

@@ -73,7 +73,9 @@ func main() {
cachePath := flag.String("cache", path.Join(os.TempDir(), "go_away_cache"), "path to temporary cache directory")
policyFile := flag.String("policy", "", "path to policy YAML file")
policySnippets := flag.String("policy-snippets", "", "path to YAML snippets folder")
var policySnippets MultiVar
flag.Var(&policySnippets, "policy-snippets", "path to YAML snippets folder (can be specified multiple times)")
flag.StringVar(&opt.ChallengeTemplate, "challenge-template", opt.ChallengeTemplate, "name or path of the challenge template to use (anubis, forgejo)")
templateTheme := flag.String("challenge-template-theme", opt.ChallengeTemplateOverrides["Theme"], "name of the challenge template theme to use (forgejo => [forgejo-auto, forgejo-dark, forgejo-light, gitea...])")
@@ -232,7 +234,7 @@ func main() {
return nil, fmt.Errorf("failed to read policy file: %w", err)
}
p, err := policy.NewPolicy(bytes.NewReader(policyData), *policySnippets)
p, err := policy.NewPolicy(bytes.NewReader(policyData), policySnippets...)
if err != nil {
return nil, fmt.Errorf("failed to parse policy file: %w", err)
}

View File

@@ -20,66 +20,77 @@ type Policy struct {
Rules []Rule `yaml:"rules"`
}
func NewPolicy(r io.Reader, snippetsDirectory string) (*Policy, error) {
func NewPolicy(r io.Reader, snippetsDirectories ...string) (*Policy, error) {
var p Policy
p.Networks = make(map[string][]Network)
p.Conditions = make(map[string][]string)
p.Challenges = make(map[string]Challenge)
if snippetsDirectory == "" {
if len(snippetsDirectories) == 0 {
err := yaml.NewDecoder(r).Decode(&p)
if err != nil {
return nil, err
}
} else {
err := yaml.NewDecoder(r, yaml.ReferenceDirs(snippetsDirectory)).Decode(&p)
var entries []string
for _, dir := range snippetsDirectories {
if dir == "" {
// skip nil directories
continue
}
dirFiles, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
for _, file := range dirFiles {
if file.IsDir() {
continue
}
entries = append(entries, path.Join(dir, file.Name()))
}
}
err := yaml.NewDecoder(r, yaml.ReferenceFiles(entries...)).Decode(&p)
if err != nil {
return nil, err
}
// add specific entries from snippets
entries, err := os.ReadDir(snippetsDirectory)
if err != nil {
return nil, err
}
for _, entry := range entries {
var entryPolicy Policy
if !entry.IsDir() {
entryData, err := os.ReadFile(path.Join(snippetsDirectory, entry.Name()))
if err != nil {
return nil, err
}
err = yaml.NewDecoder(bytes.NewReader(entryData), yaml.ReferenceDirs(snippetsDirectory)).Decode(&entryPolicy)
if err != nil {
return nil, err
}
entryData, err := os.ReadFile(entry)
if err != nil {
return nil, err
}
err = yaml.NewDecoder(bytes.NewReader(entryData), yaml.ReferenceFiles(entries...)).Decode(&entryPolicy)
if err != nil {
return nil, err
}
// add networks / conditions / challenges definitions if they don't exist already
// add networks / conditions / challenges definitions if they don't exist already
for k, v := range entryPolicy.Networks {
// add network if policy entry does not exist
_, ok := p.Networks[k]
if !ok {
p.Networks[k] = v
}
for k, v := range entryPolicy.Networks {
// add network if policy entry does not exist
_, ok := p.Networks[k]
if !ok {
p.Networks[k] = v
}
}
for k, v := range entryPolicy.Conditions {
// add condition if policy entry does not exist
_, ok := p.Conditions[k]
if !ok {
p.Conditions[k] = v
}
for k, v := range entryPolicy.Conditions {
// add condition if policy entry does not exist
_, ok := p.Conditions[k]
if !ok {
p.Conditions[k] = v
}
}
for k, v := range entryPolicy.Challenges {
// add challenge if policy entry does not exist
_, ok := p.Challenges[k]
if !ok {
p.Challenges[k] = v
}
for k, v := range entryPolicy.Challenges {
// add challenge if policy entry does not exist
_, ok := p.Challenges[k]
if !ok {
p.Challenges[k] = v
}
}
}
}