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 isin
the154.12.45.0/24
subnet, 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