在Camel中使用publickey认证配置SCP路由的正确方法是什么?

Mak*_*oto 5 java jsch apache-camel

我目前正在利用Apache Camel(编写本文时的版本2.20.2)作为更大的ETL流程的一部分,将处理过的文件从Camel盒复制到另一台机器.

但是,我有一段时间处理SCP配置.其目的是使其不必在私钥所在的位置以及已知主机所在的位置之外提供更多内容.

以下是示例路线.样本路由仅用于交谈; 它可能不准确,但这里的意图不是将上游部分显示为"工作".我确信文件生成部分正在运行,因为我已经为它编写了上游测试.


什么有效:

如果我指定用户名和密码禁用严格的主机密钥检查,我的路由可行.

from("direct:init")
    .to("file:///tmp")
    .to("scp://my.server.local?username=makoto&password=XXXXXX" + 
                              "&preferredAuthentications=password" +
                              "&strictHostKeyChecking=no");
Run Code Online (Sandbox Code Playgroud)

当然,由于政策原因,没有严格的主机检查是绝对不首选的.

什么行不通:

  • 如果我指定我的用户名和密码,也不会禁用严格主机键检查,我得到这个错误:

    com.jcraft.jsch.JSchException: reject HostKey: my.server.local
        at com.jcraft.jsch.Session.checkHost(Session.java:789) ~[jsch-0.1.54.jar:na]
        at com.jcraft.jsch.Session.connect(Session.java:345) ~[jsch-0.1.54.jar:na]
        at org.apache.camel.component.scp.ScpOperations.createSession(ScpOperations.java:284) [camel-jsch-2.20.2.jar:2.20.2]
        at org.apache.camel.component.scp.ScpOperations.connect(ScpOperations.java:179) [camel-jsch-2.20.2.jar:2.20.2]
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果我指定我的用户名和密码,也不会禁用严格主机键检查,做指定我的首选认证方式为"密码",我得到了同样的错误如上.

  • 如果我省略了我的密码而支持指定我的私钥的路径,并且我禁用严格的主机密钥检查,我收到此错误:

    com.jcraft.jsch.JSchException: Auth cancel
        at com.jcraft.jsch.Session.connect(Session.java:518) ~[jsch-0.1.54.jar:na]
        at org.apache.camel.component.scp.ScpOperations.createSession(ScpOperations.java:284) [camel-jsch-2.20.2.jar:2.20.2]
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果我执行上述所有操作并将 publickey包含为首选身份验证,则会收到以下错误:

    com.jcraft.jsch.JSchException: Auth fail
        at com.jcraft.jsch.Session.connect(Session.java:519) ~[jsch-0.1.54.jar:na]
        at org.apache.camel.component.scp.ScpOperations.createSession(ScpOperations.java:284) [camel-jsch-2.20.2.jar:2.20.2]
        at org.apache.camel.component.scp.ScpOperations.connect(ScpOperations.java:179) [camel-jsch-2.20.2.jar:2.20.2]
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,似乎Camel完全忽略了我的用户,并且选择使用它自己:

    2018-02-19 10:46:15.142 DEBUG 23940 --- [obfuscated-route] o.a.camel.component.scp.ScpOperations    : Passphrase for camel-jsch
    2018-02-19 10:46:15.142  WARN 23940 --- [obfuscated-route] o.a.camel.component.scp.ScpOperations    : Private Key authentication not supported
    2018-02-19 10:46:15.142 DEBUG 23940 --- [obfuscated-route] o.a.camel.component.scp.ScpOperations    : Passphrase for camel-jsch
    2018-02-19 10:46:15.142  WARN 23940 --- [obfuscated-route] o.a.camel.component.scp.ScpOperations    : Private Key authentication not supported
    
    Run Code Online (Sandbox Code Playgroud)

毋庸置疑,这里的错误消息并没有给我带来太多的东西,因为:

  • 鉴于这种情况,他们会发生很大变化
  • 它们是特定于配置的; 就好像每个配置都缺少一些东西

考虑到这一点,配置这个的正确方法是什么?Camel邮件列表中的分散文档不会产生任何具体内容,SCP文档对这些情况几乎没有实际帮助.

其他一些需要注意的环境因素:

  • 我不"控制"Camel将要使用的机器,也不"控制"将接收文件的机器.
  • 我在我的机器上本地测试它,我的公钥完全包含在主机的authorized_keys文件中.
  • 我机器上的known_hosts条目经过哈希/混淆.

Mak*_*oto 5

这感觉令人难以置信的倒退和错误,但我相信我已经解决了我自己的问题。

执行摘要:

  • JSch 正在寻找您的散列主机名的匹配项。
  • 如果它无法通过您机器上的所有身份找到匹配项,它会将存储库标记为“不包含”。
  • 如果存储库没有标记为“OK”并且启用了严格的主机密钥检查,它将将此注册为失败。

执行解决方案:

  • 主机密钥必须添加到您的系统中(通过使用ssh-keyscan -t rsa -H <hostname>. 仅在目标机器上拥有主机密钥是不够的。
  • 如果您的私钥有密码,您仍然有义务提供它。

有趣的是,Camel 似乎使用自己的用户和身份连接到服务器的事实有点像吸烟枪。这让我从异常的角度观察代码流。

第一个我看到的是那个散列主机是无处的身份向量JSch被遍历被发现。这意味着,尽管我之前已经通过 SSH 连接到这台机器,但 JSch 没有它并且不知道它的存在。

所以我从这个服务器故障问题中找到了一些灵​​感,因为我需要将一个新的散列主机添加到我自己的身份文件中。

我有效地利用了这个答案,因为它似乎是最实用和最安全的方法:

  • ssh-keyscan -t rsa -H my.server.local
  • 从该命令的输出中显式复制 RSA -only 散列(我相信最多可以有 3 行)并将其附加到我的 known_hosts 文件的末尾

然而,我确实发现身份验证仍然莫名其妙地失败了。为了调试和诊断正在发生的事情,我选择保留私钥的路径,并将私钥的密码添加到系统中,以便 JSch 可以使用它。

我可以承认需要的密码是我的疏忽,但它无法选择一个理智的私钥来使用这一事实让我感到惊讶,特别是考虑到正常的 SSH 会遍历所有这些。

现在完成,完整的路线看起来像这样:

from("direct:init")
    .to("file:///tmp")
    .to("scp://my.server.local?username=makoto&privateKeyFilePassphrase=XXXXXX" + 
                          "&preferredAuthentications=publickey" +
                          "&privateKeyFile=/path/to/.ssh/id_rsa");
Run Code Online (Sandbox Code Playgroud)