skip to Main Content

I have been trying to execute bash commands in Java. I have done it with a couple of ovations, for instance:

try {
    Process p = Runtime.getRuntime().exec(new String[]{"bash", "-c", "cd " + folder + "&& find . -type f | grep :*.txt "});
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
    return stdInput.lines().count();
} catch (IOException e) {
    throw new RuntimeException(e);
}

This code works properly, without any errors.

I have tried to use docker with java, in 2 different ways. First way was the "Runtime.exec()", as in the previous example:

Process p = Runtime.getRuntime().exec(new String[]{"bash", "-c", "cd", "~/IdeaProjects/test/src/main/java/Docker", "&& docker", "build", " -f", "Dockerfile.txt", "-t", "java-app9", "."});

The other way was to use the "ProcessBuilder", as in the following example:

ProcessBuilder processBuilder = new ProcessBuilder();

processBuilder.command("sh","cd", "/home/alex/IdeaProjects/test/src/main/java/Docker", "&& docker", "build", " -f", "Dockerfile.txt", "-t", "java-app1", ".");

Process process =processBuilder.start();

Both ways do not work without throwing any error.

I have tried also to do it in python:

import os


os.system('''cd /home/alex/IdeaProjects/test/src/main/java/Docker && docker build -f Dockerfile.txt -t java-app3 . ''')

The python works as it is presented in the following picture:

enter image description here

I expect from this code to run java and create custom containers directly from java. I am using Java 19 and Docker version 20.10.21 .

2

Answers


  1. try to add "/c" at the end of your string, it use to start the command you refer.

    Login or Signup to reply.
  2. When you invoke a command in Unix, you provide a sequence of "words". These are not processed or reinterpreted at all; the first word is the command to invoke and the remaining words are its arguments. (In a Dockerfile, compare to the JSON-array exec-form syntax of CMD.)

    In your examples, you’re trying to mix this string-array syntax with shell constructs. If you try to run "bash", "foo", "&&", "bar", then it will specifically use bash as an interpreter to run foo as a shell script, passing it two arguments && and bar. In your very first example you use sh -c passing the rest of the command as a single argument. This has the right effect, but it makes you vulnerable to a shell injection attack if, for example, the folder name includes a semicolon.

    String folder = "; rm -rf /;";
    // uh oh
    Runtime.getRuntime().exec(new String[]{"bash", "-c", "cd " + folder + "&& ..."});
    

    All of your commands are of the form cd directory && command. You can use ProcessBuilder.directory() to set the directory name, and then directly run command without actually involving a shell. This both solves your problem and the security issue.

    Process process = new ProcessBuilder()
      .directory(new File("/home/alex/IdeaProjects/test/src/main/java/Docker"))
      .command("docker", "build", " -f", "Dockerfile.txt", "-t", "java-app1", ".")
      .start();
    

    The actual right answer to this is to use a Docker SDK rather than invoke the docker CLI tool. Using docker-java, for example, you might write

    DockerClientConfig standard = DefaultDockerClientConfig
      .createDefaultConfigBuilder()
      .build();
    DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
      .dockerHost(config.getDockerHost())
      .sslConfig(config.getSSLConfig())
      .build();
    DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient);
    
    dockerClient.buildImageCmd()
      .withBaseDirectory(new File("/home/alex/IdeaProjects/test/src/main/java/Docker"))
      .withDockerfilePath("Dockerfile.txt")
      .withTags(Set.of("java-app1"))
      .start();
    // ...and wait for its completion
    

    Remember in any case that, if you can access the Docker socket at all, then you can launch a new container, running as root, bind-mounting the host filesystem, and take over the whole machine.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search