System.DirectoryServices.Protocols のLinuxとMac対応について

.Net 5のお勉強

11月に正式に公開された .Net 5 ですが、更新の内容が多く、またオンライン上で公開イベントをやっているのを目にして、ライブ配信のお勉強会に参加させていただいてました。

やっぱりワイガヤでも話ながら内容を追っていくのは一人で資料見てるだけよりモチベーションが変わってきますね。根詰めてやらないといけない、って状況でなければこういう催し物に参加するのも良いなと思いました。

その中で、System.DirectoryServices.Protocols が LinuxMac に対応した、とアナウンス記事に入っていることが紹介されました。(下記URLの真ん中あたり)

devblogs.microsoft.com

お仕事でやってる製品がC#LDAP検索するもので、マルチプラットフォームにしたいなぁと思いつつ、どうしようかなぁと考えていたところだったので、ちょうどベストなタイミングで情報を得ることができました。

dotnetも触りがてら動作確認してみます。

ということで旧版でまず試してみる

CentOS 8にdotnet 3.1を入れて、テストプロジェクトを作成します、

[akky@centos8 src]$ dotnet new console -o test

.NET Core 3.1 へようこそ!
---------------------
SDK バージョン: 3.1.107

----------------
ドキュメントを確認する: https://aka.ms/dotnet-docs
問題を報告し、GitHub でソースを参照する: https://github.com/dotnet/core
新機能を参照する: https://aka.ms/dotnet-whats-new
インストール済みの HTTPS 開発者の証明書の詳細情報: https://aka.ms/aspnet-core-https
'dotnet --help' を使用して利用可能なコマンドを確認するか、次にアクセスする: https://aka.ms/dotnet-cli-docs
初めてのアプリを作成する: https://aka.ms/first-net-core-app
--------------------------------------------------------------------------------------
Getting ready...
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on test/test.csproj...
  Restore completed in 58.78 ms for /home/akky/src/test/test.csproj.

Restore succeeded.


An update for template pack Microsoft.DotNet.Common.ProjectTemplates.3.1::3.1.7 is available.
    install command: dotnet new -i Microsoft.DotNet.Common.ProjectTemplates.3.1::5.0.0

続けて下記サイトを確認しながら、一つ前のバージョンの System.DirectoryServices.Protocols の参照を追加します。

www.nuget.org

[akky@centos8 test]$ dotnet add package System.DirectoryServices.Protocols --version 4.7.0
  Writing /tmp/tmpT2rHTt.tmp
info : Adding PackageReference for package 'System.DirectoryServices.Protocols' into project '/home/akky/src/test/test.csproj'.
info : Restoring packages for /home/akky/src/test/test.csproj...
info :   CACHE https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/index.json
info :   GET https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/4.7.0/system.directoryservices.protocols.4.7.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/4.7.0/system.directoryservices.protocols.4.7.0.nupkg 400ms
info :   CACHE https://api.nuget.org/v3-flatcontainer/microsoft.netcore.platforms/index.json
info :   GET https://api.nuget.org/v3-flatcontainer/microsoft.netcore.platforms/3.1.0/microsoft.netcore.platforms.3.1.0.nupkg
info :   CACHE https://api.nuget.org/v3-flatcontainer/system.security.principal.windows/index.json
info :   GET https://api.nuget.org/v3-flatcontainer/system.security.principal.windows/4.7.0/system.security.principal.windows.4.7.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/microsoft.netcore.platforms/3.1.0/microsoft.netcore.platforms.3.1.0.nupkg 74ms
info :   OK https://api.nuget.org/v3-flatcontainer/system.security.principal.windows/4.7.0/system.security.principal.windows.4.7.0.nupkg 295ms
info : Installing System.Security.Principal.Windows 4.7.0.
info : Installing Microsoft.NETCore.Platforms 3.1.0.
info : Installing System.DirectoryServices.Protocols 4.7.0.
info : Package 'System.DirectoryServices.Protocols' is compatible with all the specified frameworks in project '/home/akky/src/test/test.csproj'.
info : PackageReference for package 'System.DirectoryServices.Protocols' version '4.7.0' added to file '/home/akky/src/test/test.csproj'.
info : Committing restore...
info : Writing assets file to disk. Path: /home/akky/src/test/obj/project.assets.json
log  : Restore completed in 1.31 sec for /home/akky/src/test/test.csproj.

