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
}