Add classified NTFS path template placeholders
This commit is contained in:
@@ -1342,6 +1342,9 @@ namespace C4IT.LIAM
|
|||||||
$"NTFS filesystem engine creation stage. Stage=Start Path='{folderPath}', ParentPath='{parentFolderPath}'",
|
$"NTFS filesystem engine creation stage. Stage=Start Path='{folderPath}', ParentPath='{parentFolderPath}'",
|
||||||
LogLevels.Debug);
|
LogLevels.Debug);
|
||||||
|
|
||||||
|
var groupNameSanitizeReplacement = GetAdditionalConfigurationValueOrDefault(
|
||||||
|
AdditionalConfigurationGroupNameSanitizeReplacementKey,
|
||||||
|
Helper.DefaultGroupNameSanitizeReplacement);
|
||||||
var requiresDomainLocalTag = this.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP
|
var requiresDomainLocalTag = this.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP
|
||||||
|| (NamingConventions ?? Enumerable.Empty<cLiamNamingConvention>())
|
|| (NamingConventions ?? Enumerable.Empty<cLiamNamingConvention>())
|
||||||
.Any(i => i.Scope == eLiamAccessRoleScopes.DomainLocal);
|
.Any(i => i.Scope == eLiamAccessRoleScopes.DomainLocal);
|
||||||
@@ -1398,9 +1401,8 @@ namespace C4IT.LIAM
|
|||||||
engine.forceStrictAdGroupNames = IsAdditionalConfigurationEnabled("ForceStrictAdGroupNames");
|
engine.forceStrictAdGroupNames = IsAdditionalConfigurationEnabled("ForceStrictAdGroupNames");
|
||||||
engine.adGroupReuseMode = GetAdGroupReuseMode();
|
engine.adGroupReuseMode = GetAdGroupReuseMode();
|
||||||
engine.adGroupMarkerBackfill = IsAdditionalConfigurationEnabled(AdditionalConfigurationAdGroupMarkerBackfillKey);
|
engine.adGroupMarkerBackfill = IsAdditionalConfigurationEnabled(AdditionalConfigurationAdGroupMarkerBackfillKey);
|
||||||
engine.groupNameSanitizeReplacement = GetAdditionalConfigurationValueOrDefault(
|
engine.groupNameSanitizeReplacement = groupNameSanitizeReplacement;
|
||||||
AdditionalConfigurationGroupNameSanitizeReplacementKey,
|
engine.GetTemplateContextForPath = path => GetTemplateContextForPath(path, groupNameSanitizeReplacement);
|
||||||
Helper.DefaultGroupNameSanitizeReplacement);
|
|
||||||
engine.preserveAdGroupNameCase = IsAdditionalConfigurationEnabled(AdditionalConfigurationPreserveAdGroupNameCaseKey);
|
engine.preserveAdGroupNameCase = IsAdditionalConfigurationEnabled(AdditionalConfigurationPreserveAdGroupNameCaseKey);
|
||||||
engine.OwnerACLPermission = this.OwnerACLPermission;
|
engine.OwnerACLPermission = this.OwnerACLPermission;
|
||||||
engine.WriteACLPermission = this.WriteACLPermission;
|
engine.WriteACLPermission = this.WriteACLPermission;
|
||||||
@@ -1427,6 +1429,50 @@ namespace C4IT.LIAM
|
|||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Helper.RootPathTemplateContext GetTemplateContextForPath(string path, string groupNameSanitizeReplacement)
|
||||||
|
{
|
||||||
|
var context = Helper.GetRootPathTemplateContext(this.RootPath, groupNameSanitizeReplacement);
|
||||||
|
var normalizedPath = NormalizeUncPath(path);
|
||||||
|
var segments = GetUncSegments(normalizedPath);
|
||||||
|
if (segments.Length > 0)
|
||||||
|
context.ServerName = Helper.SanitizePathSegment(segments[0], groupNameSanitizeReplacement);
|
||||||
|
|
||||||
|
var classification = ClassifyPath(normalizedPath);
|
||||||
|
var dfsPrefixes = GetDfsObjectPrefixes(normalizedPath);
|
||||||
|
if (dfsPrefixes.Count > 0)
|
||||||
|
{
|
||||||
|
context.DfsNamespaceName = GetLastSanitizedPathSegment(dfsPrefixes[0], groupNameSanitizeReplacement);
|
||||||
|
|
||||||
|
if (classification != null && classification.Kind != eNtfsPathKind.DfsNamespaceRoot)
|
||||||
|
context.ShareName = GetLastSanitizedPathSegment(classification.BoundaryPath, groupNameSanitizeReplacement);
|
||||||
|
else
|
||||||
|
context.ShareName = string.Empty;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classification != null
|
||||||
|
&& !string.IsNullOrWhiteSpace(classification.BoundaryPath)
|
||||||
|
&& (classification.Kind == eNtfsPathKind.ClassicShare || classification.Kind == eNtfsPathKind.Folder))
|
||||||
|
{
|
||||||
|
context.ShareName = GetLastSanitizedPathSegment(classification.BoundaryPath, groupNameSanitizeReplacement);
|
||||||
|
}
|
||||||
|
else if (segments.Length > 1)
|
||||||
|
{
|
||||||
|
context.ShareName = Helper.SanitizePathSegment(segments[1], groupNameSanitizeReplacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLastSanitizedPathSegment(string path, string groupNameSanitizeReplacement)
|
||||||
|
{
|
||||||
|
var segments = GetUncSegments(path);
|
||||||
|
return segments.Length == 0
|
||||||
|
? string.Empty
|
||||||
|
: Helper.SanitizePathSegment(segments[segments.Length - 1], groupNameSanitizeReplacement);
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsAdditionalConfigurationEnabled(string key)
|
private bool IsAdditionalConfigurationEnabled(string key)
|
||||||
{
|
{
|
||||||
if (AdditionalConfiguration == null || string.IsNullOrWhiteSpace(key))
|
if (AdditionalConfiguration == null || string.IsNullOrWhiteSpace(key))
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ namespace C4IT_IAM_SET
|
|||||||
public string groupNameSanitizeReplacement = Helper.DefaultGroupNameSanitizeReplacement;
|
public string groupNameSanitizeReplacement = Helper.DefaultGroupNameSanitizeReplacement;
|
||||||
public bool preserveAdGroupNameCase;
|
public bool preserveAdGroupNameCase;
|
||||||
public bool WhatIf;
|
public bool WhatIf;
|
||||||
|
public Func<string, Helper.RootPathTemplateContext> GetTemplateContextForPath;
|
||||||
|
|
||||||
public int ReadACLPermission = cLiamAclPermissionDefaults.Read;
|
public int ReadACLPermission = cLiamAclPermissionDefaults.Read;
|
||||||
public int WriteACLPermission = cLiamAclPermissionDefaults.Write;
|
public int WriteACLPermission = cLiamAclPermissionDefaults.Write;
|
||||||
@@ -331,6 +332,12 @@ namespace C4IT_IAM_SET
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Helper.RootPathTemplateContext GetEffectiveTemplateContext(string path)
|
||||||
|
{
|
||||||
|
return GetTemplateContextForPath?.Invoke(path)
|
||||||
|
?? Helper.GetRootPathTemplateContext(baseFolder, groupNameSanitizeReplacement);
|
||||||
|
}
|
||||||
|
|
||||||
private ResultToken ValidateTraverseBoundaryForCurrentFolder()
|
private ResultToken ValidateTraverseBoundaryForCurrentFolder()
|
||||||
{
|
{
|
||||||
var resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString());
|
var resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString());
|
||||||
@@ -569,7 +576,8 @@ namespace C4IT_IAM_SET
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
groupNameSanitizeReplacement,
|
groupNameSanitizeReplacement,
|
||||||
preserveAdGroupNameCase);
|
preserveAdGroupNameCase,
|
||||||
|
GetEffectiveTemplateContext(newDataArea.IAM_Folders[0].technicalName));
|
||||||
|
|
||||||
var existingGroups = new List<IAM_SecurityGroup>();
|
var existingGroups = new List<IAM_SecurityGroup>();
|
||||||
foreach (var securityGroup in newSecurityGroups.IAM_SecurityGroups)
|
foreach (var securityGroup in newSecurityGroups.IAM_SecurityGroups)
|
||||||
@@ -803,7 +811,7 @@ namespace C4IT_IAM_SET
|
|||||||
? sanitizedSegments[sanitizedSegments.Length - 1]
|
? sanitizedSegments[sanitizedSegments.Length - 1]
|
||||||
: Helper.SanitizePathSegment(Path.GetFileName(parent.FullName.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)), groupNameSanitizeReplacement);
|
: Helper.SanitizePathSegment(Path.GetFileName(parent.FullName.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)), groupNameSanitizeReplacement);
|
||||||
var traverseTags = GetTraverseReplacementTags(parent.FullName, traverseGroupTemplate.Scope);
|
var traverseTags = GetTraverseReplacementTags(parent.FullName, traverseGroupTemplate.Scope);
|
||||||
var rootContext = Helper.GetRootPathTemplateContext(baseFolder, groupNameSanitizeReplacement);
|
var rootContext = GetEffectiveTemplateContext(parent.FullName);
|
||||||
var boundedTraverseContext = Helper.GetBoundedAdGroupTemplateContext(
|
var boundedTraverseContext = Helper.GetBoundedAdGroupTemplateContext(
|
||||||
traverseGroupTemplate.NamingTemplate,
|
traverseGroupTemplate.NamingTemplate,
|
||||||
true,
|
true,
|
||||||
@@ -1605,7 +1613,8 @@ namespace C4IT_IAM_SET
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
groupNameSanitizeReplacement,
|
groupNameSanitizeReplacement,
|
||||||
preserveAdGroupNameCase);
|
preserveAdGroupNameCase,
|
||||||
|
GetEffectiveTemplateContext(newDataArea.IAM_Folders[0].technicalName));
|
||||||
|
|
||||||
List<UserPrincipal> owners = getUserPrincipalBySid(ownerUserSids);
|
List<UserPrincipal> owners = getUserPrincipalBySid(ownerUserSids);
|
||||||
List<UserPrincipal> writers = getUserPrincipalBySid(writerUserSids);
|
List<UserPrincipal> writers = getUserPrincipalBySid(writerUserSids);
|
||||||
@@ -1771,7 +1780,8 @@ namespace C4IT_IAM_SET
|
|||||||
existingADGroupCount,
|
existingADGroupCount,
|
||||||
0,
|
0,
|
||||||
groupNameSanitizeReplacement,
|
groupNameSanitizeReplacement,
|
||||||
preserveAdGroupNameCase);
|
preserveAdGroupNameCase,
|
||||||
|
GetEffectiveTemplateContext(newDataArea.IAM_Folders[0].technicalName));
|
||||||
/*
|
/*
|
||||||
if (existingADGroupCount > 0 && !templates.All(t => t.Type == SecurityGroupType.Traverse || Regex.IsMatch(t.NamingTemplate, @"(?<loopTag>{{(?<prefix>[^}]*)(?<loop>LOOP)(?<postfix>[^{]*)}})")))
|
if (existingADGroupCount > 0 && !templates.All(t => t.Type == SecurityGroupType.Traverse || Regex.IsMatch(t.NamingTemplate, @"(?<loopTag>{{(?<prefix>[^}]*)(?<loop>LOOP)(?<postfix>[^{]*)}})")))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ namespace C4IT_IAM_Engine
|
|||||||
public sealed class RootPathTemplateContext
|
public sealed class RootPathTemplateContext
|
||||||
{
|
{
|
||||||
public string Server { get; set; } = string.Empty;
|
public string Server { get; set; } = string.Empty;
|
||||||
|
public string ServerName { get; set; } = string.Empty;
|
||||||
|
public string DfsNamespaceName { get; set; } = string.Empty;
|
||||||
|
public string ShareName { get; set; } = string.Empty;
|
||||||
public string[] Segments { get; set; } = Array.Empty<string>();
|
public string[] Segments { get; set; } = Array.Empty<string>();
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public string Path { get; set; } = string.Empty;
|
public string Path { get; set; } = string.Empty;
|
||||||
@@ -109,6 +112,8 @@ namespace C4IT_IAM_Engine
|
|||||||
return new RootPathTemplateContext
|
return new RootPathTemplateContext
|
||||||
{
|
{
|
||||||
Server = server,
|
Server = server,
|
||||||
|
ServerName = server,
|
||||||
|
ShareName = sanitizedPathSegments.Length == 0 ? string.Empty : sanitizedPathSegments[sanitizedPathSegments.Length - 1],
|
||||||
Segments = sanitizedPathSegments,
|
Segments = sanitizedPathSegments,
|
||||||
Name = sanitizedPathSegments.Length == 0 ? string.Empty : sanitizedPathSegments[sanitizedPathSegments.Length - 1],
|
Name = sanitizedPathSegments.Length == 0 ? string.Empty : sanitizedPathSegments[sanitizedPathSegments.Length - 1],
|
||||||
Path = sanitizedPathSegments.Length == 0 ? string.Empty : JoinSanitizedPathSegments(sanitizedPathSegments, groupNameSanitizeReplacement),
|
Path = sanitizedPathSegments.Length == 0 ? string.Empty : JoinSanitizedPathSegments(sanitizedPathSegments, groupNameSanitizeReplacement),
|
||||||
@@ -308,6 +313,9 @@ namespace C4IT_IAM_Engine
|
|||||||
|
|
||||||
var context = rootContext ?? new RootPathTemplateContext();
|
var context = rootContext ?? new RootPathTemplateContext();
|
||||||
var result = Regex.Replace(templateValue, @"{{\s*ROOT_SERVER\s*}}", context.Server ?? string.Empty, RegexOptions.IgnoreCase);
|
var result = Regex.Replace(templateValue, @"{{\s*ROOT_SERVER\s*}}", context.Server ?? string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
result = Regex.Replace(result, @"{{\s*SERVER_NAME\s*}}", context.ServerName ?? context.Server ?? string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
result = Regex.Replace(result, @"{{\s*DFS_NAMESPACE_NAME\s*}}", context.DfsNamespaceName ?? string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
result = Regex.Replace(result, @"{{\s*SHARE_NAME\s*}}", context.ShareName ?? string.Empty, RegexOptions.IgnoreCase);
|
||||||
result = Regex.Replace(result, @"{{\s*ROOT_NAME\s*}}", context.Name ?? string.Empty, RegexOptions.IgnoreCase);
|
result = Regex.Replace(result, @"{{\s*ROOT_NAME\s*}}", context.Name ?? string.Empty, RegexOptions.IgnoreCase);
|
||||||
result = Regex.Replace(result, @"{{\s*ROOT_PATH(?:\s*\(\s*(\d+)\s*\))?\s*}}", match =>
|
result = Regex.Replace(result, @"{{\s*ROOT_PATH(?:\s*\(\s*(\d+)\s*\))?\s*}}", match =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -142,7 +142,8 @@ namespace C4IT_IAM_Engine
|
|||||||
int loop = 0,
|
int loop = 0,
|
||||||
int existingADGroupCount = 0,
|
int existingADGroupCount = 0,
|
||||||
string groupNameSanitizeReplacement = Helper.DefaultGroupNameSanitizeReplacement,
|
string groupNameSanitizeReplacement = Helper.DefaultGroupNameSanitizeReplacement,
|
||||||
bool preserveAdGroupNameCase = false)
|
bool preserveAdGroupNameCase = false,
|
||||||
|
Helper.RootPathTemplateContext templateContext = null)
|
||||||
{
|
{
|
||||||
LogMethodBegin(MethodBase.GetCurrentMethod());
|
LogMethodBegin(MethodBase.GetCurrentMethod());
|
||||||
try
|
try
|
||||||
@@ -163,7 +164,7 @@ namespace C4IT_IAM_Engine
|
|||||||
var folderName = sanitizedSegments.Length > 0
|
var folderName = sanitizedSegments.Length > 0
|
||||||
? sanitizedSegments[sanitizedSegments.Length - 1]
|
? sanitizedSegments[sanitizedSegments.Length - 1]
|
||||||
: Helper.SanitizePathSegment(Path.GetFileName(newFolderPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)), groupNameSanitizeReplacement);
|
: Helper.SanitizePathSegment(Path.GetFileName(newFolderPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)), groupNameSanitizeReplacement);
|
||||||
var rootContext = Helper.GetRootPathTemplateContext(baseFolder, groupNameSanitizeReplacement);
|
var rootContext = templateContext ?? Helper.GetRootPathTemplateContext(baseFolder, groupNameSanitizeReplacement);
|
||||||
|
|
||||||
foreach (var template in resolvedTemplates)
|
foreach (var template in resolvedTemplates)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ Die wichtigsten Eingaben fuer die Ersetzung sind:
|
|||||||
| `{{RELATIVEPATH(0)}}` | Letztes relatives Pfadsegment. | `test33` |
|
| `{{RELATIVEPATH(0)}}` | Letztes relatives Pfadsegment. | `test33` |
|
||||||
| `{{RELATIVEPATH(1)}}` | Die letzten zwei relativen Pfadsegmente. Bei weniger Segmenten werden alle vorhandenen verwendet. | z. B. `team1_test33` |
|
| `{{RELATIVEPATH(1)}}` | Die letzten zwei relativen Pfadsegmente. Bei weniger Segmenten werden alle vorhandenen verwendet. | z. B. `team1_test33` |
|
||||||
| `{{ROOT_SERVER}}` | Server-/Namespace-Teil des UNC-RootPath. | `server` |
|
| `{{ROOT_SERVER}}` | Server-/Namespace-Teil des UNC-RootPath. | `server` |
|
||||||
|
| `{{SERVER_NAME}}` | Server-/Namespace-Teil des aktuell verarbeiteten UNC-Pfads. | `server` |
|
||||||
|
| `{{DFS_NAMESPACE_NAME}}` | Name des DFS-Namespaces, wenn der aktuelle Pfad in einem DFS-Namespace liegt. | `File_Shares` |
|
||||||
|
| `{{SHARE_NAME}}` | Klassifizierter Share-Name: klassischer Share oder DFS-Link, in dem die aktuelle DataArea liegt. | `share2` |
|
||||||
| `{{ROOT_NAME}}` | Letztes Segment des RootPath. | `share2` |
|
| `{{ROOT_NAME}}` | Letztes Segment des RootPath. | `share2` |
|
||||||
| `{{ROOT_PATH}}` | Alle RootPath-Segmente ohne Server, mit Segmenttrenner verbunden. | `file_shares_share2` |
|
| `{{ROOT_PATH}}` | Alle RootPath-Segmente ohne Server, mit Segmenttrenner verbunden. | `file_shares_share2` |
|
||||||
| `{{ROOT_PATH(1)}}` | Letztes RootPath-Segment. | `share2` |
|
| `{{ROOT_PATH(1)}}` | Letztes RootPath-Segment. | `share2` |
|
||||||
@@ -31,6 +34,8 @@ Die wichtigsten Eingaben fuer die Ersetzung sind:
|
|||||||
|
|
||||||
`{{RELATIVEPATH(n)}}` zaehlt von hinten: `0` ist das letzte Segment, `1` sind die letzten zwei Segmente, `2` die letzten drei Segmente usw. `{{ROOT_PATH(n)}}` verwendet dagegen die letzten `n` Segmente des RootPath.
|
`{{RELATIVEPATH(n)}}` zaehlt von hinten: `0` ist das letzte Segment, `1` sind die letzten zwei Segmente, `2` die letzten drei Segmente usw. `{{ROOT_PATH(n)}}` verwendet dagegen die letzten `n` Segmente des RootPath.
|
||||||
|
|
||||||
|
`{{ROOT_*}}` bezieht sich immer auf den konfigurierten `RootPath`. `{{SERVER_NAME}}`, `{{DFS_NAMESPACE_NAME}}` und `{{SHARE_NAME}}` werden dagegen anhand der NTFS-Pfadklassifizierung des aktuell verarbeiteten Pfads ermittelt. Bei einem klassischen Share ist `{{SHARE_NAME}}` der Share. Bei DFS ist `{{DFS_NAMESPACE_NAME}}` der Namespace und `{{SHARE_NAME}}` der DFS-Link.
|
||||||
|
|
||||||
Wenn die aktuelle DataArea dem `RootPath` selbst entspricht, ist `{{RELATIVEPATH}}` leer. `{{NAME}}` ist dann der Name des RootPath, also z. B. `share2` oder `LEI.01.test`.
|
Wenn die aktuelle DataArea dem `RootPath` selbst entspricht, ist `{{RELATIVEPATH}}` leer. `{{NAME}}` ist dann der Name des RootPath, also z. B. `share2` oder `LEI.01.test`.
|
||||||
|
|
||||||
### Rollen- und Scope-Platzhalter
|
### Rollen- und Scope-Platzhalter
|
||||||
|
|||||||
Reference in New Issue
Block a user