5.  Sicurezza nelle applicazioni WEB

Le Applicazioni che espongono una Web API sono particolarmente esposte ai consueti problemi di sicurezza. Questa particolare predisposizione al rischio, proviene dal fatto che, contrariamente alle API tradizionali, si tratta di interfacce di cui a priori non è facile individuare esattamente gli usi che ne saranno fatti. Le testsuite che vengono tipicamente messe in campo per un collaudo pre-esercizio sono quindi inevitabilmente limitate rispetto alla creatività dei futuri fruitori dell'applicazione.

Un problema ulteriore è la tipica complessitè delle infrastrutture che ospitano le applicazioni Internet, che abbbiamo già discusso nella sezione sulle architetture applicative. Di fatto il processo di autenticazione ed autorizzazione delle richieste è tipicamente distribuito tra diversi componenti infrastrutturali ed applicativi e è abbastanza frequente che alcuni aspetti di sicurezza (tipicamente quelli relativi all'autorizzazione delle richieste in arrivo) finiscano per essere trascurati.

Uno dei problemi più peculiari riguarda la presenza di intermediari nella catena di comunicazioni tra fruitore ed erogatore del servizio. I tradizionali meccanismi per la sicurezza di rete come il Transport Layer Security (SSL/TLS), Virtual Private Networks (VPNs), Internet Protocol Security (IPSec) ed il Multipurpose Internet Mail Exchange (S/MIME) sono tecnologie punto a punto (Point-to-Point). Nonostante queste tecniche siano ampiamente utilizzate per la sicurezza dei Web Service, è spesso necessario impiegare ulteriori tecnologie che agiscono a livello di messaggio anzichè a livello di trasporto, e si dimostrano quindi più adatte a gestire le comunicazioni di tipo 'End-to-End'.

Un messaggio xml o json può infatti passare attraverso degli intermediari prima di raggiungere la propria destinazione, ed in queste situazioni si presentano prolematiche che non è possibile gestire con protocolli legati al trasporto. Ad esempio è possibile che un requisito di sicurezza richieda che soltanto l'applicazione finale possa leggere il contenuto del messaggio, ma l'uso del protocollo SSL su http (https) garantisce la riservatezza del dato solo fino al prossimo endpoint a cui il mittente è collegato. Se questi non è l'applicazione finale ma un intermediario, ci verificheranno due problemi: l'intermediario avrà accesso al dato in chiaro e non sarà garantito che la comunicazione tra l'intermediario e la destinazione finale sia cifrata. Un'altra controindicazione delle comunicazioni basate su https è che richiedono la cifratura dell'intero canale, anche se il dato da proteggere è magari soltanto un campo specifico del messaggio. Questo pone due controindicazioni: il costo eccessivo della cifratura e l'impossibilità di trattare a livello infrastrutturale il contenuto del messaggio (si pensi ad esempio un proxy http che funga da antivirus).

Per ovviare a queste problematiche è necessario utilizzare tecnologie di sicurezza basate sul messaggio piuttosto che sul trasporto. In questo corso analizzeremo la specifica WS-Security per la gestione della sicurezza a livello messaggio nel protocollo SOAP.

5.1.  La sicurezza nelle Applicazioni Internet

Anche WS-Security si appoggia alle tecniche crittografiche di base per garantire la sicurezza dei messaggi scambiati. Per un richiamo sui concetti basi rimandiamo alla lezione sulla sicurezza nelle applicazioni internet.

5.1.1. Setup con Keytool

Per l'utilizzo delle tecnologie di base viste a lezione utilizzeremo certificati X509. Vediamo nel seguito come utilizzare il comando Java keytool per creare e gestire coppie di chiavi private/pubbliche e relativi certificati. Specificando l'opzione -genkey il keytool crea una chiave privata e la sua corrispettiva chiave pubblica in un file criptato denominato keystore che viene generato nella directory dalla quale è stato lanciato il comando. La chiave pubblica viene inclusa in un certificato self signed all'interno del file prodotto. Un certificato self-signed è semplicemente quello in cui issuer e subject sono la stessa entità.

[user@home ~]$ keytool -genkey -alias Alice -keypass alicekeys -keystore alice.ks
Immettere la password del keystore:  alicestore
Specificare nome e cognome
 [Unknown]:  Alice
Specificare il nome dell'unità aziendale
 [Unknown]:  Unipi
Specificare il nome dell'azienda
 [Unknown]:  Unipi
Specificare la località
 [Unknown]:  Pisa
Specificare la provincia
 [Unknown]:  Pisa
Specificare il codice a due lettere del paese in cui si trova l'unità
 [Unknown]:  IT
Il dato CN=Alice, OU=Unipi, O=Unipi, L=Pisa, ST=Pisa, C=IT è corretto?
 [no]:  si

[user@home ~]$ ls
alice.keystore
            

Questo genera la coppia di chiavi, con la chiave privata cifrata con la password "alicekeys", il tutto inserito nel keystore "alice.ks" a sua volta cifrato con la password "alicestore"

Adesso estraiamo il certificato pubblico che consegneremo a Bob.

[user@home ~]$ keytool -export -keystore alice.ks -alias alice -storepass alicestore -file alice.cer
Il certificato è memorizzato nel file <alice.cer>

Una volta che alice avrà consegnato il certificato a Bob, questo lo includerà nel suo truststore, ovvero un archivio JKS (lo stesso del keystore) contenente i certificati dei soggetti fidati.

[user@home ~]$ keytool -import -keystore "bob.ts" -alias "alice" -file "alice.cer" -storepass "bobtrust"
Proprietario: CN=Alice, OU=Unipi, O=Unipi, L=Pisa, ST=Pisa, C=IT
Organismo di emissione: CN=Alice, OU=Unipi, O=Unipi, L=Pisa, ST=Pisa, C=IT
Numero di serie: 4982e1c9
Valido da Fri Jan 30 12:17:29 CET 2009 a Thu Apr 30 13:17:29 CEST 2009
Impronte digitali certificato:
         MD5: 20:72:F9:D0:30:08:D7:AB:14:64:F1:BE:22:18:44:20
         SHA1: 9B:77:8E:A6:EF:51:5B:CA:C2:B9:12:E4:EB:E7:5B:53:AE:AC:FF:07
Considerare attendibile questo certificato? [no]:  si
Il certificato è stato aggiunto al keystore

[Nota] Nota

Per semplicità e' possibile mettere certificati pubblici e chiavi private nel solito keystore invece che separarli in keystore e truststore.

Non rimane dunque che fare lo stesso per Bob:

  • Generare la coppia di chiavi da includere nel keystore di Bob

  • Estrarre il certificato e consegnarlo ad Alice

  • Creare il truststore di Alice

A questo punto abbiamo tutto quello che serve per permettere a Alice e Bob di usufruire dei servizi offerti dall'infrastruttura a chiave publica.

5.2. WS-Security

La specifica WS-Security definisce un'estensione di SOAP che implementa autenticazione, integrità e confidenzialità a livello messaggio. L'obiettivo di questa specifica non è introdurre nuove tecniche, ma quello di utilizzare le soluzioni esistenti in materia di sicurezza delle comunicazioni con SOAP ed i Web Service.

Il punto di ingresso di WS-Security è un header SOAP, chiamato <Security>. Contiene i dati riguardanti la sicurezza e le informazioni necessarie per implementare meccanismi come firma e cifratura. Questo elemento può essere presente più volte all'interno del messaggio se le informazioni di sicurezza da inserire sono destinate a differenti destinatari (indicati con l'attributo actor). Due header <Security> non possono avere il solito actor, mentre un header senza actor specificato, può essere consumato da qualsiasi ricevente.

Vediamo un esempio di messaggio SOAP con un header <Security>.

<SOAP:Envelope xmlns:SOAP="...">
  <SOAP:Header>
    <wsse:Security SOAP:actor="..." SOAP:mustUnderstand="...">
      ...
    </wsse:Security>
  </SOAP:Header>
  <SOAP:Body Id="MsgBody">
      <!-- SOAP Body data -->
  </SOAP:Body>
</SOAP:Envelope>
            

5.2.1. Authentication

Uno dei requisiti centrali di un'infrastruttura di comunicazione è la possibilità di fornire e ricevere referenze attendibili sull'identità dei soggetti coinvolti nella comunicazione. Queste referenze sono informazioni aggiuntive che trovano naturale collocazione nell'header SOAP del messaggio.

Ci sono molteplici modi per fornire prove della propria identità e WS-Security fornisce un metodo astratto per implementarle. I metodi che analizzeremo sono:

  • Username/Password

  • Certificati X.509 su PKI

Vediamo ad esempio di autenticazione tramite Username e Password utilizzata anche in HTTP. Le informazioni sono aggiunte all'Header SOAP tramite l'elemento UsernameToken:

<!-- No Password -->
<UsernameToken>
  <Username>Alice</Username>
</UsernameToken>

<!-- Clear Text Password -->
<UsernameToken>
  <Username>Alice</Username>
  <Password Type="wsse:PasswordText">Wonderland</Password>
</UsernameToken>

<!-- Digest: SHA1 hash of base64-encoded Password -->
<UsernameToken>
  <Username>Alice</Username>
  <Password Type="wsse:PasswordDigest">gpBDXjx79eutcXdtlULIlcrSiRs=<Password>
  <Nonce>h52sI9pKV0BVRPUolQC7Cg==</Nonce>
  <Created>2002-11-04T19:16:50Z</Created>
</UsernameToken>

Nel primo caso inviamo il nome dell'utente senza nessuna password di sicurezza. Questo tipo di autenticazione deve essere utilizzato in combinazione con altre tecniche di sicurezza perchè chiaramente poco robusta.

Stesse considerazioni anche per la seconda tecnica di autenticazione, che prevede di passare la password di sicurezza in chiaro nel messaggio.

Fornisce invece una buon livello di sicurezza il terzo tipo di autenticazione, che invia la password di sicurezza codificata ed accompagnata da un digest (o impronta) in combinazione con la data di creazione per ovviare ad attacchi di tipo replay.

Un'altra opzione è quella di inviare un certificato X.509 che, avvalendosi dell'infrastruttura a chiave pubblica, fornisce l'identità di un soggetto e garantisce l'attendibilità di tali informazioni.

Il certificato X.509 viene incluso in un messaggio in un elemento WS-Security chiamato BinarySecurityToken. L'algoritmo usato per la codifica viene specificato nell'attributo EncodingType mentre il tipo di certificato è specificato in ValueType.

<wsse:BinarySecurityToken 
    ValueType="wsse:X509v3" 
    EncodingType="wsse:Base64Binary" 
    Id="...">MIIHdjCCB...</wsse:BinarySecurityToken>

5.2.2. Signature

Il processo di autenticazione ci fornisce garanzie sull'identità del soggetto con cui stiamo scambiando informazioni. Quello che non sappiamo è se le informazioni che giungono a destinazione siano le stesse inserite dal mittente e che non abbiano subito alterazioni durante il tragitto. Non abbiamo quindi garanzie sull'integrità dei dati, garanzie che che possiamo fornire firmandoli.

WS-Security si appoggia alla specifica XML Signature per firmare un messaggio. Una volta che un messaggio è stato firmato, è praticamente impossibile poterlo modificare senza che il destinatario non se ne accorga. La firma non impedisce che il messaggio sia letto, ma assicura al ricevente che

  • Le parti firmate del messaggio non sono state modificate dopo la firma

  • Il soggetto che ha apposto la firma è lo stesso identificato dal certificato.

A grandi linee, quando viene firmata una parte del messaggio, viene aggiungo un ID alla parte in chiaro nel messaggio, il certificato del firmatario, anch'esso identificabile univocamente, e un elemento Signature contenente l'elemento firmato, i riferimenti al certificato del firmatario e all'elemento in chiaro oltre ai dettagli del processo di firma.

<Signature>
  <SignedInfo>
    <CanonicalizationMethod Algorithm=".../xml-exc-c14n#"/>
    <SignatureMethod Algorithm=".../xmldsig#rsa-sha1"/>
    <Reference URI="#myBody">
        ...
      <DigestMethod Algorithm=".../xmldsig#sha1"/>
      <DigestValue>EULddytSo1...</ds:DigestValue>
    <Reference>
  <SignedInfo>
  <SignatureValue>
   BL8jdfToEb1l/vXcMZNNjPOV...
  <SignatureValue>
  <KeyInfo>
    <SecurityTokenReference>
      <Reference URI="#MyX509Token"/>
    </SecurityTokenReference>
  </KeyInfo>
</Signature>

Nella prima parte del messaggio troviamo il <CanonicalizationMethod>. Qualsiasi documento che viene firmato deve esser prima portato in forma canonica. Per la natura dell'XML, non esiste un modo di definire l'ordine degli attributi, ne di come trattare gli spazi. Il processo di canonizzazione elimina gli spazi bianchi e ordina gli attributi secondo uno specifico schema.

Il valore della firma è contenuto nell'elemento SignatureValue, SecurityTokenReference riferisce il certificato del firmatario, mentre Reference contiene un riferimento all'elemento firmato.

In questo modo è possibile firmare parti diverse con certificati diversi, risolvendo i problemi addizionali inerenti alle comunicazioni end to end.

5.2.3. Encryption

Abbiamo adesso gli strumenti e le tecniche per garantire integrità e autenticità del contenuto delle informazioni scambiate. Dobbiamo ancora fornire garanzie di confidenzialità di tali informazioni, ovvero impedire che dati sensibili possano essere letti da soggetti non autorizzati.

Quello che vogliamo è la possibilità di cifrare il contenuto del messaggio, o parti di esso, di modo che solo il destinatario sia in grado di decifrarlo e leggerlo. Anche in questo caso il WS-Security si appoggia su uno standard preesistente e collaudato, l'XML Encryption.

Quando si codificano i dati, si può scegliere la codifica simmetrica o asimmetrica. La prima richiede di condividere un'informazione segreta. Infatti la chiave usata per cifrare è la medesima usata per decifrare. Questa soluzione è efficace se si ha un buon controllo sulle parti in causa e un buon livello di fiducia su chi detiene le chiavi, ma pone il problema su come distribuire le chiavi.

Se invece vogliamo un metodo che non pone il problema della distribuzione delle chiavi possiamo utilizzare la codifica asimmetrica che abbiamo usato anche per la firma. Mentre nella firma usavamo la chiave privata per firmare e il certificato pubblico per verificare l'integrità, adesso usiamo il certificato pubblico per cifrare e la chiave privata per riportare le parti cifrate in chiaro.

5.2.4. TimeStamp

Un concetto comune ai sistemi orientati ai messaggi è quello dello della temporalità dei dati. Se i dati di un messaggio sono troppo vecchi, dovrebbe essere scartato. Se arrivano due messaggi contradditori, la data di creazione può aiutare a decidere quale processare e quale scartare. Per gestire queste situazioni, è stato definito l'elemento TimeStamp.

Gli eventi rilevanti di un messaggio sono il momento della creazione, la scadenza scelta dal mittente, e il momento della ricezione. Sapendo la data di creazione e il tempo di validità il destinatario può decidere se i dati di un messaggio sono usabili o meno. Gli elementi sono quindi:

  • Created: contiene l'istante di creazione

  • Expires: Settato dal mittente o da un intermediario, determina la validità temporale dei dati.

  • Received: Notifica quando un intermediario ha ricevuto il messaggio.

Per default il tipo di questi elementi è xs:dateTime anche se è possibile usare altri tipi ma incorrendo in problemi di interoperabilità L'elemento Received può contenere un attributo Actor che indica la URI di chi ha impostato l'ora di ricezione.

<wsu:Timestamp>
    <wsu:Created wsu:Id=
        "Id-2af5d5bd-1f0c-4365-b7ff-010629a1256c">
        2007-09-19T16:15:31Z
    </wsu:Created>
    <wsu:Expires wsu:Id=
        "Id-4c337c65-8ae7-439f-b4f0-d18d7823e240">
        2007-09-19T16:20:31Z
    </wsu:Expires>
</wsu:Timestamp>

5.3. WS-Security con CXF

Esistono numerose implementazioni della specifica WS-Security in Java. Alcune sono studiate per essere usare stand alone (es. XWSS) altre specificatamente per essere integrate in infrastrutture come CXF o Axis2.

Vediamo come esempio come configurare due interlocutori SOAP che utilizzano CXF e intendono rendere sicuri i loro messaggi. CXF, come altri Web Service Framework, grazie alla componibilità del messaggio SOAP, separa l'implementazione della logica del servizio da quella dei componenti aggiuntivi dello stack WS-*. Il risultato è che l'utilizzo di questi componenti spesso si riduce ad un esercizio di configurazione.

Dobbiamo modificare il file di configurazione per istruire il framework sui componenti aggiuntivi da inserire:

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                          http://www.springframework.org/schema/beans/spring-beans.xsd
                          http://cxf.apache.org/jaxws
                          http://cxf.apache.org/schemas/jaxws.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <jaxws:endpoint id="..."
                  implementor="..."
                  address="...">

    <jaxws:inInterceptors>
      <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
      <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
        <constructor-arg>
          <map>
            <entry key="..." value="..." />
            <entry key="..." value="..." />
            ...
          </map>
        </constructor-arg>
      </bean>
    </jaxws:inInterceptors>
  </jaxws:endpoint>
</beans>

  • L'endpoint specifica i dettagli di un servizio. L'attributo implementor specifica la classe che ne implementa la logica, mentra address specifica a quale indirizzo il servizio deve rispondere.

  • Il figlio di endpoint, InInterceptor, definisce una sequenza di intercettori che il messaggio in ingresso deve attraversare e viene modificato.

  • Il SAAJInInterceptor si occupa di trasformare il messaggio xml in un SOAPMessage, operazione necessaria per l'intercettore successivo.

  • Il WSS4JInInterceptor implementa la specifica WS-Security e, dal momento che si basa su WSS4J, richiede che il messaggio passi nella forma di SOAPMessage. Questo intercettore richiede dei parametri di configurazione che vengono forniti nella forma di coppie chiave/valore.

Con una configurazione simile si abilita il client ad utilizzare l'implementazione di WS-Security:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                      http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <bean id="..." class="...">
        <property name="serviceClass" value="..."/>
        <property name="address" value="..."/>
        <property name="outInterceptors">
            <list>
                <bean id="client" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" factory-bean="proxyFactory" factory-method="create" />
                <bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
                <bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
                    <constructor-arg>
                        <map>
                            <entry key="..." value="..." />
                            <entry key="..." value="..." />
                            ...
                        </map>
                    </constructor-arg>
                </bean>    
            </list>
        </property>
    </bean>
</beans>

I parametri da che invieremo all'interceptor abiliteranno le funzionalità di WS-Security.

5.3.1. Autentication con Username Token

Analizziamo un esempio di configurazione che abilita l'inserimento di un UsernameToken per l'autenticazione. Cominciamo con il Client. Dobbiamo indicare all'infrastruttura il tipo di azione da applicare al messaggio, lo username e la password.

<entry key="action" value="UsernameToken" />
<entry key="user" value="Alice" /> 
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="ClientPasswordCallbackClass" />

a classe specificata in passwordCallbackClass indica un'implementazione di CallbackHandler e decide quale password inserire in relazione all'utente passato.

public class ClientPasswordCallback implements CallbackHandler {
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        pc.setPassword("Wonderland);
    }

}

Lato server dobbiamo specificare che ci aspettiamo un UsernameToken con password inviata in chiaro.

<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="ServerPasswordCallbackClass" />

con la classe ServerPasswordCallbackClass implementata come segue:

public class ServerPasswordCallbackClass implements CallbackHandler {
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
         if (pc.getIdentifer().equals("Alice") {
           if (!pc.getPassword().equals("Wonderland")) {
                throw new SecurityException("Password errata");
           }
        }
    }
}