デフォルトで作成されている Hello World に System.DirectoryServices.Protocols で利用できるLDAP処理を入れてみます。

using System;
using System.DirectoryServices.Protocols;
using System.Net;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            // LDAP接続情報
            LdapDirectoryIdentifier identifier = new LdapDirectoryIdentifier("akky.com", true, false);

            // LDAP接続用ID情報(ドメイン参加ユーザならdefaultcredentialでも問題ない、はず)
            NetworkCredential credential = new NetworkCredential("test001@akky.com", "passw0rd!");

            using (LdapConnection connection = new LdapConnection(identifier, credential, AuthType.Negotiate))
            {
                SearchRequest searchRequest = new SearchRequest("OU=test,DC=akky,DC=com", "(objectclass=user)", SearchScope.Subtree, new string[] { "userPrincipalName" });
                SearchResponse response = (SearchResponse)connection.SendRequest(searchRequest);
                SearchResultEntryCollection entryCollection = response.Entries;

                foreach (SearchResultEntry entry in entryCollection)
                {
                    Console.WriteLine("user: {0}", entry.Attributes["userPrincipalName"][0]);
                }
            }
        }
    }
}

LDAPConnectionを利用してユーザ情報を取得するサンプルになります。続いて実行してみます。

[akky@centos8 test]$ dotnet run
Hello World!
Unhandled exception. System.PlatformNotSupportedException: System.DirectoryServices.Protocols is not supported on this platform.
   at System.DirectoryServices.Protocols.DirectoryIdentifier..ctor()
   at System.DirectoryServices.Protocols.LdapDirectoryIdentifier..ctor(String server, Boolean fullyQualifiedDnsHostName, Boolean connectionless)
   at test.Program.Main(String[] args) in /home/akky/src/test/Program.cs:line 14

ちゃんと(?)サポートされていないよ、と出てきました。

ライブラリを新しく置き換えてみる

いったん今入れたライブラリを削除します。

[akky@centos8 test]$ dotnet remove package System.DirectoryServices.Protocols
info : Removing PackageReference for package 'System.DirectoryServices.Protocols' from project '/home/akky/src/test/test.csproj'.

最新バージョンをインストールします。

[akky@centos8 test]$ dotnet add package System.DirectoryServices.Protocols --version 5.0.0
  Writing /tmp/tmp6A4wvb.tmp
info : Adding PackageReference for package 'System.DirectoryServices.Protocols' into project '/home/akky/src/test/test.csproj'.
info : Restoring packages for /home/akky/src/test/test.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/index.json 268ms
info :   GET https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/5.0.0/system.directoryservices.protocols.5.0.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/system.directoryservices.protocols/5.0.0/system.directoryservices.protocols.5.0.0.nupkg 939ms
info : Installing System.DirectoryServices.Protocols 5.0.0.
info : Package 'System.DirectoryServices.Protocols' is compatible with all the specified frameworks in project '/home/akky/src/test/test.csproj'.
info : PackageReference for package 'System.DirectoryServices.Protocols' version '5.0.0' updated in file '/home/akky/src/test/test.csproj'.
info : Committing restore...
info : Assets file has not changed. Skipping assets file writing. Path: /home/akky/src/test/obj/project.assets.json
log  : Restore completed in 2.18 sec for /home/akky/src/test/test.csproj.

再度実行してみます。

[akky@centos8 test]$ dotnet run
Hello World!
user: test001@akky.com
user: test002@akky.com

お、未サポートエラーは出なくなってLDAPのユーザ情報が取得できました!(当たり前)

LDAP(今回はAD)上のオブジェクトは以下のようになっており、取得処理は問題なさそうです。

f:id:akky97:20201123162134p:plain