Nac, Adding support for Junos - next steps?

Hello everyone,

Converted to Libre last year and love it. Thank you for everything. I would like to assist in getting the NAC polling for Junos working properly.
All the relevent MIB’s appear to be there:
IEEE8021-PAE-MIB::dot1xPaePortCapabilities.
JUNIPER-PAE-EXTENSION-MIB::jnxPaeAuthConfigEntry

I started trying to integrate a Shared OS model for junos similar to the Cisco one. I can poll the data with a snmpbulkwalk and get reasonable data back.
My problem is I don’t understand how the PortsNac module works. I was thinking it was part of the OS polling and hence why there needed to be a similar file for Juniper.

I only have 1 switch reporting Cisco, so I have been able to muddle things around. So, I will attach what I can.

Scott Thomas

1 Like
public function pollNac()
{
    $nac = collect();
// Juniper has stuff in both the IEEE and their own extension...  so 2 oid cache entries?
    $portAuthSessionEntry = snmpwalk_cache_oid($this->getDevice(), 'dot1xPaePortCapabilities', [], 'IEEE8021-PAE-MIB');
    if (!empty($portAuthSessionEntry)) {
        $cafSessionMethodsInfoEntry = collect(snmpwalk_cache_oid($this->getDevice(), 'dot1xAuthSessionAuthenticMethod', [], 'IEEE8021-PAE-MIB'))->mapWithKeys(function ($item, $key) {
            $key_parts = explode('.', $key);
            $key = implode('.', array_slice($key_parts, 0, 2)); // remove the auth method
            return [$key => ['method' => $key_parts[2], 'authc_status' => $item['cafSessionMethodState']]];
        });

    $jnprPortAuthSessionEntry = snmpwalk_cache_oid($this->getDevice(), 'jnxPaeAuthConfigEntry', [], 'JUNIPER-PAE-EXTENSION-MIB');
    if (!empty($jnprPortAuthSessionEntry)) {
        $jnprcafSessionMethodsInfoEntry = collect(snmpwalk_cache_oid($this->getDevice(), 'jnxPaeAuthConfigEntry', [], 'JUNIPER-PAE-EXTENSION-MIB'))->mapWithKeys(function ($item, $key) {
            $key_parts = explode('.', $key);
            $key = implode('.', array_slice($key_parts, 0, 2)); // remove the auth method
            return [$key => ['method' => $key_parts[2], 'authc_status' => $item['cafSessionMethodState']]];
        });


        // cache port ifIndex -> port_id map
        $ifIndex_map = $this->getDeviceModel()->ports()->pluck('port_id', 'ifIndex');

        // update the DB
        foreach ($portAuthSessionEntry as $index => $portAuthSessionEntryParameters) {
            list($ifIndex, $auth_id) = explode('.', str_replace("'", '', $index));
            $session_info = $cafSessionMethodsInfoEntry->get($ifIndex . '.' . $auth_id);
            $mac_address = strtolower(implode(array_map('zeropad', explode(':', $portAuthSessionEntryParameters['cafSessionClientMacAddress'])))); //not neccessarily available in dot1x sequence.

            $nac->put($mac_address, new PortsNac([
                'port_id' => $ifIndex_map->get($ifIndex, 0),
                'mac_address' => $mac_address,
                'auth_id' => $auth_id,
                'domain' => 'null', // No such entry in Junos
                'username' => $portAuthSessionEntryParameters['dot1xAuthSessionUserName'],
                'ip_address' => (string)IP::fromHexString($portAuthSessionEntryParameters['cafSessionClientAddress'], true),
                'host_mode' => $portAuthSessionEntryParameters['jnxPaeAuthConfigSupplicantMode'],
                'authz_status' => $portAuthSessionEntryParameters['dot1xAuthPaeState'],
                'authz_by' => $portAuthSessionEntryParameters['dot1xAuthSessionAuthenticMethod'],
                'timeout' => $portAuthSessionEntryParameters['cafSessionTimeout'],  // needs adjusting
                'time_left' => $portAuthSessionEntryParameters['cafSessionTimeLeft'], // needs adjusting
                'vlan' => $portAuthSessionEntryParameters['cafSessionAuthVlan'],  // needs adjusting
                'authc_status' => $session_info['authc_status'],
                'method' => $session_info['method'],
            ]));
        }
    }

    return $nac;
}