5.3.2. Signature

Vediamo come configurare i nostri interlocutori per firmare una parte del messaggio. Per prima cosa dobbiamo creare un file di properties contenente le seguenti informazioni necessarie a leggere i keystore e truststore contenenti i certificati e le chiavi private usati nel nostro scenario:

  • org.apache.ws.security.crypto.provider indica quale implementazione di org.apache.ws.security.components.crypto.Crypto passare a WSS4J con le informazioni di cifratura.

  • org.apache.ws.security.crypto.merlin.keystore.type indica il tipo di keystore usato

  • org.apache.ws.security.crypto.merlin.keystore.password indica la password per accedere al keystore

  • org.apache.ws.security.crypto.merlin.file indica il path del keystore.

Vediamo le properties per il keystore di Alice (alice.ks.properties)

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=alicestore
org.apache.ws.security.crypto.merlin.file=alice.ks

Adesso per il truststore di Alice (alice.ts.properties)

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=alicetrust
org.apache.ws.security.crypto.merlin.file=alice.ts

Keystore di Bob (bob.ks.properties)

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=bobstore
org.apache.ws.security.crypto.merlin.file=bob.ks

Truststore di Bob (bob.ts.properties)

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=bobtrust
org.apache.ws.security.crypto.merlin.file=bob.ts

Prodotti i files con le properties dei keystore e truststore, configuriamo gli interceptor affichè Alice firmi parte del messaggio:

<entry key="action" value="Signature" />
<entry key="user" value="alice" /> 
<entry key="passwordCallbackClass" value="ClientPasswordCallbackClass" />
<entry key="signaturePropFile" value="alice.ks.properties" />
<entry key="signatureParts" value="{Element}{http://banca.com/ns}Saldo;{Element}{http://banca.com/ns}CodiceCarta" />

dove user indica l'alias della chiave privata nel keystore, passwordCallbackClass è la classe che deve fornire la password per leggere quella chiave privata ed il signaturePropFile è il file di properties per il keystore di Alice. signatureParts indica quali parti si devono firmare. Se non viene specificato viene firmato tutto il Body del messaggio

Configuriamo il servizio con le informazioni necessarie per la verifica della firma:

<entry key="action" value="Signature" />
<entry key="signaturePropFile" value="bob.ts.properties" />

5.3.3. Encryption

Il processo di cifratura è molto simile a quello di firma e le configurazioni si somigliano molto. Il client così configurato cifra tutto il body del proprio messaggio:

<entry key="action" value="Encrypt" />
<entry key="encryptionUser" value="bob" /> 
<entry key="encryptionPropFile" value="alice.ts.properties" />

ed il servizio decifra grazie a questa configurazione:

<entry key="action" value="Encrypt" />
<entry key="decryptionPropFile" value="bob.ks.properties" /> 
<entry key="passwordCallbackClass" value="ServerPasswordCallbackClass" />

5.3.4. Timestamp

Apporre il timestamp al messaggio è l'operazione più semplice da configurare. Lato client indichiamo l'operazione nella action aggiungendo il parametro opzionale timeToLive che esprime, in millisecondi, il gap tra data di creazione e di scadenza

<entry key="action" value="Timestamp" />
<entry key="timeToLive" value="50" />

Ancora più semplice lato server:

<entry key="action" value="Timestamp" />

5.3.5. Timestamp Signature Encrypt

Vediamo un esempio tipico di configurazione di un client che applica un alto livello di sicurezza ai propri messaggi. Le azioni applicate sono in ordine:

  • Applicazione del Timestamp

  • Firma del Timestamp e del Body

  • Cifratura della firma e del Body

<entry key="action" value="Timestamp Signature Encrypt"/>
<entry key="user" value="alice"/>
<entry key="signaturePropFile" value="alice.ks.properties"/>
<entry key="encryptionPropFile" value="alice.ts.properties"/>
<entry key="encryptionUser" value="Bob"/>
<entry key="passwordCallbackClass" value="ClientPasswordCallback"/>
<entry key="signatureParts" value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body"/>
<entry key="encryptionParts" value="{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body"/>

