I use the Maraki API to control the SSID availability and change a device’s policy.
My use case is:
- Turn on/off the guest SSID via Alexa/Openhab
- 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