Example: Meraki - Control SSID's and Device Policy via Exec and BASH

exec
example
meraki
Tags: #<Tag:0x00007f01571ce030> #<Tag:0x00007f01571cdea0> #<Tag:0x00007f01571cdd10>

(Gordon Geist) #1

I use the Maraki API to control the SSID availability and change a device’s policy.

My use case is:

  1. Turn on/off the guest SSID via Alexa/Openhab
  2. Allow my wife/rules to turn off streaming content and similar when our kids should get back to the real world

You should know how to manipulate your linux environment and secure your installation along with good RBAC controls to your configs.

First section id Device Policy and the second is the SSID control. Bash scripts are kept executable by openhab’s user. I am sure that I could have mapped this via the HTTP binding but I already had the Bash scripts sooo.

_Device Policies - Change network behavior based upon a sitemap _
DevicePolicy.items

  • Create items to manipulate/display in the sitemap.
//Device Policy
String	Policy_LivingRoomRoku	"Living Room Roku"
String	Policy_NintendoSwitch	"Nintendo Switch"
String	Policy_BlueNintendo3DS	"Blue 3DS"
String	Policy_RedNintendo3DS	"Red 3DS"
String	Policy_Chromebook		"Chromebook"
String	Policy_AppleTV			"MB AppleTV"
String	Policy_DominicsiPhone	"DominicsiPhone"
String	Policy_OfficeiMac		"Office iMac"
String  Policy_FireTV           "FireTV"
String  Policy_XBOX_ONE         "XBOX ONE"
String  Policy_MB_ROKU          "Master Bedroom Roku"

devicepolicy.things

//device policy normal
Thing exec:command:DevicePolicyExecNormal "Device Policy Normal" [command="sudo /home/openhabian/meraki_client_policy_Normal %2$s", interval=0, timeout=5, autorun=false]
//device policy blocked
Thing exec:command:DevicePolicyExecBlocked "Device Policy Blocked" [command="sudo /home/openhabian/meraki_client_policy_Blocked %2$s", interval=0, timeout=5, autorun=false]
//device group policy 102
Thing exec:command:GroupPolicyExec102 "Group Policy 102" [command="sudo /home/openhabian/meraki_client_policy_PolicyNum102 %2$s", interval=0, timeout=5, autorun=false]
//device group policy 103
Thing exec:command:GroupPolicyExec103 "Group Policy 103" [command="sudo /home/openhabian/meraki_client_policy_PolicyNum103 %2$s", interval=0, timeout=5, autorun=false]
//device group policy 104
Thing exec:command:GroupPolicyExec104 "Group Policy 104" [command="sudo /home/openhabian/meraki_client_policy_PolicyNum104 %2$s", interval=0, timeout=5, autorun=false]
//device group policy 105
Thing exec:command:GroupPolicyExec105 "Group Policy 105" [command="sudo /home/openhabian/meraki_client_policy_PolicyNum105 %2$s", interval=0, timeout=5, autorun=false]

Exec.items

  • Maraki has two default policies Normal and Blocked then your group policies are exposed in order of creation by 102,103, etc - u can find the # of your policy by editing the policy within the Meraki portal and looking at the url in your browser:
