Skip to main content

I was asked by a customer to write an NQE check that would trigger a violation if there was not an explicit deny rule at the end of an ACL list. This query breaks down the acl list by acl name leveraging the group-by qualifier. 

We are also leveraging the `maxBy` function to find the last entry by leveraging the lineNumber property.
 

// /**
// * @intent Find acls by name, count and last entry
// * @description test if there is an explicity deny rule at end of acl list
// */
acl_pattern_1 =
`access-list {aclName:string} {!"remark"} {action:string} {rest:(string*)}`;

maxLine(l) = l.line.lineNumber;

foreach device in network.devices
where device.platform.vendor == Vendor.CISCO
let acls = patternMatches(device.files.config, acl_pattern_1)
let acl_groups = (foreach acl in acls
group acl as group_acls_by_name
by { deviceName: device.name, aclName: acl.data.aclName
}
as v
select {
device: v.deviceName,
aclName: v.aclName,
count: length(group_acls_by_name),
last: maxBy(group_acls_by_name, maxLine)
})
foreach acl in acl_groups
let violation = !matches(toLowerCase(acl.last.data.action), "deny")
select {
violation,
device: acl.device,
aclName: acl.aclName,
aclCount: acl.count,
lastRule: acl.last
}

 

@GaryB

Any idea how can I accomplish the same on a Juniper device? Basically looking to Ensure firewall filters contain explicit deny and log term.


cabellooa contacted me directly.  We went though his issue.  I essentially used the same function as Garyb.  I had to use patternMatches to get a single line match, this way I could get the lineNumber.  With that lineNumber I used the “maxBy” function to find the last filter “term” by sorting on the lineNumber of the term name.

Look at “lastTerm”.

 

pattern = ```
firewall
family inet
filter {filter_name:string}
term {term_name:string}
```;

pattern1 =
```
firewall
family inet
filter
term {term_name:string}
then
log;
discard;
```;

getLastTerm(term) = term.line.lineNumber;

foreach device in network.devices
where device.platform.os == OS.JUNOS
let config = device.files.config

foreach firewall in patternMatches(config, `firewall`)
foreach family in patternMatches(firewall.line.children, `family inet`)
foreach filter
in patternMatches(family.line.children, `filter {filter_name:string}`)
let termList = (foreach term
in patternMatches(filter.line.children, `term {term_name:string}`)
select term)
let lastTerm = maxBy(termList, getLastTerm)
let termWithStuffList = (foreach termWithStuff in blockMatches(config, pattern1)
select termWithStuff)
let termNameWithStuffList = (foreach termWithStuff
in blockMatches(config, pattern1)
select termWithStuff.data.term_name)
foreach term in termList
select {
"Device Name": device.name,
Platform: "junos",
Result: if term.data.term_name in termNameWithStuffList
then "PASS"
else "FAIL",
violation: term.data.term_name not in termNameWithStuffList,
Filterame: filter.data.filter_name,
TermName: if isPresent(term) then term.data.term_name else "",
lastTerm: lastTerm.data.term_name
}

 


Reply