IS client excample, keycloak config from IS

This commit is contained in:
Alfredo Oliviero 2024-03-28 19:29:06 +01:00
parent 74b53ae193
commit c81ef827aa
12 changed files with 537 additions and 223 deletions

View File

@ -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/*.gcubekey /tomcat/lib
COPY ./target/helloworld.war /tomcat/webapps/
EXPOSE 8080

View File

@ -14,7 +14,7 @@
# optional, for local develop in docker containers
├── docker/
│ ├── ontainer.ini
│ ├── container.ini
│ └── logback.xml
├── docker-compose.yaml
└── Dockerfile
@ -33,7 +33,6 @@
* mode: [online/offline]: register the service on IS. use offline for local docker instances
# EXCECUTION
start the docker container

3
docker/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
container*.ini
!container.default.ini
*.gcubekey

View File

@ -1,23 +0,0 @@
[node]
mode = offline
hostname = mb-lelii.isti.cnr.it
protocol= http
port = 8080
infrastructure = gcube
authorizeChildrenContext = true
publicationFrequencyInSeconds = 60
[properties]
SmartGearsDistribution = 4.0.0-SNAPSHOT
SmartGearsDistributionBundle = UnBundled
[site]
country = it
location = pisa
[authorization]
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.secret = 979bd3bc-5cc4-11ec-bf63-0242ac130002

1
docker/container.ini Symbolic link
View File

@ -0,0 +1 @@
container.alf.ini

View File

@ -8,51 +8,170 @@
},
"item": [
{
"name": "hello TOKEN PARAM",
"name": "[UAT] Obtain CONTEXT id token for a user",
"event": [
{
"listen": "test",
"script": {
"exec": [
"var jsonData = JSON.parse(responseBody);",
"pm.collectionVariables.set(\"access_token\", jsonData.access_token);",
"pm.collectionVariables.set(\"refresh_token\", jsonData.refresh_token);",
""
],
"type": "text/javascript",
"packages": {}
}
},
{
"listen": "prerequest",
"script": {
"exec": [
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"method": "POST",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"value": "application/x-www-form-urlencoded",
"type": "text"
},
{
"key": "X-D4Science-Context",
"value": "{{url-encoded-context}}",
"type": "text"
},
{
"key": "",
"value": "{{token}}",
"value": "",
"type": "text",
"disabled": true
}
],
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "client_id",
"value": "{{client-id-user}}",
"type": "text"
},
{
"key": "username",
"value": "{{username}}",
"type": "text"
},
{
"key": "password",
"value": "{{password}}",
"type": "text"
},
{
"key": "grant_type",
"value": "password",
"type": "text"
}
]
},
"url": {
"raw": "{{keycloak_url}}/realms/{{realm}}/protocol/openid-connect/token",
"host": [
"{{keycloak_url}}"
],
"path": [
"realms",
"{{realm}}",
"protocol",
"openid-connect",
"token"
]
},
"description": "Obtain UAT = user access token from a user in realm"
},
"response": []
},
{
"name": "[UAT] refresh CONTEXT token",
"event": [
{
"listen": "test",
"script": {
"exec": [
"var jsonData = JSON.parse(responseBody);",
"",
"pm.collectionVariables.set(\"access_token\", jsonData.access_token);",
"pm.collectionVariables.set(\"refresh_token\", jsonData.refresh_token);",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-D4Science-Context",
"value": "{{url-encoded-context}}",
"type": "text"
}
],
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "grant_type",
"value": "refresh_token",
"type": "text"
},
{
"key": "client_id",
"value": "{{client-id-user}}",
"type": "text"
},
{
"key": "refresh_token",
"value": "{{refresh_token}}",
"type": "text"
},
{
"key": "client_secret",
"value": "{{service_client_secret}}",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "{{base_url}}/{{application}}/hello?gcube-token={{gcube_token}}",
"raw": "{{keycloak_url}}/realms/{{realm}}/protocol/openid-connect/token",
"host": [
"{{base_url}}"
"{{keycloak_url}}"
],
"path": [
"{{application}}",
"hello"
],
"query": [
{
"key": "gcube-token",
"value": "{{gcube_token}}"
}
"realms",
"{{realm}}",
"protocol",
"openid-connect",
"token"
]
}
},
"response": []
},
{
"name": "hello BEARER",
"name": "hello",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{uma_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
@ -69,45 +188,8 @@
"response": []
},
{
"name": "details TOKEN PARAM",
"name": "details",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/{{application}}/details?gcube-token={{gcube_token}}",
"host": [
"{{base_url}}"
],
"path": [
"{{application}}",
"details"
],
"query": [
{
"key": "gcube-token",
"value": "{{gcube_token}}"
}
]
}
},
"response": []
},
{
"name": "details BEARER",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{uma_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
@ -123,6 +205,25 @@
},
"response": []
},
{
"name": "auth org member",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/{{application}}/auth/org_member",
"host": [
"{{base_url}}"
],
"path": [
"{{application}}",
"auth",
"org_member"
]
}
},
"response": []
},
{
"name": "guest",
"request": {
@ -145,75 +246,8 @@
"response": []
},
{
"name": "auth org member BEARER",
"name": "auth member",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{uma_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/{{application}}/auth/org_member",
"host": [
"{{base_url}}"
],
"path": [
"{{application}}",
"auth",
"org_member"
]
}
},
"response": []
},
{
"name": "auth org member TOKEN PARAM",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/{{application}}/auth/org_member?gcube-token={{gcube_token}}",
"host": [
"{{base_url}}"
],
"path": [
"{{application}}",
"auth",
"org_member"
],
"query": [
{
"key": "gcube-token",
"value": "{{gcube_token}}"
}
]
}
},
"response": []
},
{
"name": "auth member BEARER",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{uma_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
@ -230,47 +264,9 @@
},
"response": []
},
{
"name": "auth member TOKEN PARAM",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/{{application}}/auth/member?gcube-token={{gcube_token}}",
"host": [
"{{base_url}}"
],
"path": [
"{{application}}",
"auth",
"member"
],
"query": [
{
"key": "gcube-token",
"value": "{{gcube_token}}"
}
]
}
},
"response": []
},
{
"name": "test keycloak",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{uma_token}}a",
"type": "string"
}
]
},
"method": "GET",
"header": [
{
@ -281,7 +277,7 @@
}
],
"url": {
"raw": "{{base_url}}/{{application}}/keycloak?client_secret={{service_client_secret}}",
"raw": "{{base_url}}/{{application}}/keycloak",
"host": [
"{{base_url}}"
],
@ -290,10 +286,6 @@
"keycloak"
],
"query": [
{
"key": "client_secret",
"value": "{{service_client_secret}}"
},
{
"key": "client_id",
"value": "{{current_client-id}}",
@ -305,6 +297,16 @@
"response": []
}
],
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{access_token}}",
"type": "string"
}
]
},
"event": [
{
"listen": "prerequest",
@ -331,30 +333,48 @@
"value": "http://localhost:8081",
"type": "string"
},
{
"key": "keycloak_url",
"value": "https://accounts.dev.d4science.org/auth",
"type": "string"
},
{
"key": "url-encoded-context",
"value": "%2Fgcube%2Fdevsec%2FdevVRE",
"type": "string"
},
{
"key": "realm",
"value": "d4science",
"type": "string"
},
{
"key": "client-id-user",
"value": "next.d4science.org",
"type": "string"
},
{
"key": "application",
"value": "helloworld",
"type": "string"
},
{
"key": "gcube_token",
"key": "username",
"value": "",
"type": "string"
},
{
"key": "uma_token",
"key": "password",
"value": "",
"type": "string"
},
{
"key": "service_client_secret",
"value": "",
"type": "string"
"key": "access_token",
"value": ""
},
{
"key": "service_client_id",
"value": "",
"type": "string"
"key": "refresh_token",
"value": ""
}
]
}

View File

@ -1,5 +1,7 @@
package org.gcube.service.helloworld.serializers;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.security.Owner;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.security.SimpleCredentials;
@ -14,7 +16,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
*
*/
public class ContextSerializator {
public class CustomSerializator {
private static ObjectMapper serializer = null;
public static ObjectMapper getSerializer() {
@ -24,7 +26,9 @@ public class ContextSerializator {
// module.addSerializer(Owner.class, new OwnerSerializer());
module.addSerializer(ContainerConfiguration.class, new ContainerConfigurationSerializer());
module.addSerializer(Owner.class, new OwnerSerializer());
module.addSerializer(ContainerContext.class, new ContainerContextSerializer());
module.addSerializer(ServiceEndpoint.AccessPoint.class, new ServiceEndpointAccessPointSerializer());
module.addSerializer(SimpleCredentials.class, new SimpleCredentialsSerializer());
om.registerModule(module);

View File

@ -0,0 +1,64 @@
package org.gcube.service.helloworld.serializers;
import java.io.IOException;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Jackson serializer for ServiceEndpoint.AccessPoint
*
* @author Alfredo Oliviero (ISTI-CNR)
*
*/
public class ServiceEndpointAccessPointSerializer extends StdSerializer<ServiceEndpoint.AccessPoint> {
protected ServiceEndpointAccessPointSerializer(Class<ServiceEndpoint.AccessPoint> t) {
super(t);
}
public ServiceEndpointAccessPointSerializer() {
super(ServiceEndpoint.AccessPoint.class, true);
}
@Override
public void serialize(ServiceEndpoint.AccessPoint accessPoint, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
String error = null;
String clientSecret = null;
try {
clientSecret = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
} catch (Exception e) {
error = e.getMessage();
}
jgen.writeStringField("address", accessPoint.address());
jgen.writeStringField("name", accessPoint.name());
jgen.writeStringField("description", accessPoint.description());
try {
jgen.writeStringField("username", accessPoint.username());
} catch (Exception e) {
jgen.writeStringField("username", null);
}
try {
jgen.writeStringField("tostring", accessPoint.toString());
} catch (Exception e) {
jgen.writeStringField("tostring", null);
}
if (error != null) {
jgen.writeStringField("key_error", error);
jgen.writeBooleanField("key_decoded", false);
} else {
jgen.writeBooleanField("key_decoded", true);
}
jgen.writeEndObject();
}
}

View File

@ -13,7 +13,7 @@ import org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
import org.gcube.service.helloworld.HelloWorldManager;
import org.gcube.service.helloworld.serializers.ContextSerializator;
import org.gcube.service.helloworld.serializers.CustomSerializator;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.context.container.ContainerContext;
@ -70,7 +70,7 @@ public class HelloService {
ContainerContext container = ContextProvider.get().container();
data.put("container", container);
ObjectMapper objectMapper = ContextSerializator.getSerializer();
ObjectMapper objectMapper = CustomSerializator.getSerializer();
try {
String jsonData = objectMapper.writeValueAsString(data);

View File

@ -0,0 +1,95 @@
package org.gcube.service.helloworld.services;
import java.util.List;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.service.helloworld.HelloWorldManager;
import org.gcube.service.helloworld.serializers.CustomSerializator;
import org.gcube.service.helloworld.utils.InfrastrctureServiceClient;
import org.gcube.smartgears.annotations.ManagedBy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
/**
* service example that shows how to query IS and how to access Keycloak
*
* @author Alfredo Oliviero (ISTI - CNR)
*/
@ManagedBy(HelloWorldManager.class)
@Path("is")
public class IsService {
private final static Logger logger = LoggerFactory.getLogger(IsService.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;
public static String getClientIdContext(String context) {
return context.replace("/", "%2F");
}
@GET
@Path("/test")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response test(
@QueryParam("resource") @DefaultValue(RUNTIME_RESOURCE_NAME) String resourceName,
@QueryParam("category") @DefaultValue(CATEGORY) String categoryName,
@QueryParam("realm") @DefaultValue(REALM_D4S) String realm,
@QueryParam("is_root") @DefaultValue("" + IS_ROOT_SERVICE) boolean is_root) {
return this.queryIS(resourceName, categoryName, realm, is_root);
}
@GET
@Path("/query")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response queryIS(
@QueryParam("resource") String resourceName,
@QueryParam("category") String categoryName,
@QueryParam("realm") @DefaultValue(REALM_D4S) String realm,
@QueryParam("is_root") @DefaultValue("false") boolean is_root) {
try {
List<AccessPoint> accessPoints = InfrastrctureServiceClient.getAccessPointsFromIS(
resourceName,
categoryName,
realm,
is_root);
if (accessPoints.size() == 0) {
String error_log = "Unable to retrieve service endpoint " + REALM_D4S;
logger.error(error_log);
throw new NotFoundException(error_log);
}
ObjectMapper objectMapper = CustomSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(accessPoints);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
e.printStackTrace();
return Response.serverError().build();
}
}
}

View File

@ -3,8 +3,11 @@ package org.gcube.service.helloworld.services;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.service.helloworld.HelloWorldManager;
import org.gcube.service.helloworld.serializers.ContextSerializator;
import org.gcube.service.helloworld.serializers.CustomSerializator;
import org.gcube.service.helloworld.utils.InfrastrctureServiceClient;
import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
@ -24,21 +27,29 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.core.Response;
/**
* service example that shows how to query IS and how to access Keycloak
* @author Alfredo Oliviero (ISTI - CNR)
*/
@ManagedBy(HelloWorldManager.class)
@Path("")
public class KeycloakTestService {
private final String CLIENT_SECRET = "NOT_COMMITTED";
private final static Logger logger = LoggerFactory.getLogger(KeycloakTestService.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;
public static String getClientIdContext(String context) {
return context.replace("/", "%2F");
}
@ -47,23 +58,37 @@ public class KeycloakTestService {
@Path("/keycloak")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response testKeycloak(
@QueryParam("serverUrl") @DefaultValue("https://accounts.dev.d4science.org/auth") String serverUrl,
@QueryParam("realm") @DefaultValue("d4science") String realm,
@QueryParam("role-name") @DefaultValue("Member") String roleName,
@QueryParam("client_id") @DefaultValue("id.d4science.org") String clientId,
@QueryParam("client_secret") @DefaultValue(CLIENT_SECRET) String client_secret
) {
@QueryParam("role-name") @DefaultValue("Member") String roleName) {
String client_contenxt = "/gcube";
List<String> usernames = new ArrayList<String>();
try {
ServiceEndpoint.AccessPoint accessPoint = InfrastrctureServiceClient.getAccessPointFromIS(
RUNTIME_RESOURCE_NAME,
CATEGORY,
REALM_D4S,
IS_ROOT_SERVICE);
if (accessPoint == null) {
String error_log = "Unable to retrieve service endpoint " + REALM_D4S;
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());
Keycloak kclient = KeycloakBuilder.builder()
.serverUrl(serverUrl)
.serverUrl(keycloakURL)
.realm(realm)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(clientId) //
.clientSecret(client_secret).build();
.clientSecret(clientSecret).build();
List<UserRepresentation> users = searchByRole(kclient, realm, client_contenxt, roleName);
if (users != null) {
@ -75,7 +100,7 @@ public class KeycloakTestService {
// responseBean.setResult(usernames);
// responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer();
ObjectMapper objectMapper = CustomSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(usernames);
return Response.ok(jsonData).build();

View File

@ -0,0 +1,126 @@
package org.gcube.service.helloworld.utils;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.gcube.common.resources.gcore.ServiceEndpoint;
// import org.gcube.common.scope.api.ScopeProvider;
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;
/**
* 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);
/**
* 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);
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;
}
/**
* @param resource_name
* @param category
* @param accessPointName
* @return
* @throws Exception
*/
public static List<ServiceEndpoint.AccessPoint> getAccessPointsFromIS(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;
}
List<ServiceEndpoint.AccessPoint> response = new ArrayList<ServiceEndpoint.AccessPoint>();
resources.forEach(res -> {
Stream<ServiceEndpoint.AccessPoint> access_points_res = res.profile().accessPoints().stream();
if (accessPointName == null) {
access_points_res = access_points_res.filter(ap -> ap.name().equals(accessPointName));
}
access_points_res.forEach(a -> response.add(a));
});
return response;
}
/**
* @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.AccessPoint> access_points = getAccessPointsFromIS(resource_name, category, accessPointName, root_service);
if (access_points.size() == 0) {
logger.error("Unable to retrieve service endpoint " + accessPointName);
return null;
}
return access_points.get(0);
}
}

View File

@ -8,8 +8,7 @@ import org.gcube.common.security.Owner;
import org.gcube.smartgears.context.container.ContainerContext;
/**
*
* @author Lucio Lelii (ISTI-CNR)
* @author Alfredo Oliviero (ISTI - CNR)
*/
public class RestUtils {