Compare commits

...

7 Commits

32 changed files with 625 additions and 471 deletions

2
.vscode/launch.json vendored
View File

@ -9,7 +9,7 @@
{
"type": "java",
"name": "Debug (Attach)",
"projectName": "identity-manager",
"projectName": "idm-service",
"request": "attach",
"hostName": "localhost",
"port": 5005

View File

@ -1,10 +1,14 @@
ARG JAVA_VERSION=11
FROM d4science/smartgears-distribution:4.0.0-SNAPSHOT-java$JAVA_VERSION-tomcat10.1.19
#FROM smartgears-distribution:4.0.0-SNAPSHOT-java$JAVA_VERSION-tomcat10.1.19
ARG SMARTGEARS_VERSION=4.0.0-SNAPSHOT
COPY ./docker/logback.xml /etc/
COPY ./docker/container.ini /etc/
COPY ./docker/*.gcubekey /tomcat/lib
COPY ./target/idm.war /tomcat/webapps/
#FROM d4science/smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-tomcat10.1.19
FROM hub.dev.d4science.org/gcube/smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-tomcat10.1.19
#FROM smartgears-distribution:4.0.0-SNAPSHOT-java$JAVA_VERSION-tomcat10.1.19
ARG CONTAINER_INI="./docker/container.ini"
EXPOSE 8080
COPY ./docker/logback.xml /etc/
COPY ${CONTAINER_INI} /etc/container.ini
COPY ./docker/*.gcubekey /tomcat/lib
COPY ./target/idm-service.war /tomcat/webapps/
EXPOSE 8080

View File

@ -1,13 +1,30 @@
#!/bin/bash
accepted_java_versions=(11 17)
# set -x # uncomment to debug script
ACCEPTED_JAVA_VERSIONs=(11 17)
NAME=idm-service
BUILD_VERSION=0.0.1-SNAPSHOT
SMARTGEARS_VERSION=4.0.1-SNAPSHOT
CONTAINER_INI="./docker/container.ini"
IMAGE_VERSION=${BUILD_VERSION}-java${JAVA_VERSION}-smartgears${SMARTGEARS_VERSION}
NAME=identity-manager
PORT=8080
DEBUG_PORT=5005
DEBUG=false
EXECUTE=false
TEST=false
COMPILE=true
java_version=11
JAVA_VERSION=11
PUSH_DOCKER=false
PUSH_HARBOR=false
LOGIN_HARBOR=false
BUILD_NAME=$NAME:$IMAGE_VERSION
echo "BUILD_NAME=$BUILD_NAME"
################################################################################
# Help #
@ -18,14 +35,20 @@ Help() {
echo
echo "Syntax: buildDistribution [-n arg] [-p arg] [-j arg] [-d arg?] [-h]"
echo "options:"
echo "-s skip maven package"
echo "-n arg specifies the docker image name (default is identity-manager)."
echo "-p arg specifies the port to be exposed for the docker container to access the service (default $PORT)"
echo "-j arg specify java version (default is $java_version)"
echo " accepted version are: ${accepted_java_versions[@]}"
echo "-d arg? enable java debug mode"
echo " arg is the debug port (default is $DEBUG_PORT)"
echo "-h Print this Help."
echo "-s skip maven package"
echo "-t exec also maven tests"
echo "-n arg specifies the docker image name (default is identity-manager)."
echo "-p arg specifies the port to be exposed for the docker container to access the service (default $PORT)"
echo "-j arg specify java version (default is $JAVA_VERSION)"
echo " accepted version are: ${ACCEPTED_JAVA_VERSIONs[@]}"
echo "-e execute the image"
echo "-d arg? enable java debug mode for execution"
echo " arg is the debug port (default is $DEBUG_PORT)"
echo "-r push image to d4science harbo[r] (with login already done, or -l to login)"
echo "-l [l]ogin to d4science harbor"
echo "-u p[u]sh image to dockerhub (with docker login already done)"
echo "-c arg path of the file to deploy as container.ini (default ./docker/container.ini)"
echo "-h Print this Help."
echo
}
@ -37,28 +60,42 @@ Help() {
set -e
OPTSTRING=":sn:p:d:j:?h"
OPTSTRING=":slmurn:p:c:ed:j:?h"
while getopts $OPTSTRING opt; do
# echo "Option -${opt} was triggered, Argument: ${OPTARG}"
case "${opt}" in
s) COMPILE=false && echo "compile $COMPILE" ;;
c)
CONTAINER_INI=${OPTARG}
echo "CONTAINER_INI: $CONTAINER_INI";;
m) MULTI_PLATFORM=true ;;
n) NAME=${OPTARG} ;;
p) PORT=${OPTARG} ;;
u) PUSH_DOCKER=true ;;
l) LOGIN_HARBOR=true ;;
r) PUSH_HARBOR=true ;;
t) TEST=true ;;
e) EXECUTE=true ;;
d)
EXECUTE=true
DEBUG=true
DEBUG_PORT=${OPTARG}
echo "debug enabled, port $DEBUG_PORT"
;;
j)
if [[ ${accepted_java_versions[@]} =~ ${OPTARG} ]]; then
java_version=${OPTARG}
if [[ ${ACCEPTED_JAVA_VERSIONs[@]} =~ ${OPTARG} ]]; then
JAVA_VERSION=${OPTARG}
else
echo "Invalid java version" && echo "accepted version are: ${accepted_java_versions[@]}" && exit 1
echo "Invalid java version" && echo "accepted version are: ${ACCEPTED_JAVA_VERSIONs[@]}" && exit 1
fi
;;
h) Help && exit 0 ;;
:) # matched when an option that is expected to have an argument is passed without one
# matched when an option that is expected to have an argument is passed without one
:)
if [ ${OPTARG} = "d" ]; then
DEBUG=true
echo "debug enabled, port $DEBUG_PORT"
@ -76,15 +113,50 @@ while getopts $OPTSTRING opt; do
done
if [ $COMPILE = true ]; then
mvn clean package
if [ $TEST = false ]; then
mvn clean package -Dmaven.test.skip
else
mvn clean package
fi
else
echo "skipping mvn package"
fi
docker build -t $NAME --build-arg JAVA_VERSION=${java_version} .
if [ $DEBUG = false ]; then
docker run -p $PORT:8080 $NAME
if [ -z $MULTI_PLATFORM ]; then
docker build -t $BUILD_NAME --build-arg="CONTAINER_INI=$CONTAINER_INI" --build-arg="JAVA_VERSION=${JAVA_VERSION}" --build-arg="SMARTGEARS_VERSION=${SMARTGEARS_VERSION}" .
else
docker run -p $PORT:8080 -p $DEBUG_PORT:5005 -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=*:5005,server=y,suspend=y" $NAME
docker build -t $BUILD_NAME --build-arg="CONTAINER_INI=$CONTAINER_INI" --build-arg="JAVA_VERSION=${JAVA_VERSION}" --build-arg="SMARTGEARS_VERSION=${SMARTGEARS_VERSION}" --platform=linux/amd64,linux/arm64,linux/arm/v7 .
# docker manifest create hub.dev.d4science.org/gcube/$BUILD_NAME \
# hub.dev.d4science.org/gcube/$NAME-amd64-linux:$IMAGE_VERSION \
# hub.dev.d4science.org/gcube/$NAME-arm-linux:$IMAGE_VERSION \
# hub.dev.d4science.org/gcube/$NAME-arm-linux:$IMAGE_VERSION
fi
if [ ${PUSH_DOCKER} = true ]; then
DOCKER_NAME=d4science/$BUILD_NAME
docker tag $BUILD_NAME $DOCKER_NAME
docker push $DOCKER_NAME
echo ">>> pushed on dockerhub the image $DOCKER_NAME"
fi
if [ ${LOGIN_HARBOR} = true ]; then
./loginHarborHub.sh
fi
if [ $PUSH_HARBOR = true ]; then
HARBOR_NAME=hub.dev.d4science.org/gcube/$BUILD_NAME
echo ">>> PUSHING on hub.dev.d4science.org the image $HARBOR_NAME"
docker tag $BUILD_NAME $HARBOR_NAME
docker push $HARBOR_NAME
echo ">>> pushed on hub.dev.d4science.org the image $HARBOR_NAME"
fi
if [ $EXECUTE = true ]; then
if [ $DEBUG = true ]; then
docker run -p $PORT:8080 -p $DEBUG_PORT:5005 -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=*:5005,server=y,suspend=y" $BUILD_NAME
else
docker run -p $PORT:8080 $BUILD_NAME
fi
fi

13
loginHarborHub.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
REGISTRY_URL="hub.dev.d4science.org"
#USERNAME="alfredo.oliviero"
echo "to obtain Harbor username and CLI secret:"
echo "https://hub.dev.d4science.org/ -> user profile -> CLI secret"
read -p "username:" USERNAME
echo ""
read -s -p "CLI secret:" ACCESS_TOKEN
echo "$ACCESS_TOKEN" | docker login $REGISTRY_URL -u $USERNAME --password-stdin
unset ACCESS_TOKEN

46
pom.xml
View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.gcube.idm</groupId>
<artifactId>idm</artifactId>
<artifactId>idm-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Identity Manager (IDM) Service</name>
<description>Identity Manager (IDM) Service - Smartgears</description>
@ -55,13 +56,12 @@
</dependencyManagement>
<dependencies>
<!--
Keycloak use a older version of jackson (2.12.3).
some jackson libraries are imported only by keyclock,
not by smartgears so it mixed different versions.
We explicity import its jackson dependency to ovverride the version
-->
<dependency>
<groupId>org.gcube.idm</groupId>
<artifactId>idm-common-library</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
@ -160,12 +160,6 @@ solution: bind version, or exclude them in usermanagement-core
<artifactId>common-authorization</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-utils</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId>
@ -174,14 +168,23 @@ solution: bind version, or exclude them in usermanagement-core
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears-app</artifactId>
</dependency>
<!-- jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<scope>compile</scope>
</dependency>
<!--
https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-cdi2-se -->
<dependency>
@ -243,6 +246,13 @@ solution: bind version, or exclude them in usermanagement-core
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>compile</scope>
</dependency>
<!-- needed by com.liferay.portal -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
@ -270,8 +280,6 @@ java.lang.NoClassDefFoundError: org/apache/http/ssl/TrustStrategy
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--
@ -300,7 +308,7 @@ java.lang.NoClassDefFoundError: org/apache/http/ssl/TrustStrategy
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warName>identity-manager</warName>
<warName>idm-service</warName>
<outputDirectory>tomcat/webapps</outputDirectory>
</configuration>
</plugin>

View File

@ -1,5 +1,6 @@
package org.gcube.service.idm.controller;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -19,6 +20,7 @@ import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.WebApplicationException;
public class AdminKeycloakController {
@ -28,7 +30,8 @@ public class AdminKeycloakController {
// level)
// https://gist.github.com/thomasdarimont/c4e739c5a319cf78a4cff3b87173a84b
public static UserRepresentation createUser(String username, String email, String password, String firstName,
String lastName, Map<String, List<String>> attributes, List<String> roles) throws WebApplicationException {
String lastName, Map<String, List<String>> attributes, List<String> roles)
throws WebApplicationException, ServerException {
UserRepresentation newUser = new UserRepresentation();
newUser.setEnabled(true);
newUser.setUsername(username);

View File

@ -1,5 +1,6 @@
package org.gcube.service.idm.controller;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -112,6 +113,8 @@ public class KCClientsController {
* the context
*
* @param clientId null for current context
* @throws ServerException
* @throws NotFoundException
*/
public static List<UserRepresentation> getMemberGroupUsersCurrent() {
@ -126,6 +129,8 @@ public class KCClientsController {
* @param clientId null for current context
* @param firstResult
* @param maxResults
* @throws ServerException
* @throws NotFoundException
*/
public static List<UserRepresentation> getMemberGroupUsers(String clientId, Integer firstResult,
Integer maxResults) {

View File

@ -1,5 +1,6 @@
package org.gcube.service.idm.controller;
import java.rmi.ServerException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

View File

@ -1,5 +1,6 @@
package org.gcube.service.idm.controller;
import java.rmi.ServerException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

View File

@ -27,7 +27,7 @@ public class LiferayProfileClient {
}
return user;
} catch (NotFoundException | ServerException | UserManagementSystemException e) {
} catch (UserManagementSystemException e) {
e.printStackTrace();
throw new ServiceUnavailableException(errormsg);
} catch (UserRetrievalFault e) {

View File

@ -1,177 +0,0 @@
package org.gcube.service.idm.is;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.security.AuthorizedTasks;
import org.gcube.common.security.secrets.Secret;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.NotFoundException;
/**
* Utility class to query EndPoints and search for AccessPoints from IS
*
* @author Alfredo Oliviero (ISTI - CNR)
*/
public class InfrastrctureServiceClient {
private static final Logger logger = LoggerFactory.getLogger(InfrastrctureServiceClient.class);
/**
* obatins from IS the list of ServiceEndpoint matching the parameters
*
* @param resource_name
* @param category
* @param accessPointName
* @param is_root_service
*
* @return the list of EndPoints matching the parameters
* @throws Exception
*/
public static List<ServiceEndpoint> getEndopintsFromIS(String resource_name, String category,
boolean root_service) {
SimpleQuery query = queryFor(ServiceEndpoint.class);
if (resource_name != null) {
query.addCondition("$resource/Profile/Name/text() eq '" + resource_name + "'");
}
if (category != null) {
query.addCondition("$resource/Profile/Category/text() eq '" + category + "'");
}
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
ApplicationContext ctx = ContextProvider.get();
String infra_context = "/" + ctx.container().configuration().infrastructure();
Secret secret = ctx.container().authorizationProvider().getSecretForContext(infra_context);
List<ServiceEndpoint> endpoints = null;
try {
if (root_service) {
endpoints = AuthorizedTasks.executeSafely(() -> {
// esegui la query
List<ServiceEndpoint> toReturn = client.submit(query);
return toReturn;
}, secret);
} else {
endpoints = client.submit(query);
}
} catch (Throwable e) {
e.printStackTrace();
}
return endpoints;
}
/**
* obatains the list of AccessPoints matching the parameters
*
* @param resource_name
* @param category
* @param endPointName
* @param is_root_service
* @return the list of AccessPoints
* @throws Exception
*/
public static List<ServiceEndpoint.AccessPoint> getAccessPointsFromIS(String resource_name, String category,
String endPointName, boolean is_root_service) {
List<ServiceEndpoint> resources = getEndopintsFromIS(resource_name, category, is_root_service);
if (resources.size() == 0) {
logger.error("There is no Runtime Resource having name " + resource_name + " and Category "
+ category + " in this scope.");
return null;
}
List<ServiceEndpoint.AccessPoint> response = new ArrayList<ServiceEndpoint.AccessPoint>();
resources.forEach(res -> {
Stream<ServiceEndpoint.AccessPoint> access_points_res = res.profile().accessPoints().stream();
if (endPointName == null) {
access_points_res = access_points_res.filter(ap -> ap.name().equals(endPointName));
}
access_points_res.forEach(a -> response.add(a));
});
return response;
}
/**
* obatains the list of AccessPoints matching the parameters, and returns the
* first one
*
* @param resource_name
* @param category
* @param entryPointName
* @return an AccessPoints matching the parameters
* @throws Exception
*/
public static ServiceEndpoint.AccessPoint getFirstAccessPointFromIS(String resource_name, String category,
String entryPointName, boolean root_service) {
List<ServiceEndpoint.AccessPoint> access_points = getAccessPointsFromIS(resource_name, category, entryPointName,
root_service);
if (access_points.size() == 0) {
logger.error("Unable to retrieve service endpoint " + entryPointName);
return null;
}
return access_points.get(0);
}
/**
* Reads the service configuration from the IS
*
* @param resourceName
* @param category
* @param accessPointName
* @param is_root_service
* @return
* @throws Exception
*/
public static IsServerConfig serviceConfigFromIS(String resourceName, String category, String endPointName,
boolean is_root_service)
throws NotFoundException, ServerException {
logger.info("Starting creating service credentials");
ServiceEndpoint.AccessPoint accessPoint = InfrastrctureServiceClient.getFirstAccessPointFromIS(resourceName,
category, endPointName, is_root_service);
if (accessPoint == null) {
String error_log = "Unable to retrieve service endpoint " + endPointName;
logger.error(error_log);
throw new NotFoundException(error_log);
}
try {
IsServerConfig config = new IsServerConfig(accessPoint);
return config;
} catch (Exception e) {
logger.error("cannot create server config from {}", accessPoint);
e.printStackTrace();
throw new ServerException(e.getMessage());
}
}
}

View File

@ -1,89 +0,0 @@
package org.gcube.service.idm.is;
import java.util.HashMap;
import java.util.Map;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
import org.keycloak.OAuth2Constants;
public class IsServerConfig {
private String serverUrl;
private String name;
private String clientId;
private Map<String, String> properties = new HashMap<String, String>();
private String clientSecret;
private String grantType = OAuth2Constants.CLIENT_CREDENTIALS;
public Map<String, String> getProperties() {
return this.properties;
}
public String getServerUrl() {
return serverUrl;
}
public String getName() {
return name;
}
public String getClientId() {
return clientId;
}
public String getClientSecret() {
return clientSecret;
}
public String getGrantType() {
return grantType;
}
public boolean hasProperty(String key) {
return this.properties.containsKey(key);
}
public String getProperty(String key) {
return this.properties.get(key);
}
public IsServerConfig(String serverUrl, String name, String clientId, String clientSecret) {
this.serverUrl = serverUrl;
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
}
public IsServerConfig(String serverUrl, String name, String clientId, String clientSecret,
Map<String, String> properties) {
this(serverUrl, name, clientId, clientSecret);
this.properties = properties;
}
public IsServerConfig(ServiceEndpoint.AccessPoint accessPoint) throws Exception {
this.serverUrl = accessPoint.address();
this.name = accessPoint.name();
this.clientId = accessPoint.username();
this.clientSecret = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
this.properties = new HashMap<String, String>();
for (Property p : accessPoint.properties()) {
String value = p.value();
if (p.isEncrypted()) {
value = StringEncrypter.getEncrypter().decrypt(value);
}
this.properties.put(p.name(), value);
}
}
public IsServerConfig(String serverUrl, String name, String clientId, String clientSecret,
Map<String, String> properties,
String grantType) {
this(serverUrl, name, clientId, clientSecret, properties);
this.grantType = grantType;
}
}

View File

@ -4,8 +4,9 @@ import java.rmi.ServerException;
import java.util.List;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.service.idm.is.InfrastrctureServiceClient;
import org.gcube.service.idm.is.IsServerConfig;
import org.gcube.common.security.secrets.Secret;
import org.gcube.idm.common.is.InfrastrctureServiceClient;
import org.gcube.idm.common.is.IsServerConfig;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.ClientResource;
@ -14,6 +15,7 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.NotFoundException;
public class KkClientFactory {
@ -25,16 +27,11 @@ public class KkClientFactory {
private final static boolean IS_ROOT_SERVICE = true;
// the singleton obj
private IsServerConfig config;
private Secret secret;
private static KkClientFactory singleton = new KkClientFactory();
/**
* keycloak configuration obtained from IS in the private constructor
* using the singleton pattern, it's retrieved from IS only for the first
* access, then kept in the singleton object
*/
private IsServerConfig config;
public static KkClientFactory getSingleton() {
if (singleton == null)
singleton = new KkClientFactory();
@ -42,57 +39,47 @@ public class KkClientFactory {
}
/**
* Private constructor
* obtains the config from IS
* keycloak configuration obtained from IS in the private constructor
* using the singleton pattern, it's retrieved from IS only for the first
* access, then kept in the singleton object
*/
private KkClientFactory() {
logger.info("Building KeycloakAPICredentials object");
public Secret getSecret() {
return secret;
}
public void setSecret(Secret secret) {
this.secret = secret;
this.config = fetchIsConfig(this.secret);
}
// allows to configure the factory
// e.g. from external configuration file
public void setConfig(IsServerConfig configuration) {
config = configuration;
}
public IsServerConfig fetchIsConfig(Secret secret) throws InternalServerErrorException {
try {
if (this.config == null) {
this.config = fetchIsConfig();
}
logger.info("KeycloakAPICredentials object built {} - {}", config.getServerUrl(), config.getName());
if (this.secret == null)
this.secret = InfrastrctureServiceClient.getSecretForInfrastructure();
} catch (
IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY,
END_POINT_NAME, IS_ROOT_SERVICE, secret);
logger.info("KeycloakAPICredentials object built {} - {}", cfg.getServerUrl(), cfg.getName());
Exception e) {
logger.error("error obtaining IAM configuration from IS {} ", e);
return cfg;
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException(e);
}
}
// public IsServerConfig configFromINI() throws NotFoundException,
// ServerException{
// ApplicationContext appContext = ContextProvider.get();
// SimpleCredentials credentials =
// (SimpleCredentials)appContext.authorizationProvider().getCredentials();
// IsServerConfig cfg = fetchIsConfig();
// IsServerConfig newConfig = new IsServerConfig(
// cfg.getServerUrl(),
// cfg.getName(),
// credentials.getClientID(), // cfg.getClientId(),
// credentials.getSecret(), // cfg.getClientSecrxet(),
// cfg.getProperties()
// );
// return newConfig;s
// }
public IsServerConfig fetchIsConfig() throws NotFoundException, ServerException {
IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY,
END_POINT_NAME, IS_ROOT_SERVICE);
return cfg;
}
public static String encodeClientIdContext(String context) {
return context.replace("/", "%2F");
}
public KeycloackApiClient createtKeycloakInstance(String context) {
if (this.config == null) {
this.config = fetchIsConfig(this.secret);
}
return createtKeycloakInstance(this.config, context);
}
@ -140,12 +127,14 @@ public class KkClientFactory {
return realm.clients().get(id);
}
/**
* select the ClientResource by name, or current client if clientId parameter is null;
* select the ClientResource by name, or current client if clientId parameter is
* null;
*
* @param clientId
* @return
* @throws ServerException
* @throws NotFoundException
*/
public ClientResource getKKClientById(String clientId) {
@ -174,4 +163,7 @@ public class KkClientFactory {
// return new IsServerConfig(serverUrl, realm, clientId, clientSecret);
// }
public static String encodeClientIdContext(String context) {
return context.replace("/", "%2F");
}
}

View File

@ -1,14 +1,13 @@
package org.gcube.service.idm.liferay;
import java.rmi.ServerException;
import org.gcube.service.idm.is.InfrastrctureServiceClient;
import org.gcube.service.idm.is.IsServerConfig;
import org.gcube.common.security.secrets.Secret;
import org.gcube.idm.common.is.InfrastrctureServiceClient;
import org.gcube.idm.common.is.IsServerConfig;
import org.gcube.vomanagement.usermanagement.impl.ws.LiferayWSUserManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.InternalServerErrorException;
public class LiferayClientFactory {
private static final Logger logger = LoggerFactory.getLogger(LoggerFactory.class);
@ -22,49 +21,7 @@ public class LiferayClientFactory {
LiferayWSUserManager client = null;
private IsServerConfig config;
public static LiferayWSUserManager createtLiferayClientInstance(IsServerConfig config)
throws NotFoundException, ServerException {
String host = config.getServerUrl();
String schema = config.getProperty("schema");
String user = config.getProperty("username");
String password = config.getProperty("password");
Integer port = Integer.valueOf(config.getProperty("port"));
LiferayWSUserManager client = null;
try {
client = new LiferayWSUserManager(user, password, host, schema, port);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ServerException("cannot create Liferay client");
}
if (client == null) {
throw new ServerException("cannot create Liferay client");
}
logger.info("Liferay object built {} - {}", config.getServerUrl(), config.getName());
return client;
}
public IsServerConfig getConfig() throws NotFoundException, ServerException {
if (this.config == null) {
this.config = fetchIsConfig();
}
return this.config;
}
public LiferayWSUserManager getClient() throws NotFoundException, ServerException {
if (this.client == null) {
IsServerConfig configuration = this.getConfig();
this.client = createtLiferayClientInstance(configuration);
}
return this.client;
}
private Secret secret;
private static LiferayClientFactory singleton = new LiferayClientFactory();
@ -74,12 +31,75 @@ public class LiferayClientFactory {
return singleton;
}
public IsServerConfig fetchIsConfig() throws NotFoundException, ServerException {
IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY,
END_POINT_NAME,
IS_ROOT_SERVICE);
public Secret getSecret() {
return secret;
}
return cfg;
public void setSecret(Secret secret) {
this.secret = secret;
this.config = fetchIsConfig(this.secret);
}
public IsServerConfig fetchIsConfig(Secret secret) throws InternalServerErrorException {
try {
if (this.secret == null)
this.secret = InfrastrctureServiceClient.getSecretForInfrastructure();
IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY,
END_POINT_NAME, IS_ROOT_SERVICE, secret);
logger.info("KeycloakAPICredentials object built {} - {}", cfg.getServerUrl(), cfg.getName());
return cfg;
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException(e);
}
}
public LiferayWSUserManager createtLiferayClientInstance() {
if (this.config == null) {
this.config = fetchIsConfig(this.secret);
}
return createtLiferayClientInstance(this.config);
}
public static LiferayWSUserManager createtLiferayClientInstance(IsServerConfig config) {
String host = config.getServerUrl();
String schema = config.getProperty("schema");
String user = config.getProperty("username");
String password = config.getProperty("password");
Integer port = Integer.valueOf(config.getProperty("port"));
LiferayWSUserManager client = null;
try {
client = new LiferayWSUserManager(user, password, host, schema, port);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new InternalServerErrorException("cannot create Liferay client");
}
if (client == null) {
throw new InternalServerErrorException("cannot create Liferay client");
}
logger.info("Liferay object built {} - {}", config.getServerUrl(), config.getName());
return client;
}
// public IsServerConfig getConfig() {
// if (this.config == null) {
// this.config = fetchIsConfig();
// }
// return this.config;
// }
public LiferayWSUserManager getClient() {
if (this.client == null) {
this.client = createtLiferayClientInstance();
}
return this.client;
}
}

View File

@ -1,5 +1,7 @@
package org.gcube.service.idm.mappers;
import org.gcube.service.utils.beans.ResponseBean;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
@ -8,8 +10,6 @@ import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.gcube.service.rest.ResponseBean;
/**
* @author Alfredo Oliviero (ISTI - CNR)
*/

View File

@ -1,5 +1,7 @@
package org.gcube.service.idm.mappers;
import org.gcube.service.utils.beans.ResponseBean;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@ -7,8 +9,6 @@ import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.gcube.service.rest.ResponseBean;
/**
* @author Luca Frosini (ISTI - CNR)
*/

View File

@ -0,0 +1,300 @@
package org.gcube.service.idm.models;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.idm.common.models.IdmProfileInterface;
public class IdmUser implements IdmProfileInterface {
protected String self; // link
protected String id;
// protected String origin;
protected Long createdTimestamp;
protected String username;
protected Boolean enabled;
// protected Boolean totp;
protected Boolean emailVerified;
protected String firstName;
protected String lastName;
protected String email;
protected String federationLink;
protected String serviceAccountClientId; // For rep, it points to clientId (not DB ID)
// @JsonDeserialize(using = StringListMapDeserializer.class)
protected Map<String, List<String>> attributes;
// protected List<CredentialRepresentation> credentials;
// protected Set<String> disableableCredentialTypes;
protected List<String> requiredActions;
// protected List<FederatedIdentityRepresentation> federatedIdentities;
protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles;
// protected List<UserConsentRepresentation> clientConsents;
protected Integer notBefore;
// @Deprecated
// protected Map<String, List<String>> applicationRoles;
// @Deprecated
// protected List<SocialLinkRepresentation> socialLinks;
protected List<String> groups;
private Map<String, Boolean> access;
public String getSelf() {
return self;
}
public void setSelf(String self) {
this.self = self;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Long getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(Long createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Boolean isEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
// @Deprecated
// public Boolean isTotp() {
// return totp;
// }
// @Deprecated
// public void setTotp(Boolean totp) {
// this.totp = totp;
// }
public Boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(Boolean emailVerified) {
this.emailVerified = emailVerified;
}
public Map<String, List<String>> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, List<String>> attributes) {
this.attributes = attributes;
}
// public UserRepresentation singleAttribute(String name, String value) {
// if (this.attributes == null)
// this.attributes = new HashMap<>();
// attributes.put(name, (value == null ? new ArrayList<String>() :
// Arrays.asList(value)));
// return this;
// }
// public String firstAttribute(String key) {
// return this.attributes == null ? null
// : this.attributes.get(key) == null ? null
// : this.attributes.get(key).isEmpty() ? null :
// this.attributes.get(key).get(0);
// }
// public List<CredentialRepresentation> getCredentials() {
// return credentials;
// }
// public void setCredentials(List<CredentialRepresentation> credentials) {
// this.credentials = credentials;
// }
public List<String> getRequiredActions() {
return requiredActions;
}
public void setRequiredActions(List<String> requiredActions) {
this.requiredActions = requiredActions;
}
// public List<FederatedIdentityRepresentation> getFederatedIdentities() {
// return federatedIdentities;
// }
// public void setFederatedIdentities(List<FederatedIdentityRepresentation>
// federatedIdentities) {
// this.federatedIdentities = federatedIdentities;
// }
// public List<SocialLinkRepresentation> getSocialLinks() {
// return socialLinks;
// }
// public void setSocialLinks(List<SocialLinkRepresentation> socialLinks) {
// this.socialLinks = socialLinks;
// }
public List<String> getRealmRoles() {
return realmRoles;
}
public void setRealmRoles(List<String> realmRoles) {
this.realmRoles = realmRoles;
}
public Map<String, List<String>> getClientRoles() {
return clientRoles;
}
public void setClientRoles(Map<String, List<String>> clientRoles) {
this.clientRoles = clientRoles;
}
// public List<UserConsentRepresentation> getClientConsents() {
// return clientConsents;
// }
// public void setClientConsents(List<UserConsentRepresentation> clientConsents)
// {
// this.clientConsents = clientConsents;
// }
public Integer getNotBefore() {
return notBefore;
}
public void setNotBefore(Integer notBefore) {
this.notBefore = notBefore;
}
// @Deprecated
// public Map<String, List<String>> getApplicationRoles() {
// return applicationRoles;
// }
public String getFederationLink() {
return federationLink;
}
public void setFederationLink(String federationLink) {
this.federationLink = federationLink;
}
public String getServiceAccountClientId() {
return serviceAccountClientId;
}
public void setServiceAccountClientId(String serviceAccountClientId) {
this.serviceAccountClientId = serviceAccountClientId;
}
public List<String> getGroups() {
return groups;
}
public void setGroups(List<String> groups) {
this.groups = groups;
}
// /**
// * Returns id of UserStorageProvider that loaded this user
// *
// * @return NULL if user stored locally
// */
// public String getOrigin() {
// return origin;
// }
// public void setOrigin(String origin) {
// this.origin = origin;
// }
// public Set<String> getDisableableCredentialTypes() {
// return disableableCredentialTypes;
// }
// public void setDisableableCredentialTypes(Set<String>
// disableableCredentialTypes) {
// this.disableableCredentialTypes = disableableCredentialTypes;
// }
public Map<String, Boolean> getAccess() {
return access;
}
public void setAccess(Map<String, Boolean> access) {
this.access = access;
}
public Map<String, List<String>> toAttributes() {
Map<String, List<String>> attrs = new HashMap<>();
if (getAttributes() != null)
attrs.putAll(getAttributes());
if (getUsername() != null)
attrs.put("username", Collections.singletonList(getUsername()));
else
attrs.remove("username");
if (getEmail() != null)
attrs.put("email", Collections.singletonList(getEmail()));
else
attrs.remove("email");
if (getLastName() != null)
attrs.put("lastName", Collections.singletonList(getLastName()));
if (getFirstName() != null)
attrs.put("firstName", Collections.singletonList(getFirstName()));
return attrs;
}
}

View File

@ -14,9 +14,9 @@ import org.gcube.service.idm.controller.KCRolesController;
import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.service.utils.ErrorMessages;
import org.gcube.service.utils.beans.ResponseBean;
import org.gcube.service.utils.beans.ResponseBeanMap;
import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.GroupResource;
@ -235,8 +235,6 @@ public class ClientsAPI {
AuthController.checkIsRealmAdmin(ErrorMessages.RESERVED_PARAMETER + "client_id");
}
// String role_name = "Member";
boolean show_groups = !format_group.equals(KCGroupsController.REPR.none);

View File

@ -6,8 +6,8 @@ import java.util.Map;
import org.gcube.service.idm.controller.AuthController;
import org.gcube.service.idm.controller.JWTController;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean;
import org.gcube.service.utils.ErrorMessages;
import org.gcube.service.utils.beans.ResponseBean;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -27,8 +27,8 @@ import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("jwt")
public class JwtAPI {

View File

@ -8,9 +8,9 @@ import org.gcube.service.idm.controller.KCRolesController;
import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.service.rest.ResponseBeanPaginated;
import org.gcube.service.utils.beans.ResponseBean;
import org.gcube.service.utils.beans.ResponseBeanMap;
import org.gcube.service.utils.beans.ResponseBeanPaginated;
import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RoleResource;

View File

@ -5,8 +5,8 @@ import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.service.utils.ErrorMessages;
import org.gcube.service.utils.beans.ResponseBeanMap;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;

View File

@ -14,8 +14,8 @@ import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean;
import org.gcube.service.utils.ErrorMessages;
import org.gcube.service.utils.beans.ResponseBean;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.keycloak.admin.client.resource.RealmResource;
@ -200,7 +200,6 @@ public class SocialUsersAPI {
@QueryParam("max") @DefaultValue("100") int max,
@QueryParam("firstResult") @DefaultValue("0") int firstResult,
@QueryParam("maxResults") @DefaultValue("100") int maxResults) {
if (firstResult > 0) {
first = firstResult;

View File

@ -14,10 +14,10 @@ import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.service.rest.ResponseBeanPaginated;
import org.gcube.service.utils.ErrorMessages;
import org.gcube.service.utils.beans.ResponseBean;
import org.gcube.service.utils.beans.ResponseBeanMap;
import org.gcube.service.utils.beans.ResponseBeanPaginated;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.keycloak.admin.client.resource.RealmResource;
@ -65,8 +65,8 @@ import jakarta.ws.rs.core.Response;
@ManagedBy(IdMManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("users")
public class UserAPI {
@ -208,10 +208,16 @@ public class UserAPI {
UserRepresentation user = KCUserController.getUserByUsername(username);
result.put("user", user);
if (getProfile) {
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
result.put("profile", profile);
// throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
try {
if (getProfile) {
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
result.put("profile", profile);
// throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
}
} catch (Exception e) {
e.printStackTrace();
// throw new ServiceUnavailableException("Liferay portal: " + e.getMessage());
result.put("profile", null);
}
if (isInspect) {

View File

@ -1,4 +1,4 @@
package org.gcube.service.idm.rest.test;
package org.gcube.service.idm.rest.examples;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.security.providers.SecretManagerProvider;

View File

@ -1,4 +1,4 @@
package org.gcube.service.idm.rest.test;
package org.gcube.service.idm.rest.examples;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

View File

@ -1,4 +1,4 @@
package org.gcube.service.idm.rest.test;
package org.gcube.service.idm.rest.examples;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package org.gcube.service.idm.rest.test;
package org.gcube.service.idm.rest.examples;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,4 +1,4 @@
package org.gcube.service.rest;
package org.gcube.service.utils;
public class ErrorMessages {
@ -11,11 +11,6 @@ public class ErrorMessages {
public static final String RESERVED_PARAMETER = "The parameter can be used only by realm administrators: ";
//
// protected static final String CANNOT_RETRIEVE_SERVICE_ENDPOINT_INFORMATION =
// "Unable to retrieve such service endpoint information";

View File

@ -1,4 +1,4 @@
package org.gcube.service.rest;
package org.gcube.service.utils.beans;
import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package org.gcube.service.rest;
package org.gcube.service.utils.beans;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package org.gcube.service.rest;
package org.gcube.service.utils.beans;
/**
* Response bean

View File

@ -1,9 +1,13 @@
# OPENSTACK
* [ ] deploy su openstack
* [ ] aggiungere accounting
# CONFIGURAZIONE
* [ ] leggere parametri da file di container.ini
* [ ] rivedere gestione errori
*
# MASSI
* API REST social
@ -24,4 +28,3 @@
* [ ] implementare client (rif. gcat-client)
* [ ] verificare controllo diritti
* [ ] mettere su openstack