Exemplo n.º 1
0
def check_version_status(lint=False):
    """Check our version string in DNS for known issues and warn about them

    the lookup should be <7 chars of commitid>.<patch>.<minor>.<major>.versioncheck.fuglu.org
    in case of a release version, use 'release' instead of commit id

    eg, the lookup for 0.6.3 would be:
    release.3.6.0.versioncheck.fuglu.org

    DNS will return NXDOMAIN or 127.0.0.<bitmask>
    2: generic non security related issue
    4: low risk security issue
    8: high risk security issue
    """
    bitmaskmap = {
        2:
        "there is a known (not security related) issue with this version - consider upgrading",
        4:
        "there is a known low-risk security issue with this version - an upgrade is recommended",
        8:
        "there is a known high-risk security issue with this version - upgrade as soon as possible!",
    }

    m = re.match(
        r'^(?P<major>\d{1,4})\.(?P<minor>\d{1,4})\.(?P<patch>\d{1,4})(?:\-(?P<commitno>\d{1,4})\-g(?P<commitid>[a-f0-9]{7}))?$',
        FUGLU_VERSION)
    if m is None:
        logging.warn("could not parse my version string %s" % FUGLU_VERSION)
        return
    parts = m.groupdict()
    if 'commitid' not in parts or parts['commitid'] is None:
        parts['commitid'] = 'release'

    lookup = "{commitid}.{patch}.{minor}.{major}.versioncheck.fuglu.org".format(
        **parts)
    result = None
    try:
        result = socket.gethostbyname(lookup)
    except Exception:
        # DNS fails happen - try again next time
        pass

    if result is None:
        return

    ret = re.match(r'^127\.0\.0\.(?P<replycode>\d{1,4})$', result)
    if ret is not None:
        code = int(ret.groupdict()['replycode'])
        for bitmask, message in bitmaskmap.items():
            if code & bitmask == bitmask:
                logging.warn(message)
                if lint:
                    fc = FunkyConsole()
                    print(fc.strcolor(message, "yellow"))
Exemplo n.º 2
0
def check_version_status(lint=False):
    """Check our version string in DNS for known issues and warn about them

    the lookup should be <7 chars of commitid>.<patch>.<minor>.<major>.versioncheck.fuglu.org
    in case of a release version, use 'release' instead of commit id

    eg, the lookup for 0.6.3 would be:
    release.3.6.0.versioncheck.fuglu.org

    DNS will return NXDOMAIN or 127.0.0.<bitmask>
    2: generic non security related issue
    4: low risk security issue
    8: high risk security issue
    """
    bitmaskmap = {
        2: "there is a known (not security related) issue with this version - consider upgrading",
        4: "there is a known low-risk security issue with this version - an upgrade is recommended",
        8: "there is a known high-risk security issue with this version - upgrade as soon as possible!",
    }

    m = re.match(
        r"^(?P<major>\d{1,4})\.(?P<minor>\d{1,4})\.(?P<patch>\d{1,4})(?:\-(?P<commitno>\d{1,4})\-g(?P<commitid>[a-f0-9]{7}))?$",
        FUGLU_VERSION,
    )
    if m == None:
        logging.warn("could not parse my version string %s" % FUGLU_VERSION)
        return
    parts = m.groupdict()
    if "commitid" not in parts or parts["commitid"] == None:
        parts["commitid"] = "release"

    lookup = "{commitid}.{patch}.{minor}.{major}.versioncheck.fuglu.org".format(**parts)
    result = None
    try:
        result = socket.gethostbyname(lookup)
    except:
        # DNS fails happen - try again next time
        pass

    if result == None:
        return

    ret = re.match(r"^127\.0\.0\.(?P<replycode>\d{1,4})$", result)
    if ret != None:
        code = int(ret.groupdict()["replycode"])
        for bitmask, message in bitmaskmap.items():
            if code & bitmask == bitmask:
                logging.warn(message)
                if lint:
                    fc = FunkyConsole()
                    print(fc.strcolor(message, "yellow"))
