Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

Navigation
Guide That Contains This Content
[+] Expand All
[-] Collapse All

    Building Templates

    A rule performs checking based upon patterns. Thus, to form a rule, you should define both pattern(s) and rule(s).


    Cisco IOS Example


    The following is an example Cisco IOS template made up of two patterns “hasip” and “shutdown” followed by a rule “Shutdown_or_noip” which checks the interface block based on the presence or absence of these two patterns. The interface blocks (represented by keyword “interface”) are looped through with a “foreach” statement. If either pattern “hasip” is not matched or pattern “shutdown” is matched, a severity level of “warning” is raised. Otherwise, a severity level of “information” is raised via the print statement (equivalent of “raise info”).

    #conform name ciscotemplate
    #conform type cisco ios
    @define hasip
    ip address $(myip) *
    @define shutdown
    shutdown
    @define rule Shutdown_or_noip
    foreach interface do
    if (!hasip || shutdown) then raise warning "$(interface.name) has no ip
    address or shutdown"
    else print "$(interface.name) has an ip $(myip)"
    end
    end

    Note: In the pattern hasip, note that the word following “ip address” is being saved into a variable with name “myip”, so that the IP address can be printed out subsequently in the Shutdown_or_noip rule.

    Blank lines and white spaces in templates are ignored (except when used in regular expressions). So using blank lines to separate blocks of text in the template are not necessary


    Juniper JUNOS Example


    The following is a simple Juniper example to check a global variable, the OS version, and raise different severity levels depending upon the OS version. In this case, referencing a pattern is not necessary, since $(version) is a global variable.

    #conform name junipertemplate
    #conform type juniper junos
    #conform use regular-expression
    @define rule junosversion
    if $(version) ~= "7.*" then raise critical "version $(version)"
    elseif $(version) ~= "8.*" then raise major "version $(version)"
    elseif $(version) ~= "9.[1-3].*" then raise minor "version $(version)"
    else print "version $(version)"
    end

    Because Junos contains a well-defined hierarchical structure defined by braces, it is possible to design configuration compliance assessments at specific levels of the hierarchy. For example, the following rule check_rsvp checks for the existence of traceoptions under the protocols rsvp clause of each device:

    #conform type junos
    @define rsvptraceoptions
    traceoptions {
    file rsvp.log size 10m;
    flag error;
    flag resv;
    flag route;
    flag resvtear;
    flag all;
    }
    @define rule check_rsvp
    foreach protocols.rsvp do
    if rsvptraceoptions then raise info "matched rsvp trace options"
    else raise major "no match for rsvp trace options in $(hostname)"
    end
    end

    Note: For Junos pattern definitions, key structural characters like ‘{‘ and ‘;’ should not be substituted by a regular-expression, since they have special meanings to the program.

    For example, if there is a section for chassis as follows, the user can use the syntax chassis.fpc.pic to loop through the pic’s as in “foreach chassis.fpc.pic do”:

    chassis (
    fpc 0 {
    pic 0 {
    }
    }
    }

    If the next item in the hierarchy is an unknown name, such as for the interfaces {} block, under which are the interface names such as ge-0/0/1, ge-0/0/2, etc. the keyword “child” can be used as follows, and its contents can be printed using $(instance).

    @define hasdescription
    description $(intfdesc)
    @define rule maindescription
    foreach interfaces.child do
    if (hasdescription) then print "$(instance) has description $(intfdesc)"
    end
    end

    For more IP/MPLSView keywords, see IP/MPLSView Keywords For Use Within a Rule.


    Match Ordered, Unordered, or Exact


    In addition to performing compliance assessments on specific blocks of code, there is a rule to check for lines within the entire configlet, using the keyword “match”, or its equivalent keyword “conform.”

    Suppose the config file contains five lines:

    a
    b
    c
    d
    e

    Then within the template file, we can define patterns, and rules to check for an exact match of the pattern, an ordered match, or an unordered match:

    @define block
    a
    b
    d
    @define block2
    a
    c
    b
    @define rule exactmatch
    match exact block # not matched due to additional lines c and e
    @define rule orderedmatch
    match ordered block2 # not matched due to out of order lines (lines c and b)
    @define rule exactmach2
    match exact block2 # not matched by the same reason above (an exact match must
    also be ordered)
    @define rule match
    match block2 # matched

    Match and Severity


    The match function will categorize the matched results based on different matched conditions. The severity of these categories be changed from the Settings option and saved per project. The following categories are available:

    • Matched: matched
    • Missing line: missing line from the defined template
    • Missing block: the first line is missing from the defined template
    • Extra line: there is an extra line from the defined template
    • Unordered line: the line is not in the same order as the defined template.

    Match Block with Variables


    In some configurations, the block to match may be slightly different based on different routers or vendors. This match block with variable feature allows users to define statements to account for these cases.

    In the following example, we will try to match the policy statement. On each router, the term is different based on the router’s country code and location which can be extracted from the router’s hostname.

    @define policy_statement_a
    policy-statement a {
    term term_a {
    from {
    protocol bgp;
    community [ to-$(country) to-$(location) ];
    }
    then reject;
    }
    then accept;
    }
    @define rule rule_a
    set $(location) right(hostname,2)
    set $(country) left(hostname,2)
    foreach policy-options do
    match policy_statement_a
    end

    Table 1: Template Syntax

    @define <Pattern Name>

    Define a pattern of a block of text. It could contain one word, one line or multiple lines.

    - Wild card, *, can be used to match any text. Alternatively, regular expression can be used if appropriate #conform use regular-expression statement is included in the header.

    - Note: The wild card should not be used to hide key syntax operators on the first line such as braces ‘{‘ and semi-colons ‘;’

    - $(<Variable Name>) can be used to capture and turn any text into a variable, which can then be printed out in the subsequent rule.

    Example: @define pattern1
    ip vrf $(vrf)
    rd $(rd)
    route-target export *
    route-target import *

    @define rule <Rule Name>

    Define a compliance assessment rule used for the syntax checking.

    - Multiple rules can be defined within one template.

    - Rules can be assigned to different categories by adding category=<Category Name> in the end. - Various flow control, loop, logic boolean, logic operator, print functions can used in the rule.

    - Additional flow controller keyword:

    Exit : Once flow reaches exit statement, program will immediately stop checking for the current rule and move on to the next rule if any.

    Example :

    @define rule BFD-Check category=Protocol

    @define external <Rule Name> output=[<path>|append]

    Define a rule to execute an external program:

    - A external program can be written in any language which uses stdout as result output, e.g., a perl script could be used. Make sure this program is executable from the command line.

    - The result can be either output to a file or it can be appended to wandl’s compliance assessment report if the result is in the same CSV format or can be output to another separate file.

    Example :

    @define external rule1 output=/tmp/ls.csv /usr/bin/ls -l
    @define external rule2 output=append /export/home/wandl/myscript.sh

    @define description <Rule Name>

    Provide a description/explanation for the compliance assessment rule.

    Example :
    @define description
    This rule checks whether the interface is shutdown or not

    Table 2: Flow Control Syntax

    foreach <block> do

    end

    Define a loop function to go through each pattern block matched in configuration, or to loop through each array element of an array. Flow controller keywords to use within the loop function include the following:

    - Next : Once flow reaches next statement, program will immediately stop the current loop and move on to the next loop.

    - Break : program will immediately leave the current foreach loop. Note that nested loops can be used in configuration files with well-defined hierarchical structures, such as Junos.

    Example for array, using reserved keyword $(element):

    foreach $(your_array) do
    print $(element)
    done

    You can get an array element by using the subscript operation. It’s syntax as follows:

    $(array_name.array_index)
    or
    $(array_name.array_index_variable)

    If $(array) is an array and $(index) is a number variable, then $(array.index), $(array.0), $(array.1), are valid syntax.

    $(array.length) will return the size of the array.

    The keyword in can be used to check if a variable exists in an array if $(string1) in $(array1) then...

    Example for pattern block:

    @define hasbandwidth
    bandwidth $(bandwidth);
    @define rule junosrule1 category=Interface
    foreach interfaces.child.unit do
    if hasbandwidth then print “$(interfaces.child)
    has bw $(bandwidth)”
    end
    end

    Note: Nested loops are allowed for pattern blocks only if the nested loop loops through a descendent of the parent loop. For example, the above could be written as follows:

    foreach interfaces.child do
    for each unit do
    if hasbandwidth then print “$(interfaces.child)
    has bw $(bandwidth)”
    end
    end
    end

    if (<boolean logic condition>) then

    elseif (<boolean logic condition>)
    then

    else

    end

    Define a boolean logic condition to separate flow into different scenarios based on true or false boolean result.

    - Both elseif and else statements are optional.

    - Multiple elseif statements are allowed, if necessary.

    - Additional Boolean logic operator keywords include the following:

    &: AND
    ==: EQUAL
    ||: OR
    !=: NOT EQUAL
    !: FALSE
    ~=: WILD CARD EQUAL

    Example:

    if (pattern1 && !pattern2) then print “pattern1 matched and pattern2 unmatched”
    elseif (pattern1 && pattern2) then print "both pattern1 and pattern2 matched "
    elseif (pattern3 ~= “Loopback*”) then print "loopback found in pattern3"
    else print "none of above"
    end

    Table 3: Built-In Functions For Use Within a Rule

    $(<Variable Name>)

    To define a variable.

    Example:
    $(x)

    “…”

    To define a string.

    Example:
    “This is a string”

    set

    To define a value to a variable

    Example:
    set $(x) 1

    +

    Arithmetic addition between number value or number variable or concatenate between string and string variable.

    Example 1 :
    set $(count) $(count) + 1

    Example 2 :
    set $(string1) $(hostname) + "," + $(interface.name)

    read

    To read in an external plain-text file containing multiple lines into a single degree string array variable. One line per array member which can be used together with “In: function.

    Example :
    read $(array1) "/tmp/interface-list.txt"

    Note: Note:
    /tmp/interface-list.txt contains following lines
    Router1,interface1
    Router2,interface2

    RouterN,interfaceN

    add

    To add an element to an array. add $(your_array) $(your_element)

    Example :
    foreach interfaces.child do
    if $(instance) ~= "xe*" then
    add $(full_interface_list) $(instance)
    end
    end

    To copy one array to another array.
    add $(array1) "a"
    add $(array1) "b"
    add $(array2) $(array1)
    print “test case 1: $(array2)” # prints “[a, b]”
    add $(array2) "c"
    print "test case 1: $(array2)" # prints "[a, b, c]"

    remove

    To remove an element from an array. remove $(your_array) $(your_element)

    Example :
    foreach protocols.isis.interface do
    if $(interface.name) ~= "xe*" then
    if isis_disable then
    remove $(full_interface_list) $(interface.name)
    end
    end
    end

    in

    To check if a string variable exists in a string array and yield true or false boolean value.

    Example :
    fif $(string1) in $(array1) then
    raise info "$(string) is in the file"
    end

    writeIn

    To write strings into a file. This can be used to create custom reports or output file. The first input parameter is the file to write in. The second input parameter is the string to write in the file. If the file already exists, it will be overwritten.

    Example :
    @define rule test_write
    set $(file) "/home/wandl/CAT/test/write_file.txt"
    foreach interfaces.child do
    print "$(hostname),$(instance),$(description)"
    writeln $(file) "$(hostname),$(instance),$(description)"
    end

    This will generate a file called write_file.txt in the directory /home/wandl/CAT/test/ with content similar to this sample:

    J1,ge-0/0/0,management interface for J1
    J1,ge-0/0/1,to 3550S2 FastEthernet0/23
    J1,ge-0/0/2,to_EX1_ge-0/0/12
    J1,ge-0/0/3,to_BRS_2600
    J1,lo0,loop - provision by WANDL
    J1,ae39,des
    J1,ae40,des

    raise

    To print a message entry to the compliance assessment result report with severity assigned (pass, info, minor, major and critical)

    To print a message entry to the compliance assessment result report with severity assigned (pass, info, minor, major and critical)

    Example :

    major “This is a major event"
    As a shortcut, a number can be used. The mapping between severities and numbers are as follows:

    - critical: 5
    - major: 4
    - minor: 3
    - warning: 2
    - info: 1
    - pass: 0

    Example :
    raise 4 “This is a major event"

    print

    Print is equivalent to raising an info message:

    Example :
    print “This is a info event"

    child

    The “child” property can be used within a foreach loop to access the child item.

    Example :
    In the following configlet segment, ge-* and xe-* can be accessed using “foreach class-of-service.interfaces.child do”

    class-of-service {
    interfaces {
    ge-* {
    }
    xe-* {
    }

    line

    To get a list of single words from config block use the keyword "line"

    prefix-list list1 {
    10.0.0.0/8;
    192.168.0.0/16;
    10.1.1.0/24;
    }
    e.g.
    foreach policy-options.prefix-list do
    if $(prefix-list.name) == "list1" then
    foreach line do
    print "$(instance)"
    end
    end
    end

    element

    For arrays, a reserved variable to refer to the value of the current array object:

    Example:
    foreach $(your_array)
    do print $(element)
    done

    conform <Pattern Name> match <Pattern Name>

    Looks for a match for the provided pattern and automatically raises a message entry into the resulting report. The Detailed Results tab will show related line numbers and line content under Template Line and Template Line #.

    Matches if all lines and subblocks exists in config file. These lines do not have to be in the same order for a match.

    Example :
    conform myconfiglet

    conform ordered <Pattern_name> match ordered <Pattern_name>

    All template lines and block should be in configuration file. In addition, all the lines must be ordered correctly. Note that config files may have additional lines or subblocks.

    Example :
    conform ordered myconfiglet

    conform exact <Pattern_name> match exact <Pattern_name>

    To match, the config file must contain the exact same section as the template. In addition to having the lines ordered in the same way, no additional lines are allowed in that section for a match.

    Example :
    conform exact myconfiglet

    Modified: 2016-11-08