Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/IM-459-New-Configure-keycloak-in…
Browse files Browse the repository at this point in the history
…-remote-engine' into IM-457-Merge-develop-in-IM-384
  • Loading branch information
kristinaBc3 committed Nov 20, 2024
2 parents e0dcde1 + 9f69087 commit 182ab89
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.integratedmodelling.klab.api.auth;

/**
* Defines constants for common HTTP headers.
*
* <p>This interface provides a set of predefined header names used
* in HTTP requests and responses. These constants can be used to
* avoid hardcoding string values and reduce errors.</p>
*
* @author Kristina
*/

public interface KlabHttpHeaders {

/**
* Designed to send session information with requests.
**/
public static final String KLAB_AUTHORIZATION = "Klab_Authorization";

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,8 @@ public class RemoteUserAuthenticationRequest extends UserAuthenticationRequest {

private String token;

/**
* @return the token
*/
public String getToken() {
return token;
}
/**
* @param token the token to set
*/
public void setToken(String token) {
this.token = token;
}

@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(token);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
RemoteUserAuthenticationRequest other = (RemoteUserAuthenticationRequest) obj;
return Objects.equals(token, other.token);
}

@Override
public String toString() {
return "RemoteUserAuthenticationRequest [username=" + getUsername() + ", token=" + getToken() + "]";
}
@Override
public String toString() {
return "RemoteUserAuthenticationRequest [username=" + getUsername() + ", token="+getToken()+"]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@

public class UserAuthenticationRequest {

private String username;
private String username;
private boolean remote = false;

private boolean remote = false;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public boolean isRemote() {
public boolean isRemote() {
return remote;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.integratedmodelling.klab.engine.rest.api;

import javax.validation.constraints.NotEmpty;


import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

@Component
@ConfigurationProperties("engine")
public class EngineProperties {

public EnvProperties env;

public EnvProperties getEnv() {
return env;
}

public void setEnv(EnvProperties env) {
this.env = env;
}

@Validated
public static class EnvProperties {

@NotEmpty
private String appBaseUrl;

@NotEmpty
private String keycloakUrl;

public String getAppBaseUrl() {
return appBaseUrl;
}

public void setAppBaseUrl(String appBaseUrl) {
this.appBaseUrl = appBaseUrl;
}

public String getKeycloakUrl() {
return keycloakUrl;
}

public void setKeycloakUrl(String keycloakUrl) {
this.keycloakUrl = keycloakUrl;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.integratedmodelling.klab.engine.rest.controllers.base;

import java.io.IOException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.integratedmodelling.klab.engine.rest.api.EngineProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class EnvironmentController {

@Autowired
private EngineProperties engineProperties;

private static final String APP_BASE_URL = "APP_BASE_URL";
private static final String KEYCLOAK_URL = "KEYCLOAK_URL";

@GetMapping(value = "/engine/environments")
public void getEnvironmentVariables(HttpServletRequest request, HttpServletResponse response) throws IOException {

response.setContentType("text/javascript;utf-8");

Map<String, String> kHubEnvironmentVariables = Map.ofEntries(Map.entry(APP_BASE_URL, engineProperties.env.getAppBaseUrl()),
Map.entry(KEYCLOAK_URL, engineProperties.env.getKeycloakUrl()));

ObjectMapper objectMapper = new ObjectMapper();
String jsonValue = objectMapper.writeValueAsString(kHubEnvironmentVariables);

System.out.println(jsonValue);

response.getWriter().append("var __ENV__= " + jsonValue + ";");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
*/
@RestController
@CrossOrigin(origins = "*")
@Secured(Roles.PUBLIC)
//@Secured(Roles.PUBLIC)
public class KlabController {

@RequestMapping(value = API.ENGINE.RESOURCE.GET_PROJECT_RESOURCE, method = RequestMethod.GET)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ public class EnginePublicController implements API.PUBLIC {
@RequestMapping(value = CREATE_CONTEXT, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public TicketResponse.Ticket contextRequest(@RequestBody ContextRequest request,
@RequestHeader(name = "Authorization") String session) {
@RequestHeader(name = "Klab_Authorization") String klabAuth, @RequestHeader(name = "Authorization") String auth) {

String session = klabAuth == null ? klabAuth : auth;

Session s = Authentication.INSTANCE.getIdentity(session, Session.class);
if (s == null) {
Expand Down Expand Up @@ -109,7 +111,7 @@ public TicketResponse.Ticket contextRequest(@RequestBody ContextRequest request,
@RequestMapping(value = OBSERVE_IN_CONTEXT, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public TicketResponse.Ticket observationRequest(@RequestBody ObservationRequest request,
@RequestHeader(name = "Authorization") String session, @PathVariable String context) {
@RequestHeader(name = "Klab_Authorization") String session, @PathVariable String context) {

Session s = Authentication.INSTANCE.getIdentity(session, Session.class);

Expand Down Expand Up @@ -143,7 +145,7 @@ public TicketResponse.Ticket observationRequest(@RequestBody ObservationRequest

@RequestMapping(value = SUBMIT_ESTIMATE, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public TicketResponse.Ticket submitEstimate(@RequestHeader(name = "Authorization") String session,
public TicketResponse.Ticket submitEstimate(@RequestHeader(name = "Klab_Authorization") String session,
@PathVariable String estimate) {

Session s = Authentication.INSTANCE.getIdentity(session, Session.class);
Expand All @@ -163,7 +165,8 @@ public TicketResponse.Ticket submitEstimate(@RequestHeader(name = "Authorization
}

if (est.contextRequest != null) {
return contextRequest(est.contextRequest, session);
//TODO only 1 sessioin parameter
return contextRequest(est.contextRequest, session, session);
}

return observationRequest(est.observationRequest, session, est.observationRequest.getContextId());
Expand All @@ -173,7 +176,7 @@ public TicketResponse.Ticket submitEstimate(@RequestHeader(name = "Authorization
MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_PDF_VALUE, MediaType.IMAGE_PNG_VALUE, "text/csv", "image/tiff",
"application/vnd.ms-excel", "application/octet-stream",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"})
public void exportData(@PathVariable String export, @RequestHeader(name = "Authorization") String session,
public void exportData(@PathVariable String export, @RequestHeader(name = "Klab_Authorization") String session,
@PathVariable String observation, @RequestHeader(name = "Accept") String format,
@RequestParam(required = false) String view, @RequestParam(required = false) String viewport,
@RequestParam(required = false) String locator, HttpServletResponse response) throws IOException {
Expand Down Expand Up @@ -385,7 +388,7 @@ private void outputImage(IObservation obs, HttpServletResponse response, Export

@RequestMapping(value = TICKET_INFO, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public TicketResponse.Ticket getTicketInfo(@RequestHeader(name = "Authorization") String session,
public TicketResponse.Ticket getTicketInfo(@RequestHeader(name = "Klab_Authorization") String session,
@PathVariable String ticket) {

Session s = Authentication.INSTANCE.getIdentity(session, Session.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
package org.integratedmodelling.klab.engine.rest.controllers.engine;

import java.security.Principal;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.integratedmodelling.klab.Authentication;
import org.integratedmodelling.klab.api.API;
import org.integratedmodelling.klab.api.auth.IIdentity;
import org.integratedmodelling.klab.api.auth.KlabHttpHeaders;
import org.integratedmodelling.klab.api.auth.Roles;
import org.integratedmodelling.klab.api.runtime.ISession;
import org.integratedmodelling.klab.engine.runtime.Session;
import org.integratedmodelling.klab.exceptions.KlabInternalErrorException;
import org.integratedmodelling.klab.rest.SessionReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
* The controller implementing the {@link org.integratedmodelling.klab.api.API.ENGINE.SESSION session API}.
* The controller implementing the
* {@link org.integratedmodelling.klab.api.API.ENGINE.SESSION session API}.
*
* @author ferdinando.villa
*
Expand All @@ -26,20 +42,57 @@
@Secured(Roles.SESSION)
public class EngineSessionController {

private static final Logger logger = LoggerFactory.getLogger(EngineSessionController.class);

@RequestMapping(value = API.ENGINE.SESSION.INFO, method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public SessionReference describeObservation(Principal principal) {
public SessionReference describeObservation(Principal principal, HttpServletRequest httpRequest) {

Map<String, String> headers = Collections.list(httpRequest.getHeaderNames()).stream()
.collect(Collectors.toMap(h -> h, httpRequest::getHeader));
ISession session = getSession(principal);
return ((Session)session).getSessionReference();
return ((Session) session).getSessionReference();
}

public static ISession getSession(Principal principal) {
if (principal instanceof PreAuthenticatedAuthenticationToken
|| !(((PreAuthenticatedAuthenticationToken) principal).getPrincipal() instanceof ISession)) {

if (principal instanceof PreAuthenticatedAuthenticationToken) {
return (ISession) ((PreAuthenticatedAuthenticationToken) principal).getPrincipal();
}

if (getCurrentHttpRequest() != null) {
String klabAuth = getCurrentHttpRequest().getHeader(KlabHttpHeaders.KLAB_AUTHORIZATION);

if (klabAuth != null) {
// send anything already known downstream
if (Authentication.INSTANCE.getIdentity(klabAuth, IIdentity.class) != null) {

IIdentity identity = Authentication.INSTANCE.getIdentity(klabAuth, IIdentity.class);
// known k.LAB identities are UserDetails and have established roles
if (identity instanceof UserDetails) {
return (ISession) identity;
} else if (identity != null) {
throw new KlabInternalErrorException(
"internal error: non-conformant session identity in Authentication catalog! "
+ identity);
}
}
}
}

throw new IllegalStateException(
"request was not authenticated using a session token or did not use preauthentication");

}

private static HttpServletRequest getCurrentHttpRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
return request;
}
logger.debug("Not called in the context of an HTTP request");
return null;
}

}
Loading

0 comments on commit 182ab89

Please sign in to comment.