diff options
Diffstat (limited to 'src')
4 files changed, 106 insertions, 17 deletions
diff --git a/src/main/java/net/libertacasa/pubsh/web/Docker.java b/src/main/java/net/libertacasa/pubsh/web/Docker.java index 1460bb3..6912d1b 100644 --- a/src/main/java/net/libertacasa/pubsh/web/Docker.java +++ b/src/main/java/net/libertacasa/pubsh/web/Docker.java @@ -1,17 +1,25 @@ package net.libertacasa.pubsh.web; import java.io.File; +import java.nio.file.Path; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; + +import org.springframework.core.io.ClassPathResource; + import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.BuildImageResultCallback; +import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectExecResponse.Container; import com.github.dockerjava.api.command.ListContainersCmd; +import com.github.dockerjava.api.command.ListImagesCmd; +import com.github.dockerjava.api.command.WaitContainerResultCallback; import com.github.dockerjava.api.model.Image; import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.core.DockerClientConfig; @@ -82,8 +90,11 @@ public class Docker { } public static String buildImage(String targetUser, String osChoice, Integer count) { - String dockerfile = "classpath:docker/Dockerfile-" + osChoice; - String tag = targetUser + ":sh" + count; + String dockerfile = "/home/georg/tmp/docker/Dockerfile_" + osChoice; + String tag = targetUser + ":sh" + count; + if (! new File(dockerfile).exists()) { + System.out.printf("\nInvalid Dockerfile: %s\n", dockerfile); + } Set<String> tags = new HashSet<String>(); tags.add(tag); String imgid = dockerClient.buildImageCmd() @@ -91,7 +102,39 @@ public class Docker { .withPull(false).withNoCache(false).withTags(tags) .exec(new BuildImageResultCallback()).awaitImageId(); + System.out.printf("\nBuilt image with ID %s", imgid); return(imgid); } + + public static void deleteImage(String username, String id) { + List<Image> imagequery = Docker.getImages(); + + if (imagequery.toString().contains(id)) { + System.out.printf("\nFound image ID %s, deleting ...", id); + dockerClient.removeImageCmd(id).withImageId(id).exec(); + } + if (! imagequery.toString().contains(id)) { + System.out.printf("\nImage ID %s not found.", id); + } + + } + + public static String createContainer(String imgid) { + //String containerid = dockerClient.createContainerCmd(imgid).exec(); + WaitContainerResultCallback resultCallback = new WaitContainerResultCallback(); + CreateContainerResponse createContainerResponse = dockerClient.createContainerCmd(imgid).exec(); + dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback); + try { + resultCallback.awaitCompletion(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String containerid = createContainerResponse.getId(); + //System.out.println(dockerClient.infoCmd().exec()); + + System.out.printf("\nCreated container with ID %s from image ID %s", containerid, imgid); + return(containerid); + } } diff --git a/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java b/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java index 630acf4..53f83ab 100644 --- a/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java +++ b/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java @@ -32,7 +32,6 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable(); super.configure(http); //.anonymous().disable() http .authorizeRequests() diff --git a/src/main/java/net/libertacasa/pubsh/web/WebApplication.java b/src/main/java/net/libertacasa/pubsh/web/WebApplication.java index e7b3cd2..bfdeb59 100644 --- a/src/main/java/net/libertacasa/pubsh/web/WebApplication.java +++ b/src/main/java/net/libertacasa/pubsh/web/WebApplication.java @@ -21,6 +21,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.MultiValueMap; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.DeleteMapping; //import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -36,7 +37,6 @@ import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.Image; import java.util.Random; -//@SessionAttributes("osChoice") @SpringBootApplication @Controller public class WebApplication { @@ -87,7 +87,7 @@ public class WebApplication { //System.out.println(images); List<Container> containers = Docker.getContainers(); //System.out.println(containers); - + model.addAttribute("docker_images", images); model.addAttribute("docker_containers", containers); @@ -113,30 +113,66 @@ public class WebApplication { username = String.valueOf(customClaims.get("username")); // [End] - System.out.printf("Deletion triggered for ID %s by %s (%s)", id, userid, username); + System.out.printf("\nDeletion triggered for ID %s by %s (%s)", id, userid, username); Docker.deleteContainer(id); return("redirect:/portal"); } - @PostMapping(path="/frontend/container/add",consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public static String addContainer(@RequestBody MultiValueMap<String, String> body, HttpServletRequest request) { + @DeleteMapping("/frontend/image/delete/{id}") + public static String deleteImage(@PathVariable String id, HttpServletRequest request, RedirectAttributes redirectAttributes) { + // [Start] This block should move to a logging method. It's only job is to print user details to the console. KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal(); String username= null; String userid = principal.getName(); IDToken token = principal.getAccount().getKeycloakSecurityContext().getIdToken(); Map<String, Object> customClaims = token.getOtherClaims(); username = String.valueOf(customClaims.get("username")); - String osChoice = (String) body.getFirst("osChoice"); + // [End] + + System.out.printf("\nImage deletion triggered for ID %s by %s (%s)", id, userid, username); + + try { + Docker.deleteImage(username, id); + String returnmessage = "Success - removed image with ID " + id + "!"; + redirectAttributes.addFlashAttribute("message", returnmessage); + } catch (com.github.dockerjava.api.exception.ConflictException exception) { + String returnmessage = "Error - Image is still being used by a container."; + redirectAttributes.addFlashAttribute("message", returnmessage); + } + + return("redirect:/portal"); + } + + @PostMapping(path="/frontend/container/add",consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public static String addContainer(@RequestBody MultiValueMap<String, String> body, HttpServletRequest request, RedirectAttributes redirectAttributes) { + KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal(); + String username = null; + String userid = principal.getName(); + IDToken token = principal.getAccount().getKeycloakSecurityContext().getIdToken(); + Map<String, Object> customClaims = token.getOtherClaims(); + username = String.valueOf(customClaims.get("username")); + String os = (String) body.getFirst("osChoice"); - System.out.printf("New container with OS %s requested by %s (%s)", osChoice, userid, username); + System.out.printf("\nNew container with OS %s requested by %s (%s)\n", os, userid, username); Random rand = new Random(); Integer randomInt = rand.nextInt(9999999-1111); Integer count = randomInt; - //Docker.buildImage(username, osChoice, count); + try { + String imageid = Docker.buildImage(username, os, count); + String returnmessage = "Success - built image with ID " + imageid + " and tag sh" + count + "!"; + redirectAttributes.addFlashAttribute("message", returnmessage); + } catch (Exception exception) { + redirectAttributes.addFlashAttribute("message", "Success!"); + String returnmessage = "Error - failed to build image :-("; + redirectAttributes.addFlashAttribute("message", returnmessage); + System.out.println(exception); + } + + //Docker.createContainer(imageid); return("redirect:/portal"); } diff --git a/src/main/resources/templates/portal.html b/src/main/resources/templates/portal.html index 836c42e..d2f1847 100644 --- a/src/main/resources/templates/portal.html +++ b/src/main/resources/templates/portal.html @@ -4,20 +4,32 @@ </head> <body> <div id="container"> + <div th:if="${message}" th:text="${message}" th:class="${'alert ' + alertClass}"/></div> <h1> Hello, <span th:text="${username}"></span>. </h1> <div th:if="${attribute01 != null}" th:text="${attribute01}"></div> - <h2>Available Docker Images:</h2> + <h2>Available images:</h2> <table> <tr th:each="image: ${docker_images}" th:if="${image.repoTags[0] != '<none>:<none>'}"> - <td th:text="${image.repoTags[0]}" /> - <td th:text="${image.created}" /> + <td> + <table> + <tr th:each="tag: ${image.repoTags}"> + <td th:text="${tag}"/> + <td> + <form id="deletion_pseudoform" action="#" th:action="@{'/frontend/image/delete/{id}'(id=${tag})}" th:method="delete" th:tag="${tag}" th:onsubmit="return confirm('Do you really want to delete the imag with tag ' + this.getAttribute('tag') + '?');"> + <button class="btn btn-danger" id="deletion_submission" type="submit">x</button> + </form> + </td> + </tr> + </table> + </td> + <td th:text="${image.created}" /> </tr> </table> <h2>Generate new throw-away shell:</h2> - <form th:object="${osChoice}" th:id="request_pseudoform" action="#" th:action="@{'/frontend/container/add'}" th:method="post" th:os="${osoption}" th:onsubmit="return confirm('You are about to generate a shell with the OS ' + this.getAttribute('os') + ' - please be patient after you confirm, as the generation may take a short while.');"> + <form th:object="${osChoice}" th:id="request_pseudoform" action="#" th:action="@{'/frontend/container/add'}" th:method="post" th:os="${osChoice}" th:onsubmit="return confirm('You are about to generate a shell with the OS ' + this.getAttribute('osoption') + ' - please be patient after you confirm, as the generation may take a short while.');"> <select class="form-control" th:object="${osChoice}" name="osChoice"> <option value="">Select operating system ...</option> <option @@ -26,14 +38,13 @@ th:attr="value=${osoption}" th:text="${osoption}"></option> </select> - <p><span th:text="${osChoice}"></span></p> <button class="btn btn-primary" th:id="request_submission" th:type="submit">Generate</button> </form> - <h2>Existing Containers:</h2> + <h2>Existing containers:</h2> <table> <tr th:each="container: ${docker_containers}"> <td th:text="${container.names[0]}" /> |