I need an ssh key in my Openshift pod to access a server from inside my application logic (Java). My application tries to add a id_ed25519 file to the pod on startup:
String executeString = "mkdir ~/.ssh && echo $SSH_CERT > ~/.ssh/id_ed25519";
Process process = Runtime.getRuntime().exec(executeString);
...
$SSH_CERT
is a OS secret string value.
This doesn't throw an error but also doesn't seem to work (ls ~/.ssh/
in the pods terminal doesn't list anything).
Is ~/.ssh the right place for this file? Is there a different, easier way to add files to a pod?
I finally found a solution! :)
There were two main problems that I had to solve:
1. How to solve permissions
I added the directory and file inside my Dockerfile. Then I gave permissions to the newly created file. Security input: If you can, try not to give permissions to all users like I do (we have dynamic user ids...) but give it to least possible users.
RUN mkdir -p ~/.ssh/
RUN touch ~/.ssh/id_ed25519
RUN chmod a+rw ~/.ssh/id_ed25519
2. How to get proper output
I added a method that looks like this:
private void attachCommandOutputStreams(Process process) {
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
InputStream errorStream = process.getErrorStream();
InputStreamReader errorStreamReader = new InputStreamReader(errorStream);
BufferedReader errorBufferedReader = new BufferedReader(errorStreamReader);
// Create a separate thread to read from the error stream
Thread errorThread = new Thread(new Runnable() {
@Override
public void run() {
try {
String line;
while ((line = errorBufferedReader.readLine()) != null) {
log.error(line);
}
} catch (IOException e) {
log.error(e.toString());
}
}
});
errorThread.start();
try {
// Read from the standard output stream in the current thread
String line;
while ((line = bufferedReader.readLine()) != null) {
log.info("Standard output: " + line);
}
// Wait for the error thread to complete
errorThread.join();
// Close the readers
bufferedReader.close();
errorBufferedReader.close();
} catch (InterruptedException | IOException e) {
log.error("Error: ", e);
}
}
Then it is called like this:
Process process = Runtime.getRuntime().exec(new String[]{"sh", "-c", executeString});
this.attachCommandOutputStreams(process);
int exitCode = process.waitFor();
assert exitCode == 0;