Blogs

Scripting How-To: Enforce a login-based CLI access from an authorized subnet

By Erdem posted 08-11-2015 21:27

  

Enforce a Login-based CLI Access From an Authorized Subnet

 

For SLAX version 1.0 and higher, you can use the check-file-acl script to enforce a login-based CLI access from an authorized subnet only.

 

This event script restricts the CLI access to logins from an authorized subnet only. You can easily extend this to multiple subnets, or use 0.0.0.0/32 to deny any access. It uses the jcs:parse-ip extension function.
 

Source Code and GitHub Links

The source code below is also available from the following GitHub locations:

 

Example Configuration

 

01	system {
02	    scripts {
03	        op {
04	            file check-cli-acl.slax;
05	        }
06	    }
07	}
08	 
09	event-options {
10	    policy no-cli-for-automation-user {
11	        events ui_login_event;
12	        attributes-match {
13	            ui_login_event.username matches "automation1|automation2";
14	        }
15	        then {
16	            /*
17	             * Invoke an event script to forcibly log out
18	             * the user who are not supposed to have CLI access.
19	             * If the "automation" user is logged in via NETCONF,
20	             * this script will have no effect.
21	             */
22	           event-script check-cli-acl.slax {
23	               arguments {
24	                   username "{$$.username}";                    
25	                   auth-subnet "0.0.0.0/32";
26	               }
27	           }      
28	        }
29	    }
30	    policy cli-for-admin-user {
31	        events ui_login_event;
32	        attributes-match {
33	            ui_login_event.username matches "admin1|admin2";
34	        }
35	        then {
36	            /*
37	             * Invoke an event script to check if the admin
38	             * user login via CLI is connected from an authorized
39	             * subnet, otherwise, forcibly log out the user.
40	             */
41	            event-script check-cli-acl.slax {
42	                arguments {
43	                    username "{$$.username}";
44	                    auth-subnet "172.17.27.0/24";
45	                }
46	            }      
47	        }
48	    }
49	}

 

SLAX Script Contents

 

