Windows Defender

Hello,
I want to monitor state of Defender on my Win 2016 server. I’m using RAW edition, I’ve installed the plugin manually and it’s available in [Host & Service Parameters].

But when I created rule and make it to be applied on specific server, it wasn’t listed at all.

When I created a manual check it appeared, but there are errors I’m not sure how to deal with:

This seemed like there’s something wrong with the check code but I couldn’t find anything there. According to info on plugin page it was created on version 1.2.8p14 and I’m using 1.6.0p8. I’m assuming there’s some config/code that has to be updated to make it work, but I’m not sure where.

You created a manual check. That will not help. First the service should be automatically discovered after you installed the agent plugin.
Then you can use the small icon before the service name to create some parameters.
Remove first your defined manual check.

You have probably only installed the .mkp (package) on the monitoring server?
You also need to install the agent plugin (plugins/win_defender.ps1) on the monitored Windows host.
(in the enterprise edition, you could also use the agent bakery to deploy the plugin, but not on raw)

See “Monitoring Windows” in the manual, specifically section “7. Adding agent plug-ins”:

https://checkmk.com/cms_agent_windows.html#plugins

Thanks, I didn’t do that step. Now the *.ps1 file is on the server and additional service to monitor was discovered but there’s still problem with parameters:

They are defined like this:

check_parameters_win_defender.py looks like this and there are values “as_age”, “av_age”:

register_check_parameters(
    subgroup_applications,
    "win_defender",
    _("Windows Defender Time Settings"),
    Dictionary(
        elements = [
            ( "av_age",
                Tuple( title = _("Time Settings for Anti-Virus Signature"),
                    elements = [
                        Age(title=_("Critical at"), default_value = 2*86400),
                    ],
                ),
            ),
            ( "as_age",
                Tuple( title = _("Time Settings for Anti-Malware Signature"),
                    elements = [
                        Age(title=_("Critical at"), default_value = 2*86400),
                    ],
                ),
            ),
        ],
    ),
    None,
    match_type = "dict",
)

Plugin itself:

$RTP = Get-MpComputerStatus | select -ExpandProperty RealTimeProtectionEnabled
$AS_Age = Get-MpComputerStatus | select -ExpandProperty AntispywareSignatureAge
$AV_Age = Get-MpComputerStatus | select -ExpandProperty AntivirusSignatureAge

"<<<win_defender:sep(9)>>>"
"$RTP`t$AS_Age`t$AV_Age"

I’m wondering if this is case-sensitive? But then the error mentions that there’s undefined av_timesettings in dictionary. But where?

Why should be there a problem with the parameters?
In your screenshot with the parameters there is 2 days selected as limits. The screenshot with the discovered service also shows 2 days (written in seconds).

Attention - don’t mix the naming between the Windows Powershell plugin and the Python source code.
These variables have nothing in common, the naming is only in this way that you know what every variable is.

Is there a problem with your limits?

It’s the message in Checkmk parameters that confuses me:

Invalid check parameter : Undefined key ‘timesettings_av’ in the dictionary. Allowed are av_age, as_age.
Variable: checkgroup_parameters:win_defender
Parameters:

{‘as_age’: (7200,), ‘av_age’: (7200,), ‘timesettings_as’: 2, ‘timesettings_av’: 2}

I switched the value from 2 days to 2 hours to see if the monitoring will catch it. I will also test later by disabling the Defender whatsoever.

Ok i had a look at the source code and saw that the parameter will not work as the check plugin uses not the right parameters. :wink:

I modified the check plugin a little bit - this should work - but i cannot test at the moment

#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
#################################################################
# Created By: Kevin Tijssen                                     #
# Created On: 18-4-2017                                         #
# Modified for right parameters: 2020-07-15                     #
#################################################################

factory_settings["win_defender_default_levels"] = {
    "as_age" : (172800),
    "av_age" : (172800)
}

def inventory_win_defender(info):
    return[ (None, {}) ]

def check_win_defender(no_item, params, info):
    as_age_crit = int(params["as_age"]) / 86400
    av_age_crit = int(params["av_age"]) / 86400
    for rtprot_status, as_age, av_age in info:
        as_age = int(as_age)
        av_age = int(av_age)
        if rtprot_status == "False":
            return 2, "RealTime Protection: Disabled(!!)"
        else:
            if (as_age > as_age_crit and av_age > av_age_crit):
                return 2, "RealTime Protection: Enabled, Anti-virus DB: Out-of-Date(!!), Anti-Malware DB: Out-of-Date(!!)"
            elif as_age > as_age_crit:
                return 2, "RealTime Protection: Enabled, Anti-virus DB: Up-to-Date, Anti-Malware DB: Out-of-Date(!!)"
            elif av_age > av_age_crit:
                return 2, "RealTime Protection: Enabled, Anti-virus DB: Out-of-Date(!!), Anti-Malware DB: Up-to-Date"
            else:
                return 0, "RealTime Protection: Enabled, Anti-virus Database: Up-to-Date, Anti-Malware DB: Up-to-Date"

check_info["win_defender"] = {
    "check_function"           : check_win_defender,
    "inventory_function"       : inventory_win_defender,
    "default_levels_variable"  : "win_defender_default_levels",
    "group"                    : "win_defender",
    "service_description"      : "Windows Defender",
    "has_perfdata"             : False,}

Replace the file “~/local/share/check_mk/checks/win_defender” and try. Make a backup of the old one if there is an error :slight_smile:

Thanks a lot. I didn’t know there was also a file in ~/local/share/check_mk/checks/

I’ll test it and let you know.

There’ still same message in parameters but on the service details status is unknown and there’s crash report.

I replaced the content again, this time error is gone from check_mk parameters section but somethign new appeared:

Details show crash again.

Can you post the readable output of the crash report?
It is possible that there is an mistake in my code.

But now you have no error message for your parameters.

I just found it. Seems like the problem is with the divide you added.

Oh there is also an error in the definition of the parameters over WATO.
But we will work around this problem as the following

change

factory_settings["win_defender_default_levels"] = {
    "as_age" : (172800),
    "av_age" : (172800)
}

to

factory_settings["win_defender_default_levels"] = {
    "as_age" : (172800,0),
    "av_age" : (172800,0)
}

and

as_age_crit = int(params["as_age"]) / 86400
av_age_crit = int(params["av_age"]) / 86400

to

as_age_crit = int(params["as_age"][0]) / 86400
av_age_crit = int(params["av_age"][0]) / 86400

It is not so nice but should work.
Important make a “Tabula rasa” on this host as we changed the default parameters.

1 Like

All errors are gone now. I’m trying to disable the Defender to make sure check works as expected.

@andreas-doehler Thank you very much for assitance. The plugin now works correctly. I have manually disabled Defender on monitored server and check_mk immediately detected critical condition.

This is only a workaround for the problems. If i look at the complete code inside this mkp it need’s some serious rework.

Nice that it works now.

It probably does, it was released in April 2017 for v1.2.8p14 and I’m using 1.6.0p8 so I bet some stuff changed in the check_mk engine since that.

Unfortunately this is the only plugin to monitor Defender so I’m very glad you could fix it.

Pretty trivial to write this as a local check btw (I might do this).

And if the Defender definitions are just a plain file on the machine, then a simple fileinfo check (“Size and age of single files”) might also be a quick&easy solution.