Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for System.DirectoryServices for Windows #14734

Closed
syeshchenko opened this issue Jun 18, 2015 · 199 comments
Closed

Support for System.DirectoryServices for Windows #14734

syeshchenko opened this issue Jun 18, 2015 · 199 comments

Comments

@syeshchenko
Copy link

@syeshchenko syeshchenko commented Jun 18, 2015

Execution plan:

  • 1. @ianhays to kick start the project in CoreFX repo - add source code, showing examples how to do it, advise with setting up build, packaging, prepare the project for future Linux/Mac ports, etc.).
  • 2. Make the code build on Windows.
    • CC @tquerec @ianhays @karelz on PRs
    • Note: We will not take any functional changes to the implementation, architecture, or API surface at this point unless they are necessary to make the code compile on .NET Core. Please give heads up on this issue as soon as you discover case like that.
    • 2.1. System.DirectoryServices.Protocol (on top of wldpap32.dll)
    • 2.2. System.DirectoryServices (on top of adsi.dll)
    • 2.3. System.DirectoryServices.AccountManagement (on top of System.DirectoryServices and SystemDirectoryServices.Protocols)
    • 2.4. System.DirectoryServices.ActiveDirectory (on top of Win32 APIs - see https://github.com/dotnet/corefx/issues/2089#issuecomment-261063131)
  • 3. Add tests - progress tracked in dotnet/corefx#20669
  • .4. Linux/Mac ports.
    • 4.1. System.DirectoryServices.Protocol (we need to decide on x-plat LDAP library to use first) - tracked in dotnet/corefx#24843
    • 4.2. Other libraries (will be difficult as most implementation is mostly part of Windows) - to be tracked by separate issue(s) when the need arises
  • .5. Further improvements and bug fixes to DirectoryServices - to be tracked by separate issues (feel free to create them)
    • Potentially parallel with [4]
  • 6. Publish DirectoryServices package
    • 6.1. Publish preview DirectoryServices package - tracked in dotnet/corefx#18090
    • 6.2. Publish final DirectoryServices package - tracked as part of dotnet/corefx#24909

If anyone is working on any step, please mention it & coordinate here to avoid duplicated effort. @karelz will co-assign the issue to you as well.


Original proposal

Hello there, I was wondering if there is a chance to add support for System.DirectoryServices in CoreCLR.

In one of our projects we are trying to implement GAL based authentication on Linux and tried to use Mono for this task, however it only works partially, check for IsUserInGroup fails. This is something similar to what we are trying to get working: http://stackoverflow.com/questions/2188954/see-if-user-is-part-of-active-directory-group-in-c-sharp-asp-net

So I was hoping that with the addition of this namespace to CoreCLR, it might solve our problem!

Thank you

@danroth27
Copy link
Member

@danroth27 danroth27 commented Oct 9, 2015

@joshfree joshfree assigned danroth27 and unassigned terrajobst Oct 12, 2015
@NickCraver
Copy link
Member

@NickCraver NickCraver commented Jan 13, 2016

Is there any update on this?

@Eaglef90
Copy link

@Eaglef90 Eaglef90 commented Jan 19, 2016

I too would like an update on this. My company is having me build a new app that requires the ability to query Active Directory via LDAP but it appears this is currently not possible. Is there planed support for it, is it being dropped in favor of something else, or is it already working just not documented anywhere?

@jozefizso
Copy link

@jozefizso jozefizso commented Jan 20, 2016

A new, fresh look at implementing the LDAP and Active Directory support would be great to have in .NET CoreFX.

@coe-jeubanks
Copy link

@coe-jeubanks coe-jeubanks commented Jan 21, 2016

We really need an Active Directory/LDAP solution we can leverage in .NET Core. Whether it's a clean sheet implementation or a port of System.DirectoryServices doesn't matter as much to me. There are a lot of business-focused Windows applications that absolutely need AD auth, and LDAP auth would be a great feature bullet point for cross-platform developers.

@NickCraver
Copy link
Member

@NickCraver NickCraver commented Jan 21, 2016

Agreed on the backwards compatible notes above - I don't feel a direct port is needed really, we just need a way to access auth (and perform other actions: search, unlock, delete, etc.) against Active Directory or any LDAP provider.

@terrajobst
Copy link
Member

@terrajobst terrajobst commented Jan 22, 2016

@NickCraver

I don't feel a direct port is needed really, we just need a way to access auth [...] against Active Directory

That's good to know. Don't read too much into my port-to-core label I just applied. It's just my way of tracking gaps in the .NET Core offering that prevents customers like you from porting their app to .NET Core.

@NickCraver
Copy link
Member

@NickCraver NickCraver commented Jan 22, 2016

@terrajobst Gotcha. I don't necessarily think this has to be a 1.0 item because of its modularity (and it sounds like it's slated for post-RTM anyway), but I do look forward to it. It'll be a blocker on porting Opserver for me, so happy to participate in API discussions if we can be of use. We have a wide range of use cases on the sysadmin side of things that may be helpful, ping if I can help out.

