2017-03-21 7 views
2

ユースケース:TLS経由でRabbitMQブローカに接続するSpring AMQPクライアントのユーザとして、X.509証明書でホスト名証明書X.509拡張の名前フィールドまたはサブジェクト代替名のいずれかに、ブローカへの接続に使用したホスト名と一致します。Spring AMQPクライアントでのTLSホスト名検証の実行

一つの可能​​な解決策:春ウサギ接続ファクトリビーンorg.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBeanを有する構成のSSLSocketを使用することができ、それにsetSocketConfigurator(com.rabbitmq.client.SocketConfigurator)メソッドを有します)(javax.net.ssl.HandshakeCompletedListenerこの単純なSocketConfigurator event.getSocket(で参照ソケットを閉じる

 

static class MySocketConfigurator implements SocketConfigurator { 

    private final String[] validHostnames; 

    public MySocketConfigurator(String[] validHostnames) { 
     this.validHostnames = validHostnames; 
    }  

    @Override 
    public void configure(final Socket socket) throws IOException { 
     if (socket instanceof SSLSocket) { 
      SSLSocket sslSocket = (SSLSocket) socket; 
      sslSocket.addHandshakeCompletedListener(new HandshakeCompletedListener() { 
       @Override 
       public void handshakeCompleted(final HandshakeCompletedEvent event) { 
        try { 
         if (event.getPeerCertificates()[0] instanceof X509Certificate) { 
          X509Certificate x509Certificate = (X509Certificate) event.getPeerCertificates()[0]; 
          boolean verified = verifyHost(validHostnames, x509Certificate); 
          if (!verified) { 
           event.getSocket().close(); 
          }  
         } else { 
          event.getSocket().close(); 
         }  
        } catch (SSLPeerUnverifiedException e) { 
         throw new RuntimeException(e); 
        } catch (CertificateParsingException e) { 
         throw new RuntimeException(e); 
        } catch (IOException e) { 
         throw new RuntimeException(e); 
        }  
       }  
      }); 
     }  
    }  

    // verify that one of the validHostname items matches a host found in the broker certificate 
    boolean verifyHost(String[] validHostnames, X509Certificate serverCertificate) throws CertificateParsingException { 
     ... 
    }  

} 
 

)で次のように。近くに少し重い利きそうですが、ダウン接続をシャットダウンするには十分でありませんアプリケーションが証明書内のホスト名が十分に一致していないとみなした場合。もともと、ホスト名が一致していないと判断したらRuntimeExceptionをスローすることを考えていましたが、Springスタックがそれらを呑み込み、アプリケーションに起因する接続設定の失敗を引き起こしていないようです。

上記のSocketConfiguratorのアプローチは、証明書のホスト名が不一致とみなされた場合にTLS接続のセットアップを失敗させる推奨される方法であるsocket.close()を直接呼び出しますか?

答えて

1

"スプリングスタックは例外を呑み込む"という意味ではわかりません。右に聞こえません。あなたが私にそのコードを指し示すことができれば、私は一見することができます。

スプリング接続ファクトリは、ウサギ接続ファクトリに委任します。

ベストプラクティスに関する基本的な質問に対する回答がわかりません。 rabbitmq-usersのGoogleグループでウサギの人にpingをしたいかもしれません。

+0

私は、ホスト名がビジネスロジックごとに検証されないときにsocket.close()を呼び出すのではなく、新しいRuntimeException()をスローして、接続に失敗するとは限りませんアプリケーションにセットアップします。 RTEをスローすると接続設定が失敗すると思われましたが、それは良い仮定ではないかもしれません。 – ae6rt

+1

右ですが、実装しているインターフェースはrabnitmq cllient(実際にはSunリスナー)からのものです。 Springはそれを委譲し、__it__が例外をスローする場合にのみ反応します。したがって私の提案はウサギの人に尋ねるが、それはjvmの質問かもしれない。 rabbitmqクライアントを直接使用しているときに希望の結果が得られたら、それを理解するのを手伝ってうれしいです。私はちょうど春の問題(まだ)とは見ていない。 –

+1

[oracle docs](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HandShakeCompletedListener)は非常にまばらです。 SSLプロトコルハンドシェークが完了したことを「ちょうど」通知したことを考えると、呼び出し元は例外がスローされたと思われます。だから私はあなたの解決策は、完了するのが好きでない場合は、ソケットを閉じることができるすべてについて考えています。 –

関連する問題