Proteggere le comunicazioni remote per Reliable Services in un servizio Java

La sicurezza è uno degli aspetti essenziali della comunicazione. Il framework di applicazioni di Reliable Services offre alcuni stack e strumenti predefiniti che è possibile usare per migliorare la sicurezza. Questo articolo discute come migliorare la sicurezza quando si usa la comunicazione remota in un servizio Java. Verrà usato un esempio esistente che spiega come configurare la comunicazione remota per Reliable Services in Java.

Per proteggere un servizio quando si usa la comunicazione remota con i servizi Java, seguire questa procedura:

  1. Creare un'interfaccia, HelloWorldStateless, che definisce i metodi che saranno disponibili per la Remote Procedure Call del servizio. Il servizio userà il metodo FabricTransportServiceRemotingListener, dichiarato nel pacchetto microsoft.serviceFabric.services.remoting.fabricTransport.runtime. Si tratta di un’implementazione CommunicationListener che fornisce funzionalità di accesso remoto.

    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. Aggiungere le impostazioni del listener e le credenziali di sicurezza.

    Assicurarsi che il certificato da usare per proteggere le comunicazioni dei servizi sia installato in tutti i nodi del cluster. Per i servizi in esecuzione su Linux, il certificato deve essere disponibile come file formattato PEM; un file .pem che contiene il certificato e la chiave privata o un file .crt che contiene il certificato e un file .key che contiene la chiave privata. Per altre informazioni, vedere Percorso e formato dei certificati X.509 nei nodi Linux.

    Esistono due modi per specificare le impostazioni del listener e le credenziali di sicurezza:

    1. Specificarle tramite un pacchetto di configurazione:

      Aggiungere una sezione denominata TransportSettings nel file 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>
      
      

      In questo caso il metodo createServiceInstanceListeners avrà un aspetto analogo al seguente:

       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 si aggiunge una sezione TransportSettings al file settings.xml senza alcun prefisso, FabricTransportListenerSettings caricherà tutte le impostazioni da questa sezione per impostazione predefinita.

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

      In questo caso il metodo CreateServiceInstanceListeners avrà un aspetto analogo al seguente:

      protected List<ServiceInstanceListener> createServiceInstanceListeners() {
          ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
          listeners.add(new ServiceInstanceListener((context) -> {
              return new FabricTransportServiceRemotingListener(context,this);
          }));
          return listeners;
      }
      
  3. Quando si chiamano metodi in un servizio protetto tramite lo stack di comunicazione remota, anziché usare la classe microsoft.serviceFabric.services.remoting.client.ServiceProxyBase per creare un proxy del servizio, usare microsoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory.

    Se il codice client viene eseguito come parte del servizio, è possibile caricare FabricTransportSettings dal file settings.xml. Creare una sezione TransportSettings simile al codice del servizio, come illustrato in precedenza. Apportare le modifiche seguenti al codice client:

    
    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();