@sqmgh
Copy link

@sqmgh sqmgh commented Jan 22, 2016

Just to throw another hat into the ring. At the moment this is the biggest blocker left for me as well. Simply being able to auth would be a huge help for now.

@Eaglef90
Copy link

@Eaglef90 Eaglef90 commented Jan 29, 2016

Can we get an official response from someone on the dev team on the plans for this, if there are even any plans at all to support this?

@ghost
Copy link

@ghost ghost commented Jan 31, 2016

I don't feel a direct port is needed really

Why? Sorry I am confused. Wouldn't that be the most easiest solution for everyone and in accord with DRY principle?
Nevertheless, if there is a reason to write the entire API from scratch, some consistency with old API (same method signatures) would be less confusing for consumer.

@NickCraver
Copy link
Member

@NickCraver NickCraver commented Jan 31, 2016

@jasonwilliams200OK let me clarify, I really meant DirectoryServices.ActiveDirectory specifically. I think authentication, and the stuff around it: e.g. group membership is the 95-99% use case of the namespace. I think a direct port of signatures of that is pretty useful. If the rest warrants change for some reason then I'd be pretty okay with that, and okay if it came later...the auth would be good to get out the door ASAP since that's a blocker to many.

@saf-itpro
Copy link

@saf-itpro saf-itpro commented Feb 6, 2016

Integrating at least a basic functionality of searching Active Directory users and mapping them with custom roles with ASP.NET 5 will ease the implementation of Windows Authentication into ASP.NET web applications. We need this functionality at our intranet site.

@Sjark
Copy link

@Sjark Sjark commented Feb 8, 2016

This is a blocker for us as well. We need to be able to auth, query users and groups, create new user and groups etc against a ldap server.

@SSiefert
Copy link

@SSiefert SSiefert commented Feb 8, 2016

It is also a blocker for me - I require quering and authenticating users.

@ClintBailiff
Copy link

@ClintBailiff ClintBailiff commented Feb 19, 2016

I came up with a solution for authenticating against Active Directory in a .NET Core rc1 web application. You just have to override the CheckPasswordAsync method in the UserManager class. Let me know what you think.

First you need make a custom register page that allows the user to input an AD username instead of an email address and password. That username goes in the UserName property of the ApplicationUser class that is generated by the ASP.NET 5 template when you chose Individual User Accounts authentication. Also, you'll have to default the Password property to something that passes the internal validation in the IdentityUser class.

My register page controller calls a Web API 2 method that finds the username in AD and returns JSON that holds the AD information for that user. I've added some custom properties to the ApplicationUser class to hold the AD information. I will post the code from my project next week.

Then add a class file in the Services folder. I named mine ApplicationUserManager.cs. Add the code below to that class file.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using [YourApp].Models;