001	/*
002	 * YOU MUST ACCEPT THE TERMS OF THIS DISCLAIMER TO USE THIS SOFTWARE.
003	 *
004	 * JUNIPER IS WILLING TO MAKE THE INCLUDED SCRIPTING SOFTWARE AVAILABLE TO YOU
005	 * ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS
006	 * DISCLAIMER. PLEASE READ THE TERMS AND CONDITIONS OF THIS DISCLAIMER CAREFULLY.
007	 *
008	 * THE SOFTWARE CONTAINED IN THIS FILE IS PROVIDED "AS IS".  JUNIPER MAKES NO
009	 * WARRANTIES OF ANY KIND WHATSOEVER WITH RESPECT TO SOFTWARE. ALL EXPRESS OR
010	 * IMPLIED CONDITIONS, REPRESENTATIVES AND WARRANTIES, INCLUDING ANY WARRANTY
011	 * OF NON-INFRINGEMENT OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
012	 * PARTICULAR PURPOSE, ARE HEREBY DISCLAIMED AND EXCLUDED TO THE EXTENT
013	 * ALLOWED BY APPLICABLE LAW.
014	 *
015	 * IN NO EVENT WILL JUNIPER BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
016	 * FOR DIRECT, SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES
017	 * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY ARISING OUT OF THE
018	 * USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF JUNIPER HAS BEEN ADVISED OF
019	 * THE POSSIBILITY OF SUCH DAMAGES.
020	 *
021	 *
022	 * Author        : Roy Lee
023	 * Version       : 1.0
024	 * Last Modified : 2008-12-01
025	 *
026	 * Description   : check-cli-acl.slax
027	 * This event script is written to restrict the cli access with a given login
028	 * from an authorized subnet only. This can be easily extended to multiple
029	 * authorized subnets, or use 0.0.0.0/32 to deny any access.
030	 *
031	 *
032	 * Below is a sample event policy configuration which will be triggered
033	 * when the administrative user "adminX" has login to the device via CLI.
034	 * The name of the user and the authorized subnet are the two arguments passed
035	 * to the event-script.
036	 *
037	 * ---
038	 * event-options {
039	 *     policy cli-for-admin-user {
040	 *         events UI_LOGIN_EVENT;
041	 *         attributes-match {
042	 *             UI_LOGIN_EVENT.username matches "admin1|admin2";
043	 *         }
044	 *         then {
045	 *             event-script check-cli-acl.slax {
046	 *                 arguments {
047	 *                     username "{$$.username}";
048	 *                     auth-subnet "172.17.27.0/24";
049	 *                 }
050	 *             }      
051	 *         }
052	 *     }
053	 * }
054	 * ---
055	 *
056	 * When a CLI login with the matching username is found, the script
057	 * will compare its source IP with the authorized subnet. It will forcibly
058	 * log out the CLI user who is not connected from the authorized subnet. 
059	 *
060	 * If the requirement is to completely disallow CLI login for a given username
061	 * from any subnet, specify the value "0.0.0.0/32" as the auth-subnet argument.
062	 *
063	 */
064	 
065	version 1.0;
066	 
067	ns junos = "http://xml.juniper.net/junos/*/junos";
068	ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
069	ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
070	 
071	 
072	param $username;
073	param $auth-subnet;
074	 
075	match / {
076	    <op-script-results> {
077	          
078	        /*
079	         * "show system users no resolve" command displays
080	         *  only the user which has TTY assigned to it,
081	         *  which means the users who are logged in
082	         *  through the CLI.
083	         */
084	 
085	        var $cmd1 = <command> "show system users no-resolve";
086	        var $out1 = jcs:invoke($cmd1);
087	         
088	        for-each ($out1/uptime-information/user-table/user-entry[user=$username]) {
089	            var $ipaddr = from;
090	       
091	            /*
092	             * Process the authorized subnet params using jcs:parse-ip(),
093	             * then extract the subnet and prefix, i.e.
094	             *     auth-ip[3] is the prefix,
095	             *     auth-ip[4] is the subnet
096	             */
097	            var $auth-ip = jcs:parse-ip($auth-subnet);
098	 
099	            /*
100	             * Append the prefix to ipaddr and
101	             * then parse it
102	             */
103	            var $temp = $ipaddr _ "/" _ $auth-ip[3];
104	            var $user-ip = jcs:parse-ip($temp);
105	 
106	            /*
107	             * Now match the subnet
108	             */
109	            if ($user-ip[4] != $auth-ip[4]) {
110	                var $logout = {
111	                    <command> 'request system logout user ' _ $username _ " terminal " _ tty;
112	                }
113	 
114	                var $result = jcs:invoke($logout);
115	                expr jcs:output("Logging out cli user ", $username);
116	                expr jcs:output(" connected from an unauthorized subnet.");
117	            }
118	        }
119	    }         
120	}

 

XML Script Contents

 

01	<?xml version="1.0"?>
02	<script>
03	  <title>check-cli-acl.slax</title>
04	  <author>royklee</author>
05	  <synopsis>
06	    Enforces a login-based CLI access from an authorized subnet only
07	  </synopsis>
08	  <coe>event</coe>
09	  <type>login</type>
10	 
11	  <description>
12	This event script is to restrict the CLI access with a given login
13	from an authorized subnet only. This can be easily extended to
14	multiple subnets, or use  0.0.0.0/32 to deny any access. It uses
15	jcs:parse-ip extension function.
16	 
17	  </description>
18	 
19	  <example>
20	    <title>Configuration</title>
21	    <description>Configuration required for this event script</description>
22	    <config>example-1.conf</config>
23	  </example>
24	 
25	  <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
26	                src="../../../../../web/leaf.js"
27	            type="text/javascript"/>
28	</script>

 


#How-To
#security
#ScriptingHow-To
#login
#eventscript
#ACL
#Slax