#!/usr/bin/perl -w use strict; use warnings; use JSON; use Getopt::Long; use LWP::UserAgent; use HTTP::Cookies; use URI; use Data::Dumper; umask 077; my $user = 'zabbix'; my $pass = 'secret'; my $site = 'default'; my $url = 'https://localhost:8443'; my $certcheck = 1; my $what = 'devices'; my $type = 'all'; my $pretty = 0; my $json = {}; @{$json->{data}} = (); GetOptions ( 'user=s' => \$user, 'password|p=s' => \$pass, 'site=s' => \$site, 'url=s' => \$url, 'cert-check!' => \$certcheck, 'what=s' => \$what, 'type:s' => \$type, 'pretty' => \$pretty ); # An empty type is the same as all $type = 'all' if ($type eq ''); # If connecting to localhost, no need to check certificate my $uri = URI->new($url); if ($uri->host =~ m/^localhost|127\.0\.0/){ $certcheck = 0; } my $site_id; my $resp; my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<); my $cj = HTTP::Cookies->new( file => "/tmp/.unifi_$username.txt", autosave => 1, ignore_discard => 1 ); my $sslopts = {}; if (not $certcheck){ $sslopts = { verify_hostname => 0, SSL_verify_mode => 0 } } my $ua = LWP::UserAgent->new( ssl_opts => $sslopts, cookie_jar => $cj ); # Check if we need to login $resp = $ua->get($url . '/api/self/sites'); if ($resp->is_error){ # Login on the API $resp = $ua->post( $url . '/api/login', Content => to_json({ username => $user, password => $pass }), Content_Type => 'application/json;charset=UTF-8' ); die "Login failed: " . $resp->message . "\n" if $resp->is_error; $resp = $ua->get($url . '/api/self/sites'); die $resp->message . "\n" if $resp->is_error; } foreach (@{from_json($resp->decoded_content)->{data}}){ if ($_->{name} eq $site || $_->{desc} eq $site){ $site_id = $_->{_id}; # If site is referenced by description, translate it to name $site = $_->{name} if ($_->{name} ne $site); last; } } die "Site $site not found\n" unless ($site_id); if ($what eq 'devices'){ $resp = $ua->get($url . '/api/s/' . $site . '/stat/device'); die $resp->message . "\n" if $resp->is_error; foreach my $entry (@{from_json($resp->decoded_content)->{data}}){ next if ($type ne 'all' && $entry->{type} ne $type); push @{$json->{data}}, { '{#UNIFI_DEV_ID}' => $entry->{device_id}, '{#UNIFI_DEV_ADOPTED}' => $entry->{adopted}, '{#UNIFI_DEV_MODEL}' => $entry->{model}, '{#UNIFI_DEV_NAME}' => $entry->{name} || $entry->{mac}, '{#UNIFI_DEV_MAC}' => $entry->{mac}, '{#UNIFI_DEV_TYPE}' => $entry->{type} }; } } elsif ($what eq 'stations'){ $resp = $ua->get($url . '/api/s/' . $site . '/stat/sta'); die $resp->message . "\n" if $resp->is_error; foreach my $entry (@{from_json($resp->decoded_content)->{data}}){ # Ignore other sites next if ($entry->{site_id} ne $site_id); next if ($type eq 'wireless' and $entry->{is_wired} == JSON::true); next if ($type eq 'wired' and $entry->{is_wired} == JSON::false); push @{$json->{data}}, { '{#UNIFI_STA_ID}' => $entry->{_id}, '{#UNIFI_STA_NAME}' => (defined $entry->{hostname}) ? $entry->{hostname} : $entry->{mac}, '{#UNIFI_STA_MAC}' => $entry->{mac} }; } } elsif ($what eq 'networks'){ $resp = $ua->get($url . '/api/s/' . $site . '/rest/networkconf'); die $resp->message . "\n" if $resp->is_error; foreach my $entry (@{from_json($resp->decoded_content)->{data}}){ # Ignore other sites next if ($entry->{site_id} ne $site_id); next if ($type ne 'all' and $entry->{purpose} ne $type); push @{$json->{data}}, { '{#UNIFI_NET_ID}' => $entry->{_id}, '{#UNIFI_NET_NAME}' => $entry->{name} }; } } elsif ($what eq 'wlan') { $resp = $ua->get($url . '/api/s/' . $site . '/rest/wlanconf'); die $resp->message . "\n" if $resp->is_error; foreach my $entry (@{from_json($resp->decoded_content)->{data}}){ push @{$json->{data}}, { '{#UNIFI_WLAN_ID}' => $entry->{_id}, '{#UNIFI_WLAN_NAME}' => $entry->{name} }; } } print to_json($json, { pretty => $pretty });