Proteger as comunicações remotas do serviço em um serviço Java

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 Java. Ele compila um exemplo existente que explica como configurar a comunicação remota para os Reliable Services escritos em Java.

Para ajudar a proteger um serviço quando você estiver usando a comunicação remota de serviço com serviços Java, siga estas etapas:

  1. Crie uma interface, HelloWorldStateless, que define os métodos que estarão disponíveis para chamada de procedimento remoto no seu serviço. Seu serviço usará FabricTransportServiceRemotingListener, declarado no pacote do microsoft.serviceFabric.services.remoting.fabricTransport.runtime. Esta é uma implementação de CommunicationListener que fornece recursos de comunicação remota.

    public interface HelloWorldStateless extends Service {
        CompletableFuture<String> getHelloWorld();
    }
    
    class HelloWorldStatelessImpl extends StatelessService implements HelloWorldStateless {
        @Override
        protected List<ServiceInstanceListener> createServiceInstanceListeners() {
            ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
            listeners.add(new ServiceInstanceListener((context) -> {
                return new FabricTransportServiceRemotingListener(context,this);
            }));
        return listeners;
        }
    
        public CompletableFuture<String> getHelloWorld() {
            return CompletableFuture.completedFuture("Hello World!");
        }
    }
    
  2. 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. Para serviços executados em Linux, o certificado deve estar disponível como um arquivo em formato PEM; tanto um arquivo .pem que contenha o certificado e chave privada ou um arquivo .crt que contenha o certificado e um arquivo .key que contenha a chave privada. 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:

    1. Fornecê-las usando um pacote de configuração:

      Adicione uma seção nomeada TransportSettings ao arquivo settings.xml.

      <!--Section name should always end with "TransportSettings".-->
      <!--Here we are using a prefix "HelloWorldStateless".-->
       <Section Name="HelloWorldStatelessTransportSettings">
           <Parameter Name="MaxMessageSize" Value="10000000" />
           <Parameter Name="SecurityCredentialsType" Value="X509_2" />
           <Parameter Name="CertificatePath" Value="/path/to/cert/BD1C71E248B8C6834C151174DECDBDC02DE1D954.crt" />
           <Parameter Name="CertificateProtectionLevel" Value="EncryptandSign" />
           <Parameter Name="CertificateRemoteThumbprints" Value="BD1C71E248B8C6834C151174DECDBDC02DE1D954" />
       </Section>
      
      

      Nesse caso, o método createServiceInstanceListeners terá esta aparência:

       protected List<ServiceInstanceListener> createServiceInstanceListeners() {
           ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
           listeners.add(new ServiceInstanceListener((context) -> {
               return new FabricTransportServiceRemotingListener(context,this, FabricTransportRemotingListenerSettings.loadFrom(HelloWorldStatelessTransportSettings));
           }));
           return listeners;
       }
      

      Se você adicionar uma seção TransportSettings ao arquivo settings.xml sem nenhum prefixo, FabricTransportListenerSettings carregará todas as configurações dessa seção por padrão.

      <!--"TransportSettings" section without any prefix.-->
      <Section Name="TransportSettings">
          ...
      </Section>
      

      Nesse caso, o método CreateServiceInstanceListeners terá esta aparência:

      protected List<ServiceInstanceListener> createServiceInstanceListeners() {
          ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
          listeners.add(new ServiceInstanceListener((context) -> {
              return new FabricTransportServiceRemotingListener(context,this);
          }));
          return listeners;
      }
      
  3. 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.ServiceProxyBase para criar um proxy de serviço, use microsoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory.

    Se o código cliente estiver sendo executado como parte de um serviço, você poderá carregar FabricTransportSettings do arquivo settings.xml. Crie uma seção TransportSettings semelhante ao código de serviço, conforme mostrado acima. Faça as alterações a seguir no código cliente:

    
    FabricServiceProxyFactory serviceProxyFactory = new FabricServiceProxyFactory(c -> {
            return new FabricTransportServiceRemotingClientFactory(FabricTransportRemotingSettings.loadFrom("TransportPrefixTransportSettings"), null, null, null, null);
        }, null)
    
    HelloWorldStateless client = serviceProxyFactory.createServiceProxy(HelloWorldStateless.class,
        new URI("fabric:/MyApplication/MyHelloWorldService"));
    
    CompletableFuture<String> message = client.getHelloWorld();