зеркало из https://github.com/microsoft/lisa.git
MDATP: add mdatp existence and config test
- stop lisa from overwriting lf to crlf in bash files - mdatp script to check for json files, ascii or utf8 text script fails on detection of any logs or installation, uses exit code as issue signal instead of string parsing
This commit is contained in:
Родитель
4890deb5ee
Коммит
6c78c7f246
|
@ -1 +1,3 @@
|
|||
* text=auto
|
||||
*.sh eol=lf
|
||||
*.bash eol=lf
|
|
@ -0,0 +1,115 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
# check the following folders for printable files, print them
|
||||
# checks Azure Extension directories using globs, since they're not
|
||||
# well-known.
|
||||
|
||||
# Returns nonzero value on detection of any defender info
|
||||
# Return value is a bitmask showing the types of info detected.
|
||||
# Bits are ordered by seriousness of the issue:
|
||||
# Least significant bit is bad
|
||||
# Most significant bit is worst.
|
||||
EXIT_CODE=0
|
||||
# if any mdatp install in /etc/opt is found
|
||||
EXIT_MDATP_AGENT_INSTALLED=1
|
||||
# if mdatp az extension is installed
|
||||
EXIT_MDE_INSTALLED=2
|
||||
# if any log dirs are found
|
||||
EXIT_MDATP_LOGS_FOUND=4
|
||||
# if an installation log is found
|
||||
EXIT_MDATP_INSTALL_LOGS_FOUND=8
|
||||
# if an onboarding blob is found
|
||||
EXIT_ONBOARD_INFO_FOUND=16
|
||||
MDATP_OPT_DIR='/etc/opt/microsoft/mdatp'
|
||||
MDATP_LOG_DIR='/var/log/microsoft/mdatp'
|
||||
ERROR_MSG_HEADER="----------------------------------------------------------------------"
|
||||
|
||||
find_printable_files () {
|
||||
found_dir="$1"
|
||||
sudo find "$found_dir" -type f -exec file '{}' ';' -exec grep -Iq . '{}' ';' -exec head -c 1024 '{}' ';'
|
||||
}
|
||||
|
||||
check_unexpected_file () {
|
||||
surprise_file="$1"
|
||||
echo "Found unexpected regular file: $surprise_file" >&2
|
||||
# see what it is, print if it's printable
|
||||
file "$surprise_file"; grep -Iq . "$surprise_file" && cat "$surprise_file"
|
||||
}
|
||||
|
||||
# check for MDE extension installation, folder is version labeled, so use a shell glob
|
||||
for mde_dir in /var/lib/waagent/Microsoft.Azure.AzureDefenderForServers.MDE.Linux* ; do
|
||||
# for all the versioned folders we find...
|
||||
if [ -e "$mde_dir" ]; then
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDE_INSTALLED))
|
||||
if [ -d "$mde_dir" ]; then
|
||||
# find regular files, skip printing them if they are binary
|
||||
find_printable_files "$mde_dir"
|
||||
else
|
||||
# not expecting to find a regular file instead of a dir, but...
|
||||
check_unexpected_file "$mde_dir"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# check for ARM log files
|
||||
for log_dir in /var/log/azure/Microsoft.Azure.AzureDefenderForServers.MDE.Linux* ; do
|
||||
# for all the versioned folders we find...
|
||||
if [ -e "$log_dir" ]; then
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDATP_LOGS_FOUND))
|
||||
echo "checking $log_dir..."
|
||||
if [ -d "$log_dir" ]; then
|
||||
find_printable_files "$log_dir"
|
||||
else
|
||||
# not expecting to find a regular file in /var/log/azure, but...
|
||||
check_unexpected_file "$log_dir"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# check for ARC logs
|
||||
for log_dir in /var/lib/GuestConfig/extension_logs/Microsoft.Azure.AzureDefenderForServers.MDE.Linux* ; do
|
||||
# for all the versioned folders we find...
|
||||
if [ -e "$log_dir" ]; then
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDATP_LOGS_FOUND))
|
||||
echo "checking $log_dir..."
|
||||
if [ -d "$log_dir" ]; then
|
||||
find_printable_files "$log_dir"
|
||||
else
|
||||
check_unexpected_file "$log_dir"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# check for mde agent install in /etc/opt
|
||||
if [ -e "$MDATP_OPT_DIR" ]; then
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDATP_AGENT_INSTALLED))
|
||||
find_printable_files "$MDATP_OPT_DIR"
|
||||
fi
|
||||
|
||||
# check for install or runtime logs in /var/log
|
||||
if [ -e "$MDATP_LOG_DIR" ]; then
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDATP_LOGS_FOUND))
|
||||
find_printable_files "$MDATP_LOG_DIR"
|
||||
fi
|
||||
|
||||
# special log line for install logs
|
||||
if [ -f "$MDATP_LOG_DIR/install.log" ]; then
|
||||
echo "$ERROR_MSG_HEADER" >&2
|
||||
echo "ERROR: mdatp install logs are present in this image!" >&2
|
||||
echo "Publishers should remove this data before publishing public images." >&2
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_MDATP_INSTALL_LOGS_FOUND))
|
||||
fi
|
||||
|
||||
# special log line for mdatp_onboard.json
|
||||
if [ -f "$MDATP_OPT_DIR/mdatp_onboard.json" ]; then
|
||||
echo "$ERROR_MSG_HEADER" >&2
|
||||
echo "ERROR: mdatp onboarding info is present in this image!" >&2
|
||||
echo "Publishers should remove this data before publishing public images." >&2
|
||||
EXIT_CODE=$((EXIT_CODE|EXIT_ONBOARD_INFO_FOUND))
|
||||
fi
|
||||
|
||||
# returns nonzero value if defender info is found
|
||||
exit $EXIT_CODE
|
|
@ -0,0 +1,124 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
import pathlib
|
||||
|
||||
from assertpy import fail
|
||||
|
||||
from lisa import Node, SkippedException, TestCaseMetadata, TestSuite, TestSuiteMetadata
|
||||
from lisa.operating_system import Posix
|
||||
from lisa.sut_orchestrator import AZURE
|
||||
from lisa.testsuite import simple_requirement
|
||||
|
||||
# some constants from check-mdatp.sh
|
||||
# if any mdatp install in /etc/opt is found
|
||||
EXIT_MDATP_AGENT_INSTALLED = 1
|
||||
# if mdatp az extension is installed
|
||||
EXIT_MDE_INSTALLED = 2
|
||||
# if any log dirs are found
|
||||
EXIT_MDATP_LOGS_FOUND = 4
|
||||
# if an installation log is found
|
||||
EXIT_MDATP_INSTALL_LOGS_FOUND = 8
|
||||
# if an onboarding blob is found
|
||||
EXIT_ONBOARD_INFO_FOUND = 16
|
||||
|
||||
|
||||
@TestSuiteMetadata(
|
||||
area="mdatp",
|
||||
category="functional",
|
||||
description="""
|
||||
Test to verify there are no pre-installed copies of mdatp.
|
||||
""",
|
||||
)
|
||||
class MdatpSuite(TestSuite):
|
||||
@TestCaseMetadata(
|
||||
description="""
|
||||
Check for mdatp endpoint/cloud install, dump config info.
|
||||
Fails if mdatp is installed in the image.
|
||||
Raises specific error messages depending on the type of info
|
||||
foud
|
||||
""",
|
||||
priority=3,
|
||||
requirement=simple_requirement(
|
||||
supported_os=[Posix], supported_platform_type=[AZURE]
|
||||
),
|
||||
)
|
||||
def verify_mdatp_not_preinstalled(self, node: Node) -> None:
|
||||
# collect some paths before we start the test
|
||||
checker = "check-mdatp.sh"
|
||||
local_path = pathlib.PurePath(__file__).parent.joinpath(checker)
|
||||
working_path = node.get_working_path()
|
||||
script_path = working_path.joinpath(checker)
|
||||
|
||||
# copy the bash script to the node
|
||||
node.shell.copy(local_path=local_path, node_path=script_path)
|
||||
result = node.execute(
|
||||
cmd=f"chmod +x {str(script_path)}",
|
||||
shell=True,
|
||||
sudo=True,
|
||||
)
|
||||
# and run the script to check and dump defender info
|
||||
result = node.execute(
|
||||
cmd=f"{str(script_path)}",
|
||||
shell=True,
|
||||
sudo=True,
|
||||
no_debug_log=True,
|
||||
)
|
||||
script_output = result.stdout.strip()
|
||||
exit_code = result.exit_code
|
||||
if exit_code is None:
|
||||
raise SkippedException("exit code was None after running check-mdatp")
|
||||
if exit_code == 0:
|
||||
node.log.info("No mdatp onboarding info found, image is clean.")
|
||||
return
|
||||
|
||||
node.log.info("Found mdatp installation!")
|
||||
node.log.debug(f"Found config information: {script_output}")
|
||||
found_onboarding_info = exit_code & EXIT_ONBOARD_INFO_FOUND
|
||||
found_install_logs = exit_code & (
|
||||
EXIT_MDATP_INSTALL_LOGS_FOUND | EXIT_MDATP_LOGS_FOUND
|
||||
)
|
||||
found_mdatp_installed = exit_code & EXIT_MDATP_AGENT_INSTALLED
|
||||
found_mde_extension_install = exit_code & EXIT_MDE_INSTALLED
|
||||
|
||||
# Add some descriptive text to describe each specific problem.
|
||||
error_header = ""
|
||||
if found_onboarding_info:
|
||||
error_header += "mdatp onboarding info is present in this image! "
|
||||
if found_install_logs:
|
||||
error_header += "mdatp install logs are present in this image! "
|
||||
if found_mdatp_installed:
|
||||
error_header += "mdatp installation was found on this image! "
|
||||
if found_mde_extension_install:
|
||||
error_header += "MDE extension installation was found in this image! "
|
||||
if not any(
|
||||
[
|
||||
found_onboarding_info,
|
||||
found_install_logs,
|
||||
found_mdatp_installed,
|
||||
found_mde_extension_install,
|
||||
]
|
||||
):
|
||||
raise SkippedException(
|
||||
f"No recognized error code was found: {exit_code} output: {script_output}"
|
||||
)
|
||||
# set the error message depending on the info found by the script.
|
||||
|
||||
error_message = (
|
||||
f"{error_header}"
|
||||
"This may indicate the VM used to build this image was "
|
||||
"onboarded to mdatp and the onboarding info was not "
|
||||
"wiped before generalizing the image. Alert the publisher "
|
||||
"that their image contains leftover logs and "
|
||||
"organization info. They can use our script to check "
|
||||
"for leftover config and org info: "
|
||||
"https://github.com/microsoft/lisa/tree/main/microsoft"
|
||||
"/testsuites/mdatp/check-mdatp.sh"
|
||||
)
|
||||
# fail and raise the error message
|
||||
fail(str(error_message))
|
||||
|
||||
|
||||
# NOTE: it's possible there will be an additional case added
|
||||
# to handle filtering the result to check for expected
|
||||
# installations. For now, since there are none, we fail for
|
||||
# all cases other than 'no mdatp installed by default'
|
Загрузка…
Ссылка в новой задаче