Rego Validation Array Compare - open-policy-agent

I am new at Rego and I am trying to write a policy in order to check if there is a set of rules already created on certain Azure NSGs.
Input test:
{
"name": "<name>",
"id": "<id>",
"etag": "<etag>",
"type": "<resourcetype>",
"location": "<location>",
"properties":
{
"provisioningState": "Succeeded",
"resourceGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"securityRules":
[
{
"name": "<rule name>",
"id": "<id>",
"etag": "<etag",
"type": "<type>",
"properties":
{
"provisioningState": "Succeeded",
"description": "....",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "53",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes":
[
"10.0.0.1",
"10.0.0.2",
"10.0.0.3"
]
}
}
]
{
}
I wrote a custom function in order to check the values. Below is the code that I am testing in The Rego Playground
existRule(rule) = true
{
input.properties.securityRules[i].name == rule.name
input.properties.securityRules[i].properties.provisioningState == rule.provisioningState
input.properties.securityRules[i].properties.description == rule.description
input.properties.securityRules[i].properties.protocol == rule.protocol
input.properties.securityRules[i].properties.access == rule.access
input.properties.securityRules[i].properties.priority == rule.priority
input.properties.securityRules[i].properties.direction == rule.direction
}
rule = {
"name": "name",
"provisioningState": "Succeeded",
"description": "description",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "1",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"destinationAddressPrefix": "",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [
"10.0.0.1",
"10.0.0.2",
"10.0.0.3",
"10.0.0.4"
]
}
rules
{
existRule(rule)
}
which is working for the properties that I define above, however I am having an issue when trying to compare arrays, particularly in this example with destinationAddressPrefixes
I have tried the following:
test1 { input.properties.securityRules[i].properties.destinationAddressPrefixes == rule.destinationAddressPrefixes }
Always returns false
With the following line I can check one destination address from the input against a specific ip, however I can not achive a compare of all the address of the input against the ones of the rule that is defined in the example
onerule {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == "10.0.0.1"}
test2 {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == rule.destinationAddressPrefixes[j]}
test3 {input.properties.securityRules[i].properties.destinationAddressPrefixes[j] == rule.destinationAddressPrefixes[k]}
test2 and test3 always return true, even when there is a rule that is not in the input. I also tried and array difference
x := input.properties.securityRules[i].properties.destinationAddressPrefixes - rule.destinationAddressPrefixes
but I get the following error:
rego_type_error: minus: invalid argument(s) have: (any, array<string,
string, string, string, string, string, string, string, string,
string, string, string, string, string>, ???) want: (any<number,
set[any]>, any<number, set[any]>, any<number, set[any]>)
Do you know if it is feasible to achieve what I am looking for? Or is there a different way to make a look of the array and compare the values one by one?

What does rule3400.destinationAddressPrefixes look like?
If you want to compare for exact equality between two arrays, == should suffice.
If all elements are known to be unique and order doesn't matter (which seems to be the case in your example) you could convert the arrays to sets using a set comprehension. This makes it possible to subtract one set from another such as you tried to do with arrays directly.
to_set(arr) = {x | x := arr[_]}
input_prefixes := to_set(input.properties.securityRules[i].properties.destinationAddressPrefixes)
destination_prefixes := to_set(rule3400.destinationAddressPrefixes)
x := input_prefixes - destination_prefixes

Related

OpenAPI field validation precedence

Let's imagine I have a schema with 2 properties:
"properties": {
"name": {
"type": "string",
"minLength": 2,
"pattern": "<some unmatchable pattern>",
"x-constraints": "Capitalized(required = true)"
},
"petType": {
"type": "string",
"minLength": 2,
"pattern": "<some unmatchable pattern>",
"x-constraints": "Capitalized(required = true)"
}
}
What will happen if I send an invalid field? Is there any written in stone precedence of validation order? I.e. can a dependent service be sure it will always get the "Wrong length" error if name="a", even though other constraints don't match?
I tried official documentation but had no luck. Tests seem to return different error messages, but not sure if not due to the nature of test itself.

InfluxDB query doesn't work with the "WHERE" clause

I have a problem with WHERE clause in the URL query. Shortly, this works:
http://localhost:8086/query?pretty=true&db=boatdata&q=SELECT time,lat FROM "navigation.position" WHERE time='2021-05-19T11:21:11.448Z'
this doesn’t:
http://localhost:8086/query?pretty=true&db=boatdata&q=SELECT time,lat FROM "navigation.position" WHERE lon='23.53815'
Difference: in first statement I use ‘time’ in the WHERE clause, and in second one I use ‘lon’ instead:
WHERE time='2021-05-19T11:21:11.448Z' vs. WHERE lon='23.53815'
It doesn’t make sense to me why the second one doesn’t work. Any help would be much appreciated. Thanks.
P.S. Here’s an output of these two:
#1:
{
"results": [
{
"statement_id": 0,
"series": [
{
"name": "navigation.position",
"columns": [
"time",
"lat"
],
"values": [
[
"2021-05-19T11:21:11.448Z",
60.084066666666665
]
]
}
]
}
]
}
#2
{
"results": [
{
"statement_id": 0
}
]
}
It makes sense - lat (lon) is not a string type.
Filtering, where lat is a string type:
lat='60.084066666666665'
vs. filtering, where lat is a float type:
lat=60.084066666666665

Siri shortcuts rounding number in "Get Contents of URL" POST

I am trying to create a iOS 12 Shortcut based on the Gautrain API.
I want to do a POST to the URL https://api.gautrain.co.za/transport-api/api/0/journey/create with the following payload:
{
"geometry": {
"coordinates": [
[
28.23794,
-25.74762
],
[
28.05693,
-26.10858
]
],
"type": "MultiPoint"
},
"profile": "ClosestToTime",
"maxItineraries": 3,
"timeType": "DepartAfter",
"only": {
"agencies": [
"edObkk6o-0WN3tNZBLqKPg"
]
}
}
I have entered all these details into a "Get Contents of URL" block. For the elements of the "coordinates" arrays I have used "Number".
The problem is that when I track what my phone is sending via mitmproxy, it sends all the information correctly, but the coordinates have been rounded to integers:
{
"geometry": {
"coordinates": [
[
28,
-25
],
[
28,
-26
]
],
"type": "MultiPoint"
},
"maxItineraries": 1,
"only": {
"agencies": [
"edObkk6o-0WN3tNZBLqKPg"
]
},
"profile": "ClosestToTime",
"timeType": "DepartAfter"
}
For this reason, the request is not giving the desired results.
I have a feeling this may be a bug, but is there something I am missing where I can tell Shortcuts to use the full set of digits?
I have found the problem. Since I am in South Africa, the numbers are expected to have commas instead of periods for decimals. I would have loved some feedback in the field that this wasn't a valid number instead of just silently ignoring the decimal.
The solution therefore was to change the "28.23794" in the entry box to "28,23794".
I might also link to postman-echo.com as an excellent tool for debugging these kinds of requests.

Full text search in Neo4j, is it possible to get the score?

I am trying to use cypher to perform the query in full text index. It returns results, but they are not ranked. Is there a way to get the match score?
start recordEmployee=node:fidx_RecordEmployee("F01:Leela* OR F01:Ph*") return recordEmployee.F01
Returns this, and I cannot find match score:
{
"results": [
{
"columns": [
"recordEmployee.F01"
],
"data": [
{
"row": [
"Philip"
],
"graph": {
"nodes": [],
"relationships": []
}
},
{
"row": [
"Leela"
],
"graph": {
"nodes": [],
"relationships": []
}
}
],
"stats": {
"contains_updates": false,
"nodes_created": 0,
"nodes_deleted": 0,
"properties_set": 0,
"relationships_created": 0,
"relationship_deleted": 0,
"labels_added": 0,
"labels_removed": 0,
"indexes_added": 0,
"indexes_removed": 0,
"constraints_added": 0,
"constraints_removed": 0
}
}
],
"errors": []
}
It's not possible in Cypher yet, but with stored procedures in Neo4j 3.0 it will be again.
Until then if you really need the score you can use the REST endpoint.
http://neo4j.com/docs/stable/rest-api-indexes.html#rest-api-find-node-by-query
Getting the results with a predefined ordering requires adding the
request parameter
?order=<ordering>
where <ordering> is one of index, relevance or score. In this case an
additional field will be added to each result, named score, that holds
the float value that is the score reported by the query result.

Message parameter doesn't allow html, so tried to use message_tags parameter in this format

Message parameter doesn't allow html, so tried to use message_tags parameter in this format, but with real values(format from here http://developers.facebook.com/blog/post/592/):
{
"19": [
{
"id": 101961456910,
"name": "Marmot",
"offset": 19,
"length": 6
}
],
"0": [
{
"id": 1207059,
"name": "Dhiren Patel",
"offset": 0,
"length": 12
}
]
}
and no result. Tried different values, there are no errors, but no result.
The message_tags parameter isn't one you can set via the API.
Did you find documentation suggesting otherwise? invalid parameters are for the most part silently ignored when you make a POST request

Resources