Grammars: Parse & Write Logic - nsvp.gm tabs spaces

Version 1
    Share:|

    Hello,

     

    I am new to BMC BSA and I recently wrote my first grammar.  I must say I found this very non-intuitive and wanted to share my lessons learned.

     

    Task: Create a grammar to parse the auditd.conf.  The format MUST be "key<space>=<space>value".

    Issue: The existing nsvp.gm is writing the file as "key<tab>=<tab>value" and I was unable to find a suitable substitute grammar.

     

    Example file to parse:

     

    #

    # This file controls the configuration of the audit daemon

    #

    log_file = /var/log/audit/audit.log

    log_format = RAW

    log_group = root

    priority_boost = 4

     

    Here is my final grammar file to do this:

    VAR_SPACE \

    VAR_EQUAL =

     

    %%

     

    KEY [^\t\n# ]+

    SPACE [ ]*

    EQUAL =

    VAL [^#]*

     

    %%

     

    record KEY SPACE EQUAL SPACE VAL $new_field $0 $new_field $2 $new_field $4 $save_record $0

     

    %%

     

    add $write_field $0 $write_var $VAR_SPACE $write_var $VAR_EQUAL $write_var $VAR_SPACE $write_field $2

     

    Rules section of a grammar file


    The parse logic was not immediately clear to me for how fields were represented.  This is the final rule I ended up with:

     

     

    record KEY SPACE EQUAL SPACE VAL $new_field $0 $new_field $2 $new_field $4 $save_record $0

     


    Lets take it a field at a time looking at line "log_group = root"


    1) record <- built in syntax

    2) KEY <- Capture a string matching *log_group*  ( Regex: [^\t\n# ]+ no tab, no new line, no #, no space, any number of times)

    3)SPACE <- Capture a string which is a literal space any number of times (Regex: '[ ]*)

    4)EQUAL <- Capture a literal = sign (Regex: =)

    5)SPACE <- Capture a string which is a literal space any number of times (Regex: '[ ]*)

    6)VAL <- Capture a string which does not contain a comment *root* (Regex: [^#]*)

    7) $save_record $0 <- built in syntax

     

    Above are the the fields that are interesting to match.  Then we will decide which variables should be stored for later use:

    1) $new_field $0 <- The variable $0 now holds a string "log_group"

    2)$new_field $1 <- The variable $1 now holds any number of spaces " "

    3)$new_field $2 <- The variable $2 now holds an = sign "="

    4)$new_field $3 <- The variable $3 now holds any number of spaces " "

    5)$new_field $4 <- The variable $4 now holds a string 'root'

     

    Notice in our record line we have not stored every $0-$4 variable.  We have selectively chosen what we want to store.  The below says only store "log_group", "=", "root" as variables $0, $2, $4

     

    record KEY SPACE EQUAL SPACE VAL $new_field $0 $new_field $2 $new_field $4 $save_record $0


    Add section of a grammar file


    Our next step is to format the way the file is written back to the filesystem:

     

    add $write_field $0 $write_var $VAR_SPACE $write_var $VAR_EQUAL $write_var $VAR_SPACE $write_field $2

     

    Interestingly our variables we captured in rules or record have been re-ordered as they were passed to the add method:

    $0 <- holds "log_group"

    $1 <- holds "="

    $2 <- holds "root"

     

    Lets take this a field at a time again:

    1) add <- built in method

    2)$write_field $0 <- Write the captured field from the record parse routine "log_group"

    3)$write_var $VAR_SPACE <- Write the variable defined in top section " "

    4)$write_var $VAR_EQUAL <- Write the variable defined in top section "="

    5) $write_var $VAR_SPACE <- Write the variable defined in top section " "

    6)$write_field $0 <- Write the captured field from the record parse routine "root"

     

    Result:

     

    log_group = root

     

     

    Debugging parse logic

     

    I found a post that suggested creating a "Extended Object" to help debugging which was awesome.  In the Command/Script section I had it run "cat /etc/audit/auditd.conf" with a parse logic with the grammar file I was testing.  This wo8uld allow me to edit the grammar file on the fly and see the variable parsing in action.

    https://communities.bmc.com/message/209181

     

    Uploading your grammar file

     

    1) Autenticate: blcred cred -acquire -profile <profile created in gui> -username <user>

    2) Upload Grammar: blcli -v <profile created in gui> ConfigFileGrammar createConfigFileGrammarOnFileServer "/tmp" "test.gm" "test" "test (test.gm)" "No Tabs key = val (test.gm)"

     

    This is where it gets murky for me.  There was much confusion whether I needed to restart the application server to have my "add" changes accepted.  Some objects like BLPackages seemed to cache the old grammars unless they were deleted and re-created.  If anybody could shed some light on this it would be great.

     

    As I said, I am new to BSA.  If anybody has suggestions or corrections to above please speak up.

     

    Thanks,

     

    Nick