Exemplo n.º 3
0
Arquivo: core.py Projeto: danBLA/fuglu
    def checkConfig(self):
        """Check if all required options without default are in the config file
        Fill missing values with defaults if possible
        """
        all_ok = True
        fc = FunkyConsole()
        for config, infodic in self.requiredvars.items():
            section = infodic['section']
            try:
                var = self.config.get(section, config)

                if 'validator' in infodic and not infodic["validator"](var):
                    print("Validation failed for [%s] :: %s" % (section, config))
                    all_ok = False

            except configparser.NoSectionError:
                print(fc.strcolor(f"Missing configuration section containing variables without default "
                                  f"value [{section}] :: {config}", "red"))
                all_ok = False
            except configparser.NoOptionError:
                print(fc.strcolor(f"Missing configuration value without default [{section}] :: {config}", "red"))
                all_ok = False
                
        # missing sections -> this is only a warning since section is not required
        # as long as there are no required variables without default values...
        if all_ok:
            missingsections = set()
            for config, infodic in self.requiredvars.items():
                section = infodic['section']
                if section not in missingsections and not self.config.has_section(section):
                    missingsections.add(section)

            for section in missingsections:
                print(fc.strcolor(f"Missing configuration section [{section}] :: "
                              f"All variables will use default values", "yellow"))
        return all_ok
Exemplo n.º 4
0
    def lint(self):
        errors = 0
        fc = FunkyConsole()
        self._lint_dependencies(fc)

        print(fc.strcolor('Loading extensions...', 'magenta'))
        exts = self.load_extensions()
        for ext in exts:
            (name, enabled, status) = ext
            pname = fc.strcolor(name, 'cyan')
            if enabled:
                penabled = fc.strcolor('enabled', 'green')
            else:
                penabled = fc.strcolor('disabled', 'red')
            print("%s: %s (%s)" % (pname, penabled, status))

        print(fc.strcolor('Loading plugins...', 'magenta'))
        if not self.load_plugins():
            print(fc.strcolor('At least one plugin failed to load', 'red'))
        print(fc.strcolor('Plugin loading complete', 'magenta'))

        print("Linting ", fc.strcolor("main configuration", 'cyan'))
        if not self.checkConfig():
            print(fc.strcolor("ERROR", "red"))
        else:
            print(fc.strcolor("OK", "green"))

        trashdir = self.config.get('main', 'trashdir').strip()
        if trashdir != "":
            if not os.path.isdir(trashdir):
                print(
                    fc.strcolor("Trashdir %s does not exist" % trashdir, 'red'))

        # sql config override
        sqlconfigdbconnectstring = self.config.get(
            'databaseconfig', 'dbconnectstring')
        if sqlconfigdbconnectstring.strip() != '':
            print("")
            print("Linting ", fc.strcolor("sql configuration", 'cyan'))
            try:
                from fuglu.extensions.sql import get_session
                sess = get_session(sqlconfigdbconnectstring)
                tempsuspect = Suspect(
                    '*****@*****.**', '*****@*****.**', '/dev/null')
                sqlvars = dict(
                    section='testsection', option='testoption', scope='$GLOBAL')
                default_template_values(tempsuspect, sqlvars)
                sess.execute(self.config.get('databaseconfig', 'sql'), sqlvars)
                sess.remove()
                print(fc.strcolor("OK", 'green'))
            except Exception as e:
                print(fc.strcolor("Failed %s" % str(e), 'red'))

        allplugins = self.plugins + self.prependers + self.appenders

        for plugin in allplugins:
            print()
            print("Linting Plugin ", fc.strcolor(str(plugin), 'cyan'),
                  'Config section:', fc.strcolor(str(plugin.section), 'cyan'))
            try:
                result = plugin.lint()
            except Exception as e:
                CrashStore.store_exception()
                print("ERROR: %s" % e)
                result = False

            if result:
                print(fc.strcolor("OK", "green"))
            else:
                errors = errors + 1
                print(fc.strcolor("ERROR", "red"))
        print("%s plugins reported errors." % errors)

        if self.config.getboolean('main', 'versioncheck'):
            check_version_status(lint=True)
