Skip to content

Commit

Permalink
Add utility function for creating SNMP sessions
Browse files Browse the repository at this point in the history
This new function aids in creating nav.Snmp sessions based on
ManagementProfile instances.
  • Loading branch information
lunkwill42 committed Nov 13, 2023
1 parent a613588 commit af860f1
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
59 changes: 59 additions & 0 deletions python/nav/Snmp/profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#
# Copyright (C) 2023 Sikt
#
# This file is part of Network Administration Visualized (NAV).
#
# NAV is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3 as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details. You should have received a copy of the GNU General Public
# License along with NAV. If not, see <http://www.gnu.org/licenses/>.
#
"""Helper functions to build SNMP sessions from NAV ManagementProfile instances"""
from functools import partial
from typing import Callable

from nav.models.manage import Netbox, ManagementProfile
from nav.Snmp import Snmp


def get_snmp_session_for_profile(profile: ManagementProfile) -> Callable:
"""Returns a nav.Snmp.Snmp constructor partially pre-configured with SNMP options
from an SNMP management profile.
Example usage:
>>> netbox = Netbox.objects.get(id=1)
>>> snmp = get_snmp_session_for_profile(
... netbox.get_preferred_snmp_management_profile())
>>> session = snmp(netbox.ip)
>>> session.get()
b'Linux 16e2ac5c6456 6.1.60 #1-NixOS SMP PREEMPT_DYNAMIC Wed Oct 25 10:03:17 UTC 2023 x86_64'
>>>
"""
if not profile.is_snmp:
raise ValueError("Cannot create SNMP session from non-SNMP management profile")

if profile.snmp_version < 3:
kwargs = {
"version": profile.configuration.get("version"),
"community": profile.configuration.get("community"),
}
else:
kwargs = {
opt: profile.configuration.get(opt) or None
for opt in (
"sec_level",
"auth_protocol",
"sec_name",
"auth_password",
"priv_protocol",
"priv_password",
)
}
kwargs["version"] = 3

return partial(Snmp, **kwargs)
74 changes: 74 additions & 0 deletions tests/unittests/Snmp/profile_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#
# Copyright (C) 2023 Sikt
#
# This file is part of Network Administration Visualized (NAV).
#
# NAV is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3 as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details. You should have received a copy of the GNU General Public
# License along with NAV. If not, see <http://www.gnu.org/licenses/>.
#
from unittest.mock import Mock

import pytest

from nav.Snmp import Snmp
from nav.Snmp.profile import get_snmp_session_for_profile


class TestGetSnmpSessionForProfile:
def test_when_valid_snmpv2_profile_is_given_it_should_return_a_valid_snmp_partial(
self, mock_snmpv2_profile
):
snmp = get_snmp_session_for_profile(mock_snmpv2_profile)
assert callable(snmp)
session = snmp("127.0.0.1")
assert isinstance(session, Snmp)

def test_when_valid_snmpv3_profile_is_given_it_should_return_a_valid_snmp_partial(
self, mock_snmpv3_profile
):
snmp = get_snmp_session_for_profile(mock_snmpv3_profile)
assert callable(snmp)
session = snmp("127.0.0.1")
assert isinstance(session, Snmp)

conf = mock_snmpv3_profile.configuration
assert session.sec_level.value == conf["sec_level"]
assert session.auth_protocol.value == conf["auth_protocol"]
assert session.sec_name == conf["sec_name"]
assert session.auth_password == conf["auth_password"]

def test_when_non_snmp_profile_is_given_it_should_raise_valueerror(self):
profile = Mock(is_snmp=False)
with pytest.raises(ValueError):
get_snmp_session_for_profile(profile)


@pytest.fixture
def mock_snmpv2_profile():
profile = Mock(is_snmp=True, snmp_version=2)
profile.configuration = {
"version": "2c",
"write": False,
"community": "public",
}
return profile


@pytest.fixture
def mock_snmpv3_profile():
profile = Mock(is_snmp=True, snmp_version=3)
profile.configuration = {
"version": "3",
"sec_level": "authNoPriv",
"auth_protocol": "SHA",
"sec_name": "foobar",
"auth_password": "zaphodbeeblebrox",
}
return profile

0 comments on commit af860f1

Please sign in to comment.