Il servizio deve essere configurato di conseguenza:

<entry key="action" value="Timestamp Signature Encrypt"/>
<entry key="signaturePropFile" value="bob.ts.properties"/>
<entry key="decryptionPropFile" value="bob.ks.properties"/>
<entry key="passwordCallbackClass" value="ServerPasswordCallback"/>

[Nota] Nota

È importante osservare che l'ordine con cui sono inserite le azioni di sicurezza da applicare al messaggio è significativo.

5.4. Le specifiche WS-*

Con WS-* si intende l'insieme di specifiche in campo Web Service basate su SOAP, tra cui quella che abbiamo appena analizzato, WS-Security. Vista la pletora di specifiche redatte per i Web Service, diamo una veloce descrizione delle piuù affermate ed utilizzate:

  • WS-Addressing: Sappiamo che uno dei vantaggi dei Web Service basati su SOAP è la neutralità rispetto al livello di trasporto. Il nostro messaggio SOAP può esser quindi trasportato via HTTP, TCP, JMS, SMTP o altri. Alcuni di questi trasporti forniscono un modo per indirizzare il messaggio verso un servizio. Ad esempio l'HTTP ha una URL che può mappare uno specifico endpoint. JMS, di contro, ha solo le nozioni di coda e topic, ma potremmo avere più di un servizio associato and una coda o un topic. Lo stesso problema si propone nell'HTTP quando abbiamo più servizi con la soluta URL HTTP e non abbiamo modo di distinguere a quale servizio è destinato il messaggio.

    La specifica WS-Addressing pone rimedio a questo problema. Invece di specificare l'endpoint destinatario all'esterno nel messaggio, definisce un set di header standard che consentono di specificarlo all'interno del messaggio stesso.

  • WS-Policy: Quando pubblichiamo un servizio, dobbiamo anche comunicare quali servizi aggiuntivi offre o richiede a chi ne vuole fruire. Ad esempio, il nostro servizio potrebbe richiede la cifratura del messaggio tramite specifici algoritmi di cifratura. In qualche modo questi requisiti devono esser comunicati ai fruitori del servizio. Solitamente questo viene fatto attraverso canali esterni, come documentazioni, mail etc.

    Lo standard che copre questa problematica è il WS-Policy, fornendo un linguaggio per descrivere le capacità ed i requisiti dei Web Service tramite particolari elementi chiamati assertion.

  • WS-Security Le minacce ad un Web Service coinvolgono minacce al sistema host, all'applicazione ed all'intera infrastruttura di rete. Per rendere un Web Service sicuro, sono necessari molteplici tecnologie di sicurezza basate sull'XML per risolvere problemi inerenti l'autenticazione, la gestione degli accessi, le politiche di sicurezza distribuite, la presenza di intermediari.

    Il livello di trasporto solitamente fornisce meccanismi di sicurezza per comunicazioni point-to-point, insufficienti per comunicazioni end-to-end tipiche dei Web Service. WS-Security fornisce le specifiche per garantire la sicurezza anche per comunicazioni end-to-end a livello di messaggio, quindi indipendenti dal trasporto utilizzato.

  • WS-ReliableMessaging: Sapere che un messaggio è stato consegnato è una importante funzionalità. Mentre alcuni protocolli di trasporto, come il JMS, garantiscono l'affidabilità della consegna, altri, come l'HTTP, non sono affidabili. Di conseguenza abbiamo che l'affidabilità deve esser implementata ad un livello superiore.

    WS-ReliableMessaging specifica l'infrastruttura necessaria a garantisce la consegna al destinatario del messaggio per livelli di trasporto non affidabili.

  • WS-Transaction: Vedremo a breve i problemi derivanti dall'accesso concorrente ai database e dall'uso di database distribuiti. Queste problematiche si spostano e complicano quando usiamo database remoti interfacciati con web service. La specifica WS-Transaction risolve questi problemi fornendo un'infrastruttura che garantisce la corretta esecuzioned della logica applicativa.

Footer BGFooter BG
Tito Flagella - © 2007-2015