Exemplo n.º 5
0
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# $Id$
#
import sys
import os

sys.path.insert(0, 'src')
from ConfigParser import ConfigParser

from fuglu.funkyconsole import FunkyConsole

fc = FunkyConsole()

fugluconfigfile = '/etc/fuglu/fuglu.conf'
dconfdir = '/etc/fuglu/conf.d'


currentconfig = ConfigParser()
currentconfig.readfp(open(fugluconfigfile))

# load conf.d
if os.path.isdir(dconfdir):
    filelist = os.listdir(dconfdir)
    configfiles = [dconfdir + '/' + c for c in filelist if c.endswith('.conf')]
    readfiles = currentconfig.read(configfiles)
    print 'Read additional files: %s' % (readfiles)
Exemplo n.º 6
0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
#
import sys
import os
from configparser import ConfigParser

sys.path.insert(0, 'src')
from fuglu.funkyconsole import FunkyConsole

fc = FunkyConsole()

fugluconfigfile = '/etc/fuglu/fuglu.conf'
dconfdir = '/etc/fuglu/conf.d'

currentconfig = ConfigParser()
currentconfig.read_file(open(fugluconfigfile))

# load conf.d
if os.path.isdir(dconfdir):
    filelist = os.listdir(dconfdir)
    configfiles = [dconfdir + '/' + c for c in filelist if c.endswith('.conf')]
    readfiles = currentconfig.read(configfiles)
    print('Read additional files: %s' % readfiles)

newconfig = ConfigParser()
Exemplo n.º 7
0
# limitations under the License.
#
#
#
import sys
import os

sys.path.insert(0, 'src')
try:
    from configparser import ConfigParser
except ImportError:
    from ConfigParser import ConfigParser

from fuglu.funkyconsole import FunkyConsole

fc = FunkyConsole()

fugluconfigfile = '/etc/fuglu/fuglu.conf'
dconfdir = '/etc/fuglu/conf.d'


currentconfig = ConfigParser()
currentconfig.readfp(open(fugluconfigfile))

# load conf.d
if os.path.isdir(dconfdir):
    filelist = os.listdir(dconfdir)
    configfiles = [dconfdir + '/' + c for c in filelist if c.endswith('.conf')]
    readfiles = currentconfig.read(configfiles)
    print('Read additional files: %s' % (readfiles))
Exemplo n.º 8
0
    def lint(self):
        errors = 0
        fc = FunkyConsole()
        self._lint_dependencies(fc)

        print(fc.strcolor('Loading extensions...', 'magenta'))
        exts = self.load_extensions()
        for ext in exts:
            (name, enabled, status) = ext
            pname = fc.strcolor(name, 'cyan')
            if enabled:
                penabled = fc.strcolor('enabled', 'green')
            else:
                penabled = fc.strcolor('disabled', 'red')
            print("%s: %s (%s)" % (pname, penabled, status))

        print(fc.strcolor('Loading plugins...', 'magenta'))
        if not self.load_plugins():
            print(fc.strcolor('At least one plugin failed to load', 'red'))
        print(fc.strcolor('Plugin loading complete', 'magenta'))

        print("Linting ", fc.strcolor("main configuration", 'cyan'))
        if not self.checkConfig():
            print(fc.strcolor("ERROR", "red"))
        else:
            print(fc.strcolor("OK", "green"))

        trashdir = self.config.get('main', 'trashdir').strip()
        if trashdir != "" and not os.path.isdir(trashdir):
            print(fc.strcolor("Trashdir %s does not exist" % trashdir, 'red'))

        # sql config override
        sqlconfigdbconnectstring = self.config.get('databaseconfig',
                                                   'dbconnectstring')
        if sqlconfigdbconnectstring.strip() != '':
            print()
            print("Linting ", fc.strcolor("sql configuration", 'cyan'))
            try:
                from fuglu.extensions.sql import get_session
                sess = get_session(sqlconfigdbconnectstring)
                tempsuspect = Suspect('*****@*****.**',
                                      '*****@*****.**', '/dev/null')
                sqlvars = dict(section='testsection',
                               option='testoption',
                               scope='$GLOBAL')
                default_template_values(tempsuspect, sqlvars)
                sess.execute(self.config.get('databaseconfig', 'sql'), sqlvars)
                sess.remove()
                print(fc.strcolor("OK", 'green'))
            except Exception as e:
                print(fc.strcolor("Failed %s" % str(e), 'red'))

        allplugins = self.plugins + self.prependers + self.appenders

        for plugin in allplugins:
            print()
            print("Linting Plugin ", fc.strcolor(str(plugin), 'cyan'),
                  'Config section:', fc.strcolor(str(plugin.section), 'cyan'))
            try:
                result = plugin.lint()
            except Exception as e:
                CrashStore.store_exception()
                print("ERROR: %s" % e)
                result = False

            if result:
                print(fc.strcolor("OK", "green"))
            else:
                errors = errors + 1
                print(fc.strcolor("ERROR", "red"))
        print("%s plugins reported errors." % errors)

        if self.config.getboolean('main', 'versioncheck'):
            check_version_status(lint=True)
Exemplo n.º 9
0
Arquivo: core.py Projeto: danBLA/fuglu
    def lint(self):
        errors = 0
        fc = FunkyConsole()
        self._lint_dependencies(fc)

        print(fc.strcolor('Loading extensions...', 'magenta'))
        exts = self.load_extensions()
        for ext in exts:
            (name, enabled, status) = ext
            pname = fc.strcolor(name, 'cyan')
            if enabled:
                penabled = fc.strcolor('enabled', 'green')
            else:
                penabled = fc.strcolor('disabled', 'red')
            print("%s: %s (%s)" % (pname, penabled, status))

        print(fc.strcolor('Loading plugins...', 'magenta'))
        if not self.load_plugins():
            print(fc.strcolor('At least one plugin failed to load', 'red'))
            errors +=1
        print(fc.strcolor('Plugin loading complete', 'magenta'))

        print("Linting ", fc.strcolor("main configuration", 'cyan'))
        if not self.checkConfig():
            print(fc.strcolor("ERROR", "red"))
            errors += 1
        else:
            print(fc.strcolor("OK", "green"))

        trashdir = self.config.get('main', 'trashdir').strip()
        if trashdir != "" and not os.path.isdir(trashdir):
            print(fc.strcolor("Trashdir %s does not exist" % trashdir, 'red'))
            errors += 1

        # sql config override
        sqlconfigdbconnectstring = self.config.get('databaseconfig', 'dbconnectstring')
        if sqlconfigdbconnectstring.strip() != '':
            print()
            print("Linting ", fc.strcolor("sql configuration", 'cyan'))
            try:
                from fuglu.extensions.sql import get_session
                sess = get_session(sqlconfigdbconnectstring)
                tempsuspect = Suspect(
                    '*****@*****.**', '*****@*****.**', '/dev/null',
                    att_cachelimit=self.config.getint('performance','att_mgr_cachesize'))
                sqlvars = dict(
                    section='testsection', option='testoption', scope='$GLOBAL')
                default_template_values(tempsuspect, sqlvars)
                sess.execute(self.config.get('databaseconfig', 'sql'), sqlvars)
                sess.remove()
                print(fc.strcolor("OK", 'green'))
            except Exception as e:
                print(fc.strcolor("Failed %s" % str(e), 'red'))
                errors += 1

        allplugins = self.plugins + self.prependers + self.appenders

        perrors = 0
        for plugin in allplugins:
            print()
            print("Linting Plugin ", fc.strcolor(str(plugin), 'cyan'),
                  'Config section:', fc.strcolor(str(plugin.section), 'cyan'))
            try:
                result = plugin.lint()
            except Exception as e:
                CrashStore.store_exception()
                print("ERROR: %s" % e)
                result = False

            if result:
                print(fc.strcolor("OK", "green"))
            else:
                perrors += 1
                errors += 1
                print(fc.strcolor("ERROR", "red"))
        print("%s plugins reported errors." % perrors)

        if "milter" in self.config.get('main', 'incomingport') \
                and self.config.get('performance', 'backend') != 'process':

            try:
                minfreethreads = self.config.getint('performance', 'minfreethreads')
                if minfreethreads < 1:
                    print(fc.strcolor('\nMilter enabled with "thread" backend but "minfreethreads < 1"', 'yellow'))
                    print("To keep milter responsive it is recommended to set minfreethreads >= 1\n"
                          "to make fuglu more resonsive.\n")
            except (configparser.NoSectionError, configparser.NoOptionError):
                print(fc.strcolor('\nMilter enabled with "thread" backend but "minfreethreads is not defined!"', 'yellow'))
                print("To keep fuglu-milter responsive it is recommended to set minfreethreads >= 1\n")

        if self.config.getboolean('main', 'versioncheck'):
            check_version_status(lint=True)

        return errors
