在 spring-boot 中从 application.yaml 文件中读取 SSH 私钥?
Reading SSH Private key from application.yaml file in spring-boot?
我有一个 camel 应用程序,它使用 SSH 私钥连接到 SFTP 服务器。如果我从文件中读取 id_rsa 文件,我就能够连接到服务器。正如此 example 中给出的那样,它正在从文件加载。
registry.put("privateKey", getBytesFromFile("./src/main/resources/id_rsa"));
private byte[] getBytesFromFile(String filename) throws IOException {
InputStream input;
input = new FileInputStream(new File(filename));
ByteArrayOutputStream output = new ByteArrayOutputStream();
IOHelper.copyAndCloseInput(input, output);
return output.toByteArray();
}
我想在运行时动态提供私钥。这意味着 application.yaml in spring-boot application,它将被 docker 容器环境变量替换。
@Value("${sftp_private_key}")
private String privateKey;
registry.put("privateKey", privateKey.getBytes());
我遇到了这个异常
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot connect to sftp://<user>@<sftp_server>:22
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:146) ~[camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.connectIfNecessary(RemoteFileConsumer.java:203) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.recoverableConnectIfNecessary(RemoteFileConsumer.java:171) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.prePollCheck(RemoteFileConsumer.java:59) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:110) [camel-core-2.19.1.jar:2.19.1]
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174) [camel-core-2.19.1.jar:2.19.1]
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101) [camel-core-2.19.1.jar:2.19.1]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_121]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@5e200110
at com.jcraft.jsch.KeyPair.load(KeyPair.java:757) ~[jsch-0.1.54.jar:na]
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:46) ~[jsch-0.1.54.jar:na]
at com.jcraft.jsch.JSch.addIdentity(JSch.java:442) ~[jsch-0.1.54.jar:na]
at org.apache.camel.component.file.remote.SftpOperations.createSession(SftpOperations.java:220) ~[camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:115) ~[camel-ftp-2.19.1.jar:2.19.1]
... 13 common frames omitted
经过一些调试,我明白这是 \n characters
的问题。如果我从文件中读取私钥包含 \n 字符。但是如果我从 .yaml 文件中读取,它没有 \n 字符。我将所有新行替换为 \n 字符并将其转换为单行。还是不行。
如何在 application.yaml
中提供相当于从该文件读取的值?
也许会有帮助:
这是我的代码的一部分,它从给定路径读取 PublicKey:
import com.google.common.io.BaseEncoding;
import java.io.DataInputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
public class PublicKeyReader {
public static PublicKey get(String filename)
throws Exception {
InputStream is = PublicKeyReader.class.getResourceAsStream("/keystore/" + filename);
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[is.available()];
dis.readFully(keyBytes);
dis.close();
String base64 = new String(keyBytes);
X509EncodedKeySpec spec
= new X509EncodedKeySpec(BaseEncoding.base64().decode(base64));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}
如 here 所述,它正在与 |
一起工作
示例application.yaml
:
sftp_private_key: |
----BEGIN RSA PRIVATE KEY-----
Remaining part of key
-----END RSA PRIVATE KEY-----
我有一个 camel 应用程序,它使用 SSH 私钥连接到 SFTP 服务器。如果我从文件中读取 id_rsa 文件,我就能够连接到服务器。正如此 example 中给出的那样,它正在从文件加载。
registry.put("privateKey", getBytesFromFile("./src/main/resources/id_rsa"));
private byte[] getBytesFromFile(String filename) throws IOException {
InputStream input;
input = new FileInputStream(new File(filename));
ByteArrayOutputStream output = new ByteArrayOutputStream();
IOHelper.copyAndCloseInput(input, output);
return output.toByteArray();
}
我想在运行时动态提供私钥。这意味着 application.yaml in spring-boot application,它将被 docker 容器环境变量替换。
@Value("${sftp_private_key}")
private String privateKey;
registry.put("privateKey", privateKey.getBytes());
我遇到了这个异常
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot connect to sftp://<user>@<sftp_server>:22
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:146) ~[camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.connectIfNecessary(RemoteFileConsumer.java:203) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.recoverableConnectIfNecessary(RemoteFileConsumer.java:171) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.RemoteFileConsumer.prePollCheck(RemoteFileConsumer.java:59) [camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:110) [camel-core-2.19.1.jar:2.19.1]
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174) [camel-core-2.19.1.jar:2.19.1]
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101) [camel-core-2.19.1.jar:2.19.1]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_121]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@5e200110
at com.jcraft.jsch.KeyPair.load(KeyPair.java:757) ~[jsch-0.1.54.jar:na]
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:46) ~[jsch-0.1.54.jar:na]
at com.jcraft.jsch.JSch.addIdentity(JSch.java:442) ~[jsch-0.1.54.jar:na]
at org.apache.camel.component.file.remote.SftpOperations.createSession(SftpOperations.java:220) ~[camel-ftp-2.19.1.jar:2.19.1]
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:115) ~[camel-ftp-2.19.1.jar:2.19.1]
... 13 common frames omitted
经过一些调试,我明白这是 \n characters
的问题。如果我从文件中读取私钥包含 \n 字符。但是如果我从 .yaml 文件中读取,它没有 \n 字符。我将所有新行替换为 \n 字符并将其转换为单行。还是不行。
如何在 application.yaml
中提供相当于从该文件读取的值?
也许会有帮助:
这是我的代码的一部分,它从给定路径读取 PublicKey:
import com.google.common.io.BaseEncoding;
import java.io.DataInputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
public class PublicKeyReader {
public static PublicKey get(String filename)
throws Exception {
InputStream is = PublicKeyReader.class.getResourceAsStream("/keystore/" + filename);
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[is.available()];
dis.readFully(keyBytes);
dis.close();
String base64 = new String(keyBytes);
X509EncodedKeySpec spec
= new X509EncodedKeySpec(BaseEncoding.base64().decode(base64));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}
如 here 所述,它正在与 |
示例application.yaml
:
sftp_private_key: |
----BEGIN RSA PRIVATE KEY-----
Remaining part of key
-----END RSA PRIVATE KEY-----