Skip to content

Commit

Permalink
Only prepend if not root folder and validate directory source
Browse files Browse the repository at this point in the history
  • Loading branch information
TinaMor committed Aug 22, 2023
1 parent a47d40e commit a0baf65
Show file tree
Hide file tree
Showing 18 changed files with 289 additions and 115 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bld/

# Visual Studio 2015/2017 cache/options directory
.vs/
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

Expand Down
75 changes: 59 additions & 16 deletions LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,65 @@ namespace LogMonitorTests
}
}

TEST_METHOD(TestRootDirectoryConfigurations)
{

const std::wstring directory = L"C:\\";
bool includeSubdirectories = false;

std::wstring configFileStr;
std::wstring configFileStrFormat =
L"{ \
\"LogConfig\": { \
\"sources\": [ \
{\
\"type\": \"File\",\
\"directory\": \"%s\",\
\"includeSubdirectories\": %s\
}\
]\
}\
}";

// Valid: Root dir and includeSubdirectories = false
{
configFileStr = Utility::FormatString(
configFileStrFormat.c_str(),
Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(),
includeSubdirectories ? L"true" : L"false");

JsonFileParser jsonParser(configFileStr);
LoggerSettings settings;

bool success = ReadConfigFile(jsonParser, settings);
Assert::IsTrue(success);

std::wstring output = RecoverOuput();
Assert::AreEqual(L"", output.c_str());
}

// Invalid: Root dir and includeSubdirectories = true
{
includeSubdirectories = true;
configFileStr = Utility::FormatString(
configFileStrFormat.c_str(),
Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(),
includeSubdirectories ? L"true" : L"false");

fflush(stdout);
ZeroMemory(bigOutBuf, sizeof(bigOutBuf));

JsonFileParser jsonParser(configFileStr);
LoggerSettings settings;

bool success = ReadConfigFile(jsonParser, settings);
Assert::IsTrue(success);

std::wstring output = RecoverOuput();
Assert::IsTrue(output.find(L"WARNING") != std::wstring::npos);
}
}

///
/// Check that invalid ETW sources are not returned by ReadConfigFile.
///
Expand Down Expand Up @@ -1557,28 +1616,12 @@ namespace LogMonitorTests

TEST_METHOD(TestInvalidWaitInSeconds) {
std::wstring directory = L"C:\\LogMonitor\\logs";

std::wstring configFileStrFormat =
L"{ \
\"LogConfig\": { \
\"sources\": [ \
{\
\"type\": \"File\",\
\"directory\": \"%s\",\
\"waitInSeconds\": %f\
}\
]\
}\
}";

TestInvalidWaitInSecondsValues(L"-10", false);
TestInvalidWaitInSecondsValues(L"-Inf", true);
}

private:

void TestWaitInSecondsValues(std::wstring waitInSeconds, bool asString = false) {
std::wstring configFileStrFormat;
std::wstring directory = L"C:\\LogMonitor\\logs";
std::wstring configFileStr = GetConfigFileStrFormat(directory, waitInSeconds, asString);

Expand Down
2 changes: 1 addition & 1 deletion LogMonitor/LogMonitorTests/LogMonitorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "../src/LogMonitor/EtwMonitor.cpp"
#include "../src/LogMonitor/EventMonitor.cpp"
#include "../src/LogMonitor/JsonFileParser.cpp"
#include "../src/LogMonitor/FileMonitor/Utilities.cpp"
#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp"
#include "../src/LogMonitor/LogFileMonitor.cpp"
#include "../src/LogMonitor/ProcessMonitor.cpp"
#include "../src/LogMonitor/Utility.cpp"
Expand Down
2 changes: 1 addition & 1 deletion LogMonitor/LogMonitorTests/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
#include "../src/LogMonitor/LogWriter.h"
#include "../src/LogMonitor/EtwMonitor.h"
#include "../src/LogMonitor/EventMonitor.h"
#include "../src/LogMonitor/FileMonitor/Utilities.h"
#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.h"
#include "../src/LogMonitor/LogFileMonitor.h"
#include "../src/LogMonitor/ProcessMonitor.h"
#include "Utility.h"
Expand Down
22 changes: 22 additions & 0 deletions LogMonitor/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,28 @@ This will monitor any changes in log files matching a specified filter, given th
}
```

**Note:** When the directory is the root directory (e.g. C:\\ ) we can only monitor a file that is in the root directory, not a subfolder. This is due to access issues (even when running LogMonitor as an Admin) for some of the folders in the root directory. Therefore, `includeSubdirectories` must be `false` for the root directory. See example below:

```json
{
"LogConfig": {
"sources": [
{
"type": "File",
"directory": "C:",
"filter": "*.log",
"includeSubdirectories": false
}
]
}
}
```
When the root directory is passed and `includeSubdirectories = true`, we get an error:
```
ERROR: LoggerSettings: Invalid Source File atrribute 'directory' (C:) and 'includeSubdirectories' (true).'includeSubdirectories' attribute cannot be 'true' for the root directory
WARNING: Failed to parse configuration file. Error retrieving source attributes. Invalid source
```

## Process Monitoring

### Description
Expand Down
48 changes: 46 additions & 2 deletions LogMonitor/src/LogMonitor/ConfigFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "pch.h"
#include "./Parser/ConfigFileParser.h"
#include "./LogWriter.h"
#include "./FileMonitor/FileMonitorUtilities.h"

/// ConfigFileParser.cpp
///
Expand Down Expand Up @@ -306,8 +307,13 @@ ReadSourceAttributes(
// * directory
// * filter
//
else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0
|| _wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0)
else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0)
{
std::wstring directory = Parser.ParseStringValue();
FileMonitorUtilities::ParseDirectoryValue(directory);
Attributes[key] = new std::wstring(directory);
}
else if (_wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0)
{
Attributes[key] = new std::wstring(Parser.ParseStringValue());
}
Expand Down Expand Up @@ -396,6 +402,12 @@ ReadSourceAttributes(
} while (Parser.ParseNextObjectElement());
}

bool isSourceFileValid = ValidateDirectoryAttributes(Attributes);
if (!isSourceFileValid)
{
success = false;
}

return success;
}

Expand Down Expand Up @@ -640,6 +652,38 @@ AddNewSource(
return true;
}

///
/// Validates that when root directory is passed, includeSubdirectories is false
///
/// \param Attributes An AttributesMap that contains the attributes of the new source objet.
/// \return false when root directory is passed, includeSubdirectories = true. Otherwise, true </returns>
bool ValidateDirectoryAttributes(_In_ AttributesMap &Attributes)
{
const std::wstring key = L"directory";

if (!Utility::ConfigAttributeExists(Attributes, JSON_TAG_DIRECTORY) ||
!Utility::ConfigAttributeExists(Attributes, JSON_TAG_INCLUDE_SUBDIRECTORIES))
{
return true;
}

std::wstring directory = *(std::wstring *)Attributes[JSON_TAG_DIRECTORY];
const bool includeSubdirectories = *(bool *)Attributes[JSON_TAG_INCLUDE_SUBDIRECTORIES];

// Check if Log file monitor config is valid
const bool isValid = FileMonitorUtilities::IsValidSourceFile(directory, includeSubdirectories);
if (!isValid)
{
logWriter.TraceError(
Utility::FormatString(
L"LoggerSettings: Invalid Source File atrribute 'directory' (%s) and 'includeSubdirectories' (%s)."
L"'includeSubdirectories' attribute cannot be 'true' for the root directory",
directory.c_str(), includeSubdirectories ? L"true" : L"false")
.c_str());
}
return isValid;
}

///
/// Debug function
///
Expand Down
Loading

0 comments on commit a0baf65

Please sign in to comment.