Add NTFS ensure level filters
This commit is contained in:
@@ -53,6 +53,20 @@ namespace C4IT.LIAM
|
||||
public int Level { get; set; } = -1;
|
||||
}
|
||||
|
||||
private sealed class cNtfsLevelRange
|
||||
{
|
||||
public bool IsConfigured { get; set; }
|
||||
public bool IsValid { get; set; } = true;
|
||||
public int MinLevel { get; set; } = int.MinValue;
|
||||
public int MaxLevel { get; set; } = int.MaxValue;
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
public bool Contains(int level)
|
||||
{
|
||||
return !IsConfigured || level >= MinLevel && level <= MaxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class cNtfsDataAreaDiagnostics
|
||||
{
|
||||
private const int MaxSamples = 10;
|
||||
@@ -123,6 +137,10 @@ namespace C4IT.LIAM
|
||||
private const string AdditionalConfigurationExcludePathsKey = "NtfsExcludePaths";
|
||||
private const string AdditionalConfigurationIncludePathsKey = "NtfsIncludePaths";
|
||||
private const string AdditionalConfigurationTraverseBoundaryPathKey = "NtfsTraverseBoundaryPath";
|
||||
private const string AdditionalConfigurationPermissionGroupsMinLevelKey = "NtfsPermissionGroupsMinLevel";
|
||||
private const string AdditionalConfigurationPermissionGroupsMaxLevelKey = "NtfsPermissionGroupsMaxLevel";
|
||||
private const string AdditionalConfigurationTraverseGroupsMinLevelKey = "NtfsTraverseGroupsMinLevel";
|
||||
private const string AdditionalConfigurationTraverseGroupsMaxLevelKey = "NtfsTraverseGroupsMaxLevel";
|
||||
private const string AdditionalConfigurationGroupNameSanitizeReplacementKey = "NtfsGroupNameSanitizeReplacement";
|
||||
private const string AdditionalConfigurationPreserveAdGroupNameCaseKey = "PreserveNtfsAdGroupNameCase";
|
||||
private const string AdditionalConfigurationAdDomainControllersKey = "NtfsAdDomainControllers";
|
||||
@@ -1155,6 +1173,16 @@ namespace C4IT.LIAM
|
||||
});
|
||||
}
|
||||
|
||||
string levelSkipReason;
|
||||
if (!IsPermissionLevelManagedPath(classification, out levelSkipReason))
|
||||
{
|
||||
return Task.FromResult(new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString())
|
||||
{
|
||||
resultErrorId = 30008,
|
||||
resultMessage = levelSkipReason
|
||||
});
|
||||
}
|
||||
|
||||
var parentPath = Directory.GetParent(folderPath)?.FullName;
|
||||
var engine = CreateFilesystemEngine(
|
||||
folderPath,
|
||||
@@ -1208,7 +1236,19 @@ namespace C4IT.LIAM
|
||||
});
|
||||
}
|
||||
|
||||
if (!IsTraversePermissionManagedPath(folderPath))
|
||||
var traverseLevelRange = GetTraverseLevelRange();
|
||||
if (!traverseLevelRange.IsValid)
|
||||
{
|
||||
var message = $"NTFS traverse ensure skipped for '{folderPath}' because {traverseLevelRange.ErrorMessage}";
|
||||
LogEntry(message, LogLevels.Warning);
|
||||
return Task.FromResult(new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString())
|
||||
{
|
||||
resultErrorId = 30008,
|
||||
resultMessage = message
|
||||
});
|
||||
}
|
||||
|
||||
if (!IsTraversePermissionCandidatePath(folderPath))
|
||||
{
|
||||
return Task.FromResult(new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString())
|
||||
{
|
||||
@@ -1355,6 +1395,16 @@ namespace C4IT.LIAM
|
||||
}
|
||||
|
||||
private bool IsPermissionManagedPath(string path, params eNtfsPathKind[] supportedKinds)
|
||||
{
|
||||
if (!IsPermissionManagedPathCandidate(path, supportedKinds))
|
||||
return false;
|
||||
|
||||
var classification = ClassifyPath(path);
|
||||
string levelSkipReason;
|
||||
return IsPermissionLevelManagedPath(classification, out levelSkipReason);
|
||||
}
|
||||
|
||||
private bool IsPermissionManagedPathCandidate(string path, params eNtfsPathKind[] supportedKinds)
|
||||
{
|
||||
var classification = ClassifyPath(path);
|
||||
if (!IsSupportedPermissionManagedPathKind(classification, supportedKinds))
|
||||
@@ -1365,13 +1415,25 @@ namespace C4IT.LIAM
|
||||
if (IsPathBlacklisted(classification, out matchingConfigurationKey, out matchingRule))
|
||||
return false;
|
||||
|
||||
return IsPathWhitelisted(classification, false, out matchingConfigurationKey, out matchingRule);
|
||||
if (!IsPathWhitelisted(classification, false, out matchingConfigurationKey, out matchingRule))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsTraversePermissionManagedPath(string path)
|
||||
{
|
||||
if (!IsTraversePermissionCandidatePath(path))
|
||||
return false;
|
||||
|
||||
string levelSkipReason;
|
||||
return IsTraverseLevelManagedPath(ClassifyPath(path), out levelSkipReason);
|
||||
}
|
||||
|
||||
private bool IsTraversePermissionCandidatePath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(GetAdditionalConfigurationValue(AdditionalConfigurationTraverseBoundaryPathKey)))
|
||||
return IsPermissionManagedFolderPath(path);
|
||||
return IsPermissionManagedPathCandidate(path, eNtfsPathKind.Folder);
|
||||
|
||||
var classification = ClassifyPath(path);
|
||||
if (classification == null || classification.Kind == eNtfsPathKind.ServerRoot || classification.Kind == eNtfsPathKind.Unknown)
|
||||
@@ -1385,6 +1447,112 @@ namespace C4IT.LIAM
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
private bool IsPermissionLevelManagedPath(cNtfsPathClassification classification, out string skipReason)
|
||||
{
|
||||
return IsLevelManagedPath(
|
||||
classification,
|
||||
GetPermissionLevelRange(),
|
||||
"permission group ensure",
|
||||
out skipReason);
|
||||
}
|
||||
|
||||
private bool IsTraverseLevelManagedPath(cNtfsPathClassification classification, out string skipReason)
|
||||
{
|
||||
return IsLevelManagedPath(
|
||||
classification,
|
||||
GetTraverseLevelRange(),
|
||||
"traverse group ensure",
|
||||
out skipReason);
|
||||
}
|
||||
|
||||
private bool IsLevelManagedPath(cNtfsPathClassification classification, cNtfsLevelRange range, string operationName, out string skipReason)
|
||||
{
|
||||
skipReason = string.Empty;
|
||||
if (classification == null)
|
||||
{
|
||||
skipReason = $"NTFS {operationName} skipped because the path could not be classified.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (range == null || !range.IsConfigured)
|
||||
return true;
|
||||
|
||||
if (!range.IsValid)
|
||||
{
|
||||
skipReason = $"NTFS {operationName} skipped for '{classification.NormalizedPath}' because {range.ErrorMessage}";
|
||||
LogEntry(skipReason, LogLevels.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (range.Contains(classification.Level))
|
||||
return true;
|
||||
|
||||
skipReason = $"NTFS {operationName} skipped for '{classification.NormalizedPath}' because level {classification.Level} is outside configured range {range.MinLevel}..{range.MaxLevel}.";
|
||||
LogEntry(skipReason, LogLevels.Debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
private cNtfsLevelRange GetPermissionLevelRange()
|
||||
{
|
||||
return GetConfiguredLevelRange(
|
||||
AdditionalConfigurationPermissionGroupsMinLevelKey,
|
||||
AdditionalConfigurationPermissionGroupsMaxLevelKey,
|
||||
"permission group level range");
|
||||
}
|
||||
|
||||
private cNtfsLevelRange GetTraverseLevelRange()
|
||||
{
|
||||
return GetConfiguredLevelRange(
|
||||
AdditionalConfigurationTraverseGroupsMinLevelKey,
|
||||
AdditionalConfigurationTraverseGroupsMaxLevelKey,
|
||||
"traverse group level range");
|
||||
}
|
||||
|
||||
private cNtfsLevelRange GetConfiguredLevelRange(string minKey, string maxKey, string label)
|
||||
{
|
||||
var range = new cNtfsLevelRange();
|
||||
var minValue = GetAdditionalConfigurationValue(minKey);
|
||||
var maxValue = GetAdditionalConfigurationValue(maxKey);
|
||||
var hasMin = !string.IsNullOrWhiteSpace(minValue);
|
||||
var hasMax = !string.IsNullOrWhiteSpace(maxValue);
|
||||
range.IsConfigured = hasMin || hasMax;
|
||||
if (!range.IsConfigured)
|
||||
return range;
|
||||
|
||||
int parsedValue;
|
||||
if (hasMin)
|
||||
{
|
||||
if (!int.TryParse(minValue, out parsedValue))
|
||||
{
|
||||
range.IsValid = false;
|
||||
range.ErrorMessage = $"AdditionalConfiguration '{minKey}' for {label} is not a valid integer: '{minValue}'.";
|
||||
return range;
|
||||
}
|
||||
|
||||
range.MinLevel = parsedValue;
|
||||
}
|
||||
|
||||
if (hasMax)
|
||||
{
|
||||
if (!int.TryParse(maxValue, out parsedValue))
|
||||
{
|
||||
range.IsValid = false;
|
||||
range.ErrorMessage = $"AdditionalConfiguration '{maxKey}' for {label} is not a valid integer: '{maxValue}'.";
|
||||
return range;
|
||||
}
|
||||
|
||||
range.MaxLevel = parsedValue;
|
||||
}
|
||||
|
||||
if (range.MinLevel > range.MaxLevel)
|
||||
{
|
||||
range.IsValid = false;
|
||||
range.ErrorMessage = $"AdditionalConfiguration {label} is invalid because min level {range.MinLevel} is greater than max level {range.MaxLevel}.";
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
private static bool IsSupportedPermissionManagedPathKind(cNtfsPathClassification classification, params eNtfsPathKind[] supportedKinds)
|
||||
{
|
||||
if (classification == null || supportedKinds == null || supportedKinds.Length == 0)
|
||||
|
||||
Reference in New Issue
Block a user