Interacting with the Unifi API using Mattermost slash commands
Or, how to annoy the kids by making it easy for their mum to ban them from the Wifi.
We live in a 3 storey house, with kids usually in their rooms on the upper 2 floors. One is usually watching youtube while the other is usually gaming. They never seem to answer their phones so this is easiest way to get their attention!
This is a rundown on one of my more recent projects. This utilises 3 different pieces of software:
Mattermost: An open source, selfhosted Slack clone. I’ve tried so hard to keep away from whatsapp for several years, but it seems recently i’ve been more or less forced into using due to family. I dont like using it, i dont like the company behind and certainly dont trust them with my data.
Looking around online, Mattermost best suited my needs and i have been running this server for quite some time. the integrations are good as it tries to be slack-compatible. So anything that works with slack should work with Mattermost.
Huginn: An open source, selfhosted IFTTT clone
This is an interesting one, its software i have only recently come across and haven’t explored fully yet. In short, this software can receive, manipulate and send data to and from different web services.
I chose to go with this instead of just using IFTTT because of the access required to make this solution work and the credentials that are in use.
The Unifi API: Works in conjunction with the Unifi Controller
I run a pretty extensive home network with the wireless being provided over 3 UniFi AP-AC-Pro access points. I also run the controller 24/7 on a VM.
A basic data flow
Before i go into detail on how i have this setup, i figure its better to have an understanding how each piece interacts with the others. For this ill start with the user interaction. This is just a high level overview that wont go into the actual config. That will be further on.
The entire process is kicked off by a user on Mattermost using a slash command, here is what mine looks like:
Slash command, names removed.
This is setup within Mattermost, i set the command, the ‘help’ and the URL to POST to.
Next is the Huginn config. Within Huginn i have setup the incoming webhook URL which is used in the Mattermost config and then setup some agents to parse the incoming data. This is the flow within Huggin:
- Mattermost POST’s JSON to agent listening on Huginn
- Incoming agent on huginn passes the JSON onto a JSON parser
- The JSON parser extracts the ‘name’ from the JSON and passes it onto the “script agent” on Huginns
- The ‘script agent’ runs a premade script with the ‘name’ as an argument
- The ‘script’ interacts with the Unifi API to ban the user
- After script has run, it posts a message in Mattermost to say its been done.
Thats a quick overview of what is going on when my wife or I use the Mattermost slash command. This all happens within about 10 seconds.
The configs
Now its time for the actual configs i have used.
These arent perfect and intend on improving the whole process. The main thing i dont like about this entire process is that the Unifi API script is completely static. I have had to add the MAC addresses and names to the script to be able get this to work. I perhaps need to look at using some kind of database outside of the Unifi environment to track these. It would also be nice to be able to unban people but its not somthing ive even looked at yet.
Mattermost Settings:
Here are screenshots of the slash command settings page from mattermost:
The URL used in the “Request URL” is from Huginn, you will need to configure the incoming webhook in Huginn then come back to Mattermost to add it in.
Huginn Settings
There are multiple parts to the Huginn settings. Ill post screenshots for each agent. These all work in serial, one agent passes its data/output onto the next.
Incoming webhook agent
This is the entry point into Huginn. This receives the JSON from Mattermost
For the incoming webhook settings, some things you need to add:
- the secret – This is justrandomly generated. I just mashed the keyboard
- payload_path – this is a full stop, to bring in ALL the incoming JSON from Mattermost.
- The Mattermost token is the same as the ‘secret’
JSON Parser
This is the section that pulls out the users name that is sent via the Mattermost slash command.
Shell command agent
Before you can use the shell command agent in Huginn, you need to enable it in your config. This can be dangerous, especially if this is a multiuser server.
You also need configure the command to be able to pull the users name which is being passed on by the JOSN Parser, ill add that in as a seperate comment below the image as it doesnt get shown.
Here is the command in full:
/home/huginn/unifi-scripts/block-test.sh
The argument is whats being passed across by the JSON parser. That variable name is configured by the “data key” in the JSON Parser section.
Unifi API Script
I have had to modify the Unifi API script because of the static “mappings” i have had to create (pointing a name to certain mac address). Again, this would be nice to be somewhat automated or dynamic. Even something like using dynamic dns which points to an IP which i can find the MAC address for the user currently using that IP. Something like that.
Here are the modifications i have made:
Firstly, this is a wrapper which takes the name as an argument, then runs the actual block section of the unifi script with the users MAC address:
#! /bin/sh
# FILE NAME : Block Note9
# DESCRIPTION: Block my phone - Testing
# AUTHOR: Jon
#VARIABLES
output_file="unifi_$server_`date +%Y%m%d%H%M`.unf"
#Load Api
. ./unifi_sh_api
unifi_login
if [ "$1" = "user1-chromebook" ]; then
unifi_block_user1_chromebook
elif
[ "$1" = "user2-phone" ]; then
unifi_block_user2_phone
elif
[ "$1" = "user3-xbox" ]; then
unifi_block_user3_xbox
elif
[ "$1" = "user4-s7" ]; then
unifi_block_user4_phone_s7
elif
[ "$1" = "user5-s8" ]; then
unifi_block_user5_phone_s8
elif
[ "$1" = "jon" ]; then
unifi_block_jon
fi
unifi_logout
There is a lot of testing stuff still in there (me at the end, filename and comments). You will also need to change userx to whatever you want to be, this will have to be replicated in the unifi_sh_api script.
Here is an example of the changes i made to the unifi_sh_api script:
# Block user2 Phone
unifi_block_user2_phone() {
mac=aa:bb:cc:11:22:33
${curl_cmd} --data "{\"cmd\":\"block-sta\", \"mac\":\"${mac}\"}" $baseurl/api/s/$site/cmd/stamgr
}
You need to change block_user2_phone to the same user you set in the wrapper above. You will also need to set the correct MAC address.
Also remember to set your unifi login details at the top of the unifi_sh_api script
Post back to Mattermost
This section really isnt needed, but this just posts a message back to Mattermost in a specific channel to say the banning is complete.
This agent is just the the huginn Slackagent. Will need to create an incoming webhook URL in Mattermost.
That should get it working. Give it a test. I will be making improvements on this over time (as and when i can)