Proteger as comunicações remotas do serviço em um serviço C#
A segurança é um dos aspectos mais importantes da comunicação. A estrutura de aplicativo dos Reliable Services fornece algumas pilhas e ferramentas de comunicação predefinidas que você pode usar para aprimorar a segurança. Este artigo discute sobre como melhorar a segurança quando você estiver usando a comunicação remota em um serviço C#. Ele compila um exemplo existente que explica como configurar a comunicação remota para os Reliable Services escritos em C#.
Para ajudar a proteger um serviço quando você estiver usando a comunicação remota de serviço com serviços C#, siga estas etapas:
Crie uma interface,
IHelloWorldStateful
, que define os métodos que estarão disponíveis para chamada de procedimento remoto no seu serviço. Seu serviço usaráFabricTransportServiceRemotingListener
, que é declarado no namespaceMicrosoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime
. Esta é uma implementação deICommunicationListener
que fornece recursos de comunicação remota.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!"); } }
Adicionar credenciais de segurança e configurações de ouvinte.
Certifique-se de que o certificado que você deseja usar para ajudar proteger a comunicação do serviço esteja instalado em todos os nós do cluster.
Observação
Em nós do Linux, o certificado deve estar presente como arquivos no formato PEM no diretório /var/lib/sfcerts. Para saber mais, consulte Local e formato de certificados X.509 em nós do Linux.
Há duas maneiras de fornecer configurações de ouvinte e credenciais de segurança:
Fornecê-las diretamente no código do serviço:
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; }
Fornecê-las usando um pacote de configuração:
Adicione uma seção nomeada
TransportSettings
ao arquivo settings.xml.<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>
Nesse caso, o método
CreateServiceReplicaListeners
terá esta aparência:protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[] { new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener( context,this,FabricTransportRemotingListenerSettings .LoadFrom("HelloWorldStatefulTransportSettings"))) }; }
Se você adicionar uma seção
TransportSettings
ao arquivo settings.xml,FabricTransportRemotingListenerSettings
carregará todas as configurações dessa seção por padrão.<!--"TransportSettings" section .--> <Section Name="TransportSettings"> ... </Section>
Nesse caso, o método
CreateServiceReplicaListeners
terá esta aparência:protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new[] { return new[]{ new ServiceReplicaListener( (context) => new FabricTransportServiceRemotingListener(context,this))}; }; }
Ao chamar métodos em um serviço protegido usando a pilha de comunicação remota, em vez de usar a classe
Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy
para criar um proxy de serviço, useMicrosoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory
. PasseFabricTransportRemotingSettings
, que contémSecurityCredentials
.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();
Se o código cliente estiver sendo executado como parte de um serviço, você poderá carregar
FabricTransportRemotingSettings
do arquivo settings.xml. Crie uma seção HelloWorldClientTransportSettings semelhante ao código de serviço, conforme mostrado acima. Faça as alterações a seguir no código cliente: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();
Se o cliente não estiver sendo executado como parte de um serviço, você poderá criar um arquivo client_name.settings.xml no mesmo local em que client_name.exe estiver. Em seguida, crie uma seção TransportSettings nesse arquivo.
De forma semelhante ao serviço, se você adicionar uma seção
TransportSettings
em client settings.xml/client_name.settings.xml, oFabricTransportRemotingSettings
carregará por padrão todas as configurações dessa seção.Nesse caso, o código anterior é ainda mais simplificado:
IHelloWorldStateful client = ServiceProxy.Create<IHelloWorldStateful>( new Uri("fabric:/MyApplication/MyHelloWorldService")); string message = await client.GetHelloWorld();
Como próxima etapa, leia API Web com OWIN no Reliable Services.