Network Configuration Access Control Model Example

Use Case

RESTCONF is useful for to implement changes to our HCL3 remotely using the API, allowing remote changes to HCL3 raises security concerns. When using RESTCONF, security is extremely important to protect the integrity of the router against unauthorised changes.

Note

RESTCONF deals in JSON output and input, which is easily parsed by a variety of existing libraries for programming and scripting languages.

Example Scenario

In this example, HCL3 will be configured to allow access via RESTCONF, but the service will be protected in several key ways:

ItemValue
HCL3 HostnameHCL3.example.com
RESTCONF Usernamemyuser
NACM Group Nameadmins
Additional Useranotheruser

HCL3 Setup

Generate Certificates

Create a self-signed Certificate Authority:

HCL3(config)# pki private-key selfca generate
HCL3(config)# pki signing-request set common-name selfca
HCL3(config)# pki signing-request set digest sha256
HCL3(config)# pki signing-request selfca generate
HCL3(config)# pki signing-request selfca sign self enable-ca true

Create a certificate for the user myuser, signed by selfca:

HCL3(config)# pki private-key myuser generate key-length 4096
HCL3(config)# pki signing-request set common-name myuser
HCL3(config)# pki signing-request set digest sha256
HCL3(config)# pki signing-request myuser generate
HCL3(config)# pki signing-request myuser sign ca-name selfca days-valid 365 digest sha512 enable-ca false

Create a certificate for the RESTCONF service to use. The common-name should be the hostname of the HCL3 router, which should also exist in DNS:

HCL3(config)# pki private-key restconf generate key-length 4096
HCL3(config)# pki signing-request set common-name HCL3.example.com
HCL3(config)# pki signing-request set digest sha256
HCL3(config)# pki signing-request restconf generate
HCL3(config)# pki signing-request restconf sign ca-name selfca days-valid 365 digest sha512 enable-ca false

Setup NACM

Disable NACM while making changes, to avoid locking out the account making the changes:

HCL3(config)# nacm disable

Set default policies:

HCL3(config)# nacm exec-default deny
HCL3(config)# nacm read-default deny
HCL3(config)# nacm write-default deny

Setup an admin group containing the default users plus myuser, which will match the common-name of the user certificate created above:

HCL3(config)# nacm group admin
HCL3(config-nacm-group)# member root
HCL3(config-nacm-group)# member HCL3
HCL3(config-nacm-group)# member myuser
HCL3(config-nacm-group)# exit

Setup rules to permit any action by members of the admin group:

HCL3(config)# nacm rule-list admin-rules
HCL3(config-nacm-rule-list)# group admin
HCL3(config-nacm-rule-list)# rule permit-all
HCL3(config-nacm-rule)# module *
HCL3(config-nacm-rule)# access-operations *
HCL3(config-nacm-rule)# action permit
HCL3(config-nacm-rule)# exit
HCL3(config-nacm-rule-list)# exit

Enable NACM:

HCL3(config)# nacm enable
HCL3(config)# exit

Enable RESTCONF

Enable RESTCONF and configure it for TLS and client certificate authentication:

HCL3(config)# http server
HCL3(config-http)# server certificate restconf
HCL3(config-http)# authentication type client-certificate
HCL3(config-http)# authentication client-certificate-ca selfca
HCL3(config-http)# enable restconf

Client Configuration

On HCL3, export the CA certificate, user certificate, and user certificate key. Place the resulting files in a secure place on a client system, in a directory with appropriate permissions, readable only by the user. Additionally, the private key file must only be readable by the user. For this example, the files will be placed in ~/HCL3/.

First, export the CA certificate. Copy and paste this into a local file, named HCL3-selfca.crt:

HCL3# pki ca selfca get
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----

Next, export the user certificate, copy and paste it and save in a local file named HCL3-myuser.crt:

HCL3# pki certificate myuser get
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----

Finally, export the user certificate private key, copy and paste it and save in a local file named HCL3-myuser.key. Remember to protect this file so it is only readable by this user:

HCL3# pki private-key myuser get
-----BEGIN PRIVATE KEY-----
[...]
-----END PRIVATE KEY-----

This example uses curl to access RESTCONF, so ensure it is installed and available on the client computer.

Example Usage

This simple example shows fetching the contents of an ACL from RESTCONF as well as adding a new ACL entry. There are numerous possibilities here, for more details see the REST API documentation.

In this example, there is an existing ACL named blockbadhosts. It contains several entries including a default allow rule with a sequence number of 5000.

These examples are all run from the client configured above.

Note

This is a simple demonstration using cURL and shell commands. This makes it easy to demonstrate how the service works, and how RESTCONF URLs are formed, but does not make for a good practical example.

In real-world cases these types of queries would be handled by a program or script that interacts with RESTCONF, manipulating data directly and a lot of the details will be handled by RESTCONF and JSON programming libraries.

Retrieve a specific ACL

Retrieve the entire contents of the blockbadhosts ACL:

Command:

$ curl --cert ~/HCL3/HCL3-myuser.crt \
  --key ~/HCL3/HCL3-myuser.key \
  --cacert ~/HCL3/HCL3-selfca.crt \
  -X GET \
  https://HCL3.example.com/restconf/data/ewi-dna-acl:acl-config/acl-table/acl-list=blockbadhosts

Output:

{
    "acl-list": [
      {
        "acl-name": "blockbadhosts",
        "acl-description": "Block bad hosts",
        "acl-rules": {
          "acl-rule": [
            {
              "sequence": 1,
              "action": "deny",
              "src-ip-prefix": "203.0.113.14/32"
            },
            {
              "sequence": 2,
              "action": "deny",
              "src-ip-prefix": "203.0.113.15/32"
            },
            {
              "sequence": 555,
              "action": "deny",
              "src-ip-prefix": "5.5.5.5/32"
            },
            {
              "sequence": 5000,
              "acl-rule-description": "Default Permit",
              "action": "permit"
            }
          ]
        }
      }
    ]
  }

The cURL parameters and RESTCONF URL can be dissected as follows:

ItemValue
cURL Client Certificate–cert ~/HCL3/HCL3-myuser.crt
cURL Client Certificate Key–key ~/HCL3/HCL3-myuser.key
cURL CA Cert to validate TLS–cacert ~/HCL3/HCL3-selfca.crt
Request type (GET)-X GET
RESTCONF Server protocol/hosthttps://HCL3.example.com
RESTCONF API location:/restconf/data/
ACL config area (prefix:name)ewi-dna-acl:acl-config/
ACL tableacl-table/
ACL List, with restrictionacl-list=blockbadhosts

Note

Lists of items with a unique key can be restricted as shown above. The API documentation also calls this out as well, showing an optional ={name} in the query.

Retrieve a specific rule of a specific ACL

View only the default permit rule of the ACL:

Command:

$ curl --cert ~/HCL3/HCL3-myuser.crt \
  --key ~/HCL3/HCL3-myuser.key \
  --cacert ~/HCL3/HCL3-selfca.crt \
  -X GET \
  https://HCL3.example.com/restconf/data/ewi-dna-acl:acl-config/acl-table/acl-list=blockbadhosts/acl-rules/acl-rule=5000

Output:

{
    "ewi-dna-acl:acl-rule": [
      {
        "sequence": 5000,
        "acl-rule-description": "Default Permit",
        "action": "permit"
      }
    ]
  }

The query is nearly identical to the previous one, with the following additional components:

ItemValue
ACL rules listacl-rules/
ACL rule, with restrictionacl-rule=5000

Add a new rule to an existing ACL

Insert a new ACL rule entry with the following parameters:

ItemValue
Request Type-X PUT (add content)
ACL Nameblockbadhosts
ACL Rule Sequence10
ACL Rule Actiondeny
ACL Rule Source Address10.222.111.222/32

The new data passed in the -d parameter is JSON but with all whitespace removed so it can be more easily expressed on a command line.

The URL is the same as if the query is retrieving the rule in question.

Warning

Note the presence of the sequence number in both the supplied JSON data and in the URL. This must match.

Command:

$ curl --cert ~/HCL3/HCL3-myuser.crt \
  --key ~/HCL3/HCL3-myuser.key \
  --cacert ~/HCL3/HCL3-selfca.crt \
  -X PUT \
  -d '{"ewi-dna-acl:acl-rule":[{"sequence": 10,"action":"deny","src-ip-prefix":"10.222.111.222/32"}]}' \
  https://HCL3.example.com/restconf/data/ewi-dna-acl:acl-config/acl-table/acl-list=blockbadhosts/acl-rules/acl-rule=10

Output: This command has no output when it works successfully.

Retrieve the contents of the ACL again to see that the new rule is now present:

Command:

$ curl --cert ~/HCL3/HCL3-myuser.crt \
  --key ~/HCL3/HCL3-myuser.key \
  --cacert ~/HCL3/HCL3-selfca.crt \
  -X GET \
  https://HCL3.example.com/restconf/data/ewi-dna-acl:acl-config/acl-table/acl-list=blockbadhosts

Output:

{
    "ewi-dna-acl:acl-list": [
      {
        "acl-name": "blockbadhosts",
        "acl-description": "Block bad hosts",
        "acl-rules": {
          "acl-rule": [
            {
              "sequence": 1,
              "action": "deny",
              "src-ip-prefix": "203.0.113.14/32"
            },
            {
              "sequence": 2,
              "action": "deny",
              "src-ip-prefix": "203.0.113.15/32"
            },
            {
              "sequence": 10,
              "action": "deny",
              "src-ip-prefix": "10.222.111.222/32"
            },
            {
              "sequence": 555,
              "action": "deny",
              "src-ip-prefix": "5.5.5.5/32"
            },
            {
              "sequence": 5000,
              "acl-rule-description": "Default Permit",
              "action": "permit"
            }
          ]
        }
      }
    ]
  }

Remove a specific rule from an ACL

Say that entry is no longer needed and it is safe to remove. That can be done with a DELETE request for the URL corresponding to its sequence number:

Command:

$ curl --cert ~/HCL3/HCL3-myuser.crt \
  --key ~/HCL3/HCL3-myuser.key \
  --cacert ~/HCL3/HCL3-selfca.crt \
  -X DELETE \
  https://HCL3.example.com/restconf/data/ewi-dna-acl:acl-config/acl-table/acl-list=blockbadhosts/acl-rules/acl-rule=10

Output: This does not produce any output if it completed successfully.

Retrieve the contents of the ACL again to confirm it was removed.

Adding More Users

To create additional RESTCONF users, only two actions are required on HCL3: Generate a certificate for the new user, and then add the user to NACM. This example adds a new user named anotheruser.

Generate a new user certificate:

HCL3(config)# pki private-key anotheruser generate key-length 4096
HCL3(config)# pki signing-request set common-name anotheruser
HCL3(config)# pki signing-request set digest sha256
HCL3(config)# pki signing-request anotheruser generate
HCL3(config)# pki signing-request anotheruser sign ca-name selfca days-valid 365 digest sha512 enable-ca false

Add this user to the NACM admin group:

HCL3(config)# nacm group admin
HCL3(config-nacm-group)# member anotheruser
HCL3(config-nacm-group)# exit

Then, the user certificate can be copied to a new client and used as explained previously.