You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2019/11/08 17:23:13 UTC

[airavata-custos] branch develop updated: Draft API definitions for Resource, Secret and CILogon controllers

This is an automated email from the ASF dual-hosted git repository.

dimuthuupe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git


The following commit(s) were added to refs/heads/develop by this push:
     new 269a523  Draft API definitions for Resource, Secret and CILogon controllers
269a523 is described below

commit 269a523b125a6966c8489836f444dbd8631961aa
Author: Dimuthu Wannipurage <di...@gmail.com>
AuthorDate: Fri Nov 8 12:22:59 2019 -0500

    Draft API definitions for Resource, Secret and CILogon controllers
---
 .../custos/rest/controller/CILogonController.java  | 78 ++++++++++++++++++++--
 .../custos/rest/controller/ResourceController.java |  6 ++
 .../custos/rest/controller/SecretController.java   | 47 +++++++++++++
 .../custos/rest/controller/TenantController.java   | 20 +++++-
 .../org/apache/custos/rest/core/AppConfig.java     |  6 ++
 .../rest/resources/CILogonClientInfoResource.java  | 61 +++++++++++++++++
 .../resources/CILogonClientRequestResource.java    |  4 ++
 .../custos/rest/resources/KVSecretResource.java    | 23 +++++++
 .../org/apache/custos/rest/resources/Resource.java | 44 ++++++++++++
 .../org/apache/custos/rest/util/SecretEngine.java  | 15 +++++
 10 files changed, 296 insertions(+), 8 deletions(-)

diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/CILogonController.java b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/CILogonController.java
index 7b411e9..65329b7 100644
--- a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/CILogonController.java
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/CILogonController.java
@@ -1,15 +1,81 @@
 package org.apache.custos.rest.controller;
 
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.custos.commons.model.security.AuthzToken;
+import org.apache.custos.profile.iam.admin.services.cpi.exception.IamAdminServicesException;
+import org.apache.custos.profile.tenant.cpi.TenantProfileService;
+import org.apache.custos.rest.resources.CILogonClientInfoResource;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.ws.rs.PathParam;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
 
 @RestController
 @RequestMapping("/cilogon")
 public class CILogonController {
 
-    @RequestMapping(value = "hello", method = RequestMethod.GET)
-    public String helloMethod() {
-        return "Hello";
+    private static AuthzToken authzToken = new AuthzToken("empy_token");
+
+    private String cILogonAdminClientId = "";
+    private String cILogonAdminClientSecret = "";
+    private String cILogonAdminUrl = "";
+
+    @Autowired
+    private TenantProfileService.Client tenantClient;
+
+    @RequestMapping(value = "client/{tenant}", method = RequestMethod.POST)
+    public CILogonClientInfoResource createCILogOnClient(@PathVariable("tenant") String tenantId) throws Exception {
+        // Check realm is created is first, is callback urls exist
+        boolean gatewayExist = tenantClient.isGatewayExist(authzToken, tenantId);
+        if (!gatewayExist) {
+            throw new Exception("Tennant " + tenantId + " does not exist");
+        }
+
+        CloseableHttpClient httpClient = HttpClients.createSystem();
+
+        HttpPost httpPost = new HttpPost(cILogonAdminUrl);
+        String encoded = Base64.getEncoder().encodeToString((cILogonAdminClientId+":"+cILogonAdminClientSecret).getBytes(StandardCharsets.UTF_8));
+        httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + encoded);
+        JSONObject data = new JSONObject();
+        data.put("client_name", cILogonAdminClientId);
+        data.put("redirect_uris", new JSONArray(new ArrayList<>()));
+        data.put("comments", "Created by custos");
+        httpPost.setEntity(new StringEntity(data.toString(), ContentType.APPLICATION_JSON));
+
+        try {
+            CloseableHttpResponse response = httpClient.execute(httpPost);
+            if(response.getStatusLine().getStatusCode() < 200 ||  response.getStatusLine().getStatusCode() > 299) {
+                throw new Exception("Could not create a cilogon client");
+            }
+            try {
+                ObjectMapper objectMapper = new ObjectMapper();
+
+                CILogonClientInfoResource ciLogonClientInfoResource = objectMapper.readValue(EntityUtils.toString(response.getEntity()), CILogonClientInfoResource.class);
+                return ciLogonClientInfoResource;
+            } finally {
+                response.close();
+            }
+        } finally {
+            try {
+                httpClient.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
     }
+
 }
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/ResourceController.java b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/ResourceController.java
new file mode 100644
index 0000000..0a8cbeb
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/ResourceController.java
@@ -0,0 +1,6 @@
+package org.apache.custos.rest.controller;
+
+public class ResourceController {
+
+    // CURD operations for Resource
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/SecretController.java b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/SecretController.java
new file mode 100644
index 0000000..8e7ae1e
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/SecretController.java
@@ -0,0 +1,47 @@
+package org.apache.custos.rest.controller;
+
+import org.apache.custos.rest.resources.KVSecretResource;
+import org.apache.custos.rest.util.SecretEngine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.*;
+
+@RestController
+@RequestMapping("/secret")
+public class SecretController {
+
+    @Autowired
+    private SecretEngine secretEngine;
+
+    /**
+     * This saves a single key value pair in vault and returns a vault id
+     * @return Unique id for the secret
+     */
+    @RequestMapping(value = "single", method = RequestMethod.POST)
+    public String saveSecret(@RequestBody KVSecretResource secret) {
+        return secretEngine.soreKV(Collections.singletonMap(secret.getKey(), secret.getValue()));
+    }
+
+
+    /**
+     * This saves multiple key value pairs in vault and returns a single vault id
+     * @param secrets
+     * @return Unique id for all secrets
+     */
+    @RequestMapping(value = "multiple", method = RequestMethod.POST)
+    public String saveSecrets(@RequestBody List<KVSecretResource> secrets) {
+        Map<String, String> secMap = new HashMap<>();
+        secrets.forEach(s-> secMap.put(s.getKey(), s.getValue()));
+        return secretEngine.soreKV(secMap);
+    }
+
+    public List<KVSecretResource> getSecrets(String token) {
+        //Optional.ofNullable(secretEngine.getKV(token)).orElse(new HashMap<>());
+        //secretEngine.getKV(token).
+        return new ArrayList<>();
+    }
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/TenantController.java b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/TenantController.java
index 8329693..d9e9e62 100644
--- a/custos-rest-api/src/main/java/org/apache/custos/rest/controller/TenantController.java
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/controller/TenantController.java
@@ -9,6 +9,7 @@ import org.apache.thrift.TException;
 import org.dozer.DozerBeanMapper;
 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
 import org.keycloak.admin.client.KeycloakBuilder;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -62,7 +63,7 @@ public class TenantController {
     /*
     Sample Request
 
-    GET
+    POST
     Creating a realm on keycloak for above gateway
         http://localhost:8080/tenant/realm/40e5be38-0fde-41fe-a846-13de8b2ecfec
      */
@@ -73,16 +74,29 @@ public class TenantController {
         RealmRepresentation realmRepresentation = new RealmRepresentation();
         realmRepresentation.setRealm(gatewayT.getGatewayId());
         keycloakAdminClient.realms().create(realmRepresentation);
-
         return gateway;
     }
 
+    /*
+    Sample Request
+
+    GET
+    Get the tenant with given id
+        http://localhost:8080/tenant/40e5be38-0fde-41fe-a846-13de8b2ecfec
+     */
     @RequestMapping(value = "/{tenant}", method = RequestMethod.GET)
     public GatewayResource getTenant(@PathVariable("tenant")String tenantId) throws TException {
         Gateway gateway = tenantClient.getGateway(authzToken, tenantId);
         return mapper.map(gateway, GatewayResource.class);
     }
 
+    /*
+    Sample Request
+
+    GET
+    Get all tenants
+        http://localhost:8080/tenant
+     */
     @RequestMapping(value = "/", method = RequestMethod.GET)
     public List<GatewayResource> getAllTenants() throws TException {
 
@@ -98,4 +112,6 @@ public class TenantController {
     public Boolean isTenantExists(@PathVariable("tenant")String tenantId) throws TException {
        return tenantClient.isGatewayExist(authzToken, tenantId);
     }
+
+    // save cilogon client id / secret. Secret goes to vault
 }
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/core/AppConfig.java b/custos-rest-api/src/main/java/org/apache/custos/rest/core/AppConfig.java
index 48b607d..8f47c27 100644
--- a/custos-rest-api/src/main/java/org/apache/custos/rest/core/AppConfig.java
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/core/AppConfig.java
@@ -3,6 +3,7 @@ package org.apache.custos.rest.core;
 import org.apache.custos.client.profile.service.CustosProfileServiceClientFactory;
 import org.apache.custos.profile.tenant.cpi.TenantProfileService;
 import org.apache.custos.profile.tenant.cpi.exception.TenantProfileServiceException;
+import org.apache.custos.rest.util.SecretEngine;
 import org.dozer.DozerBeanMapper;
 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
 import org.keycloak.admin.client.Keycloak;
@@ -27,6 +28,11 @@ public class AppConfig {
         return CustosProfileServiceClientFactory.createCustosTenantProfileServiceClient("iam.custos.scigap.org", 8081);
     }
 
+    @Bean
+    public SecretEngine secretEngine() {
+        return new SecretEngine();
+    }
+
     @Bean Keycloak keycloakAdminClient() {
         ResteasyClientBuilder clientBuilder = new ResteasyClientBuilder()
                 .connectionPoolSize(10);
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientInfoResource.java b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientInfoResource.java
new file mode 100644
index 0000000..4fb336e
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientInfoResource.java
@@ -0,0 +1,61 @@
+package org.apache.custos.rest.resources;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CILogonClientInfoResource {
+
+    @JsonProperty("client_id")
+    private String clientId;
+
+    @JsonProperty("client_secret")
+    private String clientSecret;
+
+    @JsonProperty("client_id_issued_at")
+    private String clientIdIssuedAt;
+
+    @JsonProperty("client_secret_expires_at")
+    private String clientSecretExpiresAt;
+
+    @JsonProperty("registration_client_uri")
+    private String registrationClientUri;
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    public void setClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+
+    public String getClientIdIssuedAt() {
+        return clientIdIssuedAt;
+    }
+
+    public void setClientIdIssuedAt(String clientIdIssuedAt) {
+        this.clientIdIssuedAt = clientIdIssuedAt;
+    }
+
+    public String getClientSecretExpiresAt() {
+        return clientSecretExpiresAt;
+    }
+
+    public void setClientSecretExpiresAt(String clientSecretExpiresAt) {
+        this.clientSecretExpiresAt = clientSecretExpiresAt;
+    }
+
+    public String getRegistrationClientUri() {
+        return registrationClientUri;
+    }
+
+    public void setRegistrationClientUri(String registrationClientUri) {
+        this.registrationClientUri = registrationClientUri;
+    }
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientRequestResource.java b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientRequestResource.java
new file mode 100644
index 0000000..fdf973f
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/CILogonClientRequestResource.java
@@ -0,0 +1,4 @@
+package org.apache.custos.rest.resources;
+
+public class CILogonClientRequestResource {
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/resources/KVSecretResource.java b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/KVSecretResource.java
new file mode 100644
index 0000000..7f0ccb3
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/KVSecretResource.java
@@ -0,0 +1,23 @@
+package org.apache.custos.rest.resources;
+
+public class KVSecretResource {
+
+    private String key;
+    private String value;
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/resources/Resource.java b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/Resource.java
new file mode 100644
index 0000000..ae3f81c
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/resources/Resource.java
@@ -0,0 +1,44 @@
+package org.apache.custos.rest.resources;
+
+public class Resource {
+
+    private String resourceId;
+    private String resourceName;
+    private String description;
+    // TODO
+    // This should be a class. Consider moving into ENUMS
+    private String visibility;
+
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public void setResourceName(String resourceName) {
+        this.resourceName = resourceName;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getVisibility() {
+        return visibility;
+    }
+
+    public void setVisibility(String visibility) {
+        this.visibility = visibility;
+    }
+}
diff --git a/custos-rest-api/src/main/java/org/apache/custos/rest/util/SecretEngine.java b/custos-rest-api/src/main/java/org/apache/custos/rest/util/SecretEngine.java
new file mode 100644
index 0000000..7ca3ea6
--- /dev/null
+++ b/custos-rest-api/src/main/java/org/apache/custos/rest/util/SecretEngine.java
@@ -0,0 +1,15 @@
+package org.apache.custos.rest.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SecretEngine {
+
+    public String soreKV(Map<String, String> secrets) {
+        return "";
+    }
+
+    public Map<String, String> getKV(String token) {
+        return new HashMap<>();
+    }
+}