haskell amqp x509客户端身份验证

时间:2017-07-07 15:38:22

标签: haskell amqp x509

我一直在试图弄清楚如何将{x19客户端身份验证与Network.AMQP一起使用。我似乎需要创建一个AMQP.ConnectionOpts,其中coTLSSettings参数包括import qualified Network.AMQP as AMQP import Network.Connection let opts = AMQP.ConnectionOpts { .. , coTLSSettings = Just $ AMQP.TLSCustom $ ... } ,如下所示:

Network.Connection

此时(省略号),阅读了一些Network.Connection文档(而且远远超出了我的深度),它开始变得非常复杂。而且我想知道我是否会走这条路。

所以,我的问题:如何轻松实现x509客户端身份验证?如果答案是“你不能”,那么有谁知道我在哪里可以找到使用import re s = "1=value.2=value.4=value + 3=value.4=value+5=value" # finding the all value like '1=value' as a list new_dict_list = re.findall(r'\d+=?\w+', s) # declaring dict for creating key value dict new_dict={} # declare a dict for creating key counting repetition count_dict_key = {} for ls in new_dict_list: # split the list element for finding and storing key and value split_value = ls.split('=') key = split_value[0] value = split_value[1] # checking the repetition key if split_value[0] in new_dict: count_dict_key[key] = ''.join(new_dict_list).count(key) else: new_dict[split_value[0]]=value count_dict_key[split_value[0]]=1 print("printing new dictionary....\n",new_dict) print("counting key...\n",count_dict_key) 模块的x509客户端身份验证的示例?

1 个答案:

答案 0 :(得分:1)

我们需要做两件事(对于我的测试环境三件)。

  1. 阅读客户凭据
  2. 设置密码套件,因为defaultParamsClient设置了一个空的密码套件(我不知道为什么。)。
  3. (对于我的测试环境)读取CA根证书,以便我们验证提供给我们的服务器证书。如果您不在测试环境中,则应将此证书安装在系统证书存储中,并且应该是默认值。在这种情况下,您可以从程序中删除CertificateStore处理。
  4. 以下程序中的函数mkMyTLSSettingsdefaultParamsClient的结果替换为上述部分。在用作onCertificateRequest的函数中,您可以使用参数并根据参数values分发不同的凭据。读入所需的值 main要摆脱IO

    对于以下程序,我修改了在answer中找到的位。

    {-# LANGUAGE OverloadedStrings #-}
    module Main where
    
    import Data.Default.Class
    import Network.AMQP
    import Network.Socket.Internal (PortNumber)
    import Network.TLS
    import Network.TLS.Extra.Cipher (ciphersuite_default)
    import Data.X509.CertificateStore (CertificateStore (..), readCertificateStore)
    import Data.Maybe
    import qualified Data.ByteString as BS
    import qualified Network.Connection as C
    import qualified Data.ByteString.Lazy.Char8 as BL
    
    mkMyTLSSettings :: CertificateStore -> Credential -> C.TLSSettings
    mkMyTLSSettings castore creds =
      let defaultParams = defaultParamsClient "127.0.0.1" BS.empty
          newClientShared = (clientShared defaultParams) { sharedCAStore = castore }
          newClientSupported = (clientSupported defaultParams) { supportedCiphers = ciphersuite_default }
          newClientHooks = (clientHooks defaultParams) { onCertificateRequest = \_ -> return (Just creds) }
      in C.TLSSettings $ defaultParams { clientShared = newClientShared
                                       , clientSupported = newClientSupported
                                       , clientHooks = newClientHooks
                                       }
    
    myTLSSettings :: CertificateStore -> Credential -> TLSSettings
    myTLSSettings castore creds = TLSCustom $ mkMyTLSSettings castore creds
    
    myTLSConnectionOpts :: TLSSettings -> ConnectionOpts
    myTLSConnectionOpts opts = ConnectionOpts
      [("127.0.0.1", 5671 :: PortNumber)]
      "/"
      [plain "guest" "guest"]
      (Just 131072)
      Nothing
      (Just 1)
      (Just opts)
    
    testConnectionOpts :: ConnectionOpts -> IO ()
    testConnectionOpts opts = do 
       conn <- openConnection'' opts
       chan <- openChannel conn
       declareQueue chan newQueue {queueName = "hello"}
       putStrLn "Trying to register callback"
       consumeMsgs chan "hello" Ack myCallback
       publishMsg chan "" "hello" newMsg {msgBody = (BL.pack "hello world"), msgDeliveryMode = Just Persistent}
       getLine
       closeConnection conn
       putStrLn "connection closed"
    
    main :: IO ()
    main = do
      testConnectionOpts defaultConnectionOpts
      putStrLn "trying with tls"
      castore <- maybe (error "couldn't read CA root Certificate") id <$> (readCertificateStore "/pathto/rootCA.pem")
      creds <- either error id <$> credentialLoadX509 "/pathto/client.pem" "/pathto/client.key"
      let opts = myTLSSettings castore creds
      testConnectionOpts (myTLSConnectionOpts opts)
    
    myCallback :: (Message, Envelope) -> IO ()
    myCallback (msg, env) = do
      putStrLn $ "received message: " ++ (BL.unpack $ msgBody msg)
      ackEnv env
    

    作为gist

    我在这个程序中的第一次通信是为了确保rabbitmq设置正确,我真的只遇到了TLS错误。如果删除第20行和第23行,您可以测试是否正确配置了rabbitmq。在这种情况下,连接尝试失败,因为我们没有提供客户端证书。

    我创建了一个用于测试的玩具CA,并发布了一个用于rabbitmq服务器的证书和一个用于客户端的证书。所以我有一个文件rootCA.pem,它存储了CA根证书和rabbitmq.keyrabbitmq.pem之类的文件,用于设置带有rabbitmq的TLS。客户端也是client.pemclient.key。我将rabbitmq配置为仅通过设置为提供可信证书的客户提供服务 fail_if_no_peer_certtrue并设置{verify, verify_peer}选项。

    在我第一次尝试时,我遇到了LeafNotV3的错误,这意味着我在第一次尝试时创建了rabbitmq.pem错误。它是X509.v1证书,默认情况下Network.TLS不接受。我需要确保通过在颁发证书rabbitmq.pem时启用某些扩展来创建X509.v3证书,请参阅here。我需要将选项-req添加到那里引用的命令行以使其正常工作。