namespace [YourApp].Services
{
    public class ApplicationUserManager : UserManager<ApplicationUser>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationUser> passwordHasher,
                                      IEnumerable<IUserValidator<ApplicationUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators,
                                      ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationUser>> logger,
                                      IHttpContextAccessor contextAccessor)
        : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger, contextAccessor)
        {

        }

        public override async Task<bool> CheckPasswordAsync(ApplicationUser user, string password)
        {
            //Pass user.UserName and password to an ASP.NET Web API 2 method that 
            //does the Active Directory authentication and returns a bool.
        }
    }
}

Then open the Startup.cs file. Add .AddUserManager() to the AddIdentity call in the ConfigureServices method as shown below.

services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddUserManager<ApplicationUserManager>()
       .AddDefaultTokenProviders();

This at least allows me to setup policy/claims based authorization while waiting for DirectoryServices support.

@HB-2012
Copy link

@HB-2012 HB-2012 commented Feb 29, 2016

I rely on this library. It's a shame I can't port now.

@NickCraver
Copy link
Member

@NickCraver NickCraver commented Apr 16, 2016

@ClintBailiff I have to chime in here - because relaying the user's password across the wire again to another application in plaintext is a really bad idea. Please, don't use this approach. It's a security hole.

@terrajobst this will be the blocker in porting my larger applications like Opserver over - can we please get this prioritized?

@ClintBailiff
Copy link

@ClintBailiff ClintBailiff commented Apr 16, 2016

@NickCraver I never suggested passing the credentials as plaintext. As a rule I use SSL for all my web applications/services because they typically return data that only authorized users should see. I didn't think to specify that probably because it's so obvious that you would not want to send credentials in plaintext.

@PleasantD
Copy link

@PleasantD PleasantD commented Apr 18, 2016

I would be i support of at least providing a port of System.DirectoryServices.Protocols. We recently switched our LDAP-related code to this to support a larger range of LDAP servers, as the System.DirectoryServices.ActiveDirectory namespace only likes to talk to AD servers.

I suppose, it would be possible for a 3rd party library to spin up this kind of support, but since it already exists in the framework I would imagine that a port would be simpler.

@aminebizid
Copy link

@aminebizid aminebizid commented Apr 28, 2016

WTF asp team is not provide this basic functionality
This is a really blocker issue :(

@liquidboy
Copy link

@liquidboy liquidboy commented May 5, 2016

Any update on LDAP support in CoreCLR ?

@joshfree joshfree assigned joshfree and unassigned danroth27 May 6, 2016
@jnssnmrcs
Copy link

@jnssnmrcs jnssnmrcs commented May 18, 2016

I would also like an update on this. I will be developing an enterprise application with ASP.NET Core that needs to authenticate users against an AD-server.

@joshfree
Copy link
Member

@joshfree joshfree commented May 20, 2016

I'll be looking into porting System.DirectoryServices to .NET Core for v1.1.0 (https://github.com/dotnet/corefx/milestones)

@leo9223
Copy link

@leo9223 leo9223 commented Jun 6, 2016

@joshfree
I also have to authenticate users from ADLDS please also consider System.DirectoryServices.AccountManagement

@karelz karelz closed this Nov 20, 2017
@JaedsonBarbosa
Copy link

@JaedsonBarbosa JaedsonBarbosa commented Mar 14, 2018

Hi, will this work in UWP?

@tarekgh
Copy link
Member

@tarekgh tarekgh commented Mar 15, 2018

Hi, will this work in UWP?

No, it is supported only for net core apps running on Windows and full framework. if you use it in UWP or on Linux, you'll get a PlatformNotSupported exception.

@sscoleman
Copy link

@sscoleman sscoleman commented Mar 15, 2018

I am using this code in a lambda function in AWS which runs on Linux in the background and I am getting this error. "System.DirectoryServices.AccountManagement is not supported on this platform."
I am using core 2.0

 public static List<string> GetGroups(string userName, string domainString)
        {
            List<string> result = new List<string>();
            List<GroupPrincipal> gprList = new List<GroupPrincipal>();
            // establish domain context
            PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain, null, domainString);

            // find your user
            UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, userName);

            // if found - grab its groups
            if (user != null)
            {
                PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();

                // iterate over all groups
                foreach (Principal p in groups)
                {
                    // make sure to add only group principals
                    if (p is GroupPrincipal)
                    {
                        gprList.Add((GroupPrincipal)p);
                    }
                }
            }

            foreach (var gp in gprList)
            {
                result.Add(gp.Name);
            }

            return result;
        }