//Device Policy Normal
String     DevicePolicyExecNormal_Output          "Output"           {channel="exec:command:DevicePolicyExecNormal:output"}
String     DevicePolicyExecNormal_Input           "Input"            {channel="exec:command:DevicePolicyExecNormal:input"}
Number     DevicePolicyExecNormal_Exit            "Exit Value"       {channel="exec:command:DevicePolicyExecNormal:exit"}
Switch     DevicePolicyExecNormal_Run             "Running"          {channel="exec:command:DevicePolicyExecNormal:run"}
DateTime   DevicePolicyExecNormal_Lastexecution   "Last Execution"   {channel="exec:command:DevicePolicyExecNormal:lastexecution"}
//Device Policy Blocked
String     DevicePolicyExecBlocked_Output          "Output"           {channel="exec:command:DevicePolicyExecBlocked:output"}
String     DevicePolicyExecBlocked_Input           "Input"            {channel="exec:command:DevicePolicyExecBlocked:input"}
Number     DevicePolicyExecBlocked_Exit            "Exit Value"       {channel="exec:command:DevicePolicyExecBlocked:exit"}
Switch     DevicePolicyExecBlocked_Run             "Running"          {channel="exec:command:DevicePolicyExecBlocked:run"}
DateTime   DevicePolicyExecBlocked_Lastexecution   "Last Execution"   {channel="exec:command:DevicePolicyExecBlocked:lastexecution"}
//Device Policy 102
String     GroupPolicy102_Output          "Output"           {channel="exec:command:GroupPolicyExec102:output"}
String     GroupPolicy102_Input           "Input"            {channel="exec:command:GroupPolicyExec102:input"}
Number     GroupPolicy102_Exit            "Exit Value"       {channel="exec:command:GroupPolicyExec102:exit"}
Switch     GroupPolicy102_Run             "Running"          {channel="exec:command:GroupPolicyExec102:run"}
DateTime   GroupPolicy102_Lastexecution   "Last Execution"   {channel="exec:command:GroupPolicyExec102:lastexecution"}
//Device Policy 103
String     GroupPolicy103_Output          "Output"           {channel="exec:command:GroupPolicyExec103:output"}
String     GroupPolicy103_Input           "Input"            {channel="exec:command:GroupPolicyExec103:input"}
Number     GroupPolicy103_Exit            "Exit Value"       {channel="exec:command:GroupPolicyExec103:exit"}
Switch     GroupPolicy103_Run             "Running"          {channel="exec:command:GroupPolicyExec103:run"}
DateTime   GroupPolicy103_Lastexecution   "Last Execution"   {channel="exec:command:GroupPolicyExec103:lastexecution"}
//Device Policy 104
String     GroupPolicy104_Output          "Output"           {channel="exec:command:GroupPolicyExec104:output"}
String     GroupPolicy104_Input           "Input"            {channel="exec:command:GroupPolicyExec104:input"}
Number     GroupPolicy104_Exit            "Exit Value"       {channel="exec:command:GroupPolicyExec104:exit"}
Switch     GroupPolicy104_Run             "Running"          {channel="exec:command:GroupPolicyExec104:run"}
DateTime   GroupPolicy104_Lastexecution   "Last Execution"   {channel="exec:command:GroupPolicyExec104:lastexecution"}
//Device Policy 105
String     GroupPolicy105_Output          "Output"           {channel="exec:command:GroupPolicyExec105:output"}
String     GroupPolicy105_Input           "Input"            {channel="exec:command:GroupPolicyExec105:input"}
Number     GroupPolicy105_Exit            "Exit Value"       {channel="exec:command:GroupPolicyExec105:exit"}
Switch     GroupPolicy105_Run             "Running"          {channel="exec:command:GroupPolicyExec105:run"}
DateTime   GroupPolicy105_Lastexecution   "Last Execution"   {channel="exec:command:GroupPolicyExec105:lastexecution"}

Devicepolicy.rules

  • Rules to implement changes when a new policy is selected via the sitemap. This could be shortened by the bash script using multiple variables but just havent gotten around to changing it (hint hint)

  • MAC address substituted here for each device you want to control by policy. MAC is right there in the Meraki portal -copy paste

////////////////////
//Policy_OfficeiMac
/////////////////////
rule "Policy_OfficeiMac Actions"
	when Item Policy_OfficeiMac changed
	then
		if (Policy_OfficeiMac.state == "norm") {
			DevicePolicyExecNormal_Input.sendCommand("ff:ff:ff:ff:ff") //mac address of the iMAC
			DevicePolicyExecNormal_Run.sendCommand(ON)
			}
		if (Policy_OfficeiMac.state == "block") {
			DevicePolicyExecBlocked_Input.sendCommand("ff:ff:ff:ff:ff")
			DevicePolicyExecBlocked_Run.sendCommand(ON)
			}
		if (Policy_OfficeiMac.state == "p_102") { 
			GroupPolicy102_Input.sendCommand("ff:ff:ff:ff:ff")
			GroupPolicy102_Run.sendCommand(ON)
			}
		if (Policy_OfficeiMac.state == "p_103") { 
			GroupPolicy103_Input.sendCommand("ff:ff:ff:ff:ff")
			GroupPolicy103_Run.sendCommand(ON)
			}
		if (Policy_OfficeiMac.state == "p_104") { 
			GroupPolicy104_Input.sendCommand("ff:ff:ff:ff:ff")
			GroupPolicy104_Run.sendCommand(ON)
			}
		if (Policy_OfficeiMac.state == "p_105") { 
			GroupPolicy105_Input.sendCommand("ff:ff:ff:ff:ff")
			GroupPolicy105_Run.sendCommand(ON)
			}
end
//rinse repeat for all devices

Home.sitemap

  • Simple to make this pin code protected but thats out of scope here
			Group item=Device_Policy_Group {
				Switch item=Policy_OfficeiMac mappings=[norm="Norm",block="Block",p_103="Local",p_105="No Youtube"]
				}

NormalPolicy Bash script

  • The exec item sends the MAC address as the variable

  • <org_id> is your Organization ID that contains the Meraki devices your managing.Read the Meraki API manual

  • <api_key> is the unique api-key for your organization and received after you apply for api access. Consider this as important as securing your root access password i.e. where the bash script is and the users/groups that can read.

  • Change “normal” to “blocked” for …well you know.

