From 61bca1bcbabf592aa22ef2d2fc9598ad5d05e159 Mon Sep 17 00:00:00 2001 From: Marcio Date: Wed, 20 Sep 2023 00:18:58 -0300 Subject: [PATCH] Add project files. --- .dockerignore | 25 +++ ActiveDirectoryToRestApi.sln | 31 +++ LICENSE | 21 +++ README.md | 3 + .../ActiveDirectoryToRestApi.csproj | 18 ++ .../Configurations/LdapConfigs.cs | 10 + .../Controllers/GroupController.cs | 26 +++ .../Controllers/UserController.cs | 50 +++++ src/ActiveDirectoryToRestApi/Dockerfile | 20 ++ .../Extensions/LdapAttrExtensions.cs | 56 ++++++ src/ActiveDirectoryToRestApi/GlobalUsings.cs | 9 + src/ActiveDirectoryToRestApi/Models/Group.cs | 9 + src/ActiveDirectoryToRestApi/Models/User.cs | 20 ++ .../Models/UserLogin.cs | 12 ++ src/ActiveDirectoryToRestApi/Program.cs | 31 +++ .../Properties/launchSettings.json | 40 ++++ .../Services/AuthUserService.cs | 32 ++++ .../Services/LdapService.cs | 177 ++++++++++++++++++ .../appsettings.Development.json | 8 + src/ActiveDirectoryToRestApi/appsettings.json | 16 ++ 20 files changed, 614 insertions(+) create mode 100644 .dockerignore create mode 100644 ActiveDirectoryToRestApi.sln create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj create mode 100644 src/ActiveDirectoryToRestApi/Configurations/LdapConfigs.cs create mode 100644 src/ActiveDirectoryToRestApi/Controllers/GroupController.cs create mode 100644 src/ActiveDirectoryToRestApi/Controllers/UserController.cs create mode 100644 src/ActiveDirectoryToRestApi/Dockerfile create mode 100644 src/ActiveDirectoryToRestApi/Extensions/LdapAttrExtensions.cs create mode 100644 src/ActiveDirectoryToRestApi/GlobalUsings.cs create mode 100644 src/ActiveDirectoryToRestApi/Models/Group.cs create mode 100644 src/ActiveDirectoryToRestApi/Models/User.cs create mode 100644 src/ActiveDirectoryToRestApi/Models/UserLogin.cs create mode 100644 src/ActiveDirectoryToRestApi/Program.cs create mode 100644 src/ActiveDirectoryToRestApi/Properties/launchSettings.json create mode 100644 src/ActiveDirectoryToRestApi/Services/AuthUserService.cs create mode 100644 src/ActiveDirectoryToRestApi/Services/LdapService.cs create mode 100644 src/ActiveDirectoryToRestApi/appsettings.Development.json create mode 100644 src/ActiveDirectoryToRestApi/appsettings.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/ActiveDirectoryToRestApi.sln b/ActiveDirectoryToRestApi.sln new file mode 100644 index 0000000..ff0c216 --- /dev/null +++ b/ActiveDirectoryToRestApi.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34024.191 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActiveDirectoryToRestApi", "src\ActiveDirectoryToRestApi\ActiveDirectoryToRestApi.csproj", "{2A1D2EF2-8050-48ED-AD6A-0049D800DE39}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{69C1A7CC-CE13-44EC-924A-104C576C2D34}" + ProjectSection(SolutionItems) = preProject + LICENSE = LICENSE + README.md = README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A1D2EF2-8050-48ED-AD6A-0049D800DE39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A1D2EF2-8050-48ED-AD6A-0049D800DE39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A1D2EF2-8050-48ED-AD6A-0049D800DE39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A1D2EF2-8050-48ED-AD6A-0049D800DE39}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D76E9DAF-9C86-445C-B53D-A96BC45CD2C9} + EndGlobalSection +EndGlobal diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f8c464c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 zimbres + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb70287 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# ActiveDirectoryToRestApi + +Rest Api to get some data from Active Directory by LDAP \ No newline at end of file diff --git a/src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj b/src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj new file mode 100644 index 0000000..90dfb15 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj @@ -0,0 +1,18 @@ + + + + net7.0 + disable + enable + Linux + ..\.. + + + + + + + + + + diff --git a/src/ActiveDirectoryToRestApi/Configurations/LdapConfigs.cs b/src/ActiveDirectoryToRestApi/Configurations/LdapConfigs.cs new file mode 100644 index 0000000..07df7c7 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Configurations/LdapConfigs.cs @@ -0,0 +1,10 @@ +namespace ActiveDirectoryToRestApi.Configurations; + +public class LdapConfigs +{ + public string Server { get; set; } + public string DomainName { get; set; } + public string User { get; set; } + public string Pass { get; set; } + public string DistinguishedName { get; set; } +} diff --git a/src/ActiveDirectoryToRestApi/Controllers/GroupController.cs b/src/ActiveDirectoryToRestApi/Controllers/GroupController.cs new file mode 100644 index 0000000..10a0b70 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Controllers/GroupController.cs @@ -0,0 +1,26 @@ +namespace ActiveDirectoryToRestApi.Controllers; + +[ApiController] +[Route("[controller]")] +public class GroupController : ControllerBase +{ + private readonly ILogger _logger; + private readonly LdapService _ldapService; + + public GroupController(ILogger logger, LdapService ldapService) + { + _logger = logger; + _ldapService = ldapService; + } + + [HttpPost("/group")] + public ActionResult Group(string group = "mygroup") + { + var members = _ldapService.GetGroupMembers(group); + if (members == null) + { + return NotFound(); + } + return members; + } +} diff --git a/src/ActiveDirectoryToRestApi/Controllers/UserController.cs b/src/ActiveDirectoryToRestApi/Controllers/UserController.cs new file mode 100644 index 0000000..e450c5c --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Controllers/UserController.cs @@ -0,0 +1,50 @@ +namespace ActiveDirectoryToRestApi.Controllers; + +[ApiController] +[Route("[controller]")] +public class UserController : ControllerBase +{ + private readonly ILogger _logger; + private readonly LdapService _ldapService; + private readonly AuthUserService _authUserService; + + public UserController(ILogger logger, LdapService ldapService, AuthUserService authUserService) + { + _logger = logger; + _ldapService = ldapService; + _authUserService = authUserService; + } + + [HttpPost("/email")] + public ActionResult Email(string email = "test.user@zimbres.com") + { + var user = _ldapService.GetUserByEmail(email); + if (user == null) + { + return NotFound(); + } + return user; + } + + [HttpPost("/username")] + public ActionResult Username(string username = "testUser") + { + var user = _ldapService.GetUserByUserName(username); + if (user == null) + { + return NotFound(); + } + return user; + } + + [HttpPost("/authUser")] + public IActionResult AuthUser(UserLogin userLogin) + { + var status = _authUserService.AuthUser(userLogin.UserName, userLogin.Password); + if (status) + { + return Ok(); + } + return Unauthorized(); + } +} diff --git a/src/ActiveDirectoryToRestApi/Dockerfile b/src/ActiveDirectoryToRestApi/Dockerfile new file mode 100644 index 0000000..7edf0f7 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +RUN apt update && apt install -y --no-install-recommends libldap-2.4-2 && rm -rf /var/lib/apt/lists/* +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /src +COPY ["src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj", "src/ActiveDirectoryToRestApi/"] +RUN dotnet restore "src/ActiveDirectoryToRestApi/ActiveDirectoryToRestApi.csproj" +COPY . . +WORKDIR "/src/src/ActiveDirectoryToRestApi" +RUN dotnet build "ActiveDirectoryToRestApi.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "ActiveDirectoryToRestApi.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "ActiveDirectoryToRestApi.dll"] \ No newline at end of file diff --git a/src/ActiveDirectoryToRestApi/Extensions/LdapAttrExtensions.cs b/src/ActiveDirectoryToRestApi/Extensions/LdapAttrExtensions.cs new file mode 100644 index 0000000..224bb3d --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Extensions/LdapAttrExtensions.cs @@ -0,0 +1,56 @@ +namespace ActiveDirectoryToRestApi.Extensions; + +public static class LdapAttrExtensions +{ + public static string ConvertToDateTime(this string ldapTime) + { + if (ldapTime == "0" || ldapTime == "9223372036854775807") return "Never"; + var date = long.Parse(ldapTime); + + return DateTime.FromFileTime(date).ToString(); + } + + public static bool IsExpired(this string ldapTime) + { + if (ldapTime == "0" || ldapTime == "9223372036854775807") return false; + var expiration = DateTime.FromFileTime(long.Parse(ldapTime)); + if (expiration < DateTime.Now) return true; + + return false; + } + + public static bool IsPasswordExpired(this string userAccountControl) + { + if (userAccountControl == "8388608") return true; + + return false; + } + + public static bool IsEnabled(this string userAccountControl) + { + if (userAccountControl == "512" || userAccountControl == "66048" || userAccountControl == "262656") return true; + + return false; + } + + public static bool IsPasswordNeverExpire(this string userAccountControl) + { + if (userAccountControl == "66048" || userAccountControl == "66050") return true; + + return false; + } + + public static string GroupType(this string groupType) + { + return groupType switch + { + "2" => "Global distribution group", + "4" => "Global distribution group", + "8" => "Universal distribution group", + "-2147483646" => "Global security group", + "-2147483644" => "Domain local security group", + "-2147483640" => "Universal security group", + _ => null, + }; + } +} diff --git a/src/ActiveDirectoryToRestApi/GlobalUsings.cs b/src/ActiveDirectoryToRestApi/GlobalUsings.cs new file mode 100644 index 0000000..368e045 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/GlobalUsings.cs @@ -0,0 +1,9 @@ +global using ActiveDirectoryToRestApi.Configurations; +global using ActiveDirectoryToRestApi.Extensions; +global using ActiveDirectoryToRestApi.Models; +global using ActiveDirectoryToRestApi.Services; +global using Microsoft.AspNetCore.Mvc; +global using System.ComponentModel; +global using System.ComponentModel.DataAnnotations; +global using System.DirectoryServices.Protocols; +global using System.Net; diff --git a/src/ActiveDirectoryToRestApi/Models/Group.cs b/src/ActiveDirectoryToRestApi/Models/Group.cs new file mode 100644 index 0000000..81952c8 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Models/Group.cs @@ -0,0 +1,9 @@ +namespace ActiveDirectoryToRestApi.Models; + +public class Group +{ + public string Name { get; set; } + public string Type { get; set; } + public string DistinguishedName { get; set; } + public List Members { get; set; } = new(); +} diff --git a/src/ActiveDirectoryToRestApi/Models/User.cs b/src/ActiveDirectoryToRestApi/Models/User.cs new file mode 100644 index 0000000..645f8a3 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Models/User.cs @@ -0,0 +1,20 @@ +namespace ActiveDirectoryToRestApi.Models; + +public class User +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string LogonName { get; set; } + public string SamAccountName { get; set; } + public bool Enabled { get; set; } + public bool PasswordNeverExpire { get; set; } + public bool PasswordExpired { get; set; } + public string PasswordLastSet { get; set; } + public string PasswordExpiration { get; set; } + public bool Expired { get; set; } + public string Expiration { get; set; } + public string DistinguishedName { get; set; } + public List Groups { get; set; } +} diff --git a/src/ActiveDirectoryToRestApi/Models/UserLogin.cs b/src/ActiveDirectoryToRestApi/Models/UserLogin.cs new file mode 100644 index 0000000..3328539 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Models/UserLogin.cs @@ -0,0 +1,12 @@ +namespace ActiveDirectoryToRestApi.Models; + +public class UserLogin +{ + [Required] + [DefaultValue("testUser")] + public string UserName { get; set; } + + [Required] + [DefaultValue("Thi$1sMyPassw0rd")] + public string Password { get; set; } +} diff --git a/src/ActiveDirectoryToRestApi/Program.cs b/src/ActiveDirectoryToRestApi/Program.cs new file mode 100644 index 0000000..5b2000a --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Program.cs @@ -0,0 +1,31 @@ +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers(); +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddSingleton(provider => +{ + var configs = builder.Configuration.GetSection(nameof(LdapConfigs)).Get(); + var endpoint = new LdapDirectoryIdentifier(configs.Server, false, false); + var ldapConnection = new LdapConnection(endpoint, + new NetworkCredential($"{configs.User}@{configs.DomainName}", configs.Pass)) + { + AuthType = AuthType.Basic + }; + ldapConnection.SessionOptions.ReferralChasing = ReferralChasingOptions.None; + ldapConnection.Bind(); + return ldapConnection; +}); +builder.Services.AddSingleton(); +builder.Services.AddTransient(); + +var app = builder.Build(); + +app.UseSwagger(); +app.UseSwaggerUI(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/src/ActiveDirectoryToRestApi/Properties/launchSettings.json b/src/ActiveDirectoryToRestApi/Properties/launchSettings.json new file mode 100644 index 0000000..c6ecdea --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Properties/launchSettings.json @@ -0,0 +1,40 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5220" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": false, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_URLS": "http://+:80" + }, + "publishAllPorts": true + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:20943", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/src/ActiveDirectoryToRestApi/Services/AuthUserService.cs b/src/ActiveDirectoryToRestApi/Services/AuthUserService.cs new file mode 100644 index 0000000..74616f7 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Services/AuthUserService.cs @@ -0,0 +1,32 @@ +namespace ActiveDirectoryToRestApi.Services; + +public class AuthUserService +{ + private readonly IConfiguration _configuration; + + public AuthUserService(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool AuthUser(string username, string password) + { + var configs = _configuration.GetSection(nameof(LdapConfigs)).Get(); + try + { + var endpoint = new LdapDirectoryIdentifier(configs.Server, false, false); + using var connection = new LdapConnection(endpoint, + new NetworkCredential($"{configs.DomainName}\\{username}", password)) + { + AuthType = AuthType.Basic + }; + connection.SessionOptions.ReferralChasing = ReferralChasingOptions.None; + connection.Bind(); + return true; + } + catch (LdapException) + { + return false; + } + } +} diff --git a/src/ActiveDirectoryToRestApi/Services/LdapService.cs b/src/ActiveDirectoryToRestApi/Services/LdapService.cs new file mode 100644 index 0000000..beec255 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/Services/LdapService.cs @@ -0,0 +1,177 @@ +namespace ActiveDirectoryToRestApi.Services; + +public class LdapService +{ + private readonly LdapConfigs _ldapConfigs; + private readonly LdapConnection _connection; + private readonly IConfiguration _configuration; + + public LdapService(LdapConnection connection, IConfiguration configuration) + { + _connection = connection; + _configuration = configuration; + _ldapConfigs = _configuration.GetSection(nameof(LdapConfigs)).Get(); + } + public User GetUserByUserName(string username) + { + string filter = $"(&(objectClass=user)(objectCategory=person)(sAMAccountName={username}))"; + return GetUser(filter); + } + + public User GetUserByEmail(string email) + { + string filter = $"(&(objectClass=user)(objectCategory=person)(mail={email}))"; + return GetUser(filter); + } + + private User GetUser(string filter) + { + string[] attributesToReturn = { "givenName", "sn", "mail", "userPrincipalName", "displayName", "sAMAccountName", + "userAccountControl", "accountExpires", "memberOf", "distinguishedName", "pwdLastSet" }; + + SearchRequest searchRequest = new(_ldapConfigs.DistinguishedName, filter, SearchScope.Subtree, attributesToReturn); + + SearchResponse searchResponse = (SearchResponse)_connection.SendRequest(searchRequest); + + if (searchResponse.Entries.Count > 0) + { + SearchResultEntry entry = searchResponse.Entries[0]; + + string userAccountControl = entry.Attributes["userAccountControl"][0].ToString(); + string accountExpires = entry.Attributes["accountExpires"][0].ToString(); + string expiration = accountExpires.ConvertToDateTime(); + string pwdLastSet = entry.Attributes["pwdLastSet"][0].ToString().ConvertToDateTime(); + string passwordExpiration = GetPasswordExpiration(pwdLastSet); + bool expired = accountExpires.IsExpired(); + string mail = entry.Attributes["mail"]?[0].ToString() ?? ""; + string givenName = entry.Attributes["givenName"]?[0].ToString() ?? ""; + string sn = entry.Attributes["sn"]?[0].ToString() ?? ""; + string displayName = entry.Attributes["displayName"]?[0].ToString() ?? ""; + string sAMAccountName = entry.Attributes["sAMAccountName"][0].ToString(); + string userPrincipalName = entry.Attributes["userPrincipalName"]?[0].ToString() ?? ""; + string distinguishedName = entry.DistinguishedName; + bool enabled = userAccountControl.IsEnabled(); + bool passwordNeverExpire = userAccountControl.IsPasswordNeverExpire(); + bool passwordExpired = userAccountControl.IsPasswordExpired(); + + var groups = new List(); + var memberOfAttribute = entry.Attributes["memberOf"]; + if (memberOfAttribute != null) + { + foreach (var groupDn in memberOfAttribute.GetValues(typeof(string))) + { + groups.Add(ParseGroupName(groupDn.ToString())); + } + } + + var user = new User + { + DisplayName = displayName, + Email = mail, + SamAccountName = sAMAccountName, + Enabled = enabled, + LogonName = userPrincipalName, + FirstName = givenName, + LastName = sn, + PasswordNeverExpire = passwordNeverExpire, + PasswordExpired = passwordExpired, + PasswordLastSet = pwdLastSet, + PasswordExpiration = passwordExpiration, + Expiration = expiration, + Expired = expired, + DistinguishedName = distinguishedName, + Groups = groups + }; + return user; + } + else + { + return null; + } + } + + private static string ParseGroupName(string groupDn) + { + int startIndex = groupDn.IndexOf('=') + 1; + int endIndex = groupDn.IndexOf(','); + + if (startIndex > 0 && endIndex > 0) + { + return groupDn[startIndex..endIndex]; + } + else + { + return groupDn; + } + } + + public Group GetGroupMembers(string groupName) + { + Group group = GetGroup(groupName); + + if (group is null) return null; + + string filter = $"(&(objectCategory=user)(memberOf={group.DistinguishedName}))"; + string[] attributesToReturn = { "sAMAccountName" }; + + SearchRequest searchRequest = new(_ldapConfigs.DistinguishedName, filter, SearchScope.Subtree, attributesToReturn); + SearchResponse searchResponse = (SearchResponse)_connection.SendRequest(searchRequest); + + foreach (SearchResultEntry entry in searchResponse.Entries) + { + group.Members.Add(entry.Attributes["sAMAccountName"][0].ToString()); + } + return group; + } + + private Group GetGroup(string groupName) + { + string filter = $"(&(objectClass=group)(cn={groupName}))"; + string[] attributesToReturn = { "distinguishedName", "cn", "groupType" }; + + SearchRequest searchRequest = new(_ldapConfigs.DistinguishedName, filter, SearchScope.Subtree, attributesToReturn); + SearchResponse searchResponse = (SearchResponse)_connection.SendRequest(searchRequest); + + if (searchResponse.Entries.Count > 0) + { + SearchResultEntry entry = searchResponse.Entries[0]; + Group group = new() + { + Name = entry.Attributes["cn"][0].ToString(), + Type = entry.Attributes["groupType"][0].ToString().GroupType(), + DistinguishedName = searchResponse.Entries[0].DistinguishedName + }; + return group; + } + return null; + } + + private string GetPasswordExpiration(string pwdLastSet) + { + var pwdLastSetDate = DateTime.Parse(pwdLastSet); + var passwordExpiration = pwdLastSetDate.AddDays(GetMaxPwdAge()); + return passwordExpiration.ToString(); + } + + private double GetMaxPwdAge() + { + string filter = "(objectClass=domain)"; + string[] attributesToRetrieve = { "maxPwdAge" }; + + SearchRequest searchRequest = new(_ldapConfigs.DistinguishedName, filter, SearchScope.Subtree, attributesToRetrieve); + SearchResponse searchResponse = (SearchResponse)_connection.SendRequest(searchRequest); + + if (searchResponse.Entries.Count == 1) + { + SearchResultEntry entry = searchResponse.Entries[0]; + long value = long.Parse(entry.Attributes["maxPwdAge"][0].ToString()); + TimeSpan maxPwdAge = TimeSpan.FromTicks(value); + double days = maxPwdAge.TotalDays; + return Math.Abs(days); + } + else + { + return 42; + } + } +} diff --git a/src/ActiveDirectoryToRestApi/appsettings.Development.json b/src/ActiveDirectoryToRestApi/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/src/ActiveDirectoryToRestApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/ActiveDirectoryToRestApi/appsettings.json b/src/ActiveDirectoryToRestApi/appsettings.json new file mode 100644 index 0000000..49ba635 --- /dev/null +++ b/src/ActiveDirectoryToRestApi/appsettings.json @@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "LdapConfigs": { + "Server": "192.168.100.25", + "DomainName": "AD", // (pre-Windows 2000) + "User": "ldapAdmin", + "Pass": "Thi$1sMyPassw0rd", + "DistinguishedName": "DC=ad,DC=zimbres,DC=com" + } +}