One of my customers came to me with a problem.
Given a list of servers, how to determine if the keys applied are unique.
Took some overnight thinking on this but using a simple approach with our group qualifier we can restructure the output in a way we can make the evaluation.
The first thing we need to do is provide the input data.
You should always have data that will represent a pass and a failure scenario. This way when posting here on the community, others can replicate the query and have a firm understanding of the outcome
testpass =
"""
set system ntp server 1.1.1.1 key 1
set system ntp server 2.2.2.2 key 2
set system ntp server 3.3.3.3 key 3
""";
testfail =
"""
set system ntp server 1.1.1.1 key 2
set system ntp server 2.2.2.2 key 2
set system ntp server 3.3.3.3 key 3
""";
So we need to ensure that for the list of servers that each key is unique i.e. there are no servers that are using the same key. We also want to be able to identify the offenders so they can be remediated
The expression below lets us reorganize the data into a list of keys and a count. We could just do a test on the length of the list, but lets make it explicit here so whoever looks at the code can understand we are looking for a count.
let groupKeys = (foreach item in ks
group item.key as groupKey by item.key as k
select { groupKey: groupKey, count: length(groupKey) })
Now we can filter the list of servers and their keys by filtering out only the servers that have duplicates
let key_violation = (foreach server_key in ks
foreach key in groupKeys
where key.count > 1 && server_key.key in key.groupKey
select server_key)
Setup your test harness so that you can have your pass/fail tests
foreach x
in { name: "testpass", test: testpass },
{ name: "testfail", test: testfail }
]
Include test details on your output.
select {violation, Input: ks, test: x.name, key_violation }
Now anyone can repeat your test and have the proper output to understand the results.
Output
Complete query
testpass =
"""
set system ntp server 1.1.1.1 key 1
set system ntp server 2.2.2.2 key 2
set system ntp server 3.3.3.3 key 3
""";
testfail =
"""
set system ntp server 1.1.1.1 key 2
set system ntp server 2.2.2.2 key 2
set system ntp server 3.3.3.3 key 3
""";
pattern_ntp_keys =
```
set system ntp server {server:string} key {key:string}
```;
// get all keys
getServerAndKeys(config) =
foreach match in blockMatches(config, pattern_ntp_keys)
select { server: match.data.server, key: match.data.key };
foreach x
in { name: "testpass", test: testpass },
{ name: "testfail", test: testfail }
]
let config = parseConfigBlocks(OS.UNKNOWN, x.test)
let ks = getServerAndKeys(config)
let groupKeys = (foreach item in ks
group item.key as groupKey by item.key as k
select { groupKey: groupKey, count: length(groupKey) })
let key_violation = (foreach server_key in ks
foreach key in groupKeys
where key.count > 1 && server_key.key in key.groupKey
select server_key)
let violation = length(key_violation) > 0
select {violation, Input: ks, test: x.name, key_violation }