In a typical enterprise environment, NTP server configurations may differ not just between vendors, but even across OS variants within the same vendor. Ensuring that these configurations are correct and standardized is critical for time synchronization, which underpins security, logging, and automation.
Instead of building and maintaining separate validation queries for each device type, Forward Enterprise enables users to create a single exportable function that applies logic conditionally based on the OS.
This approach streamlines configuration auditing and improves operational consistency across diverse infrastructure.
The getNtpServers(device) function returns a list of NTP servers for any device type. Internally, it routes logic using a when statement to OS-specific functions such as getCiscoNtpServers, getFortinetNtpServers, and so on.
The function checks whether NTP settings are present using platform-specific patterns and logic:
Each OS-specific helper function returns a list of serverId values extracted from matching blocks.
This modular design allows you to easily add support for new vendors or update patterns without rewriting the entire function.
After creating and exporting the getNtpServers(device) function, you can use it in any query by importing it from the Helper Functions folder in your Org Repository:
import "Helper Functions/GET NTP Servers";
foreach device in network.devices
where device.platform.vendor != Vendor.FORWARD_CUSTOM
let ntpServers = getNtpServers(device)
select {
violation: !isPresent (max(ntpServers)),
device: device.name,
vendor: device.platform.vendor,
OS: device.platform.os,
"NTPSERVERS": ntpServers
}
This query will show a violation if no NTP servers are present, excluding Forward synthetic devices. The simplicity of the line let ntpServers = getNtpServers(device) demonstrates the power of reusable functions in NQE.
To maintain a scalable query library, Forward Networks recommends saving commonly used functions in a folder named Helper Functions at the root of your Org Repository.
Functions like getNtpServers, getDnsServers, and getSnmpSettings can then be imported as needed in multiple queries, reducing duplication and enabling faster onboarding for new team members.
Following this structure also ensures consistency and allows teams to quickly adopt updates to centralized logic.