@tarekgh
Copy link
Member

@tarekgh tarekgh commented Mar 15, 2018

@sscoleman Yes, this is not supported on Linux yet. It is supported on Windows only.

@euclid47
Copy link

@euclid47 euclid47 commented Mar 15, 2018

@sscoleman there is an issue created on it, https://github.com/dotnet/corefx/issues/24843. It was said there was not enough community interest in it with the exception this question comes up all the time. So now you are in a crap spot. You spent time implementing directory services and then find out Linux is supported. Now you ask yourself why is this being touted as platform agnostic if there are Windows only features.

@thedevopsmachine
Copy link

@thedevopsmachine thedevopsmachine commented Mar 15, 2018

It's fairly obvious if you look at the greater Microsoft strategy. Microsoft are throwing ALL of their development resources into Azure, and that includes Active Directory. Check out "What's new in 2016", it's mostly AzureAD/Hybrid investments. https://docs.microsoft.com/en-us/windows-server/identity/whats-new-active-directory-domain-services.

Microsoft is not investing in this library for Linux because they want everyone to move to Azure AD instead. It makes sense, why would you invest in something that you're trying to get customers to move away from?

You're doing something relatively simple though. You can use the Novel LDAP libraries, they work with AD and on .NET Core for Linux. You need to do the protocol work yourself, but it's not overly complex, and there's a lot of samples out there. The downside is that you need to manage binding yourself, which requires a user DN and password.

@terrajobst
Copy link
Member

@terrajobst terrajobst commented Mar 15, 2018

System.DirectoryServices is currently a Windows-only API and it's part of the Windows Compatibility-Pack for .NET Core. In principle, we can make parts of System.DirectoryServices work on Linux but we haven't had the resources to do that yet. dotnet/corefx#24843 is tracking this work item.

Why are we allowing to install packages that will not work on Linux? The alternative would be to fork the API surface but that doesn't work well for all cases either and makes the overall system harder to code against. Of course, our choice isn't without problems either, as it can make it harder to predict whether code will work cross-platform or. We have a preview of a compatibility analyzer that gives you live feedback as you code.

See this video for more context on how we see the Windows Compatibility Pack and the cross-platform analyzer work hand-in-hand:

https://channel9.msdn.com/Events/Connect/2017/T123

@terrajobst
Copy link
Member

@terrajobst terrajobst commented Mar 15, 2018

@thedevopsmachine

Microsoft is not investing in this library for Linux because they want everyone to move to Azure AD instead.

That's not how I see it. As you pointed out, we intend to make money via Azure. And Azure is a cloud platform that offers a wide variety of technologies and operating systems. We have no business interest to promote Windows in the cloud over Linux in the cloud. But of course, .NET has had a strong presence on Windows for 15 years. Making things fully functional across all operating systems takes time, but I honestly think most people following our open source efforts can see that we're not hamstringing Linux on purpose. It just takes time.

@liquidboy
Copy link

@liquidboy liquidboy commented Mar 15, 2018

i agree with the approach with having a consistent api x-plat and x-framework, but it is soul destroying whenever ive encountered that dreaded error .. i feel for @sscoleman ...

@hchungi
Copy link

@hchungi hchungi commented Aug 8, 2018

Can this DirectoryServices package work on CentOS 7?

@tarekgh
Copy link
Member

