config keycloak client
This commit is contained in:
parent
9508b7329c
commit
bc534cc6cb
|
@ -4,6 +4,8 @@
|
|||
// Per altre informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Debug (Attach)",
|
||||
|
|
|
@ -4,6 +4,7 @@ FROM d4science/smartgears-distribution:4.0.0-SNAPSHOT-java$JAVA_VERSION-tomcat10
|
|||
|
||||
COPY ./docker/logback.xml /etc/
|
||||
COPY ./docker/container.ini /etc/
|
||||
COPY ./docker/devsec.gcubekey /tomcat/lib
|
||||
COPY ./target/idm.war /tomcat/webapps/
|
||||
|
||||
EXPOSE 8080
|
||||
|
|
|
@ -42,14 +42,16 @@ OPTSTRING=":sn:p:d:j:?h"
|
|||
while getopts $OPTSTRING opt; do
|
||||
# echo "Option -${opt} was triggered, Argument: ${OPTARG}"
|
||||
case "${opt}" in
|
||||
s) COMPILE=false && echo "compile $COMPILE" ;;
|
||||
n) NAME=${OPTARG} ;;
|
||||
p) PORT=${OPTARG} ;;
|
||||
d) DEBUG=true
|
||||
s) COMPILE=false && echo "compile $COMPILE" ;;
|
||||
n) NAME=${OPTARG} ;;
|
||||
p) PORT=${OPTARG} ;;
|
||||
d)
|
||||
DEBUG=true
|
||||
DEBUG_PORT=${OPTARG}
|
||||
echo "debug enabled, port $DEBUG_PORT"
|
||||
;;
|
||||
j) if [[ ${accepted_java_versions[@]} =~ ${OPTARG} ]]; then
|
||||
j)
|
||||
if [[ ${accepted_java_versions[@]} =~ ${OPTARG} ]]; then
|
||||
java_version=${OPTARG}
|
||||
else
|
||||
echo "Invalid java version" && echo "accepted version are: ${accepted_java_versions[@]}" && exit 1
|
||||
|
@ -57,10 +59,10 @@ while getopts $OPTSTRING opt; do
|
|||
;;
|
||||
h) Help && exit 0 ;;
|
||||
:) # matched when an option that is expected to have an argument is passed without one
|
||||
if [ ${OPTARG} = "d" ]; then
|
||||
if [ ${OPTARG} = "d" ]; then
|
||||
DEBUG=true
|
||||
echo "debug enabled, port $DEBUG_PORT"
|
||||
else
|
||||
else
|
||||
# matched when an option that is expected to have an argument is passed without one
|
||||
echo "Option -${OPTARG} requires an argument."
|
||||
exit 1
|
||||
|
@ -73,7 +75,7 @@ while getopts $OPTSTRING opt; do
|
|||
esac
|
||||
done
|
||||
|
||||
if [ $COMPILE = true ]; then
|
||||
if [ $COMPILE = true ]; then
|
||||
mvn clean package
|
||||
else
|
||||
echo "skipping mvn package"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
container*.ini
|
||||
!container.default.ini
|
||||
*.gcubekey
|
|
@ -20,6 +20,7 @@ location = pisa
|
|||
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
|
||||
factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
|
||||
credentials.class = org.gcube.smartgears.security.SimpleCredentials
|
||||
#credentials.clientID = node-whn-test-uno-d-d4s.d4science.org
|
||||
credentials.clientID = alfredo-idm-service-dev
|
||||
credentials.secret = 979bd3bc-5cc4-11ec-bf63-0242ac130002
|
||||
credentials.clientID =
|
||||
credentials.secret =
|
||||
|
||||
|
|
@ -11,9 +11,9 @@
|
|||
<servlet-name>idm</servlet-name>
|
||||
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>jersey.config.server.provider.packages</param-name>
|
||||
<param-value>org.gcube.service.idm.rest</param-value>
|
||||
</init-param>
|
||||
<param-name>jersey.config.server.provider.packages</param-name>
|
||||
<param-value>org.gcube.service.idm.rest</param-value>
|
||||
</init-param>
|
||||
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
|
|
11
pom.xml
11
pom.xml
|
@ -262,6 +262,17 @@ java.lang.NoClassDefFoundError: org/apache/http/ssl/TrustStrategy
|
|||
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.gcube.resources.discovery</groupId>
|
||||
<artifactId>ic-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-scope</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency> -->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -8,17 +8,16 @@ public class KeycloackApiClient {
|
|||
public String clientIdContext;
|
||||
public String context;
|
||||
|
||||
public static String getClientIdContext(String context) {
|
||||
public static String encodeClientIdContext(String context) {
|
||||
return context.replace("/", "%2F");
|
||||
}
|
||||
|
||||
public KeycloackApiClient(Keycloak kclient, String realmName, String context) {
|
||||
this.clientIdContext = getClientIdContext(context);
|
||||
this.clientIdContext = encodeClientIdContext(context);
|
||||
this.context = context;
|
||||
this.kclient = kclient;
|
||||
this.realmName = realmName;
|
||||
// ClientsResource clients = kclient.realm(realmName).clients().get*
|
||||
// clients.get(context);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
package org.gcube.keycloack;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import jakarta.ws.rs.InternalServerErrorException;
|
||||
|
||||
import org.gcube.common.authorization.utils.secret.JWTSecret;
|
||||
import org.gcube.common.keycloak.DefaultKeycloakClient;
|
||||
import org.gcube.common.keycloak.KeycloakClientException;
|
||||
import org.gcube.common.keycloak.KeycloakClientFactory;
|
||||
import org.gcube.common.keycloak.model.TokenResponse;
|
||||
import org.gcube.common.security.providers.SecretManagerProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.gcube.common.authorization.utils.secret.Secret;
|
||||
|
||||
/***
|
||||
* from gcat implementation
|
||||
*
|
||||
*/
|
||||
public class KeycloackClientGcatFactory {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(KeycloackClientGcatFactory.class);
|
||||
|
||||
public static final String CATALOGUE_NAME = "IDM";
|
||||
|
||||
protected static final String CLIENT_ID_SECRET_FILENAME = "config.properties";
|
||||
protected static final String CLIENT_ID_PROPERTY_NAME = "clientId";
|
||||
|
||||
public String context;
|
||||
public String clientId;
|
||||
public String clientSecret;
|
||||
public DefaultKeycloakClient gcubeKeycloakClient;
|
||||
|
||||
// Reads the property file and extracts the keycloack configuration params
|
||||
protected static Entry<String, String> getClientIdAndClientSecret(String context) {
|
||||
try {
|
||||
Properties properties = new Properties();
|
||||
ClassLoader classLoader = KeycloackClientGcatFactory.class.getClassLoader();
|
||||
URL url = classLoader.getResource(CLIENT_ID_SECRET_FILENAME);
|
||||
logger.trace("Going to read {} at {}", CLIENT_ID_SECRET_FILENAME, url.toString());
|
||||
InputStream input = classLoader.getResourceAsStream(CLIENT_ID_SECRET_FILENAME);
|
||||
properties.load(input);
|
||||
|
||||
String clientId = "IDM";
|
||||
if (properties.containsKey(CLIENT_ID_PROPERTY_NAME)) {
|
||||
clientId = properties.getProperty(CLIENT_ID_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
int index = context.indexOf('/', 1);
|
||||
String root = context.substring(0, index == -1 ? context.length() : index);
|
||||
String clientSecret = properties.getProperty(root);
|
||||
|
||||
SimpleEntry<String, String> entry = new SimpleEntry<String, String>(clientId, clientSecret);
|
||||
return entry;
|
||||
} catch (Exception e) {
|
||||
throw new InternalServerErrorException(
|
||||
"Unable to retrieve Application Token for context "
|
||||
/* + SecretManagerProvider.instance.get().getContext() */,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: VERIFICARE
|
||||
public URL getRealmBaseURL() throws KeycloakClientException {
|
||||
return this.gcubeKeycloakClient.getRealmBaseURL(this.context);
|
||||
}
|
||||
|
||||
public URL getRealmBaseURL(String realm) throws KeycloakClientException {
|
||||
return this.gcubeKeycloakClient.getRealmBaseURL(this.context, realm);
|
||||
}
|
||||
|
||||
public URL getServerURL() {
|
||||
try {
|
||||
return this.getRealmBaseURL();
|
||||
} catch (KeycloakClientException e) {
|
||||
// That should be almost impossible
|
||||
logger.warn("Cannot create base URL", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getClientid() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
// TODO: serve? implementare
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: VERIFICARE
|
||||
public String getRealm() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
public KeycloackClientGcatFactory(String context) {
|
||||
this.context = context;
|
||||
Entry<String, String> params = getClientIdAndClientSecret(context);
|
||||
this.clientId = params.getKey();
|
||||
this.clientSecret = params.getKey();
|
||||
|
||||
this.gcubeKeycloakClient = new DefaultKeycloakClient();
|
||||
}
|
||||
|
||||
private static TokenResponse getJWTAccessToken() throws Exception {
|
||||
String context = SecretManagerProvider.get().getContext();
|
||||
Entry<String, String> entry = getClientIdAndClientSecret(context);
|
||||
TokenResponse tr = KeycloakClientFactory.newInstance().queryUMAToken(context, entry.getKey(), entry.getValue(),
|
||||
context, null);
|
||||
return tr;
|
||||
}
|
||||
|
||||
public static Secret getCatalogueSecret() throws Exception {
|
||||
TokenResponse tr = getJWTAccessToken();
|
||||
Secret secret = new JWTSecret(tr.getAccessToken());
|
||||
return secret;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
package org.gcube.keycloack;
|
||||
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
|
||||
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.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
// import org.keycloak.OAuth2Constants;
|
||||
// import org.keycloak.admin.client.Keycloak;
|
||||
// import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class KeycloakClientFactory {
|
||||
private static final Logger logger = LoggerFactory.getLogger(KeycloakClientFactory.class);
|
||||
|
||||
private final static String RUNTIME_RESOURCE_NAME = "IAM";
|
||||
private final static String CATEGORY = "Service";
|
||||
|
||||
// the singleton obj
|
||||
|
||||
private static KeycloakClientFactory singleton = new KeycloakClientFactory();
|
||||
|
||||
// properties that it contains
|
||||
private String keycloakURL;
|
||||
private String realm;
|
||||
private String clientid;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
*/
|
||||
private KeycloakClientFactory() {
|
||||
logger.info("Building KeycloakAPICredentials object");
|
||||
|
||||
lookupPropertiesFromIs();
|
||||
logger.info("KeycloakAPICredentials object built");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the properties from the infrastructure
|
||||
*/
|
||||
private void lookupPropertiesFromIs() {
|
||||
|
||||
logger.info("Starting creating KeycloakAPICredentials");
|
||||
|
||||
// String ctx = SecretManagerProvider.instance.get().getContext();
|
||||
// TODO: verificare che sia contesto corretto
|
||||
ApplicationContext ctx = ContextProvider.get();
|
||||
|
||||
logger.info("Discovering liferay user's credentials in context "
|
||||
+ ctx.container().configuration().infrastructure());
|
||||
|
||||
try {
|
||||
List<ServiceEndpoint> resources = getConfigurationFromIS();
|
||||
if (resources.size() == 0) {
|
||||
logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME + " and Category "
|
||||
+ CATEGORY + " in this scope.");
|
||||
throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME
|
||||
+ " and Category " + CATEGORY + " in this scope.");
|
||||
} else {
|
||||
for (ServiceEndpoint res : resources) {
|
||||
Iterator<AccessPoint> accessPointIterator = res.profile().accessPoints().iterator();
|
||||
while (accessPointIterator.hasNext()) {
|
||||
ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator
|
||||
.next();
|
||||
|
||||
if (accessPoint.name().equals("d4science")) {
|
||||
keycloakURL = accessPoint.address();
|
||||
realm = accessPoint.name();
|
||||
clientid = accessPoint.username();
|
||||
password = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
|
||||
logger.info("Found accesspoint URL = " + keycloakURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to retrieve such service endpoint information!", e);
|
||||
return;
|
||||
// }finally{
|
||||
// if(oldContext != null)
|
||||
// ScopeProvider.instance.set(oldContext);
|
||||
}
|
||||
|
||||
logger.info("Bean built " + toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve endpoints information from IS for DB
|
||||
*
|
||||
* @return list of endpoints for ckan database
|
||||
* @throws Exception
|
||||
*/
|
||||
private List<ServiceEndpoint> getConfigurationFromIS() throws Exception {
|
||||
SimpleQuery query = queryFor(ServiceEndpoint.class);
|
||||
query.addCondition("$resource/Profile/Name/text() eq '" + RUNTIME_RESOURCE_NAME + "'");
|
||||
query.addCondition("$resource/Profile/Category/text() eq '" + CATEGORY + "'");
|
||||
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
|
||||
List<ServiceEndpoint> toReturn = client.submit(query);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static KeycloakClientFactory getSingleton() {
|
||||
if (singleton == null)
|
||||
singleton = new KeycloakClientFactory();
|
||||
return singleton;
|
||||
}
|
||||
|
||||
public String getServerURL() {
|
||||
return keycloakURL;
|
||||
}
|
||||
|
||||
public String getClientid() {
|
||||
return clientid;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public KeycloackApiClient createtKeycloakInstance(String context) {
|
||||
|
||||
return defaultKeycloackInstance(context);
|
||||
|
||||
// // String clientIdContext = KeycloackUtils.getClientIdContext(context);
|
||||
// String realm = this.getRealm();
|
||||
// Keycloak keycloak = KeycloakBuilder.builder()
|
||||
// .serverUrl(this.getServerURL())
|
||||
// .realm(realm)
|
||||
// .grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||
// .clientId(this.getClientid()) //
|
||||
// .clientSecret(this.getPassword()).build();
|
||||
// return
|
||||
}
|
||||
|
||||
public KeycloackApiClient defaultKeycloackInstance(String context) {
|
||||
String serverUrl = "https://accounts.dev.d4science.org/auth";
|
||||
String realm = "d4science";
|
||||
String clientId = "id.d4science.org";
|
||||
String client_secret = "09c26f24-3c65-4039-9fa0-e5cc4f4032cd";
|
||||
|
||||
Keycloak kclient = KeycloakBuilder.builder()
|
||||
.serverUrl(serverUrl)
|
||||
.realm(realm)
|
||||
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||
.clientId(clientId) //
|
||||
.clientSecret(client_secret).build();
|
||||
|
||||
return new KeycloackApiClient(kclient, realm, context);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.gcube.keycloack;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
||||
public class KeycloakServerConfig {
|
||||
private String serverUrl;
|
||||
private String realm;
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
|
||||
private String grantType = OAuth2Constants.CLIENT_CREDENTIALS;
|
||||
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public KeycloakServerConfig(String serverUrl, String realm, String clientId, String clientSecret) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.realm = realm;
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public KeycloakServerConfig(String serverUrl, String realm, String clientId, String clientSecret,
|
||||
String grantType) {
|
||||
this(serverUrl, realm, clientId, clientSecret);
|
||||
this.grantType = grantType;
|
||||
}
|
||||
|
||||
//TODO: REMOVE
|
||||
static KeycloakServerConfig getTestConfig(){
|
||||
String serverUrl = "https://accounts.dev.d4science.org/auth";
|
||||
String realm = "d4science";
|
||||
String clientId = "id.d4science.org";
|
||||
String clientSecret = "09c26f24-3c65-4039-9fa0-e5cc4f4032cd";
|
||||
|
||||
return new KeycloakServerConfig(serverUrl, realm, clientId, clientSecret);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package org.gcube.keycloack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||
import org.gcube.common.security.providers.SecretManagerProvider;
|
||||
import org.gcube.service.idm.is.client.InfrastrctureServiceClient;
|
||||
import org.gcube.smartgears.ContextProvider;
|
||||
import org.gcube.smartgears.context.application.ApplicationContext;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
|
||||
public class KkClientFactory {
|
||||
private static final Logger logger = LoggerFactory.getLogger(KkClientFactory.class);
|
||||
|
||||
private final static String RUNTIME_RESOURCE_NAME = "IAM";
|
||||
private final static String CATEGORY = "Service";
|
||||
private final static String REALM_D4S = "d4science";
|
||||
private final static boolean IS_ROOT_SERVICE = true;
|
||||
|
||||
// the singleton obj
|
||||
|
||||
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 KeycloakServerConfig config_keycloak;
|
||||
|
||||
public static KkClientFactory getSingleton() {
|
||||
if (singleton == null)
|
||||
singleton = new KkClientFactory();
|
||||
return singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
* obtains the is_config_keycloak from IS
|
||||
*/
|
||||
private KkClientFactory() {
|
||||
logger.info("Building KeycloakAPICredentials object");
|
||||
try {
|
||||
if (this.config_keycloak == null)
|
||||
setIsKeycloackInstance();
|
||||
|
||||
|
||||
if (this.config_keycloak == null)
|
||||
setTestKeycloackInstance();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("error obtaining IAM configuration from IS {} ", e);
|
||||
}
|
||||
logger.info("KeycloakAPICredentials object built {} - {}", config_keycloak.getServerUrl(), config_keycloak.getRealm() );
|
||||
}
|
||||
|
||||
|
||||
public void setTestKeycloackInstance() {
|
||||
this.config_keycloak = KeycloakServerConfig.getTestConfig();
|
||||
}
|
||||
|
||||
|
||||
public void setIsKeycloackInstance() throws Exception {
|
||||
this.config_keycloak = lookupPropertiesFromIs(RUNTIME_RESOURCE_NAME, CATEGORY, REALM_D4S, IS_ROOT_SERVICE);
|
||||
}
|
||||
|
||||
public static String encodeClientIdContext(String context) {
|
||||
return context.replace("/", "%2F");
|
||||
}
|
||||
|
||||
public KeycloackApiClient createtKeycloakInstance(String context) {
|
||||
return keycloackInstanceFromConfig(this.config_keycloak, context);
|
||||
}
|
||||
|
||||
public static KeycloackApiClient keycloackInstanceFromConfig(KeycloakServerConfig config, String context) {
|
||||
|
||||
Keycloak kclient = KeycloakBuilder.builder()
|
||||
.serverUrl(config.getServerUrl())
|
||||
.realm(config.getRealm())
|
||||
.grantType(config.getGrantType())
|
||||
.clientId(config.getClientId()) //
|
||||
.clientSecret(config.getClientSecret()).build();
|
||||
|
||||
return new KeycloackApiClient(kclient, config.getRealm(), context);
|
||||
}
|
||||
|
||||
|
||||
public RealmResource getKKRealmForCurrentContext() {
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
return getKKRealmForContext(ctx);
|
||||
}
|
||||
|
||||
public RealmResource getKKRealmForContext(String ctx) {
|
||||
logger.info("Searching client for contex");
|
||||
|
||||
|
||||
KeycloackApiClient keycloackApiClient = createtKeycloakInstance(ctx);
|
||||
RealmResource realm = keycloackApiClient.kclient.realm(keycloackApiClient.realmName);
|
||||
return realm;
|
||||
}
|
||||
|
||||
|
||||
public ClientResource getKKClientForCurrentContext() {
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
return getKKClientForContext(ctx);
|
||||
}
|
||||
public ClientResource getKKClientForContext(String ctx) {
|
||||
logger.info("Searching client for contex");
|
||||
|
||||
RealmResource realm = getKKRealmForContext(ctx);
|
||||
|
||||
List<ClientRepresentation> clients = realm.clients().findByClientId(encodeClientIdContext(ctx));
|
||||
|
||||
if (clients.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
String id = clients.get(0).getId();
|
||||
return realm.clients().get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the properties from the infrastructure
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private KeycloakServerConfig lookupPropertiesFromIs(String resource_name, String category, String accessPointName, boolean root_service)
|
||||
throws Exception {
|
||||
|
||||
logger.info("Starting creating KeycloakAPICredentials");
|
||||
|
||||
|
||||
|
||||
ServiceEndpoint.AccessPoint accessPoint = InfrastrctureServiceClient.getAccesspointFromIS(resource_name,
|
||||
category, accessPointName, root_service);
|
||||
|
||||
if (accessPoint == null) {
|
||||
String error_log = "Unable to retrieve service endpoint " + accessPointName;
|
||||
|
||||
logger.error(error_log);
|
||||
throw new NotFoundException(error_log);
|
||||
}
|
||||
|
||||
String keycloakURL = accessPoint.address();
|
||||
String realm = accessPoint.name();
|
||||
String clientId = accessPoint.username();
|
||||
String clientSecret = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
|
||||
|
||||
KeycloakServerConfig config = new KeycloakServerConfig(keycloakURL, realm, clientId, clientSecret);
|
||||
logger.info("Found accesspoint URL = " + keycloakURL);
|
||||
return config;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
KKRolesClient.list
|
||||
KeycloakClientFactory.getKKClientForContext();
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
RealmResource realm = getKKRealmForContext();
|
||||
KeycloackApiClient keycloackApiClient = KeycloakClientFactory.getSingleton().createtKeycloakInstance(ctx).clientIdContext;
|
||||
List<ClientRepresentation> clients = realm.clients().findByClientId(keycloackApiClient.clientIdContext);
|
||||
|
||||
|
||||
|
||||
getUserByEmail
|
||||
RealmResource realm = KeycloakClientFactory.getKKRealmForContext();
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
KeycloakClientFactory factory = KeycloakClientFactory.getSingleton()
|
||||
new KeycloakClientFactory()
|
||||
lookupPropertiesFromIs();
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.gcube.service.idm.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.keycloack.KkClientFactory;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class KKRolesClient {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KKRolesClient.class);
|
||||
|
||||
public static List<RoleRepresentation> getRoles() {
|
||||
logger.info("Searching users for context");
|
||||
ClientResource client = KkClientFactory.getSingleton().getKKClientForCurrentContext();
|
||||
List<RoleRepresentation> roles = client.roles().list();
|
||||
return roles;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ import java.util.List;
|
|||
|
||||
import org.gcube.common.security.providers.SecretManagerProvider;
|
||||
import org.gcube.keycloack.KeycloackApiClient;
|
||||
import org.gcube.keycloack.KeycloakClientFactory;
|
||||
import org.gcube.keycloack.KkClientFactory;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
|
@ -14,44 +14,11 @@ import org.slf4j.LoggerFactory;
|
|||
public class KKUserClient {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KKUserClient.class);
|
||||
|
||||
// TODO: Move to KK CLIENTE
|
||||
public static ClientResource getKKClientForContext() {
|
||||
logger.info("Searching client for contex");
|
||||
|
||||
RealmResource realm = getKKRealmForContext();
|
||||
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
KeycloackApiClient keycloackApiClient = KeycloakClientFactory.getSingleton()
|
||||
.createtKeycloakInstance(ctx);
|
||||
|
||||
List<ClientRepresentation> clients = realm.clients().findByClientId(keycloackApiClient.clientIdContext);
|
||||
|
||||
String id = "";
|
||||
for (ClientRepresentation client : clients) {
|
||||
logger.info("found client =" + client.getClientId());
|
||||
logger.info("found client id=" + client.getId());
|
||||
id = client.getId();
|
||||
}
|
||||
|
||||
ClientResource client = realm.clients().get(id);
|
||||
return client;
|
||||
}
|
||||
|
||||
// TODO: Move to KK CLIENTE
|
||||
public static RealmResource getKKRealmForContext() {
|
||||
logger.info("Searching client for contex");
|
||||
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
KeycloackApiClient keycloackApiClient = KeycloakClientFactory.getSingleton()
|
||||
.createtKeycloakInstance(ctx);
|
||||
RealmResource realm = keycloackApiClient.kclient.realm(keycloackApiClient.realmName);
|
||||
return realm;
|
||||
}
|
||||
|
||||
public static List<UserRepresentation> getUserByEmail(String email) {
|
||||
logger.info("Searching user by email: {}", email);
|
||||
|
||||
RealmResource realm = getKKRealmForContext();
|
||||
RealmResource realm = KkClientFactory.getSingleton().getKKRealmForCurrentContext();
|
||||
List<UserRepresentation> users = realm.users()
|
||||
.searchByEmail(email, true);
|
||||
return users;
|
||||
|
@ -60,7 +27,7 @@ public class KKUserClient {
|
|||
public static List<UserRepresentation> getUserByUsername(String username) {
|
||||
logger.info("Searching user by username: {}", username);
|
||||
|
||||
RealmResource realm = getKKRealmForContext();
|
||||
RealmResource realm = KkClientFactory.getSingleton().getKKRealmForCurrentContext();
|
||||
List<UserRepresentation> users = realm.users()
|
||||
.search(username, true);
|
||||
return users;
|
||||
|
@ -68,18 +35,29 @@ public class KKUserClient {
|
|||
|
||||
public static List<UserRepresentation> searchUsersByRole(String roleName, Integer firstResult, Integer maxResults) {
|
||||
logger.info("Searching users by role: {}", roleName);
|
||||
ClientResource client = getKKClientForContext();
|
||||
ClientResource client = KkClientFactory.getSingleton().getKKClientForCurrentContext();
|
||||
|
||||
List<UserRepresentation> users = client.roles().get(roleName)
|
||||
.getUserMembers(firstResult, maxResults);
|
||||
return users;
|
||||
}
|
||||
|
||||
public static List<UserRepresentation> searchRealmUsers(Integer firstResult, Integer maxResults) {
|
||||
RealmResource realm = getKKRealmForContext();
|
||||
public static List<UserRepresentation> users(Integer firstResult, Integer maxResults) {
|
||||
RealmResource realm = KkClientFactory.getSingleton().getKKRealmForCurrentContext();
|
||||
|
||||
List<UserRepresentation> users = realm.users()
|
||||
.list(firstResult, maxResults);
|
||||
return users;
|
||||
}
|
||||
|
||||
public static List<ClientRepresentation> clients() {
|
||||
RealmResource realm = KkClientFactory.getSingleton().getKKRealmForCurrentContext();
|
||||
|
||||
String ctx = SecretManagerProvider.get().getContext();
|
||||
KeycloackApiClient keycloackApiClient = KkClientFactory.getSingleton()
|
||||
.createtKeycloakInstance(ctx);
|
||||
|
||||
List<ClientRepresentation> clients = realm.clients().findByClientId(keycloackApiClient.clientIdContext);
|
||||
return clients;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package org.gcube.service.idm.is.client;
|
||||
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||
// import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.common.security.AuthorizedTasks;
|
||||
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 org.gcube.common.security.secrets.Secret;
|
||||
|
||||
public class InfrastrctureServiceClient {
|
||||
private static final Logger logger = LoggerFactory.getLogger(InfrastrctureServiceClient.class);
|
||||
|
||||
/**
|
||||
* Retrieve endpoints information from IS for DB
|
||||
*
|
||||
* @return list of endpoints for ckan database
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static List<ServiceEndpoint> getEndopintsFromIS(String resource_name, String category,
|
||||
boolean root_service) {
|
||||
SimpleQuery query = queryFor(ServiceEndpoint.class);
|
||||
query.addCondition("$resource/Profile/Name/text() eq '" + resource_name + "'");
|
||||
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) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return endpoints;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource_name
|
||||
* @param category
|
||||
* @param accessPointName
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static ServiceEndpoint.AccessPoint getAccesspointFromIS(String resource_name, String category,
|
||||
String accessPointName, boolean root_service) throws Exception {
|
||||
|
||||
List<ServiceEndpoint> resources = getEndopintsFromIS(resource_name, category, 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;
|
||||
}
|
||||
|
||||
for (ServiceEndpoint res : resources) {
|
||||
ServiceEndpoint.AccessPoint accessPoint = res.profile().accessPoints().stream()
|
||||
.filter(ap -> ap.name().equals(accessPointName))
|
||||
.findFirst().orElse(null);
|
||||
if (accessPoint != null) {
|
||||
return accessPoint;
|
||||
}
|
||||
}
|
||||
|
||||
String error_log = "Unable to retrieve service endpoint " + accessPointName;
|
||||
logger.error(error_log);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.gcube.service.idm.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.service.idm.IdMManager;
|
||||
import org.gcube.service.idm.controller.KKRolesClient;
|
||||
import org.gcube.service.idm.controller.KKUserClient;
|
||||
import org.gcube.service.idm.serializers.ContextSerializator;
|
||||
import org.gcube.service.rest.ResponseBean;
|
||||
import org.gcube.service.rest.ResponseBeanPaginated;
|
||||
import org.gcube.smartgears.annotations.ManagedBy;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
@ManagedBy(IdMManager.class)
|
||||
@Path("roles")
|
||||
public class RolesAPI {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RolesAPI.class);
|
||||
|
||||
@GET
|
||||
@Path("/")
|
||||
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
|
||||
public Response roles() {
|
||||
Status status = Status.OK;
|
||||
ResponseBean responseBean = new ResponseBean();;
|
||||
|
||||
try {
|
||||
List<RoleRepresentation> roles = KKRolesClient.getRoles();
|
||||
|
||||
responseBean.setResult(roles);
|
||||
responseBean.setSuccess(true);
|
||||
|
||||
ObjectMapper objectMapper = ContextSerializator.getSerializer();
|
||||
|
||||
String jsonData = objectMapper.writeValueAsString(responseBean);
|
||||
return Response.ok(jsonData).build();
|
||||
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
return Response.serverError().build();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to retrieve users with the requested role", e);
|
||||
responseBean.setMessage(e.getMessage());
|
||||
status = Status.INTERNAL_SERVER_ERROR;
|
||||
return Response.status(status).entity(responseBean).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -92,6 +92,7 @@ public class UsersSocialAPI {
|
|||
responseBean.setMessage(e.getMessage());
|
||||
status = Status.INTERNAL_SERVER_ERROR;
|
||||
return Response.status(status).entity(responseBean).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +109,7 @@ public class UsersSocialAPI {
|
|||
|
||||
try {
|
||||
|
||||
List<UserRepresentation> users = KKUserClient.searchRealmUsers(firstResult, maxResults);
|
||||
List<UserRepresentation> users = KKUserClient.users(firstResult, maxResults);
|
||||
if (users != null) {
|
||||
for (UserRepresentation user : users) {
|
||||
usernamesAndFullnames.put(user.getUsername(), user.getEmail());
|
||||
|
@ -277,7 +278,7 @@ public class UsersSocialAPI {
|
|||
ResponseBean responseBean = new ResponseBean();
|
||||
List<String> usernames = new ArrayList<String>();
|
||||
try {
|
||||
List<UserRepresentation> users = KKUserClient.searchRealmUsers(firstResult, maxResults);
|
||||
List<UserRepresentation> users = KKUserClient.users(firstResult, maxResults);
|
||||
if (users != null) {
|
||||
for (UserRepresentation user : users) {
|
||||
usernames.add(user.getUsername());
|
||||
|
|
|
@ -38,7 +38,7 @@ public class KeycloakTestService {
|
|||
|
||||
private final static Logger logger = LoggerFactory.getLogger(KeycloakTestService.class);
|
||||
|
||||
public static String getClientIdContext(String context) {
|
||||
public static String encodeClientIdContext(String context) {
|
||||
return context.replace("/", "%2F");
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class KeycloakTestService {
|
|||
private static List<UserRepresentation> searchByRole(Keycloak kclient, String krealm, String clientIdContext,
|
||||
String roleName) {
|
||||
|
||||
clientIdContext = getClientIdContext(clientIdContext);
|
||||
clientIdContext = encodeClientIdContext(clientIdContext);
|
||||
|
||||
logger.info("Searching by role: {}", roleName);
|
||||
|
||||
|
|
Loading…
Reference in New Issue