aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/jshipit/ContainerManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/io/github/jshipit/ContainerManager.java')
-rw-r--r--src/main/java/io/github/jshipit/ContainerManager.java116
1 files changed, 104 insertions, 12 deletions
diff --git a/src/main/java/io/github/jshipit/ContainerManager.java b/src/main/java/io/github/jshipit/ContainerManager.java
index d276f75..4428465 100644
--- a/src/main/java/io/github/jshipit/ContainerManager.java
+++ b/src/main/java/io/github/jshipit/ContainerManager.java
@@ -17,18 +17,19 @@ public class ContainerManager {
private String containerImage;
private String containerTag;
private String containerApiRepo;
-
private String containerCommand;
private List<String> containerMounts;
+ private boolean containerIsolated;
private OCIDataStore dataStore;
- public ContainerManager(String containerName, String containerImage, String containerTag, String containerApiRepo, String containerRepo, List<String> containerMounts, OCIDataStore dataStore) {
+ public ContainerManager(String containerName, String containerImage, String containerTag, String containerApiRepo, String containerRepo, boolean containerIsolated, OCIDataStore dataStore) {
this.containerName = containerName;
this.containerImage = containerImage;
this.containerTag = containerTag;
this.containerApiRepo = containerApiRepo;
this.containerRepo = containerRepo;
- this.containerMounts = containerMounts;
+ this.containerMounts = null;
+ this.containerIsolated = containerIsolated;
this.dataStore = dataStore;
}
@@ -64,6 +65,36 @@ public class ContainerManager {
new File(containerDirectory + "/containerOverlay").mkdirs(); // The upper directory of the overlay mount, user data and any changes to root will be stored here
new File(containerDirectory + "/root").mkdirs(); // The root directory of the overlay mount
new File(containerDirectory+"/work").mkdirs(); // The work directory of the overlay mount
+
+ // Create the container TOML config file
+ try {
+ new File(containerDirectory + "/config.toml").createNewFile();
+ FileOutputStream fos = new FileOutputStream(containerDirectory + "/config.toml");
+
+ String str = "[container]\n";
+ str += "command = \"" + this.containerCommand + "\"\n";
+ str += "hostname = \"" + this.containerName + "\"\n\n";
+ str += "[permissions]\n";
+ str += "unshare-all = false\n";
+ str += "unshare-net = false\n";
+ str += "unshare-user = false\n";
+ str += "unshare-ipc = false\n";
+ str += "unshare-pid = false\n";
+ str += "unshare-uts = true\n";
+ str += "unshare-cgroup = false\n";
+ str += "mount-dev = true\n";
+ str += "mount-proc = true\n";
+ str += "mount-bind = []\n";
+
+ byte[] b = str.getBytes();
+ fos.write(b);
+ fos.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
}
/*
@@ -104,6 +135,7 @@ public class ContainerManager {
public void runCommand() {
String containerDirectory = dataStore.getContainerPath(this.containerName);
String dataStorePath = dataStore.getPath();
+ ConfigParser configParser = new ConfigParser(containerDirectory+"/config.toml");
File configPath = new File(dataStorePath + "/" + this.containerImage + "/" + this.containerTag + "/config"); // Path to the config file of the image
String content = null;
@@ -122,8 +154,8 @@ public class ContainerManager {
config.get("Env").forEach((JsonNode envVar) -> { // Get the environment variables specified in the config file
env.add(envVar.asText());
});
- cmd = config.get("Cmd").get(0).asText(); // Get the command specified in the config file
- hostname = config.get("Hostname").asText(); // Get the hostname specified in the config file
+ cmd = configParser.getString("container.command").equals("null") ? config.get("Cmd").get(0).asText() : configParser.getString("container.command"); // Get the command specified in the config file
+ hostname = configParser.getString("container.hostname").equals("null") ? config.get("Hostname").asText() : configParser.getString("container.hostname"); // Get the hostname specified in the config file
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
@@ -140,16 +172,12 @@ public class ContainerManager {
bwrapCommand.add("--bind "+containerDirectory+"/root / --chdir /"); // Bind the root to / inside the bwrap namespace
- if (this.containerMounts != null) {
- for (String mount : containerMounts) {
- bwrapCommand.add("--bind "+mount.split(":")[0]+" "+mount.split(":")[1]); // Bind the mount to the destination specified in the config file
- }
+ if (!configParser.getBoolean("permissions.unshare-all")) {
+ processBwrapPermissions(bwrapCommand);// Process the permissions specified in the config file
}
- bwrapCommand.add("--ro-bind /etc/resolv.conf /etc/resolv.conf"); // Bind the host resolv.conf to the container
- bwrapCommand.add("--share-net"); // Share the network namespace
- bwrapCommand.add("--unshare-uts --hostname "+ (!hostname.isBlank() ? hostname : this.containerName+"-"+this.containerImage)); // Unshare the UTS namespace and set the hostname
bwrapCommand.add("/bin/sh -c '"+(this.containerCommand != null ? this.containerCommand : cmd)+"'"); // Run the command specified in the config file or the command specified in the constructor
+
SysUtils sysUtils = new SysUtils();
String bwrapCMD = sysUtils.execInBwrap(bwrapCommand.toArray(new String[0]), false);
String mountCMD = startContainer(true);
@@ -165,6 +193,70 @@ public class ContainerManager {
}
}
+ private void processBwrapPermissions(List<String> bwrapCommand) {
+ ConfigParser configParser = new ConfigParser(dataStore.getContainerPath(this.containerName)+"/config.toml");
+ List<String> configMounts = configParser.getList("permissions.mount-bind");
+ if (configMounts.size() > 0) {
+ for (String mount : configMounts) {
+ bwrapCommand.add("--bind "+mount.split(":")[0]+" "+mount.split(":")[1]); // Bind the mount to the destination specified in the config file
+ }
+ }
+ if (this.containerMounts != null) {
+ for (String mount : containerMounts) {
+ bwrapCommand.add("--bind "+mount.split(":")[0]+" "+mount.split(":")[1]); // Bind the mount to the destination specified by the user
+ }
+ }
+
+ if (configParser.getBoolean("permissions.mount-dev")) {
+ bwrapCommand.add("--dev /dev"); // Mount /dev
+ }
+
+ if (configParser.getBoolean("permissions.mount-proc")) {
+ bwrapCommand.add("--proc /proc"); // Mount /proc
+ }
+
+ if (!configParser.getBoolean("permissions.unshare-net")) {
+ bwrapCommand.add("--ro-bind /etc/resolv.conf /etc/resolv.conf"); // Bind the host resolv.conf to the container
+ bwrapCommand.add("--share-net"); // Share the network namespace
+ } else {
+ bwrapCommand.add("--unshare-net"); // Unshare the network namespace
+ }
+
+ if (configParser.getBoolean("permissions.unshare-uts")) {
+ bwrapCommand.add("--unshare-uts"); // Unshare the UTS namespace
+
+ bwrapCommand.add("--hostname "+(configParser.getString("container.hostname").equals("null") ? this.containerName : configParser.getString("container.hostname"))); // Set the hostname
+ }
+
+ if (configParser.getBoolean("permissions.unshare-user")) {
+ bwrapCommand.add("--unshare-user"); // Unshare the user namespace
+ }
+
+ if (configParser.getBoolean("permissions.unshare-ipc")) {
+ bwrapCommand.add("--unshare-ipc"); // Unshare the IPC namespace
+ }
+
+ if (configParser.getBoolean("permissions.unshare-pid")) {
+ bwrapCommand.add("--unshare-pid"); // Unshare the PID namespace
+ }
+
+ if (configParser.getBoolean("permissions.unshare-uts")) {
+ bwrapCommand.add("--unshare-uts"); // Unshare the UTS namespace
+ }
+
+ if (configParser.getBoolean("permissions.unshare-cgroup")) {
+ bwrapCommand.add("--unshare-cgroup"); // Unshare the cgroup namespace
+ }
+
+ if (configParser.getBoolean("permissions.mount-dev")) {
+ bwrapCommand.add("--dev /dev"); // Mount /dev
+ }
+
+ if (configParser.getBoolean("permissions.mount-proc")) {
+ bwrapCommand.add("--proc /proc"); // Mount /proc
+ }
+ }
+
/*
* Delete a container
*/