Exemplo n.º 10
0
Arquivo: core.py Projeto: danBLA/fuglu
def check_version_status(lint=False):
    import pkg_resources
    """Check our version string in DNS for known issues and warn about them

    the lookup should be <7 chars of commitid>.<patch>.<minor>.<major>.versioncheck.fuglu.org
    in case of a release version, use 'release' instead of commit id

    lookup examples:
    - 0.9.1 -> 0.release.1.9.0.versioncheck.fuglu.org
    - 0.9.1rc5 -> 5.rc.1.9.0.versioncheck.fuglu.org
    - 0.9.1.dev20181204183236 -> 20181204183236.dev.1.9.0.versioncheck.fuglu.org

    DNS will return NXDOMAIN or 127.0.0.<bitmask>
    2: generic non security related issue
    4: low risk security issue
    8: high risk security issue
    """
    bitmaskmap = {
        2: "there is a known (not security related) issue with this version - consider upgrading",
        4: "there is a known low-risk security issue with this version - an upgrade is recommended",
        8: "there is a known high-risk security issue with this version - upgrade as soon as possible!",
    }

    try:
        version_obj = pkg_resources.parse_version(FUGLU_VERSION)._version
        if not isinstance(version_obj, pkg_resources.extern.packaging.version._Version):
            version_obj = None
    except AttributeError:
        # Older versions of setuptools (< 20.2.2) return a tuple.
        # Accessing "_version" will raise an attribute error.
        version_obj = None
    except Exception as e:
        # Skip test for other problems...
        logging.getLogger("fuglu.check_version_status").warning(str(e))
        version_obj = None

    if version_obj is None:
        logging.getLogger("fuglu.check_version_status")\
            .warning("Version string %s could not be parsed to pkg_resources version object", FUGLU_VERSION)
        return

    (major, minor, micro) = version_obj.release
    (stage_str, stage_id) = ('release', 0)

    if version_obj.dev:
        stage_str = version_obj.dev[0]
        stage_id = version_obj.dev[1]
    
    if version_obj.pre:
        stage_str = version_obj.pre[0]
        stage_id = version_obj.pre[1]

    if version_obj.post:
        stage_str = version_obj.post[0]
        stage_id = version_obj.post[1]

    parts = {
        'major': major,
        'minor': minor,
        'micro': micro,
        'stage_str': stage_str,
        'stage_id': stage_id
    }

    lookup = "{stage_id}.{stage_str}.{micro}.{minor}.{major}.versioncheck.fuglu.org".format(**parts)
    result = None
    try:
        result = socket.gethostbyname(lookup)
    except Exception:
        # DNS fails happen - try again next time
        pass

    if result is None:
        return

    ret = re.match(r'^127\.0\.0\.(?P<replycode>\d{1,4})$', result)
    if ret is not None:
        code = int(ret.groupdict()['replycode'])
        for bitmask, message in bitmaskmap.items():
            if code & bitmask == bitmask:
                logging.warn(message)
                if lint:
                    fc = FunkyConsole()
                    print(fc.strcolor(message, "yellow"))