Generalize NTFS path policy
This commit is contained in:
@@ -53,6 +53,8 @@ namespace C4IT.LIAM
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Guid nftsModuleId = new Guid("77e213a1-6517-ea11-4881-000c2980fd94");
|
public static Guid nftsModuleId = new Guid("77e213a1-6517-ea11-4881-000c2980fd94");
|
||||||
|
private const string AdditionalConfigurationExcludePathsKey = "NtfsExcludePaths";
|
||||||
|
private const string AdditionalConfigurationIncludePathsKey = "NtfsIncludePaths";
|
||||||
public readonly cNtfsBase ntfsBase = new cNtfsBase();
|
public readonly cNtfsBase ntfsBase = new cNtfsBase();
|
||||||
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
||||||
private readonly Dictionary<string, HashSet<string>> publishedShareCache = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, HashSet<string>> publishedShareCache = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -208,6 +210,9 @@ namespace C4IT.LIAM
|
|||||||
if (!await LogonAsync())
|
if (!await LogonAsync())
|
||||||
return null;
|
return null;
|
||||||
var classification = ClassifyPath(UID);
|
var classification = ClassifyPath(UID);
|
||||||
|
if (!PathsEqual(classification?.NormalizedPath, this.RootPath) && !ShouldIncludeDataArea(classification))
|
||||||
|
return null;
|
||||||
|
|
||||||
return await BuildDataAreaAsync(classification);
|
return await BuildDataAreaAsync(classification);
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
@@ -434,13 +439,13 @@ namespace C4IT.LIAM
|
|||||||
|
|
||||||
string matchingConfigurationKey;
|
string matchingConfigurationKey;
|
||||||
string matchingRule;
|
string matchingRule;
|
||||||
if (IsBlacklistedFolderPath(classification, out matchingConfigurationKey, out matchingRule))
|
if (IsPathBlacklisted(classification, out matchingConfigurationKey, out matchingRule))
|
||||||
{
|
{
|
||||||
LogEntry($"Skip NTFS path '{classification.NormalizedPath}' due to AdditionalConfiguration rule '{matchingConfigurationKey}={matchingRule}'", LogLevels.Debug);
|
LogEntry($"Skip NTFS path '{classification.NormalizedPath}' due to AdditionalConfiguration rule '{matchingConfigurationKey}={matchingRule}'", LogLevels.Debug);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsWhitelistedFolderPath(classification, true, out matchingConfigurationKey, out matchingRule))
|
if (!IsPathWhitelisted(classification, true, out matchingConfigurationKey, out matchingRule))
|
||||||
{
|
{
|
||||||
LogEntry($"Skip NTFS path '{classification.NormalizedPath}' because no AdditionalConfiguration whitelist matched", LogLevels.Debug);
|
LogEntry($"Skip NTFS path '{classification.NormalizedPath}' because no AdditionalConfiguration whitelist matched", LogLevels.Debug);
|
||||||
return false;
|
return false;
|
||||||
@@ -456,25 +461,19 @@ namespace C4IT.LIAM
|
|||||||
|
|
||||||
string matchingConfigurationKey;
|
string matchingConfigurationKey;
|
||||||
string matchingRule;
|
string matchingRule;
|
||||||
if (IsBlacklistedFolderPath(classification, out matchingConfigurationKey, out matchingRule))
|
if (IsPathBlacklisted(classification, out matchingConfigurationKey, out matchingRule))
|
||||||
{
|
{
|
||||||
LogEntry($"Skip NTFS subtree '{classification.NormalizedPath}' due to AdditionalConfiguration rule '{matchingConfigurationKey}={matchingRule}'", LogLevels.Debug);
|
LogEntry($"Skip NTFS subtree '{classification.NormalizedPath}' due to AdditionalConfiguration rule '{matchingConfigurationKey}={matchingRule}'", LogLevels.Debug);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasAdditionalConfigurationValues("NtfsIncludeFolderNames"))
|
if (!HasAdditionalConfigurationValues(AdditionalConfigurationIncludePathsKey))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!HasAdditionalConfigurationValues("NtfsIncludeRelativePaths"))
|
if (IsPathWhitelisted(classification, true, out matchingConfigurationKey, out matchingRule))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (classification.Kind != eNtfsPathKind.Folder)
|
LogEntry($"Skip NTFS subtree '{classification.NormalizedPath}' because it is outside AdditionalConfiguration whitelist '{AdditionalConfigurationIncludePathsKey}'", LogLevels.Debug);
|
||||||
return true;
|
|
||||||
|
|
||||||
if (IsWhitelistedFolderPath(classification, true, out matchingConfigurationKey, out matchingRule))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
LogEntry($"Skip NTFS subtree '{classification.NormalizedPath}' because it is outside AdditionalConfiguration whitelist 'NtfsIncludeRelativePaths'", LogLevels.Debug);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,85 +485,57 @@ namespace C4IT.LIAM
|
|||||||
return Regex.Match(displayName ?? string.Empty, this.DataAreaRegEx).Success;
|
return Regex.Match(displayName ?? string.Empty, this.DataAreaRegEx).Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsBlacklistedFolderPath(cNtfsPathClassification classification, out string matchingConfigurationKey, out string matchingRule)
|
private bool IsPathBlacklisted(cNtfsPathClassification classification, out string matchingConfigurationKey, out string matchingRule)
|
||||||
|
{
|
||||||
|
return TryMatchPathPolicy(classification, AdditionalConfigurationExcludePathsKey, false, out matchingConfigurationKey, out matchingRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPathWhitelisted(cNtfsPathClassification classification, bool allowPathAncestorMatches, out string matchingConfigurationKey, out string matchingRule)
|
||||||
{
|
{
|
||||||
matchingConfigurationKey = null;
|
matchingConfigurationKey = null;
|
||||||
matchingRule = null;
|
matchingRule = null;
|
||||||
|
|
||||||
if (classification == null || classification.Kind != eNtfsPathKind.Folder)
|
if (!HasAdditionalConfigurationValues(AdditionalConfigurationIncludePathsKey))
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (var excludedFolderName in GetAdditionalConfigurationValues("NtfsExcludeFolderNames"))
|
|
||||||
{
|
|
||||||
if (!MatchesAdditionalConfigurationPattern(classification.DisplayName, excludedFolderName))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
matchingConfigurationKey = "NtfsExcludeFolderNames";
|
|
||||||
matchingRule = excludedFolderName;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
return TryMatchPathPolicy(classification, AdditionalConfigurationIncludePathsKey, allowPathAncestorMatches, out matchingConfigurationKey, out matchingRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
var relativePath = GetRelativePathFromRoot(classification.NormalizedPath);
|
private bool TryMatchPathPolicy(cNtfsPathClassification classification, string key, bool allowPathAncestorMatches, out string matchingConfigurationKey, out string matchingRule)
|
||||||
foreach (var excludedRelativePath in GetAdditionalConfigurationValues("NtfsExcludeRelativePaths"))
|
|
||||||
{
|
|
||||||
if (!MatchesAdditionalConfigurationPattern(relativePath, excludedRelativePath))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
matchingConfigurationKey = "NtfsExcludeRelativePaths";
|
|
||||||
matchingRule = excludedRelativePath;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsWhitelistedFolderPath(cNtfsPathClassification classification, bool allowRelativePathAncestorMatches, out string matchingConfigurationKey, out string matchingRule)
|
|
||||||
{
|
{
|
||||||
matchingConfigurationKey = null;
|
matchingConfigurationKey = null;
|
||||||
matchingRule = null;
|
matchingRule = null;
|
||||||
|
|
||||||
if (classification == null || classification.Kind != eNtfsPathKind.Folder)
|
if (classification == null || string.IsNullOrWhiteSpace(key))
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
var hasIncludeFolderNames = HasAdditionalConfigurationValues("NtfsIncludeFolderNames");
|
var patterns = GetAdditionalConfigurationValues(key).ToList();
|
||||||
var hasIncludeRelativePaths = HasAdditionalConfigurationValues("NtfsIncludeRelativePaths");
|
if (patterns.Count == 0)
|
||||||
if (!hasIncludeFolderNames && !hasIncludeRelativePaths)
|
return false;
|
||||||
return true;
|
|
||||||
|
|
||||||
foreach (var includedFolderName in GetAdditionalConfigurationValues("NtfsIncludeFolderNames"))
|
foreach (var pattern in patterns)
|
||||||
{
|
{
|
||||||
if (!MatchesAdditionalConfigurationPattern(classification.DisplayName, includedFolderName))
|
if (!MatchesPathPolicy(classification, pattern))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
matchingConfigurationKey = "NtfsIncludeFolderNames";
|
matchingConfigurationKey = key;
|
||||||
matchingRule = includedFolderName;
|
matchingRule = pattern;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var relativePath = GetRelativePathFromRoot(classification.NormalizedPath);
|
if (!allowPathAncestorMatches)
|
||||||
foreach (var includedRelativePath in GetAdditionalConfigurationValues("NtfsIncludeRelativePaths"))
|
return false;
|
||||||
|
|
||||||
|
foreach (var pattern in patterns)
|
||||||
{
|
{
|
||||||
if (!MatchesAdditionalConfigurationPattern(relativePath, includedRelativePath))
|
if (!CanPathLeadToPattern(classification, pattern))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
matchingConfigurationKey = "NtfsIncludeRelativePaths";
|
matchingConfigurationKey = key;
|
||||||
matchingRule = includedRelativePath;
|
matchingRule = pattern;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowRelativePathAncestorMatches)
|
|
||||||
{
|
|
||||||
foreach (var includedRelativePath in GetAdditionalConfigurationValues("NtfsIncludeRelativePaths"))
|
|
||||||
{
|
|
||||||
if (!IsRelativePathAncestorOfPattern(relativePath, includedRelativePath))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
matchingConfigurationKey = "NtfsIncludeRelativePaths";
|
|
||||||
matchingRule = includedRelativePath;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,12 +582,45 @@ namespace C4IT.LIAM
|
|||||||
.Replace('/', '\\');
|
.Replace('/', '\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool MatchesPathPolicy(cNtfsPathClassification classification, string pattern)
|
||||||
|
{
|
||||||
|
if (classification == null || string.IsNullOrWhiteSpace(pattern))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var candidate in GetPathPolicyCandidates(classification))
|
||||||
|
{
|
||||||
|
if (MatchesAdditionalConfigurationPattern(candidate, pattern))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GetPathPolicyCandidates(cNtfsPathClassification classification)
|
||||||
|
{
|
||||||
|
if (classification == null)
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
|
||||||
|
var candidates = new List<string>();
|
||||||
|
var relativePath = GetRelativePathFromRoot(classification.NormalizedPath);
|
||||||
|
if (!string.IsNullOrWhiteSpace(relativePath))
|
||||||
|
candidates.Add(relativePath);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(classification.NormalizedPath))
|
||||||
|
candidates.Add(classification.NormalizedPath);
|
||||||
|
|
||||||
|
return candidates
|
||||||
|
.Where(i => !string.IsNullOrWhiteSpace(i))
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
private bool MatchesAdditionalConfigurationPattern(string value, string pattern)
|
private bool MatchesAdditionalConfigurationPattern(string value, string pattern)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(pattern))
|
if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(pattern))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var normalizedValue = value.Trim().Replace('/', '\\');
|
var normalizedValue = value.Trim().Replace('/', '\\').Trim('\\');
|
||||||
var normalizedPattern = pattern.Trim().Replace('/', '\\').Trim('\\');
|
var normalizedPattern = pattern.Trim().Replace('/', '\\').Trim('\\');
|
||||||
if (string.IsNullOrWhiteSpace(normalizedPattern))
|
if (string.IsNullOrWhiteSpace(normalizedPattern))
|
||||||
return false;
|
return false;
|
||||||
@@ -625,27 +629,51 @@ namespace C4IT.LIAM
|
|||||||
return Regex.IsMatch(normalizedValue, regexPattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
return Regex.IsMatch(normalizedValue, regexPattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsRelativePathAncestorOfPattern(string relativePath, string pattern)
|
private bool CanPathLeadToPattern(cNtfsPathClassification classification, string pattern)
|
||||||
{
|
{
|
||||||
var normalizedRelativePath = (relativePath ?? string.Empty).Trim().Replace('/', '\\').Trim('\\');
|
if (classification == null || string.IsNullOrWhiteSpace(pattern))
|
||||||
if (string.IsNullOrWhiteSpace(normalizedRelativePath) || string.IsNullOrWhiteSpace(pattern))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var prefixSegments = new List<string>();
|
foreach (var candidate in GetPathPolicyCandidates(classification))
|
||||||
foreach (var patternSegment in pattern.Trim().Replace('/', '\\').Trim('\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
{
|
||||||
if (patternSegment.Contains("*"))
|
if (IsPathAncestorOfPattern(candidate, pattern))
|
||||||
break;
|
return true;
|
||||||
|
|
||||||
prefixSegments.Add(patternSegment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefixSegments.Count == 0)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPathAncestorOfPattern(string path, string pattern)
|
||||||
|
{
|
||||||
|
var normalizedPath = (path ?? string.Empty).Trim().Replace('/', '\\').Trim('\\');
|
||||||
|
var normalizedPattern = (pattern ?? string.Empty).Trim().Replace('/', '\\').Trim('\\');
|
||||||
|
if (string.IsNullOrWhiteSpace(normalizedPath) || string.IsNullOrWhiteSpace(normalizedPattern))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var normalizedPatternPrefix = string.Join("\\", prefixSegments);
|
var pathSegments = normalizedPath.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
return normalizedPatternPrefix.Equals(normalizedRelativePath, StringComparison.OrdinalIgnoreCase)
|
var patternSegments = normalizedPattern.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|| normalizedPatternPrefix.StartsWith(normalizedRelativePath + "\\", StringComparison.OrdinalIgnoreCase);
|
if (pathSegments.Length > patternSegments.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var segmentIndex = 0; segmentIndex < pathSegments.Length; segmentIndex++)
|
||||||
|
{
|
||||||
|
if (segmentIndex >= patternSegments.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!MatchesPatternSegment(pathSegments[segmentIndex], patternSegments[segmentIndex]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool MatchesPatternSegment(string valueSegment, string patternSegment)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(valueSegment) || string.IsNullOrWhiteSpace(patternSegment))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var regexPattern = "^" + Regex.Escape(patternSegment).Replace("\\*", ".*") + "$";
|
||||||
|
return Regex.IsMatch(valueSegment, regexPattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> GetDfsObjectPrefixes(string path)
|
private List<string> GetDfsObjectPrefixes(string path)
|
||||||
@@ -964,10 +992,10 @@ namespace C4IT.LIAM
|
|||||||
|
|
||||||
string matchingConfigurationKey;
|
string matchingConfigurationKey;
|
||||||
string matchingRule;
|
string matchingRule;
|
||||||
if (IsBlacklistedFolderPath(classification, out matchingConfigurationKey, out matchingRule))
|
if (IsPathBlacklisted(classification, out matchingConfigurationKey, out matchingRule))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return IsWhitelistedFolderPath(classification, false, out matchingConfigurationKey, out matchingRule);
|
return IsPathWhitelisted(classification, false, out matchingConfigurationKey, out matchingRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<IAM_SecurityGroupTemplate> BuildSecurityGroupTemplates()
|
private IEnumerable<IAM_SecurityGroupTemplate> BuildSecurityGroupTemplates()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
## Ziel
|
## Ziel
|
||||||
|
|
||||||
Dieses Dokument beschreibt einen kleinen technischen Entwurf, um dem NTFS-Provider ueber `AdditionalConfiguration` eine Blacklist und spaeter optional auch eine Whitelist fuer Ordner mitzugeben.
|
Dieses Dokument beschreibt einen kleinen technischen Entwurf, um dem NTFS-Provider ueber `AdditionalConfiguration` eine Blacklist und spaeter optional auch eine Whitelist fuer NTFS-Pfade mitzugeben.
|
||||||
|
|
||||||
Im ersten Schritt soll damit die Enumeration von Unterordnern fuer `getDataAreasAsync()` gezielt eingeschraenkt werden, ohne bestehende Konfigurationen zu brechen.
|
Die Policy soll klassifizierungsunabhaengig arbeiten und damit fuer Shares, DFS-Links, DFS-Namespaces und Folder dieselbe Matching-Logik verwenden.
|
||||||
|
|
||||||
## Ausgangslage
|
## Ausgangslage
|
||||||
|
|
||||||
@@ -22,36 +22,25 @@ Der bestehende Filter `ShouldIncludeDataArea()` wirkt nur auf den `DisplayName`
|
|||||||
|
|
||||||
Die neue Logik soll eine explizite Pfad-Policy fuer den NTFS-Provider einfuehren.
|
Die neue Logik soll eine explizite Pfad-Policy fuer den NTFS-Provider einfuehren.
|
||||||
|
|
||||||
Diese Policy entscheidet fuer jeden gefundenen Unterordner:
|
Diese Policy entscheidet fuer jeden gefundenen Pfad:
|
||||||
|
|
||||||
- darf als DataArea materialisiert werden
|
- darf als DataArea materialisiert werden
|
||||||
- darf weiter traversiert werden
|
- darf weiter traversiert werden
|
||||||
|
|
||||||
Fuer Schritt 1 reicht es, wenn ein ausgeschlossener Ordner weder als DataArea geliefert noch weiter traversiert wird.
|
Ein ausgeschlossener Pfad soll weder als DataArea geliefert noch weiter traversiert werden.
|
||||||
|
|
||||||
## Vorgeschlagene Konfigurationsschluessel
|
## Vorgeschlagene Konfigurationsschluessel
|
||||||
|
|
||||||
### Minimal fuer Schritt 1
|
### Aktueller Stand
|
||||||
|
|
||||||
- `NtfsExcludeFolderNames`
|
- `NtfsExcludePaths`
|
||||||
- `NtfsExcludeRelativePaths`
|
- `NtfsIncludePaths`
|
||||||
|
|
||||||
Beispiel:
|
Beispiel:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NtfsExcludeFolderNames=Temp;Archiv;System Volume Information
|
NtfsExcludePaths=Archiv;*\Temp;Abteilung\Alt;\\server\share\legacy\*
|
||||||
NtfsExcludeRelativePaths=Abteilung\Alt;IT\_disabled
|
NtfsIncludePaths=Fachbereiche\*;Shares\Produktion\*;\\server\dfs\namespace\link\*
|
||||||
```
|
|
||||||
|
|
||||||
### Erweiterbar fuer Schritt 2
|
|
||||||
|
|
||||||
- `NtfsIncludeFolderNames`
|
|
||||||
- `NtfsIncludeRelativePaths`
|
|
||||||
|
|
||||||
Beispiel:
|
|
||||||
|
|
||||||
```text
|
|
||||||
NtfsIncludeRelativePaths=Fachbereiche\*;Shares\Produktion\*
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Matching-Regeln
|
## Matching-Regeln
|
||||||
@@ -61,9 +50,10 @@ Empfohlene Semantik:
|
|||||||
- Trennzeichen fuer Mehrfachwerte: `;`
|
- Trennzeichen fuer Mehrfachwerte: `;`
|
||||||
- Auswertung case-insensitive
|
- Auswertung case-insensitive
|
||||||
- Leerzeichen an Eintraegen vor dem Match trimmen
|
- Leerzeichen an Eintraegen vor dem Match trimmen
|
||||||
- Pfade relativ zu `RootPath` vergleichen
|
- Matching gegen relative Pfade unter `RootPath` und gegen normalisierte absolute UNC-Pfade
|
||||||
- Interne Normalisierung auf konsistente UNC-/Directory-Notation
|
- Interne Normalisierung auf konsistente UNC-/Directory-Notation
|
||||||
- Zunaechst nur einfache Wildcards `*` unterstuetzen, keine freien Regex-Ausdruecke
|
- Zunaechst nur einfache Wildcards `*` unterstuetzen, keine freien Regex-Ausdruecke
|
||||||
|
- Include-Regeln duerfen fuer die Traversierung auch uebergeordnete Pfade freischalten, wenn diese zu einem spaeter passenden Zielpfad fuehren
|
||||||
|
|
||||||
Empfohlene Prioritaet:
|
Empfohlene Prioritaet:
|
||||||
|
|
||||||
@@ -81,8 +71,8 @@ Im NTFS-Provider sollte eine kleine Policy-Schicht entstehen, zum Beispiel:
|
|||||||
|
|
||||||
- `GetAdditionalConfigurationValues(string key)`
|
- `GetAdditionalConfigurationValues(string key)`
|
||||||
- `ShouldTraversePath(string fullPath)`
|
- `ShouldTraversePath(string fullPath)`
|
||||||
- `MatchesFolderNamePolicy(string folderName)`
|
- `MatchesPathPolicy(...)`
|
||||||
- `MatchesRelativePathPolicy(string fullPath)`
|
- `TryMatchPathPolicy(...)`
|
||||||
|
|
||||||
Die Methode `IsAdditionalConfigurationEnabled()` bleibt fuer boolesche Flags bestehen und wird durch Listen-/String-Helfer ergaenzt.
|
Die Methode `IsAdditionalConfigurationEnabled()` bleibt fuer boolesche Flags bestehen und wird durch Listen-/String-Helfer ergaenzt.
|
||||||
|
|
||||||
@@ -98,11 +88,9 @@ Vorteil:
|
|||||||
- kein Umbau der allgemeinen NTFS-Basis erforderlich
|
- kein Umbau der allgemeinen NTFS-Basis erforderlich
|
||||||
- fachliche Wirkung genau dort, wo DataAreas erzeugt werden
|
- fachliche Wirkung genau dort, wo DataAreas erzeugt werden
|
||||||
|
|
||||||
### 3. Spaetere Wiederverwendung fuer Permission-Management
|
### 3. Wiederverwendung fuer Permission-Management
|
||||||
|
|
||||||
Aktuell erlaubt `IsPermissionManagedFolderPath()` jeden als `Folder` klassifizierten Pfad.
|
`IsPermissionManagedFolderPath()` bleibt fachlich auf Folder beschraenkt, verwendet fuer Black-/Whitelist aber dieselbe generische Path-Policy.
|
||||||
|
|
||||||
Wenn ausgeschlossene Ordner spaeter auch nicht mehr fuer Berechtigungs-Provisionierung oder Traverse-Gruppen bearbeitet werden sollen, sollte dieselbe Policy dort wiederverwendet werden.
|
|
||||||
|
|
||||||
Damit wird vermieden, dass ein Ordner zwar nicht mehr als DataArea sichtbar ist, aber weiterhin im Permission-Flow auftaucht.
|
Damit wird vermieden, dass ein Ordner zwar nicht mehr als DataArea sichtbar ist, aber weiterhin im Permission-Flow auftaucht.
|
||||||
|
|
||||||
@@ -112,8 +100,7 @@ Nicht Teil des ersten Schritts:
|
|||||||
|
|
||||||
- Umbau von `cNtfsBase` auf generische Filter-Callbacks
|
- Umbau von `cNtfsBase` auf generische Filter-Callbacks
|
||||||
- freie Regex-Konfiguration in `AdditionalConfiguration`
|
- freie Regex-Konfiguration in `AdditionalConfiguration`
|
||||||
- unterschiedliche Regeln fuer Shares, DFS-Links und Folder
|
- unterschiedliche Regeln je Klassifikationstyp
|
||||||
- Policy-Auswertung fuer `LoadDataArea()` ausserhalb des normalen Traversal-Falls
|
|
||||||
|
|
||||||
Diese Themen koennen spaeter folgen, sind aber fuer den initialen Nutzen nicht noetig.
|
Diese Themen koennen spaeter folgen, sind aber fuer den initialen Nutzen nicht noetig.
|
||||||
|
|
||||||
@@ -128,7 +115,7 @@ Fuer ausgeschlossene Pfade sollte auf `Debug` geloggt werden:
|
|||||||
Beispiel:
|
Beispiel:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Skip NTFS path '\\server\share\IT\_disabled' due to AdditionalConfiguration rule 'NtfsExcludeRelativePaths'
|
Skip NTFS path '\\server\share\IT\_disabled' due to AdditionalConfiguration rule 'NtfsExcludePaths=IT\_disabled'
|
||||||
```
|
```
|
||||||
|
|
||||||
Das ist wichtig, damit fehlende DataAreas spaeter im Betrieb nachvollziehbar bleiben.
|
Das ist wichtig, damit fehlende DataAreas spaeter im Betrieb nachvollziehbar bleiben.
|
||||||
@@ -136,13 +123,11 @@ Das ist wichtig, damit fehlende DataAreas spaeter im Betrieb nachvollziehbar ble
|
|||||||
## Empfohlener Umsetzungsplan
|
## Empfohlener Umsetzungsplan
|
||||||
|
|
||||||
1. Listenparser fuer `AdditionalConfiguration` im NTFS-Provider einfuehren.
|
1. Listenparser fuer `AdditionalConfiguration` im NTFS-Provider einfuehren.
|
||||||
2. Pfadnormalisierung und relatives Matching gegen `RootPath` kapseln.
|
2. Pfadnormalisierung und Matching fuer relative sowie absolute Pfade kapseln.
|
||||||
3. `GetChildDataAreasAsync()` um `ShouldTraversePath()` erweitern.
|
3. `GetChildDataAreasAsync()` um `ShouldTraversePath()` erweitern.
|
||||||
4. Debug-Logging fuer Skip-Faelle einfuehren.
|
4. Debug-Logging fuer Skip-Faelle einfuehren.
|
||||||
5. Optional in einem zweiten Schritt dieselbe Policy in `IsPermissionManagedFolderPath()` wiederverwenden.
|
5. Dieselbe Policy in `IsPermissionManagedFolderPath()` und `LoadDataArea()` wiederverwenden.
|
||||||
|
|
||||||
## Kurzfazit
|
## Kurzfazit
|
||||||
|
|
||||||
Fuer den ersten Schritt ist eine blacklist-basierte Pfad-Policy im NTFS-Provider der pragmatischste Weg.
|
Die generische Path-Policy im NTFS-Provider ist klein genug fuer eine risikoarme Implementierung, passt in die vorhandene `AdditionalConfiguration`-Architektur und arbeitet ohne Sonderregeln pro Klassifikationstyp.
|
||||||
|
|
||||||
Sie ist klein genug fuer eine risikoarme Implementierung, passt in die vorhandene `AdditionalConfiguration`-Architektur und laesst sich spaeter ohne Bruch zu einer echten Include-/Exclude-Policy ausbauen.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user