Management

 View Only
last person joined: 3 days ago 

Ask questions and share experiences with Junos Space and network management.
  • 1.  Configlet that inserts policy before other policy

    Posted 09-20-2022 10:12
    Hi,

    I do not have much experience with JunosSpace management, but was able to create few simple Configlets, that I want to apply to a number of SRX service gateways. 
    At this moment, I am able to apply Configlets that create some objects (like address object) and delete these objects. Preparing the latest (delete), I found that I need to use "delete: xxx", in Configlet Editor.

    Then, I wanted to create Configlet that will insert certain policy to SRX devices. No problem with creating policy, but after applying it, policy is inserted at the end of policy list (for certain from-to context). I am not sure, how to insert my policy at certain hierarchy location (for example, before some known policy).

    I tried with Configlet that is using following:

    security {

        policies {

            from-zone trust to-zone untrust {

                insert policy pol_MyPol before policy pol_Pol1;

           }

        }

      }


    I tried also with "insert:" instead of "insert", but all the time, I am getting error, like:

    Applied Configuration:

    <configuration-text xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" type="subtree"> security {
    policies {
    from-zone trust to-zone untrust {
    insert policy pol_toGit before policy pol_toWindGit;
    }
    }
    }
    </configuration-text>
    Job Failure Reason:
    <rpc-reply >
    <rpc-error>
    <error-type>protocol</error-type>
    <error-tag>operation-failed</error-tag>
    <error-severity>error</error-severity>
    <error-message>syntax error</error-message>
    <error-info>
    <bad-element>insert</bad-element>
    </error-info>
    </rpc-error>
    <rpc-error>
    <error-severity>warning</error-severity>
    <error-path>[edit security policies]</error-path>
    <error-message>mgd: statement has no contents; ignored</error-message>
    <error-info>
    <bad-element>from-zone trust to-zone untrust</bad-element>
    </error-info>
    </rpc-error>
    </rpc-reply>


    Any help how to configure Configlet?

    Another point would be: how to create Configlet, that could save rescue configuration (i.e. how to execute "request system configuration rescue save" using Configlet).


    Regards,
    Milan



    ​​​

    ------------------------------
    MILAN MARKOVIC
    ------------------------------


  • 2.  RE: Configlet that inserts policy before other policy

     
    Posted 01-17-2023 07:00
    CLI Configlet's do not support the ability to insert a term before/after another.   That capability is possible using XML configuration.   I'll post an example SLAX script that leverages the configuration-management/change-request API for Junos Space.  As change-requests to do support the functionality of making a configuration change using XML.

    The documentation for the API can be found here:  https://www.juniper.net/documentation/en_US/junos-space-sdk/18.1/apiref/com.juniper.junos_space.sdk.help/JSConfigMgrSvc/Docs/rest.change-requests.html

    I'll have to add the script to the library section of this forum, as I am unable to paste the contents of the script here as it is too large for a post, but in a nutshell the configuration data that is used incorporates an entry like the following to handle positioning a term before another term when it is being created.

    <change-request>
        <name>Add_route_target_to_policy</name>
        <description>Add_route_target_to_policy</description>
        <xmlData>
            <![CDATA[
                <configuration>
                    <policy-options>
                        <policy-statement>
                            <name>vrf-imp</name>
                            <term operation="create" insert="before" name="REJECT">
                                <name>foo</name>
                                <from>
                                    <community>foo</community>
                                </from>
                                <then>
                                    <accept/>
                                </then>
                            </term>
                        </policy-statement>
                        <community>
                            <name>foo</name>
                            <members>foo</members>
                        </community>
                    </policy-options>
                </configuration>
            ]]>
        </xmlData>
        <device href="/api/space/device-management/devices/1234567"/>
        <syncAfterPush>true</syncAfterPush>
    </change-request>​


    ------------------------------
    Andy Sharp
    ------------------------------



  • 3.  RE: Configlet that inserts policy before other policy

     
    Posted 01-17-2023 07:02
      |   view attached
    Sample SLAX script is attached to this post.  The file would need to be renamed from a .txt to a .slax before it could be imported into Junos Space.

    ------------------------------
    Andy Sharp
    ------------------------------

    Attachment(s)



  • 4.  RE: Configlet that inserts policy before other policy

     
    Posted 01-17-2023 12:47
    Edited by Jodi Meier 01-17-2023 12:47
    CLI Configlets do not have the ability to insert one term in front of another.   Instead XML has to be used as that does provide the ability to insert before another term,  Therefore, if you wanted to perform that within Junos Space you could leverage a SLAX script instead to perform the configuration change.   I recall a post on this subject once before, I'll take a look to see if I have an example still available.

    /*
        # <*******************
        #
        # Copyright 2017 Juniper Networks, Inc. All rights reserved.
        # Licensed under the Juniper Networks Script Software License (the "License").
        # You may not use this script file except in compliance with the License, which is located at
        # http://www.juniper.net/support/legal/scriptlicense/
        # Unless required by applicable law or otherwise agreed to in writing by the parties, software
        # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        #
        # *******************>
    */
    version 1.2;
    
    ns junos = "http://xml.juniper.net/junos/*/junos";
    ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
    ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
    ns str = "http://exslt.org/strings";
    ns func extension = "http://exslt.org/functions";
    ns curl extension = "http://xml.libslax.org/curl";
    ns xutil extension = "http://xml.libslax.org/xutil";
    ns jspace = "http://jspace-utils/asharp@juniper.net";
    
    import "../import/junos.xsl";
    
    /* Junos Space specific context, name and description */
    /* @CONTEXT = "/device" */
    /* @NAME = "Add route target to policy" */
    /* @DESCRIPTION = "Add route target to policy" */
    /* @ISLOCAL = "true" */
    /* @PASSSPACEAUTHHEADER = "true" */
    /* @PASSDEVICECREDENTIALS = "true" */
    /* @EXECUTIONTYPE = "GROUPEDEXECUTION" */
    
    var $curl = curl:open();
    var $fabric = jspace:fabric();
    
    var $arguments = {
        <argument> {
            <name> "termname";
            <description> "Name of term to add";
        }
        <argument> {
            <name> "commname";
            <description> "Name of community to add";
        }
        <argument> {
            <name> "vnitarget";
            <description> "Name of vnitarget";
        }
    }
    
    main <op-script-results> {
        <output> {
            if ($fabric) {
                var $devices = jspace:credentials();
                if ($devices) {
                    for-each ($devices/device) {
                        sort host;
                        var $myhost = host;
                        /* find the device using API call */
                        /*
                         * url, content-type, item-type, condition, item
                        */
                        var $findDevice = curl:perform($curl,jspace:findItem(
                            "http://" _ $fabric _ ":8080/api/space/device-management/devices",
                            "",
                            "name",
                            "eq",
                            $myhost
                        ));
    
                        /* get the key of the selected device */
                        var $deviceKey = $findDevice/data/devices/device/@key;
    
                        /* make changeRequest using the API */
                        /*
                         * url, content-type, deviceKey, orig-name, new-name, resync
                        */
                        var $results = curl:perform($curl,jspace:addTerm(
                            "http://" _ $fabric _ ":8080/api/space/configuration-management/change-requests",
                            "application/vnd.net.juniper.space.configuration-management.change-request+xml;version=2;charset=UTF-8",
                            $deviceKey,
                            $termname,
                            $commname,
                            $vnitarget,
                            "true"
                        ));
    
                        if ($results/headers/code == "200") {
                            /* job accepted */
                            expr "Adding term " _ $termname _ "\n";
    
                            /* need to see if the commit was successful or not */
                            /* to get the XML data which is embedded within more xml needs lots of parsing... */
                            /* parse and convert the raw-data node */
                            var $parseOne = {
                                uexpr $results/raw-data/.;
                            }
                            var $parseTwo = xutil:string-to-xml($parseOne);
                            var $parseThree := {copy-of $parseTwo;}
    
                            /*
                               parse and convert the change-request/xmlData node
                               this step is only required if you want to display
                               the configuration that was pushed to the device.
                            */
    
                            var $xmlDataOne = {
                                uexpr $parseThree/change-request/xmlData/.;
                            }
                            var $xmlDataTwo = xutil:string-to-xml($xmlDataOne);
                            var $xmlDataThree := {copy-of $xmlDataTwo;}
    
                            copy-of $xmlDataThree;
    
                            /* display the change-request/result */
                            uexpr substring-before($parseThree/change-request/result/.,"rpc-reply: ");
    
                        } else {
                            expr "Job failed with error code " _ $results/headers/code _ "\n";
                        }
                    }
                }
            } else {
                expr "Could not identify the fabric!";
            }
        }
    }
    
    /*
     * Used to identify the fabric that the script has been executed on
     * knowing this is essential in a multi fabric environment when making
     * RESTful API calls to Junos Space and using the session cookies for
     * authentication.
    */
    <func:function name="jspace:fabric"> {
        if( $CONTEXT ) {
            var $fabric = {
                if ( contains( $JSESSIONID, "server") ) {
                    expr jcs:regex("\.(space-[A-Za-z0-9]+):server",$JSESSIONID)[2];
                } else {
                    expr jcs:regex("\.(space-[A-Za-z0-9]+)",$JSESSIONID)[2];
                }
            }
            <func:result select="$fabric">;
        } else {
            <func:result select="false()">;
        }
    }
    
    /* findItem */
    <func:function name="jspace:findItem">
    {
        param $url;
        param $content-type;
        param $item-type;
        param $condition;
        param $item;
        var $curlData := {
            <method> "get";
            <insecure>;
            <url> $url;
            <header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
            <header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
            <param name="filter"> "(" _ $item-type _ " " _ $condition _ " '" _ $item _ "')";
            <content-type> $content-type;
            <format> "xml";
        }
        <func:result select=" $curlData ">;
    }
    
    /* add term */
    <func:function name="jspace:addTerm">
    {
        param $url;
        param $content-type;
        param $deviceId;
        param $termname;
        param $commname;
        param $vnitarget;
        param $syncAfterPush;   /* true | false */
        var $curlData := {
            <method> "post";
            <insecure>;
            <url> $url;
            <content-type> $content-type;
            <header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
            <header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
            <format> "xml";
            <contents> {
                uexpr '
                <change-request>
                    <name>Add_route_target_to_policy</name>
                    <description>Add_route_target_to_policy</description>
                    <xmlData>
                        <![CDATA[
                            <configuration>
                                <policy-options>
                                    <policy-statement>
                                        <name>vrf-imp</name>
                                        <term operation="create" insert="before" name="REJECT">
                                            <name>' _ $termname _ '</name>
                                            <from>
                                                <community>' _ $commname _ '</community>
                                            </from>
                                            <then>
                                                <accept/>
                                            </then>
                                        </term>
                                    </policy-statement>
                                    <community>
                                        <name>' _ $commname _ '</name>
                                        <members>' _ $vnitarget _ '</members>
                                    </community>
                                </policy-options>
                            </configuration>
                        ]]>
                    </xmlData>
                    <device href="/api/space/device-management/devices/' _ $deviceId _ '"/>
                    <syncAfterPush>' _ $syncAfterPush _ '</syncAfterPush>
                </change-request>
                ';
            }
        }
        <func:result select=" $curlData ">;
    }
    
    /*
     * Can be used to identify selected devices, and their credentials.
     * Must be used with PASSDEVICECREDENTIALS  = "true" annotation for credentials.
     * Must be used with EXECUTIONTYPE = "GROUPEDEXECUTION" annotation for multiple devices
    */
    <func:function name="jspace:credentials"> {
        if( $CONTEXT ) {
            var $splitCredentials = str:split( $credentials, "\\;" );
            var $targets := {
                for-each ( $splitCredentials ) {
                    var $splitCredential = str:split( ., "\\:" );
                    var $user-target = str:split($splitCredential[1], "\@");
                    var $host = substring-before( substring-after( $deviceipmap, substring-after( $splitCredential[1], "@" ) _ "\":\"" ), "\"" );
                    <device> {
                        <ipAddr> {
                            expr $user-target[2];
                        }
                        <user> {
                            expr $user-target[1];
                        }
                        <passwd> {
                            expr $splitCredential[2];
                        }
                        <host> {
                            expr $host;
                        }
                    }
                }
            }
            <func:result select="$targets">;
        } else {
            <func:result select="false()">;
        }
    }​


    ------------------------------
    Andy Sharp
    ------------------------------



  • 5.  RE: Configlet that inserts policy before other policy

     
    Posted 01-17-2023 12:48
    I managed to find an example SLAX script that is able to perform an insert before a specific term.

    Unfortunately the SLAX script is quite complex as it is handling a lot of different requirements as it is also supporting Junos Space in a fabric and therefore has to figure out from which node it is to be executed from, and also handling the support for multiple devices..

    The script in full is shown below, and I've added some notes here to better explain what the script is doing.

    1. curl open and fabric are used to identify if Space is running in a fabric cluster, and from which node in the cluster the script is being executed from.
    2. the script iterates through however many devices have been selected from the device management view, and searches for the selected devices so as to identify the api key that is used for each of the selected device(s).
    3. The script makes an API call the /api/space/configuration-management/change-requests using the function jspace:addTerm, this function contains the configuration that will be applied to the device(s) via the configuration-management feature of Junos Space.
    4. If the job has been accepted then it parses the XML response and displays the results in the script execution window.
    5.  The function jspace:addTerm contains the information necessary to make an API call to Junos Space using the REST client.  The structure of the change-request includes, both a name and description of the change request, and the configuration to apply as XML data.   This includes a statement "<term operation="create" insert="before" name="REJECT">" , which allows us to insert the newly created term before an existing term that in this case is called REJECT.  Finally, the change-request includes a syncAfterPush entry which can be set to true or false, so that once the change request has been made either Space will resync with the device or not.

    Anyway, this is the approach that I've used in the past to leverage inserting a term before an existing term via Junos Space.

    Hope that this might help.

    /*
        # <*******************
        #
        # Copyright 2017 Juniper Networks, Inc. All rights reserved.
        # Licensed under the Juniper Networks Script Software License (the "License").
        # You may not use this script file except in compliance with the License, which is located at
        # http://www.juniper.net/support/legal/scriptlicense/
        # Unless required by applicable law or otherwise agreed to in writing by the parties, software
        # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        #
        # *******************>
    */
    version 1.2;
    
    ns junos = "http://xml.juniper.net/junos/*/junos";
    ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
    ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
    ns str = "http://exslt.org/strings";
    ns func extension = "http://exslt.org/functions";
    ns curl extension = "http://xml.libslax.org/curl";
    ns xutil extension = "http://xml.libslax.org/xutil";
    ns jspace = "http://jspace-utils/asharp@juniper.net";
    
    import "../import/junos.xsl";
    
    /* Junos Space specific context, name and description */
    /* @CONTEXT = "/device" */
    /* @NAME = "Add route target to policy" */
    /* @DESCRIPTION = "Add route target to policy" */
    /* @ISLOCAL = "true" */
    /* @PASSSPACEAUTHHEADER = "true" */
    /* @PASSDEVICECREDENTIALS = "true" */
    /* @EXECUTIONTYPE = "GROUPEDEXECUTION" */
    
    var $curl = curl:open();
    var $fabric = jspace:fabric();
    
    var $arguments = {
        <argument> {
            <name> "termname";
            <description> "Name of term to add";
        }
        <argument> {
            <name> "commname";
            <description> "Name of community to add";
        }
        <argument> {
            <name> "vnitarget";
            <description> "Name of vnitarget";
        }
    }
    
    main <op-script-results> {
        <output> {
            if ($fabric) {
                var $devices = jspace:credentials();
                if ($devices) {
                    for-each ($devices/device) {
                        sort host;
                        var $myhost = host;
                        /* find the device using API call */
                        /*
                         * url, content-type, item-type, condition, item
                        */
                        var $findDevice = curl:perform($curl,jspace:findItem(
                            "http://" _ $fabric _ ":8080/api/space/device-management/devices",
                            "",
                            "name",
                            "eq",
                            $myhost
                        ));
    
                        /* get the key of the selected device */
                        var $deviceKey = $findDevice/data/devices/device/@key;
    
                        /* make changeRequest using the API */
                        /*
                         * url, content-type, deviceKey, orig-name, new-name, resync
                        */
                        var $results = curl:perform($curl,jspace:addTerm(
                            "http://" _ $fabric _ ":8080/api/space/configuration-management/change-requests",
                            "application/vnd.net.juniper.space.configuration-management.change-request+xml;version=2;charset=UTF-8",
                            $deviceKey,
                            $termname,
                            $commname,
                            $vnitarget,
                            "true"
                        ));
    
                        if ($results/headers/code == "200") {
                            /* job accepted */
                            expr "Adding term " _ $termname _ "\n";
    
                            /* need to see if the commit was successful or not */
                            /* to get the XML data which is embedded within more xml needs lots of parsing... */
                            /* parse and convert the raw-data node */
                            var $parseOne = {
                                uexpr $results/raw-data/.;
                            }
                            var $parseTwo = xutil:string-to-xml($parseOne);
                            var $parseThree := {copy-of $parseTwo;}
    
                            /*
                               parse and convert the change-request/xmlData node
                               this step is only required if you want to display
                               the configuration that was pushed to the device.
                            */
    
                            var $xmlDataOne = {
                                uexpr $parseThree/change-request/xmlData/.;
                            }
                            var $xmlDataTwo = xutil:string-to-xml($xmlDataOne);
                            var $xmlDataThree := {copy-of $xmlDataTwo;}
    
                            copy-of $xmlDataThree;
    
                            /* display the change-request/result */
                            uexpr substring-before($parseThree/change-request/result/.,"rpc-reply: ");
    
                        } else {
                            expr "Job failed with error code " _ $results/headers/code _ "\n";
                        }
                    }
                }
            } else {
                expr "Could not identify the fabric!";
            }
        }
    }
    
    /*
     * Used to identify the fabric that the script has been executed on
     * knowing this is essential in a multi fabric environment when making
     * RESTful API calls to Junos Space and using the session cookies for
     * authentication.
    */
    <func:function name="jspace:fabric"> {
        if( $CONTEXT ) {
            var $fabric = {
                if ( contains( $JSESSIONID, "server") ) {
                    expr jcs:regex("\.(space-[A-Za-z0-9]+):server",$JSESSIONID)[2];
                } else {
                    expr jcs:regex("\.(space-[A-Za-z0-9]+)",$JSESSIONID)[2];
                }
            }
            <func:result select="$fabric">;
        } else {
            <func:result select="false()">;
        }
    }
    
    /* findItem */
    <func:function name="jspace:findItem">
    {
        param $url;
        param $content-type;
        param $item-type;
        param $condition;
        param $item;
        var $curlData := {
            <method> "get";
            <insecure>;
            <url> $url;
            <header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
            <header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
            <param name="filter"> "(" _ $item-type _ " " _ $condition _ " '" _ $item _ "')";
            <content-type> $content-type;
            <format> "xml";
        }
        <func:result select=" $curlData ">;
    }
    
    /* add term */
    <func:function name="jspace:addTerm">
    {
        param $url;
        param $content-type;
        param $deviceId;
        param $termname;
        param $commname;
        param $vnitarget;
        param $syncAfterPush;   /* true | false */
        var $curlData := {
            <method> "post";
            <insecure>;
            <url> $url;
            <content-type> $content-type;
            <header name="Cookie"> "JSESSIONID=" _ $JSESSIONID _ ";Path=/;";
            <header name="Cookie"> "JSESSIONIDSSO=" _ $JSESSIONIDSSO _ ";Path=/;";
            <format> "xml";
            <contents> {
                uexpr '
                <change-request>
                    <name>Add_route_target_to_policy</name>
                    <description>Add_route_target_to_policy</description>
                    <xmlData>
                        <![CDATA[
                            <configuration>
                                <policy-options>
                                    <policy-statement>
                                        <name>vrf-imp</name>
                                        <term operation="create" insert="before" name="REJECT">
                                            <name>' _ $termname _ '</name>
                                            <from>
                                                <community>' _ $commname _ '</community>
                                            </from>
                                            <then>
                                                <accept/>
                                            </then>
                                        </term>
                                    </policy-statement>
                                    <community>
                                        <name>' _ $commname _ '</name>
                                        <members>' _ $vnitarget _ '</members>
                                    </community>
                                </policy-options>
                            </configuration>
                        ]]>
                    </xmlData>
                    <device href="/api/space/device-management/devices/' _ $deviceId _ '"/>
                    <syncAfterPush>' _ $syncAfterPush _ '</syncAfterPush>
                </change-request>
                ';
            }
        }
        <func:result select=" $curlData ">;
    }
    
    /*
     * Can be used to identify selected devices, and their credentials.
     * Must be used with PASSDEVICECREDENTIALS  = "true" annotation for credentials.
     * Must be used with EXECUTIONTYPE = "GROUPEDEXECUTION" annotation for multiple devices
    */
    <func:function name="jspace:credentials"> {
        if( $CONTEXT ) {
            var $splitCredentials = str:split( $credentials, "\\;" );
            var $targets := {
                for-each ( $splitCredentials ) {
                    var $splitCredential = str:split( ., "\\:" );
                    var $user-target = str:split($splitCredential[1], "\@");
                    var $host = substring-before( substring-after( $deviceipmap, substring-after( $splitCredential[1], "@" ) _ "\":\"" ), "\"" );
                    <device> {
                        <ipAddr> {
                            expr $user-target[2];
                        }
                        <user> {
                            expr $user-target[1];
                        }
                        <passwd> {
                            expr $splitCredential[2];
                        }
                        <host> {
                            expr $host;
                        }
                    }
                }
            }
            <func:result select="$targets">;
        } else {
            <func:result select="false()">;
        }
    }​


    ------------------------------
    Andy Sharp
    ------------------------------