diff --git a/Dockerfile b/Dockerfile index fb76c5d..66953a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/Instructions.md b/Instructions.md index ab1d203..7fde45f 100644 --- a/Instructions.md +++ b/Instructions.md @@ -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 diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 0000000..600791e --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1,3 @@ +container*.ini +!container.default.ini +*.gcubekey \ No newline at end of file diff --git a/docker/container.ini b/docker/container.ini deleted file mode 100644 index 9c15874..0000000 --- a/docker/container.ini +++ /dev/null @@ -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 \ No newline at end of file diff --git a/docker/container.ini b/docker/container.ini new file mode 120000 index 0000000..9ca9d2c --- /dev/null +++ b/docker/container.ini @@ -0,0 +1 @@ +container.alf.ini \ No newline at end of file diff --git a/docs/postman/Smartgears4 helloword.postman_collection.json b/docs/postman/Smartgears4 helloword.postman_collection.json index 5f34ea8..e15453a 100644 --- a/docs/postman/Smartgears4 helloword.postman_collection.json +++ b/docs/postman/Smartgears4 helloword.postman_collection.json @@ -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": "" } ] } \ No newline at end of file diff --git a/src/main/java/org/gcube/service/helloworld/serializers/ContextSerializator.java b/src/main/java/org/gcube/service/helloworld/serializers/CustomSerializator.java similarity index 79% rename from src/main/java/org/gcube/service/helloworld/serializers/ContextSerializator.java rename to src/main/java/org/gcube/service/helloworld/serializers/CustomSerializator.java index d755923..b42e5af 100644 --- a/src/main/java/org/gcube/service/helloworld/serializers/ContextSerializator.java +++ b/src/main/java/org/gcube/service/helloworld/serializers/CustomSerializator.java @@ -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); diff --git a/src/main/java/org/gcube/service/helloworld/serializers/ServiceEndpointAccessPointSerializer.java b/src/main/java/org/gcube/service/helloworld/serializers/ServiceEndpointAccessPointSerializer.java new file mode 100644 index 0000000..7340c6d --- /dev/null +++ b/src/main/java/org/gcube/service/helloworld/serializers/ServiceEndpointAccessPointSerializer.java @@ -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 { + + protected ServiceEndpointAccessPointSerializer(Class 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(); + } +} diff --git a/src/main/java/org/gcube/service/helloworld/services/HelloService.java b/src/main/java/org/gcube/service/helloworld/services/HelloService.java index c96eadb..86429a2 100644 --- a/src/main/java/org/gcube/service/helloworld/services/HelloService.java +++ b/src/main/java/org/gcube/service/helloworld/services/HelloService.java @@ -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); diff --git a/src/main/java/org/gcube/service/helloworld/services/IsService.java b/src/main/java/org/gcube/service/helloworld/services/IsService.java new file mode 100644 index 0000000..7705eaf --- /dev/null +++ b/src/main/java/org/gcube/service/helloworld/services/IsService.java @@ -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 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(); + } + } +} diff --git a/src/main/java/org/gcube/service/helloworld/services/KeycloakTestService.java b/src/main/java/org/gcube/service/helloworld/services/KeycloakTestService.java index 82d25a9..8881b70 100644 --- a/src/main/java/org/gcube/service/helloworld/services/KeycloakTestService.java +++ b/src/main/java/org/gcube/service/helloworld/services/KeycloakTestService.java @@ -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 usernames = new ArrayList(); 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 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(); diff --git a/src/main/java/org/gcube/service/helloworld/utils/InfrastrctureServiceClient.java b/src/main/java/org/gcube/service/helloworld/utils/InfrastrctureServiceClient.java new file mode 100644 index 0000000..6a02ece --- /dev/null +++ b/src/main/java/org/gcube/service/helloworld/utils/InfrastrctureServiceClient.java @@ -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 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 client = clientFor(ServiceEndpoint.class); + + ApplicationContext ctx = ContextProvider.get(); + + String infra_context = "/" + ctx.container().configuration().infrastructure(); + Secret secret = ctx.container().authorizationProvider().getSecretForContext(infra_context); + + List endpoints = null; + + try { + if (root_service) { + + endpoints = AuthorizedTasks.executeSafely(() -> { + // esegui la query + List 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 getAccessPointsFromIS(String resource_name, String category, + String accessPointName, boolean root_service) throws Exception { + + List 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 response = new ArrayList(); + resources.forEach(res -> { + Stream 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 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); + + } + +} diff --git a/src/main/java/org/gcube/service/helloworld/utils/RestUtils.java b/src/main/java/org/gcube/service/helloworld/utils/RestUtils.java index 9d707f6..cddf79c 100644 --- a/src/main/java/org/gcube/service/helloworld/utils/RestUtils.java +++ b/src/main/java/org/gcube/service/helloworld/utils/RestUtils.java @@ -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 {