package org.gcube.event.publisher; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.gcube.oidc.rest.JWTToken; import org.gcube.oidc.rest.OpenIdConnectRESTHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HTTPWithUMAAuthEventSender implements EventSender { protected static final Logger log = LoggerFactory.getLogger(HTTPWithUMAAuthEventSender.class); private URL baseEnndpointURL; private String clientId; private String clientSecret; private URL tokenURL; private String umaAudience; public HTTPWithUMAAuthEventSender(URL baseEnndpointURL, String clientId, String clientSecret, URL tokenURL, String umaAudience) { this.baseEnndpointURL = baseEnndpointURL; this.clientId = clientId; this.clientSecret = clientSecret; this.tokenURL = tokenURL; this.umaAudience = umaAudience; } @Override public void send(Event event) { log.debug("Starting HTTP POST thread to: {}", baseEnndpointURL); try { URL eventEndpoint = new URL(baseEnndpointURL, event.getName()); new Thread(new HTTPost(eventEndpoint, event.toJSONString())).start(); } catch (MalformedURLException e) { log.error("Cannot compute event endpoint URL. Event name: " + event.getName() + ", base endpoint: " + baseEnndpointURL, e); } } public class HTTPost implements Runnable { private static final int CONNECTION_TIMEOUT = 10000; private static final int READ_TIMEOUT = 5000; private URL endpoint; private String jsonString; public HTTPost(URL endpoint, String jsonString) { this.endpoint = endpoint; this.jsonString = jsonString; } @Override public void run() { try { log.debug("Getting OIDC token for client: {}", clientId); JWTToken umaToken = null; if (clientId != null && clientSecret != null && tokenURL != null && umaAudience != null) { log.debug("Getting OIDC token for clientId '{}' from: {}", clientId, tokenURL); JWTToken oidcToken = OpenIdConnectRESTHelper.queryClientToken(clientId, clientSecret, tokenURL); log.debug("Getting UMA token for audience '{}' from: {}", umaAudience, tokenURL); umaToken = OpenIdConnectRESTHelper.queryUMAToken(tokenURL, oidcToken.getAsBearer(), umaAudience, null); } else { log.debug("Can't get UMA token since not all the required params was provied"); } log.debug("Performing HTTP POST to: {}", endpoint); HttpURLConnection connection = (HttpURLConnection) endpoint.openConnection(); connection.setRequestMethod("POST"); connection.setConnectTimeout(CONNECTION_TIMEOUT); log.trace("HTTP connection timeout set to: {}", connection.getConnectTimeout()); connection.setReadTimeout(READ_TIMEOUT); log.trace("HTTP connection Read timeout set to: {}", connection.getReadTimeout()); connection.setRequestProperty("Content-Type", "application/json"); // Commented out as per the Conductor issue: https://github.com/Netflix/conductor/issues/376 // connection.setRequestProperty("Accept", "application/json"); connection.setDoOutput(true); if (umaToken != null) { log.debug("Setting authorization header as: {}", umaToken.getAsBearer()); connection.setRequestProperty("Authorization", umaToken.getAsBearer()); } else { log.debug("Sending request without authorization header"); } OutputStream os = connection.getOutputStream(); log.trace("Sending event JSON: {}", jsonString); os.write(jsonString.getBytes("UTF-8")); os.flush(); os.close(); StringBuilder sb = new StringBuilder(); int httpResultCode = connection.getResponseCode(); log.trace("HTTP Response code: {}", httpResultCode); log.trace("Reading response"); boolean ok = true; InputStreamReader isr = null; if (httpResultCode == HttpURLConnection.HTTP_OK) { isr = new InputStreamReader(connection.getInputStream(), "UTF-8"); } else { ok = false; isr = new InputStreamReader(connection.getErrorStream(), "UTF-8"); } BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } br.close(); isr.close(); if (ok) { log.debug("[{}] Event publish OK. Results: {}", httpResultCode, sb.toString()); } else { log.warn("[{}] Event publish is not OK. Results: {}", httpResultCode, sb.toString()); } } catch (Exception e) { log.error("POSTing JSON to: " + endpoint, e); } } } }