meraki_client_policy_Normal

#!/bin/sh
mac=$1
merakiurl="https://dashboard.meraki.com/api/v0/networks/<org_id>/clients/${mac}/policy?timespan=2592000"
curl -L -H 'X-Cisco-Meraki-API-Key:<api_key>' -X PUT -H'Content-Type: application/json'  --data-binary '{"devicePolicy":"normal"}' $merakiurl
exit 0

DevicePolicy102

  • Same elements as above with the exception of the Curl data payload is different for the non-default policies.

  • Change “groupPolicyId”: 102 to 103 etc etc for each of the policies you would like to control

meraki_client_policy_PolicyNum102

#!/bin/sh
mac=$1
merakiurl="https://dashboard.meraki.com/api/v0/networks/<org_id>/clients/${mac}/policy?timespan=2592000"
curl -L -H 'X-Cisco-Meraki-API-Key:<api_key>' -X PUT -H'Content-Type: application/json'  --data-binary '{"devicePolicy": "group","groupPolicyId": 102}' $merakiurl
exit 0

SSID Control

  • Same drill as above but you need the SSID # for what you want to control. In Meraki’s portal navigate to the SSID to controls “edit settings” page and the url at the top will have it as"/configure/access_control?ssid_number=0" where the number at the end is the SSID. You can see that you could programatically change your SSID’s daily/hourly etc

wirelesscontrol.things

Thing exec:command:guestwirelesscontroloff "Guest Wireless Control Off" [command="sudo /home/openhabian/merakissid_1_api_off", interval=0, timeout=5, autorun=false]
Thing exec:command:guestwirelesscontrolon "Guest Wireless Control On" [command="sudo /home/openhabian/merakissid_1_api_on", interval=0, timeout=5, autorun=false]

wirelesscontrol.items

// Guest Network
Switch Guest_Network_Switch "Guest Network" ["Switchable"]
// Guest Wireless Off
String     GuestWirelessControlOff_Output          "Output"           {channel="exec:command:guestwirelesscontroloff:output"}
String     GuestWirelessControlOff_Input           "Input"            {channel="exec:command:guestwirelesscontroloff:input"}
Number     GuestWirelessControlOff_Exit            "Exit Value"       {channel="exec:command:guestwirelesscontroloff:exit"}
Switch     GuestWirelessControlOff_Run             "Running"          {channel="exec:command:guestwirelesscontroloff:run"}
DateTime   GuestWirelessControlOff_Lastexecution   "Last Execution"   {channel="exec:command:guestwirelesscontroloff:lastexecution"}
// Guest Wireless On
String     GuestWirelessControlOn_Output          "Output"           {channel="exec:command:guestwirelesscontrolon:output"}
String     GuestWirelessControlOn_Input           "Input"            {channel="exec:command:guestwirelesscontrolon:input"}
Number     GuestWirelessControlOn_Exit            "Exit Value"       {channel="exec:command:guestwirelesscontrolon:exit"}
Switch     GuestWirelessControlOn_Run             "Running"          {channel="exec:command:guestwirelesscontrolon:run"}
DateTime   GuestWirelessControlOn_Lastexecution   "Last Execution"   {channel="exec:command:guestwirelesscontrolon:lastexecution"}

Guest.rules

rule "Guest Network"
//	when
		Item Guest_Network_Switch received command
	then
			switch(receivedCommand.toString ){
			case "ON": {
			GuestWirelessControlOn_Run.sendCommand(ON)
			//sendBroadcastNotification("Turned On the Guest Wireless at " + now,"","warning")
			}
			case "OFF": {
		GuestWirelessControlOff_Run.sendCommand(ON)
		//sendBroadcastNotification("Turned Off the Guest Wireless at " + now,"","warning")
			}
		}
end

Home.sitemap

			Switch item=Guest_Network_Switch label="Guest Wireless Control"

Bash scripts

  • replace “1” in the url below with the SSID # you want to control

merakissid_1_api_on

#!/bin/sh
curl -L -H 'X-Cisco-Meraki-API-Key:<api_key>' -X PUT -H'Content-Type: application/json' --data-binary '{"enabled":true}' 'https://dashboard.meraki.com/api/v0/networks/<org_id>/ssids/1'
END_SCRIPT
exit 0

merakissid_1_api_off

#!/bin/sh
curl -L -H 'X-Cisco-Meraki-API-Key:<api_key>' -X PUT -H'Content-Type: application/json' --data-binary '{"enabled":false}' 'https://dashboard.meraki.com/api/v0/networks/<org_id>/ssids/1'
END_SCRIPT
exit 0```

rinse repeat for other SSID's

(Vincent Regaud) #2

Of course. I don’t use Meraki but others do.
Share away!