コード例 #1
0
    def test_get_security_engine_id_not_present(self, m_fetch, m_get_cmd):
        ir2 = InventoryRecord.from_dict(
            {
                "address": "192.168.0.1",
                "port": "34",
                "version": "2c",
                "community": "public",
                "secret": "secret",
                "securityEngine": "ENGINE",
                "walk_interval": 1850,
                "profiles": "",
                "SmartProfiles": True,
                "delete": False,
            }
        )

        snmpEngine = Mock()
        logger = Mock()

        m_get_cmd.return_value = iter(
            [(None, 0, 0, "Oid1"), (None, 0, 0, "Oid2"), (None, 0, 0, "Oid3")]
        )
        m_fetch.side_effect = Exception("boom")

        with self.assertRaises(Exception) as e:
            get_security_engine_id(logger, ir2, snmpEngine)
        self.assertEqual("boom", e.exception.args[0])

        calls = snmpEngine.observer.registerObserver.call_args_list

        self.assertEqual("rfc3412.prepareDataElements:internal", calls[0].args[1])

        m_get_cmd.assert_called()
コード例 #2
0
    def test_assignment_of_static_profiles(self):
        profiles = {
            "profile1": {
                "frequency": 20
            },
            "profile2": {
                "frequency": 30
            },
            "profile3": {},
        }

        ir = InventoryRecord.from_dict({
            "address": "192.168.0.1",
            "port": "34",
            "version": "2c",
            "community": "public",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 1850,
            "profiles": "profile1;profile2;profile3;profile4",
            "SmartProfiles": False,
            "delete": False,
        })

        result = assign_profiles(ir, profiles, {})
        self.assertEqual({20: ["profile1"], 30: ["profile2"]}, result)
コード例 #3
0
    def test_address_not_commented(self):
        ir_dict = {"address": "#asd"}

        with self.assertRaises(ValueError) as e:
            InventoryRecord(**ir_dict)
        self.assertEqual("field address cannot be commented",
                         e.exception.args[0][0].exc.args[0])
コード例 #4
0
    def test_address_not_none(self):
        ir_dict = {"address": None}

        with self.assertRaises(ValueError) as e:
            InventoryRecord(**ir_dict)
        self.assertEqual("field address cannot be null",
                         e.exception.args[0][0].exc.args[0])
コード例 #5
0
def get_inventory(mongo_inventory, address):
    host, port = return_address_and_port(address)
    ir_doc = mongo_inventory.find_one({"address": host, "port": port})
    if ir_doc is None:
        raise ValueError(
            f"Inventory Doc deleted unable to complete task for {address}")
    logger.debug(f"{ir_doc}")
    ir_doc.pop("_id", None)
    return InventoryRecord(**ir_doc)
コード例 #6
0
    def test_address_not_resolvable(self):
        ir_dict = {"address": "12313sdfsf"}

        with self.assertRaises(ValueError) as e:
            InventoryRecord(**ir_dict)
        self.assertEqual(
            "field address must be an IP or a resolvable hostname 12313sdfsf",
            e.exception.args[0][0].exc.args[0],
        )
コード例 #7
0
    def test_to_json(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": "34",
            "version": "3",
            "community": "public",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 1850,
            "profiles": "",
            "SmartProfiles": True,
            "delete": "",
        }

        ir = InventoryRecord(**ir_dict)

        self.assertEqual(
            '{"address": "192.168.0.1", "port": 34, "version": "3", "community": '
            '"public", "secret": "secret", "securityEngine": "ENGINE", "walk_interval": '
            '1850, "profiles": [], "SmartProfiles": true, "delete": false}',
            ir.to_json(),
        )
コード例 #8
0
    def test_port_too_high(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": 65537,
            "version": "2c",
            "walk_interval": 1850,
            "SmartProfiles": True,
            "delete": "",
        }

        with self.assertRaises(ValueError) as e:
            InventoryRecord(**ir_dict)
        self.assertEqual("Port out of range 65537",
                         e.exception.args[0][0].exc.args[0])
コード例 #9
0
    def test_empty_community(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": "34",
            "version": "3",
            "community": "",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 1850,
            "profiles": "",
            "SmartProfiles": True,
            "delete": False,
        }

        ir = InventoryRecord(**ir_dict)
        self.assertIsNone(ir.community)
コード例 #10
0
    def test_too_high_walk_interval(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": "34",
            "version": "3",
            "community": "public",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 50000,
            "profiles": "",
            "SmartProfiles": True,
            "delete": False,
        }

        ir = InventoryRecord(**ir_dict)
        self.assertEqual(42000, ir.walk_interval)
コード例 #11
0
    def test_from_json(self):
        ir = InventoryRecord.from_json(
            '{"address": "192.168.0.1", "port": "34", "version": "3", "community": '
            '"public", "secret": "secret", "securityEngine": "ENGINE", "walk_interval": '
            '1850, "profiles": "", "SmartProfiles": true, "delete": ""}')

        self.assertEqual(ir.address, "192.168.0.1")
        self.assertEqual(ir.port, 34)
        self.assertEqual(ir.version, "3")
        self.assertEqual(ir.community, "public")
        self.assertEqual(ir.secret, "secret")
        self.assertEqual(ir.securityEngine, "ENGINE")
        self.assertEqual(ir.walk_interval, 1850)
        self.assertEqual(ir.profiles, [])
        self.assertEqual(ir.SmartProfiles, True)
        self.assertEqual(ir.delete, False)
コード例 #12
0
    def test_profiles_not_string(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": "34",
            "version": "3",
            "community": "public",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 1850,
            "profiles": [],
            "SmartProfiles": True,
            "delete": False,
        }

        ir = InventoryRecord(**ir_dict)
        self.assertEqual([], ir.profiles)
コード例 #13
0
    def test_getAuthV3_security_engine_not_str(
        self, m_get_security_engine_id, m_get_secret_value, m_exists
    ):
        m_exists.return_value = True
        m_get_secret_value.side_effect = [
            "secret1",
            "secret2",
            "secret3",
            "SHA224",
            "AES192BLMT",
            "1",
            "2",
        ]
        m_get_security_engine_id.return_value = "ENGINE123"
        logger = Mock()
        snmpEngine = Mock()

        ir2 = InventoryRecord.from_dict(
            {
                "address": "192.168.0.1",
                "port": "34",
                "version": "2c",
                "community": "public",
                "secret": "secret_ir",
                "securityEngine": 123,
                "walk_interval": 1850,
                "profiles": "",
                "SmartProfiles": True,
                "delete": False,
            }
        )

        result = getAuthV3(logger, ir2, snmpEngine)

        m_get_security_engine_id.assert_called()

        self.assertEqual("secret1", result.userName)
        self.assertEqual("secret2", result.authKey)
        self.assertEqual("secret3", result.privKey)
        self.assertEqual(usmHMAC128SHA224AuthProtocol, result.authProtocol)
        self.assertEqual(usmAesBlumenthalCfb192Protocol, result.privProtocol)
        self.assertEqual("ENGINE123", result.securityEngineId)
        self.assertEqual("secret1", result.securityName)
        self.assertEqual(1, result.authKeyType)
        self.assertEqual(2, result.privKeyType)
コード例 #14
0
def run_walk():
    poller = Poller(no_mongo=True)

    with open("inventory.csv", encoding="utf-8") as csv_file:
        # Dict reader will trust the header of the csv
        ir_reader = DictReader(csv_file)
        for source_record in ir_reader:
            address = source_record["address"]
            if address.startswith("#"):
                continue
            try:
                ir = InventoryRecord(**source_record)
                retry = True
                while retry:
                    retry, result = poller.do_work(ir, walk=True)
                    logger.debug(result)
            except Exception as e:
                logger.exception(e)
コード例 #15
0
    def test_walk_task(self):
        inventory_record_json = {
            "address": "192.68.0.1",
            "port": 456,
            "version": "3",
            "community": "public",
            "secret": "some_secret",
            "securityEngine": "test_123",
            "walk_interval": 3456,
            "profiles": "profile1;profile2;profile3",
            "SmartProfiles": True,
            "delete": False,
        }

        inventory_record = InventoryRecord.from_dict(inventory_record_json)
        result = gen_walk_task(inventory_record)

        self.assertEqual("sc4snmp;192.68.0.1:456;walk", result["name"])
        self.assertEqual("splunk_connect_for_snmp.snmp.tasks.walk", result["task"])
        self.assertEqual("192.68.0.1:456", result["target"])
        self.assertEqual([], result["args"])
        self.assertEqual(
            {"address": "192.68.0.1:456", "profile": None}, result["kwargs"]
        )
        self.assertEqual("_chain", type(result["options"]["link"]).__name__)
        self.assertEqual(
            "splunk_connect_for_snmp.enrich.tasks.enrich",
            result["options"]["link"].tasks[0].name,
        )
        self.assertEqual(
            "splunk_connect_for_snmp.inventory.tasks.inventory_setup_poller",
            result["options"]["link"].tasks[1].tasks[0].name,
        )
        self.assertEqual(
            "splunk_connect_for_snmp.splunk.tasks.prepare",
            result["options"]["link"].tasks[1].tasks[1].tasks[0].name,
        )
        self.assertEqual(
            "splunk_connect_for_snmp.splunk.tasks.send",
            result["options"]["link"].tasks[1].tasks[1].tasks[1].name,
        )
        self.assertEqual({"every": 3456, "period": "seconds"}, result["interval"])
        self.assertTrue(result["enabled"])
        self.assertTrue(result["run_immediately"])
コード例 #16
0
    def test_version_out_of_range(self):
        ir_dict = {
            "address": "192.168.0.1",
            "port": "34",
            "version": "5a",
            "community": "public",
            "secret": "secret",
            "securityEngine": "ENGINE",
            "walk_interval": 1850,
            "profiles": "",
            "SmartProfiles": True,
            "delete": False,
        }

        with self.assertRaises(ValueError) as e:
            InventoryRecord(**ir_dict)
        self.assertEqual(
            "version out of range 5a accepted is 1 or 2c or 3",
            e.exception.args[0][0].exc.args[0],
        )
コード例 #17
0
    def test_inventory_setup_poller(
        self,
        m_get_inventory,
        m_assign_profiles,
        m_find_one,
        m_task_manager,
        m_load_profiles,
    ):
        periodic_obj_mock = Mock()
        m_task_manager.return_value = periodic_obj_mock

        m_get_inventory.return_value = InventoryRecord.from_dict({
            "address":
            "192.168.0.1",
            "port":
            "34",
            "version":
            "2c",
            "community":
            "public",
            "secret":
            "secret",
            "securityEngine":
            "ENGINE",
            "walk_interval":
            1850,
            "profiles":
            "",
            "SmartProfiles":
            True,
            "delete":
            False,
        })

        m_find_one.return_value = {
            "state": {
                "SNMPv2-MIB|sysDescr": {
                    "value": "MIKROTIK"
                },
                "SNMPv2-MIB|sysName": {
                    "value": "Linux Debian 2.0.1"
                },
                "SNMPv2-MIB|sysContact": {
                    "value": "non-existing-name@splunk"
                },
            }
        }

        work = {"address": "192.168.0.1"}

        m_assign_profiles.return_value = {
            60: ["BaseUpTime"],
            30: ["profile5", "profile2"],
            20: ["profile1"],
        }

        # when
        inventory_setup_poller(work)

        m_load_profiles.assert_not_called()

        calls = periodic_obj_mock.manage_task.call_args_list

        self.assertEqual(
            {
                "address": "192.168.0.1",
                "profiles": {"BaseUpTime"},
                "frequency": 60
            },
            calls[0][1]["kwargs"],
        )
        self.assertEqual(
            {
                "address": "192.168.0.1",
                "profiles": {"profile2", "profile5"},
                "frequency": 30,
            },
            calls[1][1]["kwargs"],
        )
        self.assertEqual(
            {
                "address": "192.168.0.1",
                "profiles": {"profile1"},
                "frequency": 20
            },
            calls[2][1]["kwargs"],
        )

        periodic_obj_mock.delete_unused_poll_tasks.assert_called_with(
            "192.168.0.1",
            [
                "sc4snmp;192.168.0.1;60;poll",
                "sc4snmp;192.168.0.1;30;poll",
                "sc4snmp;192.168.0.1;20;poll",
            ],
        )
        periodic_obj_mock.delete_disabled_poll_tasks.assert_called()
コード例 #18
0
from unittest import TestCase
from unittest.mock import MagicMock, patch

from splunk_connect_for_snmp.common.inventory_record import InventoryRecord
from splunk_connect_for_snmp.snmp.exceptions import SnmpActionError
from splunk_connect_for_snmp.snmp.manager import Poller

inventory_record = InventoryRecord.from_dict({
    "address": "192.168.0.1",
    "port": "34",
    "version": "2c",
    "community": "public",
    "secret": "secret",
    "securityEngine": "ENGINE",
    "walk_interval": 1850,
    "profiles": "",
    "SmartProfiles": True,
    "delete": False,
})


class TestDoWork(TestCase):
    @patch("pymongo.MongoClient", MagicMock())
    @patch("mongolock.MongoLock.__init__", MagicMock())
    @patch("mongolock.MongoLock.lock", MagicMock())
    @patch("mongolock.MongoLock.release", MagicMock())
    @patch("splunk_connect_for_snmp.snmp.auth.GetAuth", None)
    @patch("splunk_connect_for_snmp.snmp.manager.get_context_data",
           MagicMock())
    @patch("splunk_connect_for_snmp.snmp.manager.UdpTransportTarget",
           MagicMock())
コード例 #19
0
def load():
    path = INVENTORY_PATH
    inventory_errors = False
    mongo_client = pymongo.MongoClient(MONGO_URI)
    targets_collection = mongo_client.sc4snmp.targets
    attributes_collection = mongo_client.sc4snmp.attributes
    mongo_db = mongo_client[MONGO_DB]
    inventory_records = mongo_db.inventory

    periodic_obj = customtaskmanager.CustomPeriodicTaskManager()

    migrate_database(mongo_client, periodic_obj)
    config_profiles = load_profiles()

    logger.info(f"Loading inventory from {path}")
    with open(path, encoding="utf-8") as csv_file:
        # Dict reader will trust the header of the csv
        ir_reader = DictReader(csv_file)
        for source_record in ir_reader:
            address = source_record["address"]
            if address.startswith("#"):
                logger.warning(
                    f"Record: {address} is commented out. Skipping...")
                continue
            try:
                ir = InventoryRecord(**source_record)
                target = transform_address_to_key(ir.address, ir.port)
                if ir.delete:
                    periodic_obj.disable_tasks(target)
                    inventory_records.delete_one({
                        "address": ir.address,
                        "port": ir.port
                    })
                    targets_collection.remove({"address": target})
                    attributes_collection.remove({"address": target})
                    logger.info(f"Deleting record: {target}")
                else:
                    status = inventory_records.update_one(
                        {
                            "address": ir.address,
                            "port": ir.port
                        },
                        {"$set": ir.asdict()},
                        upsert=True,
                    )
                    profiles = source_record["profiles"].split(";")
                    profile = None
                    if profiles:
                        profiles = [
                            p for p in profiles
                            if config_profiles.get(p, {}).get(
                                "condition", {}).get("type") == "walk"
                        ]
                        if profiles:
                            profile = profiles[-1]
                            ir.walk_interval = source_record["walk_interval"]
                    if status.matched_count == 0:
                        logger.info(f"New Record {ir} {status.upserted_id}")
                    elif status.modified_count == 1 and status.upserted_id is None:
                        logger.info(f"Modified Record {ir}")
                    else:
                        logger.debug(f"Unchanged Record {ir}")
                        continue

                    task_config = gen_walk_task(ir, profile)
                    periodic_obj.manage_task(**task_config)

            except Exception as e:
                inventory_errors = True
                logger.exception(f"Exception raised for {target}: {e}")

    return inventory_errors