Skip to content

Commit c2a3c07

Browse files
committed
Adds parse option for custom directives, moves nap directives
Added an API for allowing the caller of `Parse` to specify bitmasks for directives outsides the "core" set of NGINX directives. This would allow the caller to parse an NGINX configuration that contained directives from a dynamic module even if it is a unknown custom one as long as the configuration still matches the expected grammar. As part of this I moved the NAP WAF v4 directives out of the main `directives` map and added directives for WAF v5.
1 parent bbaed72 commit c2a3c07

File tree

5 files changed

+447
-2
lines changed

5 files changed

+447
-2
lines changed

analyze.go

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ func analyze(fname string, stmt *Directive, term string, ctx blockCtx, options *
9494
masks, knownDirective := directives[stmt.Directive]
9595
currCtx, knownContext := contexts[ctx.key()]
9696

97+
if !knownDirective {
98+
for _, matchFn := range options.MatchFuncs {
99+
if masks, knownDirective = matchFn(stmt.Directive); knownDirective {
100+
break
101+
}
102+
}
103+
}
104+
97105
// if strict and directive isn't recognized then throw error
98106
if options.ErrorOnUnknownDirectives && !knownDirective {
99107
return &ParseError{
@@ -2401,9 +2409,11 @@ var directives = map[string][]uint{
24012409
"zone_sync_timeout": {
24022410
ngxStreamMainConf | ngxStreamSrvConf | ngxConfTake1,
24032411
},
2412+
}
24042413

2405-
// nginx app protect specific and global directives
2406-
// [https://docs.nginx.com/nginx-app-protect/configuration-guide/configuration/#directives]
2414+
// nginx app protect specific and global directives
2415+
// [https://docs.nginx.com/nginx-app-protect/configuration-guide/configuration/#directives]
2416+
var appProtectWAFv4Directives = map[string][]uint{
24072417
"app_protect_compressed_requests_action": {
24082418
ngxHTTPMainConf | ngxConfTake1,
24092419
},
@@ -2441,3 +2451,58 @@ var directives = map[string][]uint{
24412451
ngxHTTPMainConf | ngxConfTake1,
24422452
},
24432453
}
2454+
2455+
// MatchAppProtectWAFv4 is a match function for parsing an NGINX config that contains the
2456+
// App Protect v4 module.
2457+
func MatchAppProtectWAFv4(directive string) (masks []uint, matched bool) {
2458+
masks, matched = appProtectWAFv4Directives[directive]
2459+
return
2460+
}
2461+
2462+
var appProtectWAFv5Directives = map[string][]uint{
2463+
// https://docs.nginx.com/nginx-app-protect-waf/v5/configuration-guide/configuration/#global-directives
2464+
"app_protect_physical_memory_util_thresholds": {
2465+
ngxHTTPMainConf | ngxConfTake2,
2466+
},
2467+
"app_protect_cpu_thresholds": {
2468+
ngxHTTPMainConf | ngxConfTake2,
2469+
},
2470+
"app_protect_failure_mode_action": {
2471+
ngxHTTPMainConf | ngxConfTake1,
2472+
},
2473+
"app_protect_cookie_seed": {
2474+
ngxHTTPMainConf | ngxConfTake1,
2475+
},
2476+
"app_protect_request_buffer_overflow_action": {
2477+
ngxHTTPMainConf | ngxConfTake1,
2478+
},
2479+
"app_protect_reconnect_period_seconds": {
2480+
ngxHTTPMainConf | ngxConfTake1,
2481+
},
2482+
// https://docs.nginx.com/nginx-app-protect-waf/v5/configuration-guide/configuration/#app-protect-specific-directives
2483+
"app_protect_enforcer_address": {
2484+
ngxHTTPMainConf | ngxConfTake1,
2485+
},
2486+
"app_protect_enable": {
2487+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag,
2488+
},
2489+
"app_protect_policy_file": {
2490+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1,
2491+
},
2492+
"app_protect_security_log_enable": {
2493+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfFlag,
2494+
},
2495+
"app_protect_security_log": {
2496+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2,
2497+
},
2498+
"app_protect_custom_log_attribute": {
2499+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLmtConf | ngxConfTake2,
2500+
},
2501+
}
2502+
2503+
// MatchAppProtectWAFv5 is a match function for parsing an NGINX config that contains the
2504+
// App Protect v5 module.
2505+
func MatchAppProtectWAFv5(directive string) (masks []uint, matched bool) {
2506+
masks, matched = appProtectWAFv5Directives[directive]
2507+
return
2508+
}

parse.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ type parser struct {
5353
includeInDegree map[string]int
5454
}
5555

56+
// MatchFunc is the signature of the match function used to identify NGINX directives that
57+
// can be encountered when parsing an NGINX configuration that references dynamic or
58+
// non-core modules. The argument is the name of a directive found when parsing an NGINX
59+
// configuration.
60+
//
61+
// The return value is a list of bitmasks that indicate the valid contexts in which the
62+
// directive may appear as well as the number of arguments the directive accepts. The
63+
// return value must contain at least one non-zero bitmask if matched is true.
64+
type MatchFunc func(directive string) (masks []uint, matched bool)
65+
5666
// ParseOptions determine the behavior of an NGINX config parse.
5767
type ParseOptions struct {
5868
// An array of directives to skip over and not include in the payload.
@@ -93,6 +103,12 @@ type ParseOptions struct {
93103

94104
// If true, checks that directives have a valid number of arguments.
95105
SkipDirectiveArgsCheck bool
106+
107+
// MatchFuncs are called in order when an unknown or non-core NGINX directive is
108+
// encountered by the parser to determine the valid contexts and argument count of the
109+
// directive. Set this option to enable parsing of directives belonging to non-core or
110+
// dynamic NGINX modules that follow the usual grammar rules of an NGINX configuration.
111+
MatchFuncs []MatchFunc
96112
}
97113

98114
// Parse parses an NGINX configuration file.

0 commit comments

Comments
 (0)