Auto Validation
Auto-validation can be enabled on the following protocols:
When the auto-validation mode is enabled, Validation Rules are evaluated to allow or deny an enrollment request.
Multiple rules can be defined on each profile, and the minimum number of passing rules can be defined.
Validation Rules
A validation rule is a condition that can be true or false. Inputs are taken from dictionary entries and can be manipulated using Computation Rules and validation functions and operators.
For example, to allow all requests coming from a subnet and having all DNS SANs that resolves on the Horizon server, the following rule can be used:
{{http.request.ip}} in 154.12.45.0/24 and [[csr.san.dnsname]] resolvesDNS
Here, two expressions are combined using the and operator:
-
{{http.request.ip}} in 154.12.45.0/24: a computation rule{{http.request.ip}}fetches the value of the IP from the incoming request, and checks that this IP isinthe154.12.45.0/24subnet, using the In operator. -
[[csr.san.dnsname]] resolvesDNS: a computation rule[[csr.san.dnsname]]fetches the values of the DNS SANs from the csr in the incoming request, and checks that these SANsresolvesDNS.
Examples
DNS Validation
To validate that all DNS requested in a WebRA enroll request resolve on the DNS Server with IP 192.10.132.2, the following rule can be used:
[[webra.enroll.san.dnsname]] resolvesDNS(192.10.132.2:53)
Here all the dns sans from the request are fetched and are submitted to the dns server.
Email validation
To validate that the Email SAN requested in an EST enroll request are associated to the requester’s Common Name, using a datasource that fetches the emails on an external LDAP server, the following rule can be used:
{{csr.san.rfc822name.1}} = {{ds.1.1.mail}}
Here the condition checks if the first Email SAN from the CSR is equal to the mail fetched from the LDAP datasource (supposing the LDAP datasource is the first in the flow).
Quick Reference
The table below lists the possible operators for a validation rule:
| Operator Name | Syntax |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
And
left:<expression> and right:<expression>
This outputs the logical and operation on the result evaluated from left and right
"left" = "left" and "right"="right" => true
Upper("left") = "left" and "right"="right" => false
Or
left:<expression> or right:<expression>
This outputs the logical or operation on the result evaluated from left and right
"left" = "left" or "right"="right" => true
Upper("left") = "left" or "right"="right" => true
Equals
left:<expression> equals right:<expression> left:<expression> = right:<expression>
This tests the equality operation on the result evaluated from left and right
"left" = "left" => true
Upper("left") equals "left" => false
In
Element inclusion
elem:<single expression> in array:<multi expression>
This tests if elem is contained in array
"left" in [ "left" ] => true
Upper("left") in ["left"] => false
Multiple Element inclusion
any of elems:<multi expression> in array:<multi expression> all of elems:<multi expression> in array:<multi expression>
This tests if all or any element in elems is contained in array
any of ["left", "right"] in [ "left" ] => true all of ["left", "right"] in [ "left" ] => false
IP in CIDR
ip:<single expression> in subnet:<subnet>
This tests if ip is contained in subnet (cidr notation)
"128.12.13.14" in 128.12.15.0/24 => false "2001:0db8:85a3:0000:0000:0000:0000:0001" in 2001:db8:85a3::8a2e:370:7334/64 => true
Multiple IPs in CIDR
any of ips:<multi expression> in subnet:<subnet> all of ips:<multi expression> in subnet:<subnet>
This tests if all or any IP in ips is contained in subnet (cidr notation)
any of ["128.12.13.14", "128.12.15.32" ] in 128.12.15.0/24 => true all of [ "2001:0db8:85a3:0000:0000:0000:0000:0001", "2002:0db8:85a3:0000:0000:0000:0000:0001"] in 2001:db8:85a3::8a2e:370:7334/64 => false
Element not included
elem:<single expression> not in array:<multi expression> any of elems:<multi expression> not in array:<multi expression> all of elems:<multi expression> not in array:<multi expression>
"left" not in ["right"] => true any of ["left", "right"] not in [ "left" ] => true all of ["left", "right"] not in [ "left" ] => false "128.12.13.14" not in 128.12.15.0/24 => true
Exists
elem:<expression> exists
This tests if elem exists. For single values, this will be true if the dictionary key is defined and for multi values if the array is not empty.
"" exists => true
{{will.not.exist}} exists => false
[[will.not.exist]] exists => false
Is Empty
elem:<expression> is empty
This tests if elem is empty. For single values, this will be true if the dictionary key is not defined or if the value is empty, and for multi values if the array is empty or if all values are empty.
"" is empty => true
{{will.not.exist}} is empty => true
[[will.not.exist]] is empty => true
[ "", ""] is empty => true
Contains
Single element contained
containing:<expression> contains elem:<single expression>
This tests if containing contains the elem value. If containing is a string, the presence of the substring elem is checked, if it is an array the presence of the element in the array is checked.
"google.com" contains "google" => true
["google.com", "google.fr"] contains "google.fr" => true
"google.com" contains {{does.not.exist}} => true
Multiple elements contained
containing:<multi expression> contains all of elems:<multi expression> containing:<multi expression> contains any of elems:<multi expression>
This tests if containing contains all or any of the elements of the elems array. An empty elems array will always be contained.
["google.com", "google.fr"] contains all of ["test.com"] => false ["google.com"] contains all of [[does.not.exist]] => true ["google.com", "google.fr"] contains any of ["google.com", "a"] => true
Single element not contained
containing:<expression> not contains elem:<single expression>
"google.com" not contains "" => false
Multiple elements not contained
containing:<multi expression> not contains all of elems:<multi expression> containing:<multi expression> not contains any of elems:<multi expression>
["test", "abc" ] not contains all of ["abc", "d"] => true ["test", "abcf", "d"] not contains any of ["f", "e"] => true
Matches
Single element match
elem:<single expression> matches regex:<single expression> elem:<single expression> ~ regex:<single expression>
This tests if elem matches the regex. If regex is None, this will output false.
"left" matches "\d+" => false
Upper("left") ~ "[A-Z]+" => true
Multiple element match
any of elems:<multi expression> matches regex:<single expression> all of elems:<multi expression> matches regex:<single expression>
This tests if any or all element in elems matches the regex. If regex is None, this will output false.
any of ["left", "42"] matches "\d+" => true all of Upper(["left", "42"]) matches "[A-Z]+" => false
Not matching
elem:<single expression> not matches regex:<single expression> any of elems:<multi expression> not matches regex:<single expression> all of elems:<multi expression> not matches regex:<single expression>
"left" not matches "\d+" => true any of ["left", "aaaaa"] not matches "a+" => true all of ["left", "aaaaa"] not matches "a+" => false
Within
Element matching
elem:<single expression> within array:<multi expression>
This tests if elem matches a regex in array.
"left" within [ "\d+", "[a-z]+" ] => true
Upper("left") within [ "\d+", "[a-z]+" ] => false
Multiple Element matching
any of elems:<multi expression> within array:<multi expression> all of elems:<multi expression> within array:<multi expression>
This tests if all or any element in elems matches a regex in array
any of ["left", "aaaaa"] within [ "\d+", "a+" ] => true all of ["left", "aaaaa"] within [ "\d+", "a+" ] => false
Element not matching
elem:<single expression> not within array:<multi expression> any of elems:<multi expression> not within array:<multi expression> all of elems:<multi expression> not within array:<multi expression>
"left" not within [ "\d+", "[a-z]+" ] => false any of ["left", "aaaaa"] not within [ "\d+", "a+" ] => true all of ["left", "aaaaa"] not within [ "\d+", "a+" ] => false
Starts With
Element matching
elem:<single expression> starts with start:<single expression>
This tests if elem starts with start value. An empty elem will send return false.
"left" starts with "le" => true
Upper("left") starts with "le" => false
Multiple Element matching
any of elems:<multi expression> starts with start:<single expression> all of elems:<multi expression> starts with start:<single expression>
This tests if all or any element in elems starts with start
any of ["left", "aaaaa"] starts with "aaa" => true all of ["left", "aaaaa"] starts with "aaa" => false
Element not matching
elem:<single expression> starts not with start:<single expression> any of elems:<multi expression> starts not with start:<single expression> all of elems:<multi expression> starts not with start:<single expression>
"left" starts not with "le" => false any of ["left", "aaaaa"] starts not with "a" => true all of ["left", "aaaaa"] starts not with "a" => false
Ends With
Element matching
elem:<single expression> ends with start:<single expression>
This tests if elem ends with start value. An empty elem will send return false.
"left" ends with "ft" => true
Upper("left") ends with "ft" => false
Multiple Element matching
any of elems:<multi expression> ends with start:<single expression> all of elems:<multi expression> ends with start:<single expression>
This tests if all or any element in elems ends with start
any of ["left", "aaaaa"] ends with "aaa" => true all of ["left", "aaaaa"] ends with "aaa" => false
Element not matching
elem:<single expression> ends not with start:<single expression> any of elems:<multi expression> ends not with start:<single expression> all of elems:<multi expression> ends not with start:<single expression>
"left" ends not with "ft" => false any of ["left", "aaaaa"] ends not with "a" => true all of ["left", "aaaaa"] ends not with "a" => false
Resolves DNS
host:<expression> resolvesDNS host:<expression> resolvesDNS(101.12.13.14:53)
This tests if host resolves on the DNS server. An optional DNS server in the ip:port format can be used. If host is an array, DNS must resolve for each value. An empty array returns false.
"google.com" resolvesDNS => true ["google.com", "google.fr"] resolvesDNS => true ["google.com", "not.resolving"] resolvesDNS => false