C# サービスでのサービス リモート処理通信をセキュリティで保護する
セキュリティは、通信の最も重要な側面の 1 つです。 Reliable Services アプリケーション フレームワークに最初から用意されている通信スタックとツールを利用してセキュリティを確保することができます。 この記事では、C# サービスでサービス リモート処理を使用している場合の、セキュリティの改善方法について説明します。 これは、C# で記述された Reliable Services のリモート処理の設定方法について説明した、既存の例を基に構築されます。
C# サービスでリモート処理を使用している場合、サービスのセキュリティを確保するには、次の手順を実行します。
サービスのリモート プロシージャ コールで使用できるメソッドを定義するインターフェイス (
IHelloWorldStateful
) を作成します。 実際のサービスでは、Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime
名前空間に宣言されているFabricTransportServiceRemotingListener
を使用します。 これは、リモート処理機能を提供するICommunicationListener
の実装です。public interface IHelloWorldStateful : IService { Task<string> GetHelloWorld(); } internal class HelloWorldStateful : StatefulService, IHelloWorldStateful { protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[]{ new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener(context,this))}; } public Task<string> GetHelloWorld() { return Task.FromResult("Hello World!"); } }
リスナー設定とセキュリティ資格情報を追加します。
サービスの通信のセキュリティ保護に使用する証明書が、クラスター内のすべてのノードにインストールされていることを確認します。
注意
Linux ノード上では、証明書は PEM 形式のファイルとして /var/lib/sfcerts ディレクトリ内に存在している必要があります。 詳しくは、「Linux ノード上の X.509 証明書の場所と形式」をご覧ください。
リスナー設定とセキュリティ資格情報は、次の 2 とおりの方法で指定できます。
サービスのコード内で直接指定する。
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { FabricTransportRemotingListenerSettings listenerSettings = new FabricTransportRemotingListenerSettings { MaxMessageSize = 10000000, SecurityCredentials = GetSecurityCredentials() }; return new[] { new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener(context,this,listenerSettings)) }; } private static SecurityCredentials GetSecurityCredentials() { // Provide certificate details. var x509Credentials = new X509Credentials { FindType = X509FindType.FindByThumbprint, FindValue = "4FEF3950642138446CC364A396E1E881DB76B48C", StoreLocation = StoreLocation.LocalMachine, StoreName = "My", ProtectionLevel = ProtectionLevel.EncryptAndSign }; x509Credentials.RemoteCommonNames.Add("ServiceFabric-Test-Cert"); x509Credentials.RemoteCertThumbprints.Add("9FEF3950642138446CC364A396E1E881DB76B483"); return x509Credentials; }
構成パッケージを使用して指定する。
settings.xml ファイルに、名前付きの
TransportSettings
セクションを追加します。<Section Name="HelloWorldStatefulTransportSettings"> <Parameter Name="MaxMessageSize" Value="10000000" /> <Parameter Name="SecurityCredentialsType" Value="X509" /> <Parameter Name="CertificateFindType" Value="FindByThumbprint" /> <Parameter Name="CertificateFindValue" Value="4FEF3950642138446CC364A396E1E881DB76B48C" /> <Parameter Name="CertificateRemoteThumbprints" Value="9FEF3950642138446CC364A396E1E881DB76B483" /> <Parameter Name="CertificateStoreLocation" Value="LocalMachine" /> <Parameter Name="CertificateStoreName" Value="My" /> <Parameter Name="CertificateProtectionLevel" Value="EncryptAndSign" /> <Parameter Name="CertificateRemoteCommonNames" Value="ServiceFabric-Test-Cert" /> </Section>
この場合、
CreateServiceReplicaListeners
メソッドは次のようになります。protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[] { new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener( context,this,FabricTransportRemotingListenerSettings .LoadFrom("HelloWorldStatefulTransportSettings"))) }; }
settings.xml ファイルに
TransportSettings
セクションを追加すると、FabricTransportRemotingListenerSettings
は、既定で、このセクションからすべての設定を読み込みます。<!--"TransportSettings" section .--> <Section Name="TransportSettings"> ... </Section>
この場合、
CreateServiceReplicaListeners
メソッドは次のようになります。protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[] { return new[]{ new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener(context,this))}; }; }
セキュリティで保護されたサービスのメソッドをリモート処理スタックで呼び出すときは、
Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy
クラスを使用してサービス プロキシを作成する代わりにMicrosoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory
を使用してください。 引数として、FabricTransportRemotingSettings
が格納されているSecurityCredentials
を渡します。var x509Credentials = new X509Credentials { FindType = X509FindType.FindByThumbprint, FindValue = "9FEF3950642138446CC364A396E1E881DB76B483", StoreLocation = StoreLocation.LocalMachine, StoreName = "My", ProtectionLevel = ProtectionLevel.EncryptAndSign }; x509Credentials.RemoteCommonNames.Add("ServiceFabric-Test-Cert"); x509Credentials.RemoteCertThumbprints.Add("4FEF3950642138446CC364A396E1E881DB76B48C"); FabricTransportRemotingSettings transportSettings = new FabricTransportRemotingSettings { SecurityCredentials = x509Credentials, }; ServiceProxyFactory serviceProxyFactory = new ServiceProxyFactory( (c) => new FabricTransportServiceRemotingClientFactory(transportSettings)); IHelloWorldStateful client = serviceProxyFactory.CreateServiceProxy<IHelloWorldStateful>( new Uri("fabric:/MyApplication/MyHelloWorldService")); string message = await client.GetHelloWorld();
クライアント コードがサービスの一部として実行されている場合は、settings.xml ファイルから
FabricTransportRemotingSettings
を読み込むことができます。 上記のように、サービス コードに似た HelloWorldClientTransportSettings セクションを作成します。 クライアント コードを次のように変更します。ServiceProxyFactory serviceProxyFactory = new ServiceProxyFactory( (c) => new FabricTransportServiceRemotingClientFactory(FabricTransportRemotingSettings.LoadFrom("HelloWorldClientTransportSettings"))); IHelloWorldStateful client = serviceProxyFactory.CreateServiceProxy<IHelloWorldStateful>( new Uri("fabric:/MyApplication/MyHelloWorldService")); string message = await client.GetHelloWorld();
クライアントがサービスの一部として実行されていない場合は、client_name.exe と同じ場所に client_name.settings.xml ファイルを作成し、 そのファイル内に TransportSettings セクションを作成できます。
サービスと同様、クライアントの settings.xml/client_name.settings.xml でも、
TransportSettings
セクションを追加すると、FabricTransportRemotingSettings
は既定で、このセクションからすべての設定を読み込みます。その場合は、上記のコードがさらに簡略化されます。
IHelloWorldStateful client = ServiceProxy.Create<IHelloWorldStateful>( new Uri("fabric:/MyApplication/MyHelloWorldService")); string message = await client.GetHelloWorld();
次の手順については、「Reliable Services の OWIN 対応 Web API」を参照してください。