User/Admin logic
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
This commit is contained in:
parent
67ead5b62d
commit
f105d0e1ab
@ -6,11 +6,14 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import com.github.dockerjava.api.DockerClient;
|
import com.github.dockerjava.api.DockerClient;
|
||||||
import com.github.dockerjava.api.command.BuildImageResultCallback;
|
import com.github.dockerjava.api.command.BuildImageResultCallback;
|
||||||
import com.github.dockerjava.api.command.CreateContainerResponse;
|
import com.github.dockerjava.api.command.CreateContainerResponse;
|
||||||
|
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.command.WaitContainerResultCallback;
|
||||||
import com.github.dockerjava.api.model.Image;
|
import com.github.dockerjava.api.model.Image;
|
||||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||||
@ -44,15 +47,28 @@ public class Docker {
|
|||||||
return imageList;
|
return imageList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Image> getImages() {
|
public static List<Image> getImages(String name) {
|
||||||
List<Image> imageQuery;
|
List<Image> imageQuery;
|
||||||
imageQuery = dockerClient.listImagesCmd().exec();
|
ListImagesCmd imageQueryCmd = dockerClient.listImagesCmd();
|
||||||
|
|
||||||
|
if (name != null) {
|
||||||
|
imageQueryCmd.getFilters().put("reference", Arrays.asList(name + "*")); //to-do: filter by nameshX instead
|
||||||
|
}
|
||||||
|
|
||||||
|
imageQuery = imageQueryCmd.exec();
|
||||||
return imageQuery;
|
return imageQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<com.github.dockerjava.api.model.Container> getContainers() {
|
public static List<com.github.dockerjava.api.model.Container> getContainers(String name) {
|
||||||
List<com.github.dockerjava.api.model.Container> containerQuery;
|
List<com.github.dockerjava.api.model.Container> containerQuery;
|
||||||
containerQuery = dockerClient.listContainersCmd().withShowAll(true).exec();
|
ListContainersCmd containerQueryCmd = dockerClient.listContainersCmd();
|
||||||
|
|
||||||
|
if (name != null) {
|
||||||
|
containerQueryCmd.getFilters().put("name", Arrays.asList(name + "*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
containerQuery = containerQueryCmd.withShowAll(true).exec();
|
||||||
|
|
||||||
return containerQuery;
|
return containerQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +115,19 @@ public class Docker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteImage(String username, String id) {
|
public static void deleteImage(String username, String id) {
|
||||||
List<Image> imagequery = Docker.getImages();
|
List<Image> imagequery = Docker.getImages(null);
|
||||||
|
|
||||||
if (imagequery.toString().contains(id)) {
|
if (imagequery.toString().contains(id)) {
|
||||||
System.out.printf("Found image ID %s, deleting ...\n", id);
|
try {
|
||||||
dockerClient.removeImageCmd(id).withImageId(id).exec();
|
System.out.printf("Found image ID %s, deleting ...\n", id);
|
||||||
|
dockerClient.removeImageCmd(id).withImageId(id).exec();
|
||||||
|
} catch (com.github.dockerjava.api.exception.ConflictException exception) {
|
||||||
|
System.out.println("Image is still being used by a container.");
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
//needs to wait for callback, but there is none
|
||||||
|
//System.out.printf("%s", removeQuery);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (! imagequery.toString().contains(id)) {
|
if (! imagequery.toString().contains(id)) {
|
||||||
System.out.printf("Image ID %s not found.\n", id);
|
System.out.printf("Image ID %s not found.\n", id);
|
||||||
|
@ -33,6 +33,8 @@ import com.github.dockerjava.api.model.Image;
|
|||||||
@Controller
|
@Controller
|
||||||
public class WebApplication {
|
public class WebApplication {
|
||||||
|
|
||||||
|
static ArrayList<String> availableOs = new ArrayList<String>();
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(WebApplication.class, args);
|
SpringApplication.run(WebApplication.class, args);
|
||||||
}
|
}
|
||||||
@ -44,7 +46,7 @@ public class WebApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/portal")
|
@GetMapping("/portal")
|
||||||
public String portal(Model model) {
|
public String portal(Model model) throws pubshError {
|
||||||
KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken)
|
KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken)
|
||||||
SecurityContextHolder.getContext().getAuthentication();
|
SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
@ -53,13 +55,20 @@ public class WebApplication {
|
|||||||
String email="";
|
String email="";
|
||||||
String attribute01="";
|
String attribute01="";
|
||||||
|
|
||||||
|
if (! (principal instanceof KeycloakPrincipal)) {
|
||||||
|
System.out.println("Fatal: received logon without Keycloak principal.");
|
||||||
|
throw new pubshError("Invalid request.");
|
||||||
|
}
|
||||||
if (principal instanceof KeycloakPrincipal) {
|
if (principal instanceof KeycloakPrincipal) {
|
||||||
KeycloakPrincipal<?> kPrincipal = (KeycloakPrincipal<?>) principal;
|
KeycloakPrincipal<?> kPrincipal = (KeycloakPrincipal<?>) principal;
|
||||||
IDToken token = kPrincipal.getKeycloakSecurityContext().getIdToken();
|
IDToken token = kPrincipal.getKeycloakSecurityContext().getIdToken();
|
||||||
//System.out.println("Token: " + token);
|
//System.out.println("Token: " + token);
|
||||||
|
|
||||||
Map<String, Object> customClaims = token.getOtherClaims();
|
Map<String, Object> customClaims = token.getOtherClaims();
|
||||||
|
if (! customClaims.containsKey("username")) {
|
||||||
|
System.out.println("Fatal: received logon without username.");
|
||||||
|
throw new pubshError("Invalid request.");
|
||||||
|
}
|
||||||
if (customClaims.containsKey("email")) {
|
if (customClaims.containsKey("email")) {
|
||||||
email = String.valueOf(customClaims.get("email"));
|
email = String.valueOf(customClaims.get("email"));
|
||||||
}
|
}
|
||||||
@ -75,9 +84,10 @@ public class WebApplication {
|
|||||||
model.addAttribute("attribute01", attribute01);
|
model.addAttribute("attribute01", attribute01);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Image> images = Docker.getImages();
|
List<Image> images = Docker.getImages(null);
|
||||||
|
|
||||||
//System.out.println(images);
|
//System.out.println(images);
|
||||||
List<Container> containers = Docker.getContainers();
|
List<Container> containers = Docker.getContainers(null);
|
||||||
//System.out.println(containers);
|
//System.out.println(containers);
|
||||||
|
|
||||||
model.addAttribute("docker_images", images);
|
model.addAttribute("docker_images", images);
|
||||||
@ -94,6 +104,51 @@ public class WebApplication {
|
|||||||
return("portal");
|
return("portal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/user")
|
||||||
|
public String user(Model model) throws pubshError {
|
||||||
|
KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken)
|
||||||
|
SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
Principal principal = (Principal) authentication.getPrincipal();
|
||||||
|
String username="";
|
||||||
|
String email="";
|
||||||
|
String attribute01="";
|
||||||
|
if (! (principal instanceof KeycloakPrincipal)) {
|
||||||
|
System.out.println("Fatal: received logon without Keycloak principal.");
|
||||||
|
throw new pubshError("Invalid request.");
|
||||||
|
}
|
||||||
|
if (principal instanceof KeycloakPrincipal) {
|
||||||
|
KeycloakPrincipal<?> kPrincipal = (KeycloakPrincipal<?>) principal;
|
||||||
|
IDToken token = kPrincipal.getKeycloakSecurityContext().getIdToken();
|
||||||
|
Map<String, Object> customClaims = token.getOtherClaims();
|
||||||
|
if (! customClaims.containsKey("username")) {
|
||||||
|
System.out.println("Fatal: received logon without username.");
|
||||||
|
throw new pubshError("Invalid request.");
|
||||||
|
}
|
||||||
|
if (customClaims.containsKey("email")) {
|
||||||
|
email = String.valueOf(customClaims.get("email"));
|
||||||
|
}
|
||||||
|
if (customClaims.containsKey("username")) {
|
||||||
|
username = String.valueOf(customClaims.get("username"));
|
||||||
|
}
|
||||||
|
if (customClaims.containsKey("attribute01")) {
|
||||||
|
attribute01 = String.valueOf(customClaims.get("attribute01"));
|
||||||
|
}
|
||||||
|
model.addAttribute("username", username);
|
||||||
|
model.addAttribute("principalid", principal.getName());
|
||||||
|
model.addAttribute("email", email);
|
||||||
|
model.addAttribute("attribute01", attribute01);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Image> images = Docker.getImages(username);
|
||||||
|
List<Container> containers = Docker.getContainers(username);
|
||||||
|
|
||||||
|
model.addAttribute("docker_images", images);
|
||||||
|
model.addAttribute("docker_containers", containers);
|
||||||
|
model.addAttribute("availableOs", availableOs);
|
||||||
|
|
||||||
|
return("user");
|
||||||
|
}
|
||||||
|
|
||||||
@DeleteMapping("/frontend/container/delete/{id}")
|
@DeleteMapping("/frontend/container/delete/{id}")
|
||||||
public static String deleteContainer(@PathVariable String id, HttpServletRequest request, RedirectAttributes redirectAttributes) {
|
public static String deleteContainer(@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.
|
// [Start] This block should move to a logging method. It's only job is to print user details to the console.
|
||||||
@ -185,4 +240,15 @@ public class WebApplication {
|
|||||||
private RefreshableKeycloakSecurityContext getKeycloakSecurityContext(HttpServletRequest request){
|
private RefreshableKeycloakSecurityContext getKeycloakSecurityContext(HttpServletRequest request){
|
||||||
return (RefreshableKeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
return (RefreshableKeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class pubshError extends Exception
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public pubshError(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
62
src/main/resources/templates/user.html
Normal file
62
src/main/resources/templates/user.html
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head th:include="layout :: headerFragment">
|
||||||
|
</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 images:</h2>
|
||||||
|
<table>
|
||||||
|
<tr th:each="image: ${docker_images}" th:if="${image.repoTags[0] != '<none>:<none>'}">
|
||||||
|
<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="${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
|
||||||
|
th:each="osoption : ${availableOs}"
|
||||||
|
th:value="${osoption}"
|
||||||
|
th:attr="value=${osoption}"
|
||||||
|
th:text="${osoption}"></option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-primary" th:id="request_submission" th:type="submit">Generate</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Existing containers:</h2>
|
||||||
|
<table>
|
||||||
|
<tr th:each="container: ${docker_containers}">
|
||||||
|
<td th:text="${container.names[0]}" />
|
||||||
|
<td th:text="${container.image}" />
|
||||||
|
<td th:text="${container.id}" />
|
||||||
|
<td th:text="${container.status}" />
|
||||||
|
<td>
|
||||||
|
<form id="deletion_pseudoform" action="#" th:action="@{'/frontend/container/delete/{id}'(id=${container.id})}" th:method="delete" th:containerid="${container.id}" th:containerShaSum="${container.imageId}" th:onsubmit="return confirm('Do you really want to delete the container with ID ' + this.getAttribute('containerid') + ' which is attached to the image with checksum ' + this.getAttribute('containerShaSum') + ' ?');">
|
||||||
|
<button class="btn btn-danger" id="deletion_submission" type="submit">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p></p>
|
||||||
|
<a href="/logout">Logout</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user