From a7a6e67e87c2a9e48148b569d794030d61b444f7 Mon Sep 17 00:00:00 2001 From: PipoCanaja <38363551+PipoCanaja@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:15:40 +0100 Subject: [PATCH] NAC - Improve search in WebUI - Keep Historical data (#15629) * search improvement for PortNac * rename func * style * DB migration for timestamps * style * rules * fix manually db_schema * remove vlan only search for now * add a bool column to ident historical nac entries * add columns to the table * queryByOui renamed everywhere * age value instead of delete * style * style * use Illuminate\Support\Facades\DB; * tests fix * module_tables.yaml * dump model instead of tests/module_tables.yaml * tests * testVrp * daily * config * display historical NAC entries in global view * same for NAC device page * nac tab on device/port view * and display the tab link if necessary * filter by port as well * historical data in port tab * formatters --- LibreNMS/Modules/Nac.php | 30 +- .../Controllers/Table/PortNacController.php | 103 ++- app/Models/PortsNac.php | 2 +- daily.php | 7 + daily.sh | 1 + ...10_130000_historical_data_to_ports_nac.php | 34 + doc/Support/Cleanup-options.md | 1 + includes/html/pages/device/port.inc.php | 5 + includes/html/pages/device/port/nac.inc.php | 140 ++++ lang/en/settings.php | 4 + lang/fr/settings.php | 4 + lang/it/settings.php | 4 + misc/config_definitions.json | 8 + misc/db_schema.yaml | 3 + resources/views/device/tabs/nac.blade.php | 26 +- resources/views/nac.blade.php | 28 +- tests/data/ios_nac.json | 5 + tests/data/vrp_nac.json | 648 +++++++++++++++++- 18 files changed, 1033 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2023_12_10_130000_historical_data_to_ports_nac.php create mode 100644 includes/html/pages/device/port/nac.inc.php diff --git a/LibreNMS/Modules/Nac.php b/LibreNMS/Modules/Nac.php index 95564f9f6e..3195ae0f04 100644 --- a/LibreNMS/Modules/Nac.php +++ b/LibreNMS/Modules/Nac.php @@ -28,6 +28,7 @@ namespace LibreNMS\Modules; use App\Models\Device; use App\Models\PortsNac; use App\Observers\ModuleModelObserver; +use Illuminate\Support\Facades\DB; use LibreNMS\Interfaces\Data\DataStorageInterface; use LibreNMS\Interfaces\Module; use LibreNMS\Interfaces\Polling\NacPolling; @@ -79,22 +80,37 @@ class Nac implements Module ModuleModelObserver::observe(PortsNac::class); $nac_entries = $os->pollNac()->keyBy('mac_address'); - $existing_entries = $os->getDevice()->portsNac->keyBy('mac_address'); + //filter out historical entries + $existing_entries = $os->getDevice()->portsNac->keyBy('mac_address')->filter(function ($value, $key) { + if ($value['historical'] == 0) { + return $value; + } + }); // update existing models foreach ($nac_entries as $nac_entry) { if ($existing = $existing_entries->get($nac_entry->mac_address)) { - $nac_entries->put($nac_entry->mac_address, $existing->fill($nac_entry->attributesToArray())); + // we have the same mac_address once again. Let's decide if we should keep the existing as history or not. + if (($nac_entry->port_id == $existing->port_id) || + ($nac_entry->method == $existing->method) || + ($nac_entry->vlan == $existing->vlan) || + ($nac_entry->authz_by == $existing->authz_by) || + ($nac_entry->authz_status == $existing->authz_status) || + ($nac_entry->ip_address == $existing->ip_address) || + ($nac_entry->username == $existing->username)) { + // if everything is similar, we update current entry. If not, we duplicate+history + $nac_entries->put($nac_entry->mac_address, $existing->fill($nac_entry->attributesToArray())); + } } } // persist to DB $os->getDevice()->portsNac()->saveMany($nac_entries); - $delete = $existing_entries->diffKeys($nac_entries)->pluck('ports_nac_id'); - if ($delete->isNotEmpty()) { - $count = PortsNac::query()->whereIntegerInRaw('ports_nac_id', $delete)->delete(); - d_echo('Deleted ' . $count, str_repeat('-', $count)); + $age = $existing_entries->diffKeys($nac_entries)->pluck('ports_nac_id'); + if ($age->isNotEmpty()) { + $count = PortsNac::query()->whereIntegerInRaw('ports_nac_id', $age)->update(['historical' => true, 'updated_at' => DB::raw('updated_at')]); + d_echo('Aged ' . $count, str_repeat('-', $count)); } } } @@ -117,7 +133,7 @@ class Nac implements Module 'ports_nac' => $device->portsNac()->orderBy('ports.ifIndex')->orderBy('mac_address') ->leftJoin('ports', 'ports_nac.port_id', 'ports.port_id') ->select(['ports_nac.*', 'ifIndex']) - ->get()->map->makeHidden(['ports_nac_id', 'device_id', 'port_id']), + ->get()->map->makeHidden(['ports_nac_id', 'device_id', 'port_id', 'updated_at', 'created_at']), ]; } } diff --git a/app/Http/Controllers/Table/PortNacController.php b/app/Http/Controllers/Table/PortNacController.php index 83892812b7..c9d4e0b4ed 100644 --- a/app/Http/Controllers/Table/PortNacController.php +++ b/app/Http/Controllers/Table/PortNacController.php @@ -25,7 +25,11 @@ namespace App\Http\Controllers\Table; +use App\Models\Port; use App\Models\PortsNac; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; use LibreNMS\Util\Mac; use LibreNMS\Util\Url; @@ -34,7 +38,8 @@ class PortNacController extends TableController public function rules() { return [ - 'device_id' => 'int', + 'device_id' => 'nullable|integer', + 'searchby' => 'in:mac,ip,description,vendor,', ]; } @@ -62,6 +67,8 @@ class PortNacController extends TableController 'authc_status', 'authz_status', 'method', + 'created_at', + 'updated_at', ]; } @@ -73,13 +80,53 @@ class PortNacController extends TableController */ public function baseQuery($request) { - return PortsNac::select('device_id', 'port_id', 'mac_address', 'ip_address', 'vlan', 'domain', 'host_mode', 'username', 'authz_by', 'timeout', 'time_elapsed', 'time_left', 'authc_status', 'authz_status', 'method') + return PortsNac::select('device_id', 'port_id', 'mac_address', 'ip_address', 'vlan', 'domain', 'host_mode', 'username', 'authz_by', 'timeout', 'time_elapsed', 'time_left', 'authc_status', 'authz_status', 'method', 'created_at', 'updated_at', 'historical') ->when($request->device_id, fn ($q, $id) => $q->where('device_id', $id)) + ->when($request->port_id, fn ($q, $id) => $q->where('port_id', $id)) + ->when($request->showHistorical != 'true', fn ($q, $h) => $q->where('historical', 0)) ->hasAccess($request->user()) ->with('port') ->with('device'); } + /** + * @param string $search + * @param Builder $query + * @param array $fields + * @return Builder|\Illuminate\Database\Query\Builder + */ + protected function search($search, $query, $fields = []) + { + if ($search = trim(\Request::get('searchPhrase') ?? '')) { + $mac_search = '%' . str_replace([':', ' ', '-', '.', '0x'], '', $search) . '%'; + + switch (\Request::get('searchby') ?? '') { + case 'mac': + return $query->where('ports_nac.mac_address', 'like', $search); + case 'ip': + return $query->whereIn('ports_nac.ip_address', $search); + case 'description': + return $query->whereIntegerInRaw('ports_nac.port_id', $this->findPorts($search)); + case 'vendor': + $vendor_ouis = $this->ouisFromVendor($search); + + return $this->queryByOui($vendor_ouis, $query); + default: + return $query->where(function ($query) use ($search, $mac_search) { + $vendor_ouis = $this->ouisFromVendor($search); + $this->queryByOui($vendor_ouis, $query) + ->orWhereIntegerInRaw('ports_nac.port_id', $this->findPorts($search)) + ->orWhere('ports_nac.vlan', 'like', '%' . $search . '%') + ->orWhere('ports_nac.mac_address', 'like', $mac_search) + ->orWhere('ports_nac.username', 'like', '%' . $search . '%') + ->orWhere('ports_nac.ip_address', 'like', '%' . $search . '%'); + }); + } + } + + return $query; + } + /** * @param PortsNac $nac */ @@ -87,12 +134,62 @@ class PortNacController extends TableController { $item = $nac->toArray(); $mac = Mac::parse($item['mac_address']); + $item['updated_at'] = $nac->updated_at ? ($item['historical'] == 0 ? $nac->updated_at->diffForHumans() : $nac->updated_at->toDateTimeString()) : ''; + $item['created_at'] = $nac->created_at ? $nac->created_at->toDateTimeString() : ''; $item['port_id'] = Url::portLink($nac->port, $nac->port->getShortLabel()); $item['mac_oui'] = $mac->vendor(); $item['mac_address'] = $mac->readable(); - $item['port'] = null; //free some unused data to be sent to the browser $item['device_id'] = Url::deviceLink($nac->device); + unset($item['device']); //avoid sending all device data in the JSON reply + unset($item['port']); //free some unused data to be sent to the browser return $item; } + + /** + * @param string $ifAlias + * @return Collection + */ + protected function findPorts($ifAlias): Collection + { + $port_id = \Request::get('port_id'); + $device_id = \Request::get('device_id'); + + return Port::where('ifAlias', 'like', "%$ifAlias%") + ->when($device_id, function ($query) use ($device_id) { + return $query->where('device_id', $device_id); + }) + ->when($port_id, function ($query) use ($port_id) { + return $query->where('port_id', $port_id); + }) + ->pluck('port_id'); + } + + /** + * Get the OUI list for a specific vendor + * + * @param string $vendor + * @return array + */ + protected function ouisFromVendor(string $vendor): array + { + return DB::table('vendor_ouis') + ->where('vendor', 'LIKE', '%' . $vendor . '%') + ->pluck('oui') + ->toArray(); + } + + /** + * filter $query from vendor OUIs + */ + protected function queryByOui(array $vendor_ouis, Builder $query): Builder + { + $query->where(function (Builder $query) use ($vendor_ouis) { + foreach ($vendor_ouis as $oui) { + $query->orWhere('ports_nac.mac_address', 'LIKE', "$oui%"); + } + }); + + return $query; // Return the query builder instance + } } diff --git a/app/Models/PortsNac.php b/app/Models/PortsNac.php index eb42ba96d5..c02eeac568 100644 --- a/app/Models/PortsNac.php +++ b/app/Models/PortsNac.php @@ -31,7 +31,7 @@ class PortsNac extends PortRelatedModel { protected $table = 'ports_nac'; protected $primaryKey = 'ports_nac_id'; - public $timestamps = false; + public $timestamps = true; protected $fillable = [ 'auth_id', 'device_id', diff --git a/daily.php b/daily.php index 5bc5fc2aac..ce0f3d9217 100644 --- a/daily.php +++ b/daily.php @@ -111,10 +111,17 @@ if ($options['f'] === 'ports_fdb') { $ret = lock_and_purge('ports_fdb', 'updated_at < DATE_SUB(NOW(), INTERVAL ? DAY)'); exit($ret); } + +if ($options['f'] === 'ports_nac') { + $ret = lock_and_purge('ports_nac', 'updated_at < DATE_SUB(NOW(), INTERVAL ? DAY)'); + exit($ret); +} + if ($options['f'] === 'route') { $ret = lock_and_purge('route', 'updated_at < DATE_SUB(NOW(), INTERVAL ? DAY)'); exit($ret); } + if ($options['f'] === 'eventlog') { $ret = lock_and_purge('eventlog', 'datetime < DATE_SUB(NOW(), INTERVAL ? DAY)'); exit($ret); diff --git a/daily.sh b/daily.sh index f6b790fd51..4dfe541b82 100755 --- a/daily.sh +++ b/daily.sh @@ -387,6 +387,7 @@ main () { "alert_log" "rrd_purge" "ports_fdb" + "ports_nac" "route" "ports_purge") call_daily_php "${options[@]}" diff --git a/database/migrations/2023_12_10_130000_historical_data_to_ports_nac.php b/database/migrations/2023_12_10_130000_historical_data_to_ports_nac.php new file mode 100644 index 0000000000..368f8103a7 --- /dev/null +++ b/database/migrations/2023_12_10_130000_historical_data_to_ports_nac.php @@ -0,0 +1,34 @@ +timestamps(); + $table->boolean('historical')->default(0); + }); + DB::table('ports_nac')->update(['created_at' => \Carbon\Carbon::now()]); + DB::table('ports_nac')->update(['updated_at' => \Carbon\Carbon::now()]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::table('ports_nac', function (Blueprint $table) { + $table->dropColumn(['created_at', 'updated_at', 'historical']); + }); + } +}; diff --git a/doc/Support/Cleanup-options.md b/doc/Support/Cleanup-options.md index d772af128a..1dcdf0c411 100644 --- a/doc/Support/Cleanup-options.md +++ b/doc/Support/Cleanup-options.md @@ -16,6 +16,7 @@ These options rely on ```daily.sh``` running from cron as per the installation i lnms config:set alert_log_purge 365 lnms config:set authlog_purge 30 lnms config:set ports_fdb_purge 10 + lnms config:set ports_nac_purge 10 lnms config:set device_perf_purge 7 lnms config:set rrd_purge 0 lnms config:set ports_purge true diff --git a/includes/html/pages/device/port.inc.php b/includes/html/pages/device/port.inc.php index cfec5dc91c..995092ea1f 100644 --- a/includes/html/pages/device/port.inc.php +++ b/includes/html/pages/device/port.inc.php @@ -2,6 +2,7 @@ use App\Models\Port; use App\Models\PortAdsl; +use App\Models\PortsNac; use App\Models\PortVdsl; use App\Plugins\Hooks\PortTabHook; use LibreNMS\Util\Rewrite; @@ -95,6 +96,10 @@ if (PortAdsl::where('port_id', $port->port_id)->exists()) { $menu_options['xdsl'] = 'xDSL'; } +if (PortsNac::where('port_id', $port->port_id)->exists()) { + $menu_options['nac'] = 'NAC'; +} + if (DeviceCache::getPrimary()->ports()->where('pagpGroupIfIndex', $port->ifIndex)->exists()) { $menu_options['pagp'] = 'PAgP'; } diff --git a/includes/html/pages/device/port/nac.inc.php b/includes/html/pages/device/port/nac.inc.php new file mode 100644 index 0000000000..4b752df202 --- /dev/null +++ b/includes/html/pages/device/port/nac.inc.php @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
PortsMac AddressVendorIP AddressVlanDomainHost ModeUsernameAuth ByTimeoutTime ElapsedTime LeftNAC AuthcNAC AuthzNAC MethodFirst seenLast seen
+ + + diff --git a/lang/en/settings.php b/lang/en/settings.php index f5c51cd64d..e3a4302f3d 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -1260,6 +1260,10 @@ return [ 'description' => 'Port FDB entries older than', 'help' => 'Cleanup done by daily.sh', ], + 'ports_nac_purge' => [ + 'description' => 'Port NAC entries older than', + 'help' => 'Cleanup done by daily.sh', + ], 'ports_purge' => [ 'description' => 'Purge ports deleted', 'help' => 'Cleanup done by daily.sh', diff --git a/lang/fr/settings.php b/lang/fr/settings.php index 0741182745..0064ff74c9 100644 --- a/lang/fr/settings.php +++ b/lang/fr/settings.php @@ -917,6 +917,10 @@ return [ 'description' => 'Table port FDB, entrées plus anciennes que', 'help' => 'Nettoyage effectué par daily.sh', ], + 'ports_nac_purge' => [ + 'description' => 'Table port NAC, entrées plus anciennes que', + 'help' => 'Nettoyage effectué par daily.sh', + ], 'ports_purge' => [ 'description' => 'Purger les ports supprimés', 'help' => 'Nettoyage effectué par daily.sh', diff --git a/lang/it/settings.php b/lang/it/settings.php index f8b91b4dc0..b893c32b0b 100644 --- a/lang/it/settings.php +++ b/lang/it/settings.php @@ -1177,6 +1177,10 @@ return [ 'description' => 'Port FDB entries older than', 'help' => 'Cleanup done by daily.sh', ], + 'ports_nac_purge' => [ + 'description' => 'Port NAC entries older than', + 'help' => 'Cleanup done by daily.sh', + ], 'ports_purge' => [ 'description' => 'Elimina le porte', 'help' => 'Cleanup done by daily.sh', diff --git a/misc/config_definitions.json b/misc/config_definitions.json index 962c67e7d0..8cf3d6ad9e 100644 --- a/misc/config_definitions.json +++ b/misc/config_definitions.json @@ -5154,6 +5154,14 @@ "order": 5, "type": "integer" }, + "ports_nac_purge": { + "default": 10, + "units": "days", + "group": "system", + "section": "cleanup", + "order": 6, + "type": "integer" + }, "ports_page_default": { "default": "details", "type": "select", diff --git a/misc/db_schema.yaml b/misc/db_schema.yaml index f931e3296c..f6d304e988 100644 --- a/misc/db_schema.yaml +++ b/misc/db_schema.yaml @@ -1600,6 +1600,9 @@ ports_nac: - { Field: time_left, Type: varchar(50), 'Null': true, Extra: '' } - { Field: vlan, Type: 'int unsigned', 'Null': true, Extra: '' } - { Field: time_elapsed, Type: varchar(50), 'Null': true, Extra: '' } + - { Field: created_at, Type: timestamp, 'Null': true, Extra: '' } + - { Field: updated_at, Type: timestamp, 'Null': true, Extra: '' } + - { Field: historical, Type: tinyint, 'Null': false, Extra: '', Default: '0' } Indexes: PRIMARY: { Name: PRIMARY, Columns: [ports_nac_id], Unique: true, Type: BTREE } ports_nac_device_id_index: { Name: ports_nac_device_id_index, Columns: [device_id], Unique: false, Type: BTREE } diff --git a/resources/views/device/tabs/nac.blade.php b/resources/views/device/tabs/nac.blade.php index 9d7841bbad..ecf70e1207 100644 --- a/resources/views/device/tabs/nac.blade.php +++ b/resources/views/device/tabs/nac.blade.php @@ -24,7 +24,8 @@ {{ __('NAC Authc') }} {{ __('NAC Authz') }} {{ __('NAC Method') }} - + {{ __('First seen') }} + {{ __('Last seen') }} @@ -43,7 +44,15 @@ rowCount: [25, 50, 100, -1], url: "{{ route('table.port-nac') }}", post: function () { + var check_showHistorical = document.getElementById('check_showHistorical'); + if (check_showHistorical) { + var showHistorical = check_showHistorical.checked; + } else { + var showHistorical = false; + } + return { + showHistorical: showHistorical, device_id: '{{ $device->device_id }}', }; }, @@ -117,7 +126,22 @@ } } }); + var add = $(".actionBar").append( + ''); + $("#check_showHistorical").bootstrapSwitch({ + 'onSwitchChange': function(event, state){ + updateTable(); + } + }); + + function updateTable() { + $('#nac-grid').bootgrid('reload'); + }; }); @endpush diff --git a/resources/views/nac.blade.php b/resources/views/nac.blade.php index 4cd5495791..764a33e2dc 100644 --- a/resources/views/nac.blade.php +++ b/resources/views/nac.blade.php @@ -28,7 +28,8 @@ {{ __('NAC Authc') }} {{ __('NAC Authz') }} {{ __('NAC Method') }} - + {{ __('First seen') }} + {{ __('Last seen') }} @@ -48,12 +49,20 @@ @push('scripts') @endpush diff --git a/tests/data/ios_nac.json b/tests/data/ios_nac.json index a07ccdcd64..67f174e886 100644 --- a/tests/data/ios_nac.json +++ b/tests/data/ios_nac.json @@ -2427,6 +2427,7 @@ "time_left": "32", "vlan": 0, "time_elapsed": null, + "historical": 0, "ifIndex": 10001 }, { @@ -2444,6 +2445,7 @@ "time_left": "43", "vlan": 0, "time_elapsed": null, + "historical": 0, "ifIndex": 10001 }, { @@ -2461,6 +2463,7 @@ "time_left": "23", "vlan": 0, "time_elapsed": null, + "historical": 0, "ifIndex": 10002 }, { @@ -2478,6 +2481,7 @@ "time_left": "0", "vlan": 0, "time_elapsed": null, + "historical": 0, "ifIndex": 10003 }, { @@ -2495,6 +2499,7 @@ "time_left": "12", "vlan": 0, "time_elapsed": null, + "historical": 0, "ifIndex": 10003 } ] diff --git a/tests/data/vrp_nac.json b/tests/data/vrp_nac.json index 3d8b556e92..fdc08dde74 100644 --- a/tests/data/vrp_nac.json +++ b/tests/data/vrp_nac.json @@ -26737,8 +26737,8 @@ "ifName": "InLoopBack0", "portName": null, "ifIndex": 1, - "ifSpeed": 0, - "ifSpeed_prev": null, + "ifSpeed": null, + "ifSpeed_prev": 0, "ifConnectorPresent": null, "ifOperStatus": "up", "ifOperStatus_prev": "up", @@ -26837,8 +26837,8 @@ "ifName": "NULL0", "portName": null, "ifIndex": 2, - "ifSpeed": 0, - "ifSpeed_prev": null, + "ifSpeed": null, + "ifSpeed_prev": 0, "ifConnectorPresent": null, "ifOperStatus": "up", "ifOperStatus_prev": "up", @@ -26937,8 +26937,8 @@ "ifName": "Console9/0/0", "portName": null, "ifIndex": 3, - "ifSpeed": 0, - "ifSpeed_prev": null, + "ifSpeed": null, + "ifSpeed_prev": 0, "ifConnectorPresent": null, "ifOperStatus": "up", "ifOperStatus_prev": "up", @@ -53429,5 +53429,641 @@ } ] } + }, + "nac": { + "poller": { + "ports_nac": [ + { + "auth_id": "436", + "domain": "ACME", + "username": "host/PC5778.int.ACME.test", + "mac_address": "702084041dae", + "ip_address": "10.11.2.10", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "145802", + "historical": 0, + "ifIndex": 7 + }, + { + "auth_id": "240", + "domain": "ACME", + "username": "host/LT5221.int.ACME.test", + "mac_address": "0050b6cd5372", + "ip_address": "10.11.2.178", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "1869785", + "historical": 0, + "ifIndex": 11 + }, + { + "auth_id": "563", + "domain": "ACME", + "username": "host/PC5721.int.ACME.test", + "mac_address": "6c0b84e236d6", + "ip_address": "10.11.1.15", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869752", + "historical": 0, + "ifIndex": 14 + }, + { + "auth_id": "113", + "domain": "ACME", + "username": "host/PC5719.int.ACME.test", + "mac_address": "6c0b84e236d7", + "ip_address": "10.11.1.32", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "141526", + "historical": 0, + "ifIndex": 20 + }, + { + "auth_id": "513", + "domain": "ACME", + "username": "host/LT5697.int.ACME.test", + "mac_address": "0050b666e3f8", + "ip_address": "10.11.1.177", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "27778", + "historical": 0, + "ifIndex": 23 + }, + { + "auth_id": "319", + "domain": "ACME", + "username": "host/PC5784.int.ACME.test", + "mac_address": "309c2337f197", + "ip_address": "10.11.1.176", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869325", + "historical": 0, + "ifIndex": 25 + }, + { + "auth_id": "541", + "domain": "ACME", + "username": "host/LT5195.int.ACME.test", + "mac_address": "0050b6c5501b", + "ip_address": "10.11.1.17", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "30384", + "historical": 0, + "ifIndex": 26 + }, + { + "auth_id": "334", + "domain": "ACME", + "username": "host/PC5787.int.ACME.test", + "mac_address": "309c23367a1f", + "ip_address": "10.11.1.183", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "116888", + "historical": 0, + "ifIndex": 27 + }, + { + "auth_id": "305", + "domain": "ACME", + "username": "host/PC5805.int.ACME.test", + "mac_address": "309c2350d064", + "ip_address": "10.11.1.28", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "144551", + "historical": 0, + "ifIndex": 28 + }, + { + "auth_id": "441", + "domain": "ACME", + "username": "host/PC5718.int.ACME.test", + "mac_address": "6c0b84e2375c", + "ip_address": "10.11.1.173", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869746", + "historical": 0, + "ifIndex": 36 + }, + { + "auth_id": "957", + "domain": "ACME", + "username": "host/PC5722.int.ACME.test", + "mac_address": "6c0b84e236fb", + "ip_address": "10.11.1.181", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "141709", + "historical": 0, + "ifIndex": 37 + }, + { + "auth_id": "997", + "domain": "ACME", + "username": "host/PC5720.int.ACME.test", + "mac_address": "6c0b84e237bf", + "ip_address": "10.11.1.23", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "494722", + "historical": 0, + "ifIndex": 38 + }, + { + "auth_id": "451", + "domain": "ACME", + "username": "host/LT5813.int.ACME.test", + "mac_address": "0050b692bb25", + "ip_address": "10.11.1.25", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "28485", + "historical": 0, + "ifIndex": 42 + }, + { + "auth_id": "613", + "domain": "ACME", + "username": "host/PC5782.int.ACME.test", + "mac_address": "309c2336799e", + "ip_address": "10.11.1.29", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "143678", + "historical": 0, + "ifIndex": 44 + }, + { + "auth_id": "544", + "domain": "ACME", + "username": "host/PC5788.int.ACME.test", + "mac_address": "309c2337f18d", + "ip_address": "10.11.1.180", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869330", + "historical": 0, + "ifIndex": 49 + }, + { + "auth_id": "428", + "domain": "ACME", + "username": "host/PC5277.int.ACME.test", + "mac_address": "d8cb8a8aa832", + "ip_address": "10.11.2.28", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "128457", + "historical": 0, + "ifIndex": 58 + }, + { + "auth_id": "453", + "domain": "ACME", + "username": "host/PC5094.int.ACME.test", + "mac_address": "4439c453d053", + "ip_address": "10.11.2.24", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "495085", + "historical": 0, + "ifIndex": 59 + }, + { + "auth_id": "192", + "domain": "ACME", + "username": "host/PC5713.int.ACME.test", + "mac_address": "6c0b84e234df", + "ip_address": "10.11.2.11", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "143869", + "historical": 0, + "ifIndex": 63 + }, + { + "auth_id": "590", + "domain": "ACME", + "username": "host/PC5767.int.ACME.test", + "mac_address": "7020840420ef", + "ip_address": "10.11.2.21", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "1614917", + "historical": 0, + "ifIndex": 64 + }, + { + "auth_id": "139", + "domain": "ACME", + "username": "host/PC5061.int.ACME.test", + "mac_address": "4439c453d066", + "ip_address": "10.11.2.15", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "1871293", + "historical": 0, + "ifIndex": 65 + }, + { + "auth_id": "316", + "domain": "ACME", + "username": "host/PC5714.int.ACME.test", + "mac_address": "6c0b84e2274d", + "ip_address": "10.11.1.22", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869739", + "historical": 0, + "ifIndex": 66 + }, + { + "auth_id": "585", + "domain": "ACME", + "username": "host/PC5712.int.ACME.test", + "mac_address": "6c0b84e237ba", + "ip_address": "10.11.1.24", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "1869750", + "historical": 0, + "ifIndex": 69 + }, + { + "auth_id": "742", + "domain": "ACME", + "username": "host/PC5679.int.ACME.test", + "mac_address": "4ccc6aa7705f", + "ip_address": "10.11.2.22", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "1604770", + "historical": 0, + "ifIndex": 70 + }, + { + "auth_id": "321", + "domain": "ACME", + "username": "host/PC5783.int.ACME.test", + "mac_address": "309c2337f192", + "ip_address": "10.11.1.27", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "142463", + "historical": 0, + "ifIndex": 72 + }, + { + "auth_id": "169", + "domain": "ACME", + "username": "host/PC5710.int.ACME.test", + "mac_address": "6c0b84e2442e", + "ip_address": "10.11.2.175", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "490548", + "historical": 0, + "ifIndex": 74 + }, + { + "auth_id": "1022", + "domain": "ACME", + "username": "host/PC5689.int.ACME.test", + "mac_address": "4ccc6aa77523", + "ip_address": "10.11.2.27", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "974609", + "historical": 0, + "ifIndex": 75 + }, + { + "auth_id": "249", + "domain": "ACME", + "username": "host/PC5717.int.ACME.test", + "mac_address": "6c0b84e24429", + "ip_address": "10.11.1.174", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "138942", + "historical": 0, + "ifIndex": 81 + }, + { + "auth_id": "867", + "domain": "ACME", + "username": "host/LT5731.int.ACME.test", + "mac_address": "0050b68aae3d", + "ip_address": "10.11.2.18", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "376109", + "historical": 0, + "ifIndex": 84 + }, + { + "auth_id": "185", + "domain": "ACME", + "username": "host/PC5231.int.ACME.test", + "mac_address": "002324ac0ed2", + "ip_address": "10.11.1.30", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "490234", + "historical": 0, + "ifIndex": 97 + }, + { + "auth_id": "757", + "domain": "ACME", + "username": "host/PC5368.int.ACME.test", + "mac_address": "002324bcffa1", + "ip_address": "10.13.1.23", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 331, + "time_elapsed": "39895", + "historical": 0, + "ifIndex": 175 + }, + { + "auth_id": "618", + "domain": "ACME", + "username": "host/PC5680.int.ACME.test", + "mac_address": "4ccc6aa77530", + "ip_address": "10.11.2.16", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "402193", + "historical": 0, + "ifIndex": 195 + }, + { + "auth_id": "626", + "domain": "ACME", + "username": "host/LT5730.int.ACME.test", + "mac_address": "0050b68b75cf", + "ip_address": "10.11.2.26", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "1869777", + "historical": 0, + "ifIndex": 203 + }, + { + "auth_id": "64", + "domain": "ACME", + "username": "host/PC5059.int.ACME.test", + "mac_address": "4439c453cd32", + "ip_address": "10.11.2.19", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 312, + "time_elapsed": "147961", + "historical": 0, + "ifIndex": 225 + }, + { + "auth_id": "411", + "domain": "ACME", + "username": "host/PC5709.int.ACME.test", + "mac_address": "6c0b84e21fe2", + "ip_address": "10.11.1.178", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "143380", + "historical": 0, + "ifIndex": 239 + }, + { + "auth_id": "90", + "domain": "ACME", + "username": "host/PC5708.int.ACME.test", + "mac_address": "6c0b84e21fb3", + "ip_address": "10.11.1.171", + "host_mode": "default", + "authz_status": "sussess", + "authz_by": "eap", + "authc_status": "radius", + "method": "dot1x", + "timeout": "7200", + "time_left": null, + "vlan": 311, + "time_elapsed": "144268", + "historical": 0, + "ifIndex": 240 + } + ] + } } }