Plus some documentation updates Change-Id: I6fd2b04e22bca6c3d6e36e78d1995220e261206b Refs: #3809
627 lines
20 KiB
ReStructuredText
627 lines
20 KiB
ReStructuredText
Validator Configuration File Format
|
|
===================================
|
|
|
|
.. contents::
|
|
|
|
You can set up a ``Validator`` via a configuration file. Next, we will show you how to
|
|
write a configuration file.
|
|
|
|
The configuration file consists of **rules** and **trust-anchors** that will be used in
|
|
validation. **Rules** tell the validator how to validate a packet, while **trust-anchors**
|
|
tell the validator which certificates are valid immediately. Here is an example of
|
|
configuration file containing two rules.
|
|
|
|
::
|
|
|
|
rule
|
|
{
|
|
id "Simple Rule"
|
|
for data
|
|
filter
|
|
{
|
|
type name
|
|
name /localhost/example
|
|
relation is-prefix-of
|
|
}
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
|
|
relation equal
|
|
}
|
|
}
|
|
}
|
|
rule
|
|
{
|
|
id "Testbed Validation Rule"
|
|
for data
|
|
checker
|
|
{
|
|
type hierarchical
|
|
sig-type rsa-sha256
|
|
}
|
|
}
|
|
trust-anchor
|
|
{
|
|
type file
|
|
file-name "testbed-trust-anchor.cert"
|
|
}
|
|
|
|
.. note::
|
|
**ATTENTION: The order of rules MATTERS!**
|
|
|
|
A rule can be broken into two parts:
|
|
|
|
- The first part is to qualify packets to which the rule can be
|
|
applied;
|
|
- The second part is to check whether further validation process is
|
|
necessary.
|
|
|
|
When receiving a packet, the validator will apply rules in the configuration file
|
|
one-by-one against the packet, until finding a rule that the packet qualifies for. And the
|
|
second part of the matched rule will be used to check the validity of the packet. If the
|
|
packet cannot qualify for any rules, it is treated as an invalid packet. Once a packet has
|
|
been matched by a rule, the rest rules will not be applied against the packet. Therefore,
|
|
you should always put the most specific rule to the top, otherwise it will become useless.
|
|
|
|
In the example configuration, the first rule indicates that all the data packets under the
|
|
name prefix ``/localhost/example`` must be signed by a key whose certificate name is
|
|
``/ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT``. If a packet does not have a name under prefix
|
|
``/localhost/example``, validator will skip the first rule and apply the second rule. The
|
|
second rule indicates that any data packets must be validated along a hierarchy. And a
|
|
certificate stored in a file "testbed-trust-anchor.cert" is valid.
|
|
|
|
Rules in general
|
|
----------------
|
|
|
|
A rule has four types of properties: **id**, **for**, **filter**, and **checker**.
|
|
|
|
The property **id** uniquely identifies the rule in the configuration file. As long as
|
|
being unique, any name can be given to a rule, e.g., "Simple Rule", "Testbed Validation
|
|
Rule". A rule must have one and only one **id** property.
|
|
|
|
A rule is either used to validate an interest packet or a data packet. This information
|
|
is specified in the property **for**. Only two value can be specified: **data** and
|
|
**interest**. A rule must have one and only one **for** property.
|
|
|
|
The property **filter** further constrains the packets that can be checked by the
|
|
rule. Filter property is not required in a rule, in this case, the rule will capture all
|
|
the packets passed to it. A rule may contain more than one filters, in this case, a packet
|
|
can be checked by a rule only if the packet satisfies all the filters.
|
|
|
|
.. note::
|
|
**ATTENTION: A packet that satisfies all the filters may not be valid**.
|
|
|
|
The property **checker** defines the conditions that a matched packet must fulfill to be
|
|
treated as a valid packet. A rule must have at least one **checker** property. A packet is
|
|
treated as valid if it can pass at least one of the checkers and as invalid when it cannot
|
|
pass any checkers.
|
|
|
|
**filter** and **checker** have their own properties. Next, we will introduce them
|
|
separately.
|
|
|
|
Filter Property
|
|
---------------
|
|
|
|
Filter has its own **type** property. Although a rule may contain more than one filters,
|
|
there is at most one filter of each type. So far, only one type of filter is defined:
|
|
**name**. In other word, only one filter can be specified in a rule for now.
|
|
|
|
Name Filter
|
|
~~~~~~~~~~~
|
|
|
|
There are two ways to express the conditions on name. The first way is to specify a
|
|
relationship between the packet name and a particular name. In this case, two more
|
|
properties are required: **name** and **relation**. A packet can fulfill the condition if
|
|
the **name** has a **relation\* to the packet name. Three types of **\ relation\*\* has
|
|
been defined: **equal**, **is-prefix-of**, **is-strict-prefix-of**. For example, a filter
|
|
|
|
::
|
|
|
|
filter
|
|
{
|
|
type name
|
|
name /localhost/example
|
|
relation equal
|
|
}
|
|
|
|
shall only capture a packet with the exact name ``/localhost/example``.
|
|
And a filter
|
|
|
|
::
|
|
|
|
filter
|
|
{
|
|
type name
|
|
name /localhost/example
|
|
relation is-prefix-of
|
|
}
|
|
|
|
shall capture a packet with name ``/localhost/example`` or ``/localhost/example/data``, but
|
|
cannot catch a packet with name ``/localhost/another_example``. And a filter
|
|
|
|
::
|
|
|
|
filter
|
|
{
|
|
type name
|
|
name /localhost/example
|
|
relation is-strict-prefix-of
|
|
}
|
|
|
|
shall capture a packet with name ``/localhost/example/data``, but cannot catch a packet
|
|
with name ``/localhost/example``.
|
|
|
|
The second way is to specify an :doc:`utils-ndn-regex` that can match the packet. In this
|
|
case, only one property **regex** is required. For example, a filter
|
|
|
|
::
|
|
|
|
filter
|
|
{
|
|
type name
|
|
regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
|
|
}
|
|
|
|
shall capture all the identity certificates.
|
|
|
|
Checker Property
|
|
----------------
|
|
|
|
Passing all the filters in a rule only indicates that a packet can be checked using the
|
|
rule, and it does not necessarily implies that the packet is valid. The validity of a
|
|
packet is determined by the property **checker**, which defines the conditions that a
|
|
valid packet must fulfill.
|
|
|
|
Same as **filter**, **checker** has a property **type**. We have defined three types of
|
|
checkers: **customized**, and **hierarchical**, and **fixed-signer**. As suggested by its
|
|
name, **customized** checker allows you to customize the conditions according to specific
|
|
requirements. **hierarchical** checker and **fixed-signer** checker are pre-defined
|
|
shortcuts, which specify specific trust models separately.
|
|
|
|
Customized Checker
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
So far, we only allow three customized properties in a customized
|
|
checker: **sig-type**, **key-locator**. All of them are related to the
|
|
``SignatureInfo`` of a packet.
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type ...
|
|
key-locator
|
|
{
|
|
...
|
|
}
|
|
}
|
|
|
|
The property **sig-type** specifies the acceptable signature type. Right now three
|
|
signature types have been defined: **rsa-sha256** and **ecdsa-sha256** (which are strong
|
|
signature types) and **sha256** (which is a weak signature type). If sig-type is sha256,
|
|
then **key-locator** will be ignored. Validator will simply calculate the digest of a
|
|
packet and compare it with the one in ``SignatureValue``. If sig-type is rsa-sha256 or
|
|
ecdsa-sha256, you have to further customize the checker with **key-locator**.
|
|
|
|
The property **key-locator** which specifies the conditions on ``KeyLocator``. If the
|
|
**key-locator** property is specified, it requires the existence of the ``KeyLocator``
|
|
field in ``SignatureInfo``. Although there are more than one types of ``KeyLocator``
|
|
defined in the `Packet Format <http://named-data.net/doc/ndn-tlv/signature.html>`__,
|
|
**key-locator** property only supports one type: **name**:
|
|
|
|
::
|
|
|
|
key-locator
|
|
{
|
|
type name
|
|
...
|
|
}
|
|
|
|
Such a key-locator property specifies the conditions on the certificate name of the
|
|
signing key. Since the conditions are about name, they can be specified in the same way as
|
|
the name filter. For example, a checker could be:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
|
|
relation equal
|
|
}
|
|
}
|
|
|
|
This checker property requires that the packet must have a ``rsa-sha256`` signature generated
|
|
by a key whose certificate name is ``/ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT``.
|
|
|
|
Besides the two ways to express conditions on the ``KeyLocator`` name (name and regex),
|
|
you can further constrain the ``KeyLocator`` name using the information extracted from the
|
|
packet name. This third type of condition is expressed via a property
|
|
**hyper-relation**. The **hyper-relation** property consists of three parts:
|
|
|
|
- an NDN regular expression that can extract information from packet name
|
|
- an NDN regular expression that can extract information from ``KeyLocator`` name
|
|
- relation from the part extracted from ``KeyLocator`` name to the one extracted from the
|
|
packet name
|
|
|
|
For example, a checker:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
hyper-relation
|
|
{
|
|
k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
|
|
k-expand \\1\\2
|
|
h-relation is-prefix-of
|
|
p-regex ^(<>*)$
|
|
p-expand \\1
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
requires the packet name must be under the corresponding namespace of the ``KeyLocator``
|
|
name.
|
|
|
|
In some cases, you can even customize checker with another property For example:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
hyper-relation
|
|
{
|
|
k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
|
|
k-expand \\1\\2
|
|
h-relation is-prefix-of
|
|
p-regex ^(<>*)$
|
|
p-expand \\1
|
|
}
|
|
}
|
|
}
|
|
|
|
Hierarchical Checker
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
As implied by its name, hierarchical checker requires that the packet name must be under
|
|
the namespace of the packet signer. A hierarchical checker:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type hierarchical
|
|
sig-type rsa-sha256
|
|
}
|
|
|
|
is equivalent to a customized checker:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
hyper-relation
|
|
{
|
|
k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
|
|
k-expand \\1\\2
|
|
h-relation is-prefix-of
|
|
p-regex ^(<>*)$
|
|
p-expand \\1
|
|
}
|
|
}
|
|
}
|
|
|
|
Fixed-Signer Checker
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In some cases, you only accept packets signed with pre-trusted certificates,
|
|
i.e. "one-step validation". Such a trust model can be expressed with **fixed-signer**
|
|
checker. And you only need to specify the trusted certificate via property **signer**. The
|
|
definition of **signer** is the same as **trust-anchor**. For example:
|
|
|
|
::
|
|
|
|
checker
|
|
{
|
|
type fixed-signer
|
|
sig-type rsa-sha256
|
|
signer
|
|
{
|
|
type file
|
|
file-name "trusted-signer.cert"
|
|
}
|
|
signer
|
|
{
|
|
type base64
|
|
base64-string "Bv0DGwdG...amHFvHIMDw=="
|
|
}
|
|
}
|
|
|
|
.. _validator-conf-trust-anchors:
|
|
|
|
Trust Anchors
|
|
-------------
|
|
|
|
Although **trust-anchor** is always not required in the configuration file (for example,
|
|
if fixed-signer checker is used), it is very common to have a few trust-anchors in the
|
|
configuration file, otherwise most packets cannot be validated. A configuration file may
|
|
contain more than one trust anchors, but the order of trust anchors does not matter. The
|
|
structure of trust-anchor is same as the **signer** in fixed-signer checker, for example:
|
|
|
|
::
|
|
|
|
trust-anchor
|
|
{
|
|
type file
|
|
file-name "trusted-signer.cert"
|
|
}
|
|
trust-anchor
|
|
{
|
|
type base64
|
|
base64-string "Bv0DGwdG...amHFvHIMDw=="
|
|
}
|
|
|
|
You may also specify a trust-anchor directory. All certificates under this directory are
|
|
taken as trust anchors. For example, if all trust anchors are put into
|
|
``/usr/local/etc/ndn/keys``.
|
|
|
|
::
|
|
|
|
trust-anchor
|
|
{
|
|
type dir
|
|
file-name /usr/local/etc/ndn/keys
|
|
}
|
|
|
|
If certificates under the directory might be changed during runtime, you can set a refresh
|
|
period, such as
|
|
|
|
::
|
|
|
|
trust-anchor
|
|
{
|
|
type dir
|
|
file-name /usr/local/etc/ndn/keys
|
|
refresh 1h ; refresh certificates every hour, other units include m (for minutes) and s (for seconds)
|
|
}
|
|
|
|
There is another special trust anchor **any**. As long as such a trust-anchor is defined
|
|
in config file, packet validation will be turned off.
|
|
|
|
.. note::
|
|
**ATTENTION: This type of trust anchor is dangerous. You should used it only when you
|
|
want to disable packet validation temporarily (e.g, debugging code, building a demo).**
|
|
|
|
::
|
|
|
|
trust-anchor
|
|
{
|
|
type any
|
|
}
|
|
|
|
|
|
Example Configuration For NLSR
|
|
------------------------------
|
|
|
|
The trust model of NLSR is semi-hierarchical. An example certificate signing hierarchy is:
|
|
|
|
::
|
|
|
|
root
|
|
|
|
|
+--------------+---------------+
|
|
site1 site2
|
|
| |
|
|
+---------+---------+ +
|
|
operator1 operator2 operator3
|
|
| | |
|
|
+-----+-----+ +----+-----+ +-----+-----+--------+
|
|
router1 router2 router3 router4 router5 router6 router7
|
|
| | | | | | |
|
|
+ + + + + + +
|
|
NLSR NSLR NSLR NSLR NSLR NSLR NSLR
|
|
|
|
However, entities name may not follow the signing hierarchy, for
|
|
example:
|
|
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
| Entity | Identity name and examples |
|
|
+============+=====================================================================================+
|
|
| root | ``/<network>`` |
|
|
| | |
|
|
| | Identity example: ``/ndn`` |
|
|
| | |
|
|
| | Certificate name example: ``/ndn/KEY/ksk-1/ID-CERT/%01`` |
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
| site | ``/<network>/<site>`` |
|
|
| | |
|
|
| | Identity example: ``/ndn/edu/ucla`` |
|
|
| | |
|
|
| | Certificate name example: ``/ndn/edu/ucla/KEY/ksk-2/ID-CERT/%01`` |
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
| operator | ``/<network>/<site>/%C1.O.N./<operator-id>`` |
|
|
| | |
|
|
| | Identity example: ``/ndn/edu/ucla/%C1.O.N./op1`` |
|
|
| | |
|
|
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.N./op1/KEY/ksk-3/ID-CERT/%01`` |
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
| router | ``/<network>/<site>/%C1.O.R./<router-id>`` |
|
|
| | |
|
|
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1`` |
|
|
| | |
|
|
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/KEY/ksk-4/ID-CERT/%01`` |
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
| NLSR | ``/<network>/<site>/%C1.O.R./<router-id>/NLSR`` |
|
|
| | |
|
|
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR`` |
|
|
| | |
|
|
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/KEY/ksk-5/ID-CERT/%01`` |
|
|
+------------+-------------------------------------------------------------------------------------+
|
|
|
|
Assume that a typical NLSR data name is
|
|
``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/LSA/LSType.1/%01``. Then, the exception of naming
|
|
hierarchy is "operator-router". So we can write a configuration file with three rules. The
|
|
first one is a customized rule that capture the normal NLSR data. The second one is a
|
|
customized rule that handles the exception case of the hierarchy (operator->router). And
|
|
the last one is a hierarchical rule that handles the normal cases of the hierarchy.
|
|
|
|
We put the NLSR data rule to the first place, because NLSR data packets are the most
|
|
frequently checked. The hierarchical exception rule is put to the second, because it is
|
|
more specific than the last one.
|
|
|
|
And here is the configuration file:
|
|
|
|
::
|
|
|
|
rule
|
|
{
|
|
id "NSLR LSA Rule"
|
|
for data
|
|
filter
|
|
{
|
|
type name
|
|
regex ^[^<NLSR><LSA>]*<NLSR><LSA>
|
|
}
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
hyper-relation
|
|
{
|
|
k-regex ^([^<KEY>]*)<KEY><ksk-.*><ID-CERT>$
|
|
k-expand \\1
|
|
h-relation equal
|
|
p-regex ^([^<NLSR><LSA>]*)<NLSR><LSA><LSType\.\d><>$
|
|
p-expand \\1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rule
|
|
{
|
|
id "NSLR Hierarchy Exception Rule"
|
|
for data
|
|
filter
|
|
{
|
|
type name
|
|
regex ^[^<KEY><%C1.O.R.>]*<%C1.O.R.><><KEY><ksk-.*><ID-CERT><>$
|
|
}
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
hyper-relation
|
|
{
|
|
k-regex ^([^<KEY><%C1.O.N.>]*)<%C1.O.N.><><KEY><ksk-.*><ID-CERT>$
|
|
k-expand \\1
|
|
h-relation equal
|
|
p-regex ^([^<KEY><%C1.O.R.>]*)<%C1.O.R.><><KEY><ksk-.*><ID-CERT><>$
|
|
p-expand \\1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rule
|
|
{
|
|
id "NSLR Hierarchical Rule"
|
|
for data
|
|
filter
|
|
{
|
|
type name
|
|
regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
|
|
}
|
|
checker
|
|
{
|
|
type hierarchical
|
|
sig-type rsa-sha256
|
|
}
|
|
}
|
|
trust-anchor
|
|
{
|
|
type file
|
|
file-name "testbed-trust-anchor.cert"
|
|
}
|
|
|
|
Example Configuration For NFD RIB Management
|
|
--------------------------------------------
|
|
|
|
Assume `NFD RIB Management <https://redmine.named-data.net/projects/nfd/wiki/RibMgmt>`_
|
|
allows any valid testbed certificate to register prefix, the configuration file could be
|
|
written as:
|
|
|
|
::
|
|
|
|
rule
|
|
{
|
|
id "NRD Prefix Registration Command Rule"
|
|
for interest
|
|
filter
|
|
{
|
|
type name
|
|
regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]
|
|
}
|
|
checker
|
|
{
|
|
type customized
|
|
sig-type rsa-sha256
|
|
key-locator
|
|
{
|
|
type name
|
|
regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
|
|
}
|
|
}
|
|
}
|
|
rule
|
|
{
|
|
id "Testbed Hierarchy Rule"
|
|
for data
|
|
filter
|
|
{
|
|
type name
|
|
regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
|
|
}
|
|
checker
|
|
{
|
|
type hierarchical
|
|
sig-type rsa-sha256
|
|
}
|
|
}
|
|
trust-anchor
|
|
{
|
|
type file
|
|
file-name "testbed-trust-anchor.cert"
|
|
}
|