Find answers to your NQE questions and share NQEs you've developed.
Recently active
This query returns a list of devices, their public BGP peers, and the prefixes advertised to each peer.Note that the line where neighbor.neighborAddress not in nonPublicIps limits the output to peers whose IP is not an RFC 1918 or link-local IP address./*** @intent Lists public BGP peers and what prefixes are advertised to them*/import "@fwd/L3/IpAddressUtils";// The prefixes that are advertised from device to neighborAddressgetAdvRoutes(device, neighborAddress) = foreach x in [1] where isPresent(device.bgpRib) let bgpRib = device.bgpRib foreach afiSafi in bgpRib.afiSafis foreach neighbor in afiSafi.neighbors where neighbor.neighborAddress == neighborAddress where isPresent(neighbor.adjRibOutPost) let adjRibOutPost = neighbor.adjRibOutPost foreach route in adjRibOutPost.routes select distinct route.prefix;// List of IP subnets to excludenonPublicIps = ipAddressSet(privateSubnets + [ipSubnet("169.254.0.0/16")]);foreach device in network.devicesforeach networkInstance in de
Is often necessary to audit the same setting across multiple vendors.For example, the NTP server setting differs across vendors.You can write an exportable function that returns the NTP servers for ANY device type.The following NQE query creates a reusable function called getNtpServers with the export command. The function takes a single argument device and returns a list of NTP servers based on the device type. A different function is called using the when statement based on the OS. Note that the NTP server configuration in Cisco devices is in the device.files.config file (the running configuration), but for Fortinet and F5 devices you need the result of a Custom Command to see the NTP configuration.Note also that the same nested function getCiscoNtpServers is used for multiple Cisco OS types.If you find an OS type or pattern that isn’t identified, you can add in new patterns and functions, or alter or expand the patterns already included./** * @intent Helper function getNtpServers(de
Often you need to verify that the configuration of your network matches certain requirements. These could be standard benchmarks, such as CIS benchmarks, or internal benchmarks specific to your environment.For example, you may need to:Verify that all Cisco devices have only SSH version 2 enabled Verify that all Palo Alto devices have a login banner set Verify the mininum password length for Fortinet devices Combining multiple checks into a single NQE queryYou can verify these settings, or anything else in the configuration, using NQE. Verify that all Cisco devices have only SSH version 2 enabled The following query looks for the exact pattern ssh version 2 in the device configuration file (device.files.config). If the pattern does not exist (!checkpattern), then the violation will be True. pattern =```ssh version 2```;checkPattern(config) =hasBlockMatch(config, pattern);foreach device in network.deviceswhere device.platform.vendor == Vendor.CISCOselect {device: device.name,os: device.p
In Inventory, you have probably noticed how some table columns make it easy to spot issues at a glance. Green means things are healthy and red means something needs attention. The Status column in the Network devices table, located in Inventory, is a good example: “processed” shows up in green while something like “connection refused” stands out in red.Now, you can bring the same visual feedback into your own NQE queries. We’ve added a new builtin called withInfoStatus. It lets you tag any value in your result table with a label: OK, WARNING, or ERROR. The results table uses that label to color values appropriately.Here is an example. Suppose you want to flag devices whose OS support has already ended. This query checks if the support date is in the past and then labels it. foreach device in network.deviceslet platform = device.platformlet osSupport = platform.osSupportwhere isPresent(osSupport) && isPresent(device.snapshotInfo.collectionTime)let collectionDate = date(device.s
This NQE script helps you spot firewall rules that haven’t processed traffic lately. It flags rules as unused if they haven’t processed any packets in the last 30 days—but only on active firewalls (not ones in BACKUP or STANDALONE_INACTIVE modes).If you have rules that are supposed to be quiet (like for failover scenarios), you can list them in expectedUnusedRules so they don’t show up as false positives.As a bonus, it also highlights newly created rules—anything added in the last 30 days—so you get visibility into what’s changing as well as what’s sitting idle.All timing is based on the device’s snapshot collection time. You can also find this script in the Forward NQE LibraryForward Library > Security > Firewalls with Unused Security Rules/** * @intent Verifies that active firewalls have no unused security rules * @description This query considers a rule to be unused if it last processed * a packet more than 30 days ago. This query only applies this check to * firewalls that
Is it possible to write a Forward NQE query that will produce a list of firewall rules that have been modified in the last 30 days? It would be helpful to have firewall name, the rule ID numbers, and date/time last modified if possible.
This NQE uses the L3 interface info and ARP tables to find the subnets in use on your network. It lists the associated vlan, used addresses, devices, and usage statistics.An optional parameter allows you to search for an IP address, and whether the IP is in use or not, it will display the subnet it belongs to.import "@fwd/L3/Interface Utilities";numHostsInSubnetV4(maskLength) = if 2 ^ (32 - maskLength) >= 4 then 2 ^ (32 - maskLength) - 2 else 2 ^ (32 - maskLength);numHostsInSubnetV6(maskLength) = 2 ^ (128 - maskLength);@queryquery(IP_Addresses: List<IpAddress>) = foreach device in network.devices foreach interface in getL3Interfaces(device) let addresses = (foreach address in interface.ipv4.addresses select { ip: address.ip, mask: address.prefixLength }) + (foreach address in interface.ipv6.addresses select { ip: address.ip, mask: address.prefixLength }) let neighbors = (foreach address in interface.ipv4.neighbors
Before I started using Forward Networks, I was deep in the weeds of daily network operations. Like many of you, I relied on the CLI to do everything—whether it was compliance checks, interface audits, or config validation. It worked, but it was slow, manual, and honestly, a bit exhausting. Then I discovered Network Query Engine (NQE), and everything changed. My Background: Life in the CLI Before discovering NQE, I managed networks using CLI commands across dozens or hundreds of devices every day.Logging into individual devices—one at a time Running the same commands repeatedly (show run | include, show run | section, etc.) Copying results into spreadsheets to figure out what was going on Trying to get ahead of issues, but always feeling like I was behind This approach worked for a while, but it became clear that it couldn’t scale with the needs of a modern network. The Breakthrough: Pattern and Block MatchingWhen I began exploring NQE, I realized I didn’t need to learn everythin
Motivation A customer recently approached me with a challenge: they wanted to feed downstream systems with ordered and banded firewall data. Specifically, they had the following use cases:Identify Top-N firewalls based on configuration complexity and other attributes like greatest number of permissive or shadow rules. Flag percentile-based thresholds for various attributes (e.g., top 10%, bottom 25%) Enable dynamic device selection for exhaustive, compute-heavy rule analysis The challenge? NQE is designed for efficient set-based analysis, therefore it doesn’t require sorting or ranking functions in general. Nevertheless, this customer’s use case called for an approach to simulate these behaviors without external processing.So instead of relying on a built-in sort function, we can create a lightweight, math-driven approach that simulates ranking behavior. It’s fast, deterministic, and works entirely inside the NQE layer so that no external processing or comparisons are required.In th
I am trying to match against a Palo Alto configuration looking for rules that are using a specific destination object. Rules are under this structure:config devices {string} vsys {string} rulebase security rules {rule_name: (string)*} and an example of what I am trying to match is: "Example Rule" e32ff2ab-a82f-43b6-953e-7e113v624779 { destination [ non-client "External SRC EDL" "Another EDL-wehave"]; First line would be the rule name and the second is where I would really want to do the regex match. The items past “destination” can be a single entry or multiples within []’s. If there are spaces in the names then the whole name is confined in “’s. My goal is to find all rules which have “External SRC EDL” in the destination and I can’t quite figure out how to do it. Any help would be appreciated.
How can i get output in single coloum . team , i am using below query to get the NTP Server data , however is tried all option to get the output in single coloum , but i am not sucess. NQE Query ciscontppattern=```ntp server {server:string}```;ciscontppattern2=```ntp server {vrf:string} {dir:string} {ser:ipv4Address}```;patternf5 = ```sys ntp servers { server1:string} {server2:string}```;cisco1(device) =foreach command in device.outputs.commands let response = parseConfigBlocks(device.platform.os, command.response) foreach match in blockMatches(response, ciscontppattern) select match.data.server;cisco2(device) =foreach command in device.outputs.commands let response = parseConfigBlocks(device.platform.os, command.response) foreach match in blockMatches(response, ciscontppattern2) select match.data.ser;getServers(device) =foreach command in device.outputs.commands where command.commandText == "list sys ntp"let filtered_response = replace(command.response, "{", "")let filtered_
This NQE will validate that only the SSID’s in allowedSSID’s can be used, if it does not exists in the list it will fail the query.Taking advice from an earlier post I have used blockMatches this time, there is some tuning required to remove the duplicates as a result of the table have the entry for each /** * @intent Validate that the arista AP's have only the approved SSID's configured * @description This will check each arista AP for the approved SSIDs and violate when ther SSID does not match * the allowedSSID list. * * You will get multiple entries due to the VAPS list having an entry for each frequency. This will be a future * fix to show only once when the unauthoirised SSID exists */pattern = ```VAP-ID : {VAPId:string} ESSID : {SSID:string}```;// Replace the SSID's with your own.allowedSSID = ["ssid1","ssid2","ssid3"];foreach endpoint in network.endpointswhere endpoint.profileName == "Arista Wireless AP's"foreach command in endpoint.cliCommandRespons
Following on from I thought I would share this NQE if others are using Arista AP’s and want to maintain version numbers across their estate. /** * @intent List all Arista AP's and there software version. * @description List all Arista AP End Points and there software version. */allowedVersion = "18.0.0";foreach endpoint in network.endpointswhere endpoint.profileName == "Arista Wireless AP's"foreach command in endpoint.cliCommandResponseswhere command.command == "show device info"let ParsedResponse = parseConfigBlocks(OS.UNKNOWN,command.response)foreach line in ParsedResponselet modelNo = patternMatch(line.text,`Device Model : {string}`)foreach line in ParsedResponselet software = patternMatch(line.text, `Device Version : {string}`)foreach line in ParsedResponselet serialNo = patternMatch(line.text,`Serial Number : {string}`)where isPresent(modelNo)where isPresent(software)where isPresent(serialNo)select { violation: software != allowedVersion, name: endpoint.name, location
I have put together a query to enhance inventory by adding LDoS dates and ‘approved software’. It has greatly improved our Life Cycle Mgmt. conversations. The CSV Files reside separately in a ‘standards’ folder. (there are just too many fields to keep in the same script).The resulting output provides:Vendor | Hostname | Model | Location | Vendor LDoS Date | HW Compliance Date | Current OS | Approved OS | Compliance to OS | Replacement Mode | And more /** * @intent Get OS Versions of all models and compare to ADP and Vendor Standards */// Get TagName Function - If you put tagnames on objects in forward Networks and you want to pull them out into columns.// You can define the tags in the export functions below and pull them out as a column. Below you can see the // Tags in "xxx" that we want to pull - ex ["DC", "CoLo", "Branch", "Cloud", "AWS"]);// Environment: get_env_from_tags(device.tagNames),// Region: get_region_from_tags(device.tagNames),// Function: get_function_from_tags(device.
It is possible to compare the output of an NQE query using the Diffs feature by first adding the NQE query to Inventory+.Consider the following NQE query, which lists all the static routes on all devices. (Note that the next hop is listed in this example provided that the next hop is an IP address. The query could be expanded to handle other types of next hops). getStaticRoutes(routingTable) = foreach ipEntry in routingTable.ipEntries foreach nextHop in ipEntry.nextHops where nextHop.originProtocol == OriginProtocol.STATIC select { prefix: ipEntry.prefix, nextHopType: nextHop.nextHopType, nextHop: ipEntry.nextHops };foreach device in network.devicesforeach networkInstance in device.networkInstanceslet afts = networkInstance.aftswhere isPresent(afts.ipv4Unicast)let ipv4Unicast = afts.ipv4Unicastlet staticRouteCount = length(getStaticRoutes(ipv4Unicast))where staticRouteCount > 0foreach entry in getStaticRoutes(ipv4Unicast)select { Device: device.name, "Network Instanc
I provided a query for doing this some time ago. However, it was written for running where the Data Model did not have as many BGP elements as the current Data Model. Now that there are more BGP elements in the data model it makes this query much simpler. Which also means it runs faster.The inspiration for this query was a customer that run BGP between pretty much all devices. This is why it is only based on BGP peers./** * @intent Input the device under maintenance. get the list of BGP peers and outbound interfaces * @description This is a Parameterized Query. You input the devicename string. * it will look for the BGP peers of that devices, plus determine the interfaces that connect the * devices together. This way you can mute the alarms for the BGP peers and links before a maintenance window. */import "@fwd/L3/Interface Utilities"; //getL3Interfaces(device: Device)getPeerInfo(neighbor, sourceRouterId) = max(foreach device in network.devices where device.name == neighbor.
When working with STIG compliance checks, a common challenge is that many checks only verify the existence of a control—not whether the configured values align with site-specific requirements. This can be a problem when compliance policies vary across different data centers and locations.With a little work, it is easy to customize the queries. Benefits are apparent. You get: more precision to verify your specific ACL and group names Verifying differing configuration policies across multiple data centers or locations Improved compliance and governance across a variety of configurations and regionsThere are two approaches you can use to customize queries.Copy the query and modify the block match to include the value of your parameter Parametrize the query and use your location-specific string value as a query parameter. Parameterized queries are slightly more complex but make existing STIG checks - and other NQEs - more flexible.Let’s use an example of a library STIG query /Forward Libra
we are using 4 different query to get some information in FWD , is their any way to merge these queries into one and get the output in single file.Query 1 for NTP Fortinet :- pattern_fmg = ```config system ntp config ntpserver edit 1 set server {ntp1:string}```;pattern_servers = ```config system ntp config ntpserver edit 2 set server {ntp2:string} ```;pattern_servers2 = ```config system ntp config ntpserver edit 3 set server {ntp3:string}```;// Loop through list of devices finding those that are Fortinet// and store outputs of commands in the 'outputs' variable// Loop through list of devices finding those that are Fortinetforeach device in network.devices/* where device.platform.vendor == Vendor.FORTINET */let outputs = device.outputs// Loop through the commands in the outputs var, looking for custom// commands that are from 'show system ntp' and store in a variable called central_mgmtforeach command in outputs.com
Team ,we are using belong NQE to get the information about Fortinet Firewall SNMP config and server white list information , however NQE provide the result , but devices are repeating ,ex, 1 devices we can see approx. 44 entry , can you please have a look on this and help us to fix . NQE Query // Patterns to match pattern_community= ```config system snmp community edit {string} set name {community:string} config hosts edit {string} set ip {ip:string} {netmask:string} next ```; foreach device in network.deviceslet outputs = device.outputs foreach command in outputs.commandswhere command.commandType == CommandType.CUSTOMwhere command.commandText == "show system snmp community"let central_mgmt = parseConfigBlocks(OS.FORTINET, command.response) // Search for the ""pattern_fmg" pattern looking for a matchforeach match in blockMatches(central_mgmt, pattern_community)//loop through the all server-address IP's and store them in variable
We continue to rely almost exclusively on Forward Networks for our lifecycle management and planning (purchasing). One of the big gaps, however, was I couldn’t get the Wireless Access Points on the network, and had to go to other devices and export it into excel. Not terrible, but time consuming. You can also check out my related post: I threw together simple script to collect the Cisco AP’s “Name/Location/AP-Model/IP-Address/Country-Code. @AhmedKhedr Pre-requisites: Add Custom Command to IOS-XE for collection “show ap sum” Add Tag of “WLC” on your Wireless Controllers WLC’s are on c9800 running IOS-XE IOS-XE version is 17.9.6It appears older versions of OS (<17.9.6) don’t align nicely, but i’m sure you can adjust for it using the core of this script. I’m adding one more table to this, to pull the LDoS date from the model that is pulled from the custom command… which I will update when I get it to work ;-)/*** @intent - pull Name & Model & IP address* @description Log into
how can i convert OS EOL query into basis of vendor and version ? as of now in OS Support query showing output via device wise , i want to see this in to vendor os wise.
I was asked to do pull all the password encryption methods for Cisco (route-switch) devices from our security team.Here are a couple of NQE that I wrote to send off to the security team, hopefully it might be of use to someone else. They are pretty simple but if anyone has recommendations to enhance or combine into a single script, lemme know!Results: Showing IOS/IOS_XE DevicesNexus - ** Add custom command to collection for NX-OS Devicesshow run | grep admin password/** * @intent Show encryption level and method on Cisco NX-OS devices * Test * @description Use CSV table below to match Encryption Level to Method * add custom command for NXOS devices: show run | grep admin password**/Encrpytion = """csvEncryLvl,EncryMeth9,SCRYPT-Hash5,MD54,SHA25610,SHA5127,Cisco_Type7-Algorithm0,No-Encryption""";pattern1 = ```{username:string} {admin:string} {PW:string} {Level:number} {str:string} {role:string} {NA:string}```;foreach device in network.deviceslet platform = device.platformwhere platform
It may be useful to compare the output of a traceroute against the Path Search output from Forward Networks.The following NQE query takes a list of IP addresses as a parameter, and returns a list of devices based on interface IPs.This query could be used while onboarding sources into Forward Networks. If there is no device entry for an interface IP address from this NQE, it could mean that the device with that IP address needs to be added to the collection (to Sources).If there is overlapping IP space in the network - for example, if private IP space for network interface IPs at difference locations is the same - this query will return ALL the devices with a given interface IP.Note that Forward Networks’ Path Search is superior to traceroute in that Path Search will shows layer-2 hops and cloud network objects that don’t respond to traceroute. import "@fwd/Interfaces/Interface IPs";deviceIps = foreach device in network.devices select { device: device.name, ips: (foreach record
how can i get information about device uptime ?
This NQE can be a quick way for you to identify interfaces and subinterfaces with configured ACLs. This could be invaluable from a couple angles: path analysis/troubleshooting and audit.Check it out! Let me know what you think!*I put both where length(acls.inboundAclNames) > 0 && length(acls.outboundAclNames) > 0andwhere length(acls.inboundAclNames) > 0 || length(acls.outboundAclNames) > 0because I feel both can have benefit in their own circumstances.foreach device in network.devicesforeach interface in device.interfacesforeach subinterface in interface.subinterfaceslet acls = subinterface.aclswhere length(acls.inboundAclNames) > 0 && length(acls.outboundAclNames) > 0// where length(acls.inboundAclNames) > 0 || length(acls.outboundAclNames) > 0select { deviceName: device.name, asset: device.tagNames, interfaceName: interface.name, subinterfaceName: subinterface.name, inboundAclNames: acls.inboundAclNames, outboundAclNames: acls.outboundAcl
Already have an account? Login
No account yet? Create an account
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.