4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.NET 8のプロセス間通信にgRPCのパイプ通信を使う場合に、パイプへのユーザーアクセス許可(ACL)を与える方法

Last updated at Posted at 2025-06-11

概要

.NET 8のプロセス間通信にgRPCのパイプ通信を使う際に、そのパイプにユーザーアクセス許可(ACL)を与える方法についてです。

以前の記事で、.NET 8のプロセス間通信にはgRPCのパイプ通信が良さそうだという話と、その実装方法を書きました。その時にはパイプのACLを与える方法として別途Win32APIを使う方法を書いたのですが、もっと簡単にC#だけで実現できたので、その方法をこの記事に書きます。

最初に結論まとめ

次のように、パイプの待ち受けを行うIWebHostBuilderに対して、IWebHostBuilder.UseNamedPipesメソッドで使うパイプの設定を与えます。そこで、ACLの設定も行います。

IHost host = Host.CreateDefaultBuilder(args)
//~略~
    .ConfigureWebHostDefaults(webBuilder =>
    {
        var ps = new PipeSecurity();
        ps.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));
        webBuilder.UseNamedPipes(option =>
        {
            option.PipeSecurity = ps;
            option.CurrentUserOnly = false;
        });

//~略~

説明

次の画像のように、Windowsサービスとユーザーセッションのプロセス間通信の用途で、gRPCのパイプ通信を使うケースの話になります。

image.png

この利用シーンについて詳しくは、以前の記事「.NET 8のプロセス間通信には、gRPCのパイプ通信が優秀なようです」に書きました。

Windowsサービス(LocalSystem権限)からパイプを作ると、デフォルトではユーザー権限の書き込み不可になります。しかし上の図のような用途では、ユーザーセッションのアプリはユーザー権限で起動しているため、書き込みを許可する必要があります。

Windowsサービス側(gRPCサーバー側)でのパイプの作り方は、GenericHostを使う方法を以前の記事で書きました。

ポイントとなるコードだけ引用すると、次の通りです。

IHost host = Host.CreateDefaultBuilder(args)
//~略~
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.ConfigureKestrel(options =>
        {
            options.ListenNamedPipe("gRPCWinServiceSamplePipeName", listenOptions =>
            {
                listenOptions.Protocols = HttpProtocols.Http2;
            });
        });

このままではユーザー権限書き込み不可です。これに対して、Kestrelが使用するパイプの設定を与える処理を足すことで、ユーザー権限書き込み可にできます。そのコードも足すと、次のようになります。

IHost host = Host.CreateDefaultBuilder(args)
//~略~
    .ConfigureWebHostDefaults(webBuilder =>
    {
        var ps = new PipeSecurity();
        ps.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));
        webBuilder.UseNamedPipes(option =>
        {
            option.PipeSecurity = ps;
            option.CurrentUserOnly = false;
        });
        
        webBuilder.ConfigureKestrel(options =>
        {
            options.ListenNamedPipe("gRPCWinServiceSamplePipeName", listenOptions =>
            {
                listenOptions.Protocols = HttpProtocols.Http2;
            });
        });

//~略~

このコードでは、AuthenticatedUserからの読み書きを許可するPipeSecurityを作成し、それをUseNamedPipesメソッドのパラメータに渡しています。また、パイプを作成したのとは異なるユーザーからのアクセスを許可するため、CurrentUserOnly = falseも設定しています。

これだけで、パイプへのユーザーアクセス許可(ACL)を与えることができます。Win32APIを使ってむりやり実現する方法よりだいぶシンプルですし、こちらの方が正しいやり方に見えます。今後はこの方法を使っていこうと思います。

GitHubのサンプルも更新しておきました。

まとめ

以前の記事で紹介したWin32APIを使う方法よりも、今回紹介した方法の方がより良いようです。良いものはどんどん取り込んで使っていきましょう!

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?