Classify NTFS and DFS data areas
This commit is contained in:
@@ -32,6 +32,7 @@ namespace C4IT.LIAM
|
||||
Unknown = 0,
|
||||
NtfsShare = 101,
|
||||
NtfsFolder = 102,
|
||||
DfsNamespaceRoot = 103,
|
||||
MsTeamsTeam = 401,
|
||||
MsTeamsChannel = 402,
|
||||
MsTeamsFolder = 403,
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
||||
|
||||
using C4IT.Logging;
|
||||
using C4IT.Matrix42.ServerInfo;
|
||||
using C4IT_IAM;
|
||||
using C4IT_IAM_Engine;
|
||||
using C4IT_IAM_SET;
|
||||
using LiamNtfs;
|
||||
@@ -30,9 +31,30 @@ namespace C4IT.LIAM
|
||||
|
||||
public class cLiamProviderNtfs : cLiamProviderBase
|
||||
{
|
||||
private enum eNtfsPathKind
|
||||
{
|
||||
Unknown = 0,
|
||||
ServerRoot = 1,
|
||||
ClassicShare = 2,
|
||||
DfsNamespaceRoot = 3,
|
||||
DfsLink = 4,
|
||||
Folder = 5
|
||||
}
|
||||
|
||||
private sealed class cNtfsPathClassification
|
||||
{
|
||||
public string NormalizedPath { get; set; } = string.Empty;
|
||||
public eNtfsPathKind Kind { get; set; } = eNtfsPathKind.Unknown;
|
||||
public string BoundaryPath { get; set; } = string.Empty;
|
||||
public string ParentBoundaryPath { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public int Level { get; set; } = -1;
|
||||
}
|
||||
|
||||
public static Guid nftsModuleId = new Guid("77e213a1-6517-ea11-4881-000c2980fd94");
|
||||
public readonly cNtfsBase ntfsBase = new cNtfsBase();
|
||||
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
||||
private readonly Dictionary<string, HashSet<string>> publishedShareCache = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
//public readonly bool WithoutPrivateFolders = true;
|
||||
|
||||
@@ -145,40 +167,15 @@ namespace C4IT.LIAM
|
||||
return null;
|
||||
|
||||
var DataAreas = new List<cLiamDataAreaBase>();
|
||||
|
||||
var rootpathSplit = this.RootPath.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
cLiamNtfsShare share = null;
|
||||
cLiamNtfsFolder NtfsRootFolder = null;
|
||||
switch (rootpathSplit.Length)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
var rootClassification = ClassifyPath(this.RootPath);
|
||||
var rootDataArea = await BuildDataAreaAsync(rootClassification);
|
||||
if (rootDataArea == null)
|
||||
return null;
|
||||
case 2:
|
||||
{
|
||||
share = new cLiamNtfsShare(this, new cNtfsResultShare()
|
||||
{
|
||||
DisplayName = rootpathSplit.Last(),
|
||||
Path = RootPath,
|
||||
Level = 0
|
||||
});
|
||||
await share.ResolvePermissionGroupsAsync(share.TechnicalName);
|
||||
DataAreas.Add(share);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
NtfsRootFolder = new cLiamNtfsFolder(this, null, null, new cNtfsResultFolder()
|
||||
{
|
||||
DisplayName = rootpathSplit.Last(),
|
||||
Path = RootPath,
|
||||
Level = 0
|
||||
});
|
||||
await NtfsRootFolder.ResolvePermissionGroupsAsync(NtfsRootFolder.TechnicalName);
|
||||
DataAreas.Add(NtfsRootFolder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DataAreas.Add(rootDataArea);
|
||||
|
||||
if (Depth == 0)
|
||||
return DataAreas;
|
||||
|
||||
var DAL = await ntfsBase.RequestFoldersListAsync(this.RootPath, Depth);
|
||||
if (DAL == null)
|
||||
@@ -189,10 +186,10 @@ namespace C4IT.LIAM
|
||||
if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Value.DisplayName, this.DataAreaRegEx).Success)
|
||||
continue;
|
||||
|
||||
|
||||
var Folder = new cLiamNtfsFolder(this, share, NtfsRootFolder, (cNtfsResultFolder)Entry.Value);
|
||||
await Folder.ResolvePermissionGroupsAsync(Folder.TechnicalName);
|
||||
DataAreas.Add(Folder);
|
||||
var classification = ClassifyPath(Entry.Value.Path);
|
||||
var dataArea = await BuildDataAreaAsync(classification, Entry.Value as cNtfsResultFolder);
|
||||
if (dataArea != null)
|
||||
DataAreas.Add(dataArea);
|
||||
}
|
||||
return DataAreas;
|
||||
}
|
||||
@@ -209,7 +206,6 @@ namespace C4IT.LIAM
|
||||
}
|
||||
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
|
||||
{
|
||||
//TODO implement LoadDataArea
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
@@ -222,36 +218,8 @@ namespace C4IT.LIAM
|
||||
}
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
var splt = UID.Split(System.IO.Path.DirectorySeparatorChar);
|
||||
var name = Path.GetDirectoryName(UID);
|
||||
switch (splt.Length)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
return null;
|
||||
case 2:
|
||||
{
|
||||
var share = new cLiamNtfsShare(this, new cNtfsResultShare()
|
||||
{
|
||||
DisplayName = name,
|
||||
Path = UID,
|
||||
Level = getDepth(UID)
|
||||
});
|
||||
await share.ResolvePermissionGroupsAsync(share.TechnicalName);
|
||||
return share;
|
||||
}
|
||||
default:
|
||||
{
|
||||
var folder = new cLiamNtfsFolder(this, null, null, new cNtfsResultFolder()
|
||||
{
|
||||
DisplayName = name,
|
||||
Path = UID,
|
||||
Level = getDepth(UID)
|
||||
});
|
||||
await folder.ResolvePermissionGroupsAsync(folder.TechnicalName);
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
var classification = ClassifyPath(UID);
|
||||
return await BuildDataAreaAsync(classification);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -265,6 +233,208 @@ namespace C4IT.LIAM
|
||||
|
||||
}
|
||||
|
||||
private async Task<cLiamDataAreaBase> BuildDataAreaAsync(cNtfsPathClassification classification, cNtfsResultFolder folderResult = null)
|
||||
{
|
||||
if (classification == null)
|
||||
return null;
|
||||
|
||||
switch (classification.Kind)
|
||||
{
|
||||
case eNtfsPathKind.ClassicShare:
|
||||
case eNtfsPathKind.DfsLink:
|
||||
{
|
||||
var share = new cLiamNtfsShare(this, new cNtfsResultShare()
|
||||
{
|
||||
DisplayName = classification.DisplayName,
|
||||
Path = classification.NormalizedPath,
|
||||
Level = classification.Level
|
||||
}, classification.ParentBoundaryPath);
|
||||
await share.ResolvePermissionGroupsAsync(share.TechnicalName);
|
||||
return share;
|
||||
}
|
||||
case eNtfsPathKind.DfsNamespaceRoot:
|
||||
{
|
||||
var namespaceRoot = new cLiamNtfsDfsNamespaceRoot(this, new cNtfsResultShare()
|
||||
{
|
||||
DisplayName = classification.DisplayName,
|
||||
Path = classification.NormalizedPath,
|
||||
Level = classification.Level
|
||||
});
|
||||
await namespaceRoot.ResolvePermissionGroupsAsync(namespaceRoot.TechnicalName);
|
||||
return namespaceRoot;
|
||||
}
|
||||
case eNtfsPathKind.Folder:
|
||||
{
|
||||
var folderData = folderResult ?? new cNtfsResultFolder()
|
||||
{
|
||||
DisplayName = classification.DisplayName,
|
||||
Path = classification.NormalizedPath,
|
||||
Level = classification.Level,
|
||||
CreatedDate = Directory.Exists(classification.NormalizedPath)
|
||||
? new DirectoryInfo(classification.NormalizedPath).CreationTimeUtc.ToString("s")
|
||||
: DateTime.MinValue.ToString("s")
|
||||
};
|
||||
var folder = new cLiamNtfsFolder(this, null, null, folderData, classification.ParentBoundaryPath);
|
||||
await folder.ResolvePermissionGroupsAsync(folder.TechnicalName);
|
||||
return folder;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private cNtfsPathClassification ClassifyPath(string path)
|
||||
{
|
||||
var normalizedPath = NormalizeUncPath(path);
|
||||
var segments = GetUncSegments(normalizedPath);
|
||||
var classification = new cNtfsPathClassification()
|
||||
{
|
||||
NormalizedPath = normalizedPath,
|
||||
DisplayName = GetDisplayName(normalizedPath),
|
||||
Level = getDepth(normalizedPath)
|
||||
};
|
||||
|
||||
if (segments.Length == 1)
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.ServerRoot;
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (segments.Length < 2)
|
||||
return classification;
|
||||
|
||||
var serverName = segments[0];
|
||||
var publishedShares = GetPublishedShareNames(serverName);
|
||||
var firstBoundaryPath = BuildUncPath(segments, 2);
|
||||
|
||||
if (segments.Length == 2)
|
||||
{
|
||||
if (publishedShares.Contains(segments[1]))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.ClassicShare;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (Directory.Exists(normalizedPath))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.DfsNamespaceRoot;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (publishedShares.Contains(segments[1]))
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.BoundaryPath = firstBoundaryPath;
|
||||
classification.ParentBoundaryPath = segments.Length == 3
|
||||
? firstBoundaryPath
|
||||
: BuildUncPath(segments, segments.Length - 1);
|
||||
return classification;
|
||||
}
|
||||
|
||||
if (Directory.Exists(firstBoundaryPath))
|
||||
{
|
||||
if (segments.Length == 3)
|
||||
{
|
||||
classification.Kind = eNtfsPathKind.DfsLink;
|
||||
classification.BoundaryPath = normalizedPath;
|
||||
classification.ParentBoundaryPath = firstBoundaryPath;
|
||||
return classification;
|
||||
}
|
||||
|
||||
classification.Kind = eNtfsPathKind.Folder;
|
||||
classification.BoundaryPath = BuildUncPath(segments, 3);
|
||||
classification.ParentBoundaryPath = segments.Length == 4
|
||||
? BuildUncPath(segments, 3)
|
||||
: BuildUncPath(segments, segments.Length - 1);
|
||||
return classification;
|
||||
}
|
||||
|
||||
return classification;
|
||||
}
|
||||
|
||||
private string NormalizeUncPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return string.Empty;
|
||||
|
||||
var segments = path.Trim().Replace('/', '\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
return @"\\" + string.Join("\\", segments);
|
||||
}
|
||||
|
||||
private string[] GetUncSegments(string path)
|
||||
{
|
||||
var normalized = NormalizeUncPath(path);
|
||||
return normalized.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
private string BuildUncPath(string[] segments, int segmentCount)
|
||||
{
|
||||
if (segments == null || segmentCount <= 0 || segments.Length < segmentCount)
|
||||
return string.Empty;
|
||||
|
||||
return @"\\" + string.Join("\\", segments.Take(segmentCount));
|
||||
}
|
||||
|
||||
private string GetDisplayName(string path)
|
||||
{
|
||||
var segments = GetUncSegments(path);
|
||||
if (segments.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
return segments.Last();
|
||||
}
|
||||
|
||||
private HashSet<string> GetPublishedShareNames(string serverName)
|
||||
{
|
||||
HashSet<string> shares;
|
||||
if (publishedShareCache.TryGetValue(serverName, out shares))
|
||||
return shares;
|
||||
|
||||
shares = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
try
|
||||
{
|
||||
using (var connection = new cNetworkConnection(this.RootPath, this.Credential?.Identification, this.Credential?.Secret))
|
||||
{
|
||||
foreach (var share in connection.EnumNetShares(serverName))
|
||||
{
|
||||
if (!IsVisibleDiskShare(share))
|
||||
continue;
|
||||
|
||||
shares.Add(share.shi1_netname);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
|
||||
publishedShareCache[serverName] = shares;
|
||||
return shares;
|
||||
}
|
||||
|
||||
private bool IsVisibleDiskShare(C4IT_IAM.SHARE_INFO_1 share)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(share.shi1_netname))
|
||||
return false;
|
||||
|
||||
if (share.shi1_netname.StartsWith("ERROR=", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (share.shi1_netname.EndsWith("$", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
var shareType = share.shi1_type & 0xFF;
|
||||
return shareType == (uint)C4IT_IAM.SHARE_TYPE.STYPE_DISKTREE;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
|
||||
{
|
||||
|
||||
@@ -689,7 +859,7 @@ namespace C4IT.LIAM
|
||||
{
|
||||
private readonly cNtfsResultBase Share = null;
|
||||
|
||||
public cLiamNtfsShare(cLiamProviderNtfs Provider, cNtfsResultBase Share) :
|
||||
public cLiamNtfsShare(cLiamProviderNtfs Provider, cNtfsResultBase Share, string parentPath = null) :
|
||||
base(Provider)
|
||||
{
|
||||
this.Share = Share;
|
||||
@@ -701,6 +871,8 @@ namespace C4IT.LIAM
|
||||
this.DataType = eLiamDataAreaTypes.NtfsShare;
|
||||
if (Directory.Exists(Share.Path))
|
||||
this.CreatedDate = new DirectoryInfo(Share.Path).CreationTimeUtc.ToString("s");
|
||||
if (!string.IsNullOrWhiteSpace(parentPath))
|
||||
this.ParentUID = cLiamNtfsFolder.GetUniqueDataAreaID(parentPath);
|
||||
}
|
||||
|
||||
internal async Task<List<cLiamDataAreaBase>> getFolders()
|
||||
@@ -746,6 +918,30 @@ namespace C4IT.LIAM
|
||||
}
|
||||
|
||||
}
|
||||
public class cLiamNtfsDfsNamespaceRoot : cLiamNtfsPermissionDataAreaBase
|
||||
{
|
||||
private readonly cNtfsResultBase NamespaceRoot = null;
|
||||
|
||||
public cLiamNtfsDfsNamespaceRoot(cLiamProviderNtfs Provider, cNtfsResultBase NamespaceRoot) :
|
||||
base(Provider)
|
||||
{
|
||||
this.NamespaceRoot = NamespaceRoot;
|
||||
|
||||
this.DisplayName = NamespaceRoot.Path.Split('\\').Last();
|
||||
this.TechnicalName = NamespaceRoot.Path;
|
||||
this.UID = cLiamNtfsFolder.GetUniqueDataAreaID(NamespaceRoot.Path);
|
||||
this.Level = NamespaceRoot.Level;
|
||||
this.DataType = eLiamDataAreaTypes.DfsNamespaceRoot;
|
||||
if (Directory.Exists(NamespaceRoot.Path))
|
||||
this.CreatedDate = new DirectoryInfo(NamespaceRoot.Path).CreationTimeUtc.ToString("s");
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
return new List<cLiamDataAreaBase>();
|
||||
}
|
||||
}
|
||||
public class cLiamAdGroup : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderNtfs Provider = null;
|
||||
@@ -768,7 +964,7 @@ namespace C4IT.LIAM
|
||||
{
|
||||
public readonly cLiamNtfsShare Share = null;
|
||||
public readonly cLiamNtfsFolder NtfsRootFolder = null;
|
||||
public cLiamNtfsFolder(cLiamProviderNtfs Provider, cLiamNtfsShare share, cLiamNtfsFolder ntfsRootFolder, cNtfsResultFolder NtfsFolder) : base(Provider)
|
||||
public cLiamNtfsFolder(cLiamProviderNtfs Provider, cLiamNtfsShare share, cLiamNtfsFolder ntfsRootFolder, cNtfsResultFolder NtfsFolder, string parentPathOverride = null) : base(Provider)
|
||||
{
|
||||
var ntfsParent = NtfsFolder.Parent;
|
||||
this.NtfsRootFolder = ntfsRootFolder;
|
||||
@@ -787,6 +983,8 @@ namespace C4IT.LIAM
|
||||
{
|
||||
this.ParentUID = GetUniqueDataAreaID(this.Provider.RootPath);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(this.ParentUID) && !string.IsNullOrWhiteSpace(parentPathOverride))
|
||||
this.ParentUID = GetUniqueDataAreaID(parentPathOverride);
|
||||
}
|
||||
|
||||
public static string GetUniqueDataAreaID(string fullPath)
|
||||
|
||||
@@ -628,7 +628,7 @@ namespace LiamWorkflowActivities
|
||||
if (!IsAdditionalConfigurationEnabled(providerEntry.Provider, "EnsureNtfsPermissionGroups"))
|
||||
return true;
|
||||
|
||||
foreach (var ntfsArea in dataAreas.OfType<cLiamNtfsPermissionDataAreaBase>())
|
||||
foreach (var ntfsArea in dataAreas.OfType<cLiamNtfsFolder>())
|
||||
{
|
||||
var folderPath = ntfsArea.TechnicalName;
|
||||
if (string.IsNullOrWhiteSpace(folderPath))
|
||||
|
||||
Reference in New Issue
Block a user