2011-11-02 13 views
6

Sto lavorando a un'app per un client che richiede una connessione SSL con un'API. Mi sono stati forniti tre file; un file di certificato (root) certificato di attendibilità (root), un file di certificato intermedio (.cer) e un file di risposta firmato. Le istruzioni che ho ricevuto per installarlo riguardano IIS o il programma keytool Java; Sto costruendo l'app in Ruby on Rails quindi nessuna delle due è un'opzione (per quanto ne so).Utilizzo di SSL client in un'applicazione Ruby on Rails

I certificati sono autofirmati dall'organizzazione che esegue il servizio API e sembra che vengano forniti certificati client per l'autenticazione reciproca di una connessione https. Sono sicuri di come

  1. uso dei certificati nella mia richiesta di connettersi e utilizzare l'API
  2. ciò che il file di risposta firmata fa

Ho letto "Using a self-signed certificate" e this article on OpenSSL in Ruby ma nessuno dei due sembra abbastanza azzeccati (ed entrambi hanno una certa dipendenza da Java/JRuby che confonde le cose).

Qualsiasi suggerimento sarebbe molto apprezzato.

+0

Giusto per chiarire, l'articolo mathish.com che hai collegato in realtà non ha nulla a che fare con jRuby. Il codice che stavo dimostrando doveva parlare con un broker di messaggi ActiveMQ, che è basato su Java e utilizza le convenzioni dei certificati SSL di Java. La maggior parte dei commenti in quel codice erano lì per ricordarmi come ottenere i certificati SSL di Java da un keystore e in un formato che OpenSSL avrebbe riconosciuto. –

+0

Se apri i file .cer in un editor di testo, iniziano con '----- BEGIN CERTIFICATE -----' o qualcos'altro? –

+0

Hey @ian, grazie per aver chiarito questo. Non iniziano con '----- INIZIO CERTIFICATO -----'; no. Aprendolo con un editor di testo; sembra che i contenuti siano criptati in qualche modo (solo un gruppo casuale di simboli e spazi ASCII ecc., senza lettere leggibili). – jkale

risposta

4

Sulla base delle vostre osservazioni, sto supponendo che i certificati sono in formato DER, che è possibile convertire in PEM con il openssl x509 di comando (vedi: openssl x509 command):

openssl x509 -inform DER -outform PEM -in certfile.cer -out certfile.pem 

Dopo di che, è possibile istruire la libreria Ruby OpenSSL per utilizzare il certificato principale attendibile per autenticare la connessione SSL con qualcosa di simile:

require 'socket' 
require 'openssl' 

tcp_sock = TCPSocket.new("my.host.tld", 443) 
ctx = OpenSSL::SSL::SSLContext.new 
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT 
#You may need to specify the absolute path to the file 
ctx.ca_file = "certfile.pem" 

ssl_sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) 
ssl_sock.sync_close = true 
ssl_sock.connect 
begin 
    ssl_sock.post_connection_check('my.host.tld') 
rescue 
    puts "Certificate host did not match expected hostname" 
end 

Dopo di che, si dovrebbe essere in grado di leggere e scrivere su ssl_sock come qualsiasi altro oggetto di Ruby IO. Se le viene somministrato un certificato client da utilizzare per consentire al server di autenticazione che si, è possibile configurare il contesto SSL con:

ctx.cert = OpenSSL::X509::Certificate.new(File.read("my_cert.pem")) 
ctx.key = OpenSSL::PKey::RSA.new(File.read("my_key.rsa")) 

prima di creare ssl_sock. La libreria OpenSSL supporta anche altri tipi di chiave oltre a RSA, come DSA (vedi:. OpenSSL::PKey module)

Infine, un ultimo consiglio, se si accede a un'API RESTful, si consiglia di considerare l'utilizzo di un gioiello come rest-client invece di gestire direttamente tutte le risorse di connessione HTTP/S. Indipendentemente dal fatto che tale libreria sia appropriata o utile dipenderà dal servizio che si sta utilizzando, naturalmente.

+0

Volevo solo notare che, diversamente dall'attributo 'ca_file' sugli oggetti' SSLContext', 'cert' e' key' richiedono i dati del file effettivo, non solo il nome del file. –

+0

Inoltre non è necessario eseguire 'post_connection_check' e il relativo' begin ... rescue' block se non si cura della verifica del nome sul certificato. –

+0

La riga 4 del blocco di codice grande deve essere 'tcp_sock' invece di' sock' – SnareChops