@tarekgh tarekgh commented Aug 8, 2018

Can this DirectoryServices package work on CentOS 7?

The package can be installed but will not work. when using it you'll get platform not supported exception. we are looking how we can support directory services in general on Linux. this is on our radar.

@niemyjski
Copy link

@niemyjski niemyjski commented Jan 14, 2020

This really needs support linux

@tarekgh
Copy link
Member

@tarekgh tarekgh commented Jan 14, 2020

CC @joperezr

@karelz
Copy link
Member

@karelz karelz commented Jan 15, 2020

@niemyjski see dotnet/corefx#24843

@jol64
Copy link

@jol64 jol64 commented Feb 25, 2020

This really needs support linux

.. plus be able to run in a docker container. Imho it is a pain in the ass that one needs to fall back to the old Novell directory implementation when one wants to use .NET Core 2+ on linux.
Thanks anyway for working on it!

@rafis
Copy link

@rafis rafis commented Jun 19, 2020

Why close this issue? System.DirectoryServices.AccountManagement is still not in .NET Core outside Windows:

# dotnet --list-runtimes
Microsoft.AspNetCore.All 2.2.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.2.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.2.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

#reopen 14734

@JustinGrote
Copy link

@JustinGrote JustinGrote commented Oct 14, 2020

@tarekgh still on the radar?
#reopen 14734

@tarekgh
Copy link
Member

@tarekgh tarekgh commented Oct 14, 2020

@JustinGrote what is the exact functionality you want to for scenario? DirectoryServices is huge and I doubt the whole functionality can be supported in just one release. Having specific requests may help better than just requesting the whole DS libraries to be supported. In .NET 5.0 we have enabled a scenario #23944.

CC @joperezr

@JustinGrote
Copy link

@JustinGrote JustinGrote commented Oct 14, 2020

@tarekgh
I wasn't aware System.DirectoryServices.Protocols had been ported but it looks like it still has a dependency on security.principal.windows, does it work in linux even with that (via basic auth etc.) or will it throw a missing assembly error?

Goal is to reimplement something like ActiveDirectory Powershell module to be xplat, I was considering either the novell ldap module or ldap4net for that purpose if there wasn't going to be at least basic interaction support available.

@jol64
Copy link

@jol64 jol64 commented Oct 15, 2020

Implementing ActiveDirectory Powershell is likely a very big use case. Let me share my two use cases:

  1. I am deriving from UserPrincipal as I need attributes that are not supported out of the box. I followed https://stackoverflow.com/questions/24798037/extend-userprincipal-class and I guess this is kind of a standard in the old .NET framework, and getting that approach to work will probably help more developers.

  2. I also have code like the following:

`

        DirectoryEntry entry = new DirectoryEntry("LDAP://CN=some base address");
        String objectClass = "some object";
        String filter = "(objectClass=" + objectClass + ")";
        using (DirectorySearcher search = new DirectorySearcher(entry, filter,
             new string[] { "some attribute" },
             SearchScope.Subtree))
        {
            using (SearchResultCollection src = search.FindAll())
                foreach (SearchResult s in src)
                {
                    /* do something with */ s.Properties["some attribute"][0]);
                }
        }

`

No clue what is already supported today, last time I checked was in February.
Thanks, Joachim

@tarekgh
Copy link
Member

@tarekgh tarekgh commented Oct 15, 2020

@jol64 can't you achieve the same using the Protocols?

@jol64
Copy link

@jol64 jol64 commented Oct 16, 2020

@jol64 can't you achieve the same using the Protocols?

Likely I can. I rewrote some stuff to use the Novell library. But it requires a rewrite and thus redundant code to my existing .NET framework code. I definitely prefer to avoid a code split of all code, and I am sure others dislike the idea as well.
I am also wondering how authentication works. With Novell (the old version I tried) I have to specify credentials, whereas with my existing code I don´t need to.
Thanks, Joachim

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet