mardi 11 mars 2014

Using bcfg2 data to generate IDS config file.

We use Suricata as and IDS and our typical configuration file define list of hosts sharing the same firewall rules, the firewall rules are function of the purpose of the box and since our configuration management tool (BCFG2) knows all about that, I was curious to see if I could generate part of the configuration using bcfg2 ...
#!/usr/bin/python

""" the idea is to use the bcfg2 backend to generate a list of ip's and associated with heir security groups
 like bcfg2-info groups give the list of groups and bcfg2-client query -g "group" gives the list of bcfg2-client
then resolve it like SER = "1.1.1.1,1.1.1.2,...." and so on
this should allow us to genereate normal rules for every security group and stuff that into the ids to spot any non compliance with the
firewall ruleset, possibly some other shit as well ? """

import os
import re
import socket
import sys
import cmd
import getopt
import fnmatch
import logging
import lxml.etree
import traceback
from code import InteractiveConsole
import Bcfg2.Logger
import Bcfg2.Options
import Bcfg2.Server.Core
import Bcfg2.Server.Plugin
import Bcfg2.Client.Tools.POSIX


def main():
    optinfo = dict(profile=Bcfg2.Options.CORE_PROFILE,
        command_timeout=Bcfg2.Options.CLIENT_COMMAND_TIMEOUT)

    optinfo.update(Bcfg2.Options.INFO_COMMON_OPTIONS)
    setup = Bcfg2.Options.OptionParser(optinfo)
    setup.hm = "\n".join(["prepareIdsMetadata","Options:",setup.buildHelpMessage()])
    setup.parse(sys.argv[1:])

    Bcfg2.Logger.setup_logging('prepareIdsMetadata', to_syslog=False, level=0)

    bcfg2 = Bcfg2.Server.Core.BaseCore(setup)
    bcfg2.load_plugins()
    bcfg2.block_for_fam_events(handle_events=True)
    f = open("group.txt", "w")
    for group in list(bcfg2.metadata.groups.keys()):
        hosts =  bcfg2.metadata.get_client_names_by_groups([group])
        first = True
        if hosts :
            f.write(group.upper() + '="')
            for h in hosts:
                try:
                    (hostname, aliases, ips) = socket.gethostbyname_ex(h)
                    if first:
                        f.write(ips[0])
                        first = False
                    else:
                        f.write(',' + ips[0])
                except:
                    pass
            f.write('"\n')
    f.close()

if __name__ == '__main__':
    sys.exit(main())

Which will generate a text file (group.txt) containing something like that:

DEBIAN-SQUEEZE="10.5.1.21,10.5.1.22,10.5.1.23,10.5.1.24"
SIP="10.21.81.249"
MYSQLNDBAPI="10.4.16.101,10.4.16.102,10.4.16.103,10.4.16.104"

Which I can then add as groups in my suricata yaml config file, and then build rules specific to those host purpose :-) Some host appears in several groups since some of our groups are OS based (CentOS/Debian-Wheezy ... ), geographic (BE, US, ...) and purpose based (WEB, PROXY, DB, ...)

The obvious advantages are to keep everything consistent, get rid of duplicate information and automatic updates of the IDS whenever you add an hosts. bcfg2 also has a plugin for Nagios which is nice to use too to make sure no host is left behind.

Thanks to the people on #bcfg2 on freenode for their support.

Aucun commentaire:

Enregistrer un commentaire

Hadoop / Spark2 snippet that took way too long to figure out

This is a collection of links and snippet that took me way too long to figure out; I've copied them here with a bit of documentation in...