How-To Create a Compliance Policy in opConfig

In this section we are assuming that you have opConfig up and running.

Step 1. Create the command on opConfig to get the information that you need for the compliance policy.

In this case we want to check if the pre-login banner is enable on a Fortigate device.

a) Fortigate configuration.

# config system global
# set pre-login-banner ?
enable     Enable pre-login banner.
disable    Disable pre-login banner.
# set pre-login-banner enable
# end

This information is available using "show full-configuration" command on Fortigate. 

# show full-configuration | grep pre-login
set pre-login-banner enable

b) Create the command on opCharts.

On opCharts GUI navigate to System > Manage Command Sets 

Click on add to create a new Command Sets

Configure the command sets with the following information:

Name: FORTINET_Config

Active: True

OS: Fortinet

Command: show full-configuration

Active: True

Store Internal: True

Compare to previous revision: True

Then click on Save



Now we have to execute the command. On opCharts GUI navigate to Virtual Operator > New Virtual Operator Job

Configure the virtual operator job with the following information:

Refine Node: Pick from Node List

Nodes: Select the node in mi case "FortigateTest"   > This node/device was previously add and configure the credential sets.

Command Sets: FORTINET_Config

Schedule: Now

Name: Banner

Then click Schedule

After some seconds you will see the result

Click on Command "show full-cobfiguration" and you can see the Fortigate configuration

Now we have the value that we are looking for


Step 2. Create the Parser

opConfig's configuration parsers are more than just parsers and we might have called them "knowledge extractors" instead. The purpose of such a config parser is to consume a particular type of command output and transform (relevant parts of) it into a tree structure.

Parsers are installed in the directory  /usr/local/omk/conf/config_parsers.

# cd /usr/local/omk/conf/config_parsers
# ll
-rw-rw-r--. 1 root root 3052 Sep 24  2021 cisco-config.pm
-rw-rw-r--. 1 root root  927 Sep 19 19:28 cisco-interface.pm
-rw-rw-r--. 1 root root  594 Sep 24  2021 cisco-version.pm
-rw-rw-r--. 1 root root  272 Sep 24  2021 jsonpassthrough.pm
-rw-rw-r--. 1 root root  450 Sep 24  2021 meminfo.pm
-rw-rw-r--. 1 root root 2087 Apr 29  2021 README


All config parsers must be valid Perl scripts, and we made this choice for efficiency reasons: a language flexible enough to parse and extract information from arbitrary configuration or status command outputs would have been almost as complicated as perl but much less robust. In addition to that you will likely change your policy rules much more often than any of the parsers.

For more information about the parsers please check the following link OpConfig and Compliance Management

Now we have to create the parser for the "show full-configuration" command. We can copy the cisco-interface.pm parser to create fortigate-config.pm parser. 

Please avoid to use the character "_" in the parser file name.  Example: don't use fortigate_config.pm, please use fortigate-config.pm


# cp cisco-interface.pm fortigate-config.pm

Edit the  fortigate-config.pm parser in order to find if the pre-login banner is enable or disable. 

# vi fortigate-config.pm
# this is a Fortigate "show full-configuration" parser for opconfig, which amends the config_features->config section
our $VERSION = "1.0.0";

my (%config);
for my $line (split(/\r?\n/,$input))
{
        if ($line =~ /.*set pre-login-banner (.+)/)
        {

                $config{disclaimer} = $1;
        }

}

return { config_features => { config => \%config } };

The $input variable contains all the output from "show full-configuration" command. 

We can check if the syntaxis is ok using this: 

# perl -c fortigate-config.pm
fortigate-config.pm syntax OK

Step 3. Parser activation

To activate a particular config parser, you have to add an entry for it to /usr/local/omk/conf/opCommon.json in the opconfig_parsers section. The entry must consist of a regular expression (which identifies which commands this parser handles), and of a path pointing to the  parser file.

# vi opCommon.json
"opconfig" : {
      "opconfig_parsers" : [
         [
            "^audit$",
            "config_parsers/jsonpassthrough.pm"
         ],
         [
            "^show full-configuration$",
            "config_parsers/fortigate-config.pm"
         ],
         [
            "^show version$",
            "config_parsers/cisco-version.pm"
         ]
      ],

Note that all matching parsers will be applied for a particular command, in the order they are given in the configuration.


Step 4. Verify Parser extraction

The result of the parsing/extraction of all of opConfig's input material is what we call the "Node Configuration Status Document": a tree-structured concise expression of properties.

To verify that your parsers have correctly extracted the expected properties, you can export the newest version of the config status document:

# /usr/local/omk/bin/opconfig-cli.pl act=export_config_status node=Node-Name debug=true

In our case 

# /usr/local/omk/bin/opconfig-cli.pl act=export_config_status node=FortigateTest debug=true

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

[2022-10-13 20:10:08.86998] [119957] [debug] new opConfig: require_db
[2022-10-13 20:10:09.01269] [119957] [debug] Creating NMISx
{
   "config_features" : {
      "config" : {
         "disclaimer" : "enable",
      },
}


Normally opConfig updates the config status document only if are new command outputs available for a particular node; parser modifications are not taken into account!

While you are fine-tuning your parser behaviours, you will therefore likely want to force opConfig to reparse and re-extract the command outputs, which is of course possible:

# /usr/local/omk/bin/opconfig-cli.pl act=update_config_status node=Node-Name force=1 debug=9

In our case 

# /usr/local/omk/bin/opconfig-cli.pl act=update_config_status node=FortigateTest force=1 debug=9

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

[2022-10-13 20:16:51.60796] [120403] [debug] new opConfig: require_db
[2022-10-13 20:16:51.74150] [120403] [debug] Creating NMISx
[2022-10-13 20:16:51.99493] [120403] [debug] getting newest config status for node FortigateTest
[2022-10-13 20:16:52.00003] [120403] [debug] Node status for FortigateTest needs updating
[2022-10-13 20:16:52.01312] [120403] [debug] found no config parser for command "diagnose ip address list" on node FortigateTest
[2022-10-13 20:16:52.01330] [120403] [debug] found no config parser for command "execute time" on node FortigateTest
[2022-10-13 20:16:52.01341] [120403] [debug] found no config parser for command "get system performance status" on node FortigateTest
[2022-10-13 20:16:52.02306] [120403] [debug] getting newest command output for show full-configuration
[2022-10-13 20:16:52.03269] [120403] [debug] newest command output for show full-configuration is in
[2022-10-13 20:16:52.03566] [120403] [debug] processing command show full-configuration, node FortigateTest, revision 8, input length 1013715, structured no
[2022-10-13 20:16:52.03585] [120403] [debug] running parser /usr/local/omk/conf/config_parsers/fortigate-config.pm for node FortigateTest and command "show full-configuration"
[2022-10-13 20:16:52.08347] [120403] [debug] parser finished, merging results
[2022-10-13 20:16:52.08441] [120403] [debug] found no config parser for command "traceroute" on node FortigateTest


Step 5. Create the Compliance Policy

Compliance policy language is very similar to opEvents language. 

Here is a quick overview of the structural rules:

  • A policy consists of one hash (or "associative array"). All hash keys (=rule numbers) must be numeric, and the keys control the order of rule evaluation.
    Rule numbers do not have to be globally unique, just within the enclosing subpolicy.
  • Each hash element must describe either one IF/THEN clause or one EACH/BLOCK iteration.
  • THEN statements can be either a single string (describing the actions to take) or a nested sub-policy (in the form of a nested hash).
  • EACH/BLOCK iterations always require a nested sub-policy.
  • IF statements are single strings, made up from structure or variable selector expressions and Perl operators and expressions.
  • The available actions for THEN statements are ok(), exception()CONTINUE() and LAST().
  • EACH statements consist of a variable name (for the iterator variable to be) and a structure selector expression (for the objects to iterate over).
  • The policy engine invokes policy rules with a number of pre-defined structure variables, to provide access to the configuration status document, the current node name and a few others.


For more information about the compliance policy please check the following link OpConfig and Compliance Management

We have to create a compliance policy, navigate to /usr/local/omk/conf/compliance_policies. 

# cd /usr/local/omk/conf/compliance_policies
# ll
-rw-rw-r--. 1 root root 7473 Nov 17  2021 cisco_nsa.json

 We can copy the cisco_nsa.json policy to create banner.json policy.

# cp cisco_nsa.json banner.json

Edit the  banner.json policy. 

# vi banner.json
{
   "10" : {
      "IF" : "not defined(${NODEINFO}.os_info)",
      "THEN" : "exception(\"Node has no os_info\",0,node=$NODENAME) AND LAST()"
   },
   "20" : {
      "IF" : "$NODEINFO.os_info.os eq \"Fortinet\"",
      "THEN" : {
         "201" : {
            "IF" : "$NODE.config_features.config.disclaimer eq \"disable\"",
            "THEN" : "exception(\"Banner is not enable\",3,node=$NODENAME,config=$NODE.config_features)"
         },
         "202" : {
            "IF" : "$NODE.config_features.config.disclaimer eq \"enable\"",
            "THEN" : "ok(\"Banner is enable\",4,node=$NODENAME,config=$NODE.config_features)"
         }
         }
      }
}

Checking the file integrity 

# json_xs < banner.json


Step 6. Policy Management

All policies are named and versioned, and managed through opconfig-cli.pl

To make a policy available to opConfig, it must be imported, we are going to import the banner.json policy like this: 

# /usr/local/omk/bin/opconfig-cli.pl act=import_policy name="banner01" file=/usr/local/omk/conf/compliance_policies/banner.json

If the policy file my_policy.nmis is different from any earlier version of "my new policy name" then opConfig will store the new version with an automatically updated revision and timestamp.

Checking the existing policies

# /usr/local/omk/bin/opconfig-cli.pl act=list_policies

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

Policy             Version   Date
banner01           1         2022-10-13T21:50:32


Step 7. Policy Evaluation

At this time compliance policy assessments are not performed automatically but have to be triggered with opconfig-cli.pl:

# /usr/local/omk/bin/opconfig-cli.pl act=check_compliance name='banner01' node=FortigateTest debug=9

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

[2022-10-13 21:58:19.07636] [129889] [debug] new opConfig: require_db
[2022-10-13 21:58:19.21568] [129889] [debug] Creating NMISx
[2022-10-13 21:58:19.47365] [129889] [debug] getting newest config status for node FortigateTest
[2022-10-13 21:58:19.47900] [129889] [debug] Node status for FortigateTest needs updating
[2022-10-13 21:58:19.48678] [129889] [debug] getting newest command output for show full-configuration
[2022-10-13 21:58:19.50876] [129889] [debug] newest command output for show full-configuration is in
[2022-10-13 21:58:19.51203] [129889] [debug] processing command show full-configuration, node FortigateTest, revision 8, input length 1013715, structured no
[2022-10-13 21:58:19.51217] [129889] [debug] running parser /usr/local/omk/conf/config_parsers/fortigate-config.pm for node FortigateTest and command "show full-configuration"
[2022-10-13 21:58:19.56652] [129889] [debug] parser finished, merging results
[2022-10-13 21:58:19.56796] [129889] [debug] found no config parser for command "traceroute" on node FortigateTest
[2022-10-13 21:58:19.57450] [129889] [debug] got config status for FortigateTest, last update at 2022-10-13T21:58:19
[2022-10-13 21:58:19.57637] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57652] [129889] [debug] iterating through policy rules, now at nr. 10, substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57659] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57664] [129889] [debug] evaluating single IF/THEN rule, IF not defined(${NODEINFO}.os_info), THEN exception("Node has no os_info",0,node=$NODENAME) AND LAST(), substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57677] [129889] [debug] IF raw:'not defined(${NODEINFO}.os_info)', expanded: 'not defined(7)', evaluates to: 0
[2022-10-13 21:58:19.57682] [129889] [debug] iterating through policy rules, now at nr. 20, substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57686] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57689] [129889] [debug] evaluating single IF/THEN rule, IF $NODEINFO.os_info.os eq "Fortinet", THEN <subpolicy>, substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57696] [129889] [debug] IF raw:'$NODEINFO.os_info.os eq "Fortinet"', expanded: '"Fortinet" eq "Fortinet"', evaluates to: 1
[2022-10-13 21:58:19.57700] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57703] [129889] [debug] iterating through policy rules, now at nr. 201, substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57711] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57716] [129889] [debug] evaluating single IF/THEN rule, IF $NODE.config_features.config.disclaimer eq "disable", THEN exception("Banner is not enable",3,node=$NODENAME,config=$NODE.config_features), substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57723] [129889] [debug] IF raw:'$NODE.config_features.config.disclaimer eq "disable"', expanded: '"enable" eq "disable"', evaluates to: 0
[2022-10-13 21:58:19.57727] [129889] [debug] iterating through policy rules, now at nr. 202, substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57730] [129889] [debug] Operating on node FortigateTest
[2022-10-13 21:58:19.57733] [129889] [debug] evaluating single IF/THEN rule, IF $NODE.config_features.config.disclaimer eq "enable", THEN ok("Banner is enable",4,node=$NODENAME,config=$NODE.config_features), substvars NODE, NODEINFO, NODENAME
[2022-10-13 21:58:19.57739] [129889] [debug] IF raw:'$NODE.config_features.config.disclaimer eq "enable"', expanded: '"enable" eq "enable"', evaluates to: 1
[2022-10-13 21:58:19.57742] [129889] [debug] IF "$NODE.config_features.config.disclaimer eq "enable"" true, processing then "ok("Banner is enable",4,node=$NODENAME,config=$NODE.config_features)"
[2022-10-13 21:58:19.57750] [129889] [debug] Raising ok "Banner is enable" for node FortigateTest
[2022-10-13 21:58:19.57755] [129889] [debug] Taking exception action ok, Banner is enable


Step 8. View Compliance Status

You can now check the Complaince Status in the opConfig GUI.  Access the opConfig GUI at http://YOUR_SERVERNAME/omk/opConfig, login and then from the Menu Bar "Views -> Compliance Status".

In our case the banner is enable on Fortigate. This is the status when the banner is enable 


Fortigate Banner


We changed the configuration on Fortigate and disable the banner. 

# config system global
# set pre-login-banner disable
# end

Then we have to execute again the "show full-configuration" command on opCharts in order to update the config with the changes. 

Now we have to update the config. 

# /usr/local/omk/bin/opconfig-cli.pl act=update_config_status node=FortigateTest force=1 debug=9
# /usr/local/omk/bin/opconfig-cli.pl act=export_config_status node=FortigateTest debug=true

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

[2022-10-13 22:30:30.30975] [2717] [debug] new opConfig: require_db
[2022-10-13 22:30:30.44241] [2717] [debug] Creating NMISx
{
   "config_features" : {
      "config" : {
         "disclaimer" : "disable",
      },
}

Now we need to run the policy evaluation 

# /usr/local/omk/bin/opconfig-cli.pl act=check_compliance name='banner01' node=FortigateTest debug=9

Command output 

opconfig-cli.pl Version 3.381.0

Copyright (C) 2015 Opmantek Limited (www.opmantek.com)
This program comes with ABSOLUTELY NO WARRANTY;
See www.opmantek.com or email contact@opmantek.com

opConfig is licensed to Opmantek Internal for 50 Nodes - Expires 15-Aug-2023

[2022-10-13 22:35:14.87127] [3153] [debug] new opConfig: require_db
[2022-10-13 22:35:15.01090] [3153] [debug] Creating NMISx
[2022-10-13 22:35:15.25586] [3153] [debug] getting newest config status for node FortigateTest
[2022-10-13 22:35:15.26091] [3153] [debug] Node status for FortigateTest already up to date as of 2022-10-13T22:34:47
[2022-10-13 22:35:15.26549] [3153] [debug] got config status for FortigateTest, last update at 2022-10-13T22:34:47
[2022-10-13 22:35:15.26684] [3153] [debug] Operating on node FortigateTest
[2022-10-13 22:35:15.26695] [3153] [debug] iterating through policy rules, now at nr. 10, substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26701] [3153] [debug] Operating on node FortigateTest
[2022-10-13 22:35:15.26705] [3153] [debug] evaluating single IF/THEN rule, IF not defined(${NODEINFO}.os_info), THEN exception("Node has no os_info",0,node=$NODENAME) AND LAST(), substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26721] [3153] [debug] IF raw:'not defined(${NODEINFO}.os_info)', expanded: 'not defined(7)', evaluates to: 0
[2022-10-13 22:35:15.26726] [3153] [debug] iterating through policy rules, now at nr. 20, substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26729] [3153] [debug] Operating on node FortigateTest
[2022-10-13 22:35:15.26733] [3153] [debug] evaluating single IF/THEN rule, IF $NODEINFO.os_info.os eq "Fortinet", THEN <subpolicy>, substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26739] [3153] [debug] IF raw:'$NODEINFO.os_info.os eq "Fortinet"', expanded: '"Fortinet" eq "Fortinet"', evaluates to: 1
[2022-10-13 22:35:15.26743] [3153] [debug] Operating on node FortigateTest
[2022-10-13 22:35:15.26746] [3153] [debug] iterating through policy rules, now at nr. 201, substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26750] [3153] [debug] Operating on node FortigateTest
[2022-10-13 22:35:15.26753] [3153] [debug] evaluating single IF/THEN rule, IF $NODE.config_features.config.disclaimer eq "disable", THEN exception("Banner is not enable",3,node=$NODENAME,config=$NODE.config_features), substvars NODENAME, NODEINFO, NODE
[2022-10-13 22:35:15.26760] [3153] [debug] IF raw:'$NODE.config_features.config.disclaimer eq "disable"', expanded: '"disable" eq "disable"', evaluates to: 1
[2022-10-13 22:35:15.26763] [3153] [debug] IF "$NODE.config_features.config.disclaimer eq "disable"" true, processing then "exception("Banner is not enable",3,node=$NODENAME,config=$NODE.config_features)"
[2022-10-13 22:35:15.26770] [3153] [debug] Raising exception "Banner is not enable" for node FortigateTest
[2022-10-13 22:35:15.26775] [3153] [debug] Taking exception action exception, Banner is not enable

Checking the compliance status on opConfig GUI.