Skip to content

Conversation

@andymillernz
Copy link

@andymillernz andymillernz commented Jul 2, 2022

Description

Initial support for Cisco FWSM and Checkpoint Gaia Firewalls..

The devtype must be set to either "fwsm" or "cpgaia" as the auto detection is not yet implemented. These are L3 devices so services implemented include route, arpnd, interfaces and device.

Bugs fixed:

  • Set self._retry to 0 in node.py when a connection fails. If devtype was set and the device was down we wouldn't exit the retry loop.

TODO:

  • Fix uptime/boottime for FWSM and CP's
  • Implement devconfig
  • Test with Cisco ASA and implement as seperate devtype if needed

Test inclusion requirements

New Textfsm templates have associated test code

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Changes to the Documentation

devtype=fwsm or devtype=cpgaia must be used

FWSM implementation assumes the ipaddress used is in a particular "context" - and the host name is derived from the actual host + context name. The code does not attempt to change between contexts so a seperate hosts entry is required for each context.

Double Check

  • I have read the comments and followed the CONTRIBUTING.md.
  • I have explained my PR according to the information in the comments or in a linked issue.
  • My PR source branch is created from the develop branch.
  • My PR targets the develop branch.
  • All my commits have --signoff applied

Bug fix where devtype is set yet device is down - would continue to retry connection - now sets self._retry to 0 when a connection error occures

Adjusted the stdio buffer size when spawning a sub process - needed as FWSM configs can be huge and were overflowing the buffer

TODO: fix uptime/boottime for FWSM and CP's - test with Cisco ASA
Copy link
Collaborator

@claudious96 claudious96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

I left some comments here and there, mostly asking the reason for some choices or pointing out possible issues.

Comment on lines 345 to 346
# Fix error - "Separator is not found, and chunk exceed the limit"
limit = 1024 * 128, # 128 KB, default is 64KB
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give us more details about this fix? In which situation the 64KB buffer was not enough?

Comment on lines +1963 to +1966
if not isinstance(output, list):
# In some errors, the output returned is not a list
self.bootupTimestamp = -1
return
Copy link
Collaborator

@claudious96 claudious96 Jul 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a log here? Something like this should do the job:

Suggested change
if not isinstance(output, list):
# In some errors, the output returned is not a list
self.bootupTimestamp = -1
return
if not isinstance(output, list):
# In some errors, the output returned is not a list
self.bootupTimestamp = -1
self.logger.error(f'nodeinit: Error getting version for '
f'{self.address}:{self.port}')
return

if ip_address not in lookup:
# This should never be needed....
try:
ip = socket.gethostbyname(ip_address)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can rely on this piece of code. The poller may not have access to the entire network.
If an entry doesn't have an ip address in the device's arp table or in the lookup dictionary, then we should either store it as is or discard the entry.
@ddutt do you have an opinion on this?

try:
ip = socket.gethostbyname(ip_address)
except Exception:
ip = fakeaddress # fake it..
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said above, if we get here I think we should either store the entry as is or discard it. I don't see any point in storing it with fake address. Am I missing something?

Comment on lines 960 to 962
with contextlib.suppress(Exception):
vlan = int (name[4:])
entry["vlan"] = vlan
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case do you expect an exception here? I think it'd be better to use a try ... except if you want to handle a specific situation or let the original exception propagate and be catched at the upper level. The latter would make it easier to notice if the output is different than expected and issue a fix.

# we need to fix - will create a new IP address for each "host" we find
try:
# lets see if the default DNS will give use the real Ip address
ip = socket.gethostbyname(entry['prefix'])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before, we should not rely on the poller to resolve domains.

else:
self.logger.error('Unable to connect to '
f'{self.address}:{self.port}, {e}')
self._retry = 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need it here. What if the device is temporarily unreachable, in that case we should keep trying.

@andymillernz
Copy link
Author

andymillernz commented Jul 5, 2022 via email

 * Flake8 mods
 * Removed outbound socket requests
 * Added Cisco ASA support
 * Fixed FWSM boottime calculations
 * Removed fix to missing devices timeout as this will be fixed elsewhere
Comment on lines 134 to 146

for entry in processed_data:
ip_address = entry['ipAddress']
try:
# check we have a valid address
_ = ipaddress.ip_address(ip_address)
except Exception:
if ip_address in lookup:
entry['ipAddress'] = lookup[ip_address]
else:
# Should never reach here unless some strange issue with the device config
logger.error(f"ERROR: FWSM has non IP address entry in APR table: {ip_address}")

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if it's very unlikely we shouldn't log this for various reasons:

  1. we might end up logging to much
  2. the parser logs at a higher level and only if something breaks badly. We intend to keep following this strategy.
  3. if it is a configuration error in the device, these poller's stdout doesn't seem to me the right place to point that out

Sorry for being pedantic on this piece of code, I'd rather get rid of the entries that aren't ipAddresses and don't match the lookup table. Here is a code suggestion:

Suggested change
for entry in processed_data:
ip_address = entry['ipAddress']
try:
# check we have a valid address
_ = ipaddress.ip_address(ip_address)
except Exception:
if ip_address in lookup:
entry['ipAddress'] = lookup[ip_address]
else:
# Should never reach here unless some strange issue with the device config
logger.error(f"ERROR: FWSM has non IP address entry in APR table: {ip_address}")
drop_indices = []
for i, entry in enumerate(processed_data):
ip_address = entry['ipAddress']
try:
# check we have a valid address
_ = ipaddress.ip_address(ip_address)
except ValueError:
if ip_address in lookup:
entry['ipAddress'] = lookup[ip_address]
else:
drop_indices.append(i)
processed_data = np.delete(processed_data, drop_indices).tolist()

entry['prefix'] = lookup[prefix]
else:
# Should never reach here unless some strange issue with the device config
logger.error(f"ERROR: FWSM has non IP address entry in route table: {entry['prefix']}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as the ARPND service

try:
# check we have a valid address
_ = ipaddress.ip_address(entry['prefix'])
except Exception:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
except Exception:
except ValueError:

try:
# check we have a valid address
_ = ipaddress.ip_address(ip_address)
except Exception:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
except Exception:
except ValueError:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants