Hello Alon Bar-Lev, I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/32335 to review the following change. Change subject: services: add proxy servlet ...................................................................... services: add proxy servlet a proxy servlet that proxy into url appending query string. example of usage: <servlet> <servlet-name>google1</servlet-name> <servlet-class>org.ovirt.engine.core.services.ProxyServlet</servlet-class> <init-param> <param-name>url</param-name> <param-value>https://www.google.com/</param-value> </init-param> <init-param> <param-name>trustStoreType</param-name> <param-value>%{ENGINE_PKI_TRUST_STORE_TYPE}</param-value> </init-param> <init-param> <param-name>trustStore</param-name> <param-value>%{ENGINE_PKI_TRUST_STORE}</param-value> </init-param> <init-param> <param-name>trustStorePassword</param-name> <param-value>%{ENGINE_PKI_TRUST_STORE_PASSWORD}</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>google1</servlet-name> <url-pattern>/google1</url-pattern> </servlet-mapping> Change-Id: Ia26768ec7a0e06a20f657cae40f6a51303970b44 Signed-off-by: Alon Bar-Lev <alo...@redhat.com> --- A backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/ProxyServlet.java M backend/manager/modules/uutils/pom.xml A backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/servlet/ProxyServletBase.java M backend/manager/modules/uutils/src/main/modules/org/ovirt/engine/core/uutils/main/module.xml 4 files changed, 295 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/35/32335/1 diff --git a/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/ProxyServlet.java b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/ProxyServlet.java new file mode 100644 index 0000000..90c7ca9 --- /dev/null +++ b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/ProxyServlet.java @@ -0,0 +1,65 @@ +package org.ovirt.engine.core.services; + +import javax.servlet.ServletException; + +import org.apache.commons.lang.StringUtils; +import org.ovirt.engine.core.utils.EngineLocalConfig; +import org.ovirt.engine.core.uutils.servlet.ProxyServletBase; + +public class ProxyServlet extends ProxyServletBase { + + private static final long serialVersionUID = 209763132892410985L; + + private static final String VERIFY_HOST_PRM = "verifyHost"; + private static final String VERIFY_CHAIN_PRM = "verifyChain"; + private static final String HTTPS_PROTOCOL_PRM = "httpsProtocol"; + private static final String TRUST_MANAGER_ALGORITHM_PRM = "trustManagerAlgorithm"; + private static final String TRUST_STORE_PRM = "trustStore"; + private static final String TRUST_STORE_TYPE_PRM = "trustStoreType"; + private static final String TRUST_STORE_PASSWORD_PRM = "trustStorePassword"; + private static final String READ_TIMEOUT_PRM = "readTimeout"; + private static final String URL_PRM = "url"; + + private String getConfigString(String name) { + String r = getServletConfig().getInitParameter(name); + if (r != null) { + r = EngineLocalConfig.getInstance().expandString(r.replaceAll("%\\{", "\\${")); + } + if (StringUtils.isEmpty(r)) { + r = null; + } + return r; + } + + private Boolean getConfigBoolean(String name) { + Boolean r = null; + String s = getConfigString(name); + if (s != null) { + r = Boolean.valueOf(s); + } + return r; + } + + private Integer getConfigInteger(String name) { + Integer r = null; + String s = getConfigString(name); + if (s != null) { + r = Integer.valueOf(s); + } + return r; + } + + @Override + public void init() throws ServletException { + setVerifyHost(getConfigBoolean(VERIFY_HOST_PRM)); + setVerifyChain(getConfigBoolean(VERIFY_CHAIN_PRM)); + setHttpsProtocol(getConfigString(HTTPS_PROTOCOL_PRM)); + setTrustManagerAlgorithm(getConfigString(TRUST_MANAGER_ALGORITHM_PRM)); + setTrustStore(getConfigString(TRUST_STORE_PRM)); + setTrustStoreType(getConfigString(TRUST_STORE_TYPE_PRM)); + setTrustStorePassword(getConfigString(TRUST_STORE_PASSWORD_PRM)); + setReadTimeout(getConfigInteger(READ_TIMEOUT_PRM)); + setUrl(getConfigString(URL_PRM)); + } + +} diff --git a/backend/manager/modules/uutils/pom.xml b/backend/manager/modules/uutils/pom.xml index 6e6db23..4633d73 100644 --- a/backend/manager/modules/uutils/pom.xml +++ b/backend/manager/modules/uutils/pom.xml @@ -30,6 +30,12 @@ <artifactId>commons-codec</artifactId> </dependency> + <dependency> + <groupId>org.jboss.spec.javax.servlet</groupId> + <artifactId>jboss-servlet-api_3.0_spec</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> <build> diff --git a/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/servlet/ProxyServletBase.java b/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/servlet/ProxyServletBase.java new file mode 100644 index 0000000..e2e48be --- /dev/null +++ b/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/servlet/ProxyServletBase.java @@ -0,0 +1,223 @@ +package org.ovirt.engine.core.uutils.servlet; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.List; +import java.util.Map; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class ProxyServletBase extends HttpServlet { + + private static final long serialVersionUID = 5331291232426186121L; + + private Boolean verifyHost = true; + private Boolean verifyChain = true; + private String httpsProtocol; + private String trustManagerAlgorithm; + private String trustStore; + private String trustStoreType; + private String trustStorePassword = "changeit"; + private Integer readTimeout; + private String url; + + protected static long copy(final InputStream input, final OutputStream output) throws IOException { + final byte[] buffer = new byte[8*1024]; + long count = 0; + int n; + while ((n = input.read(buffer)) != -1) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + protected void setVerifyHost(Boolean verifyHost) { + this.verifyHost = verifyHost; + } + + protected void setVerifyChain(Boolean verifyChain) { + this.verifyChain = verifyChain; + } + + protected void setHttpsProtocol(String httpsProtocol) { + this.httpsProtocol = httpsProtocol; + } + + protected void setTrustManagerAlgorithm(String trustManagerAlgorithm) { + this.trustManagerAlgorithm = trustManagerAlgorithm; + } + + protected void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + protected void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } + + protected void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + protected void setReadTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + } + + protected void setUrl(String url) { + this.url = url; + } + + protected URLConnection createConnection(URL url) throws IOException, GeneralSecurityException { + URLConnection connection = url.openConnection(); + connection.setDoInput(true); + connection.setDoOutput(false); + connection.setAllowUserInteraction(false); + connection.setUseCaches(false); + if (readTimeout != null) { + connection.setReadTimeout(readTimeout); + } + if (connection instanceof HttpsURLConnection) { + HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; + TrustManager[] tm = null; + if (verifyChain) { + if (trustStore != null) { + try(InputStream is = new FileInputStream(trustStore)) { + KeyStore ks = KeyStore.getInstance(trustStoreType); + ks.load(is, trustStorePassword.toCharArray()); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustManagerAlgorithm); + tmf.init(ks); + tm = tmf.getTrustManagers(); + } + } else { + tm = new TrustManager[] { + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[] {}; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + } + } + + SSLContext sslContext = SSLContext.getInstance(httpsProtocol); + sslContext.init(null, tm, null); + httpsConnection.setSSLSocketFactory(sslContext.getSocketFactory()); + + if (!verifyHost) { + httpsConnection.setHostnameVerifier( + new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + } + ); + } + } + + return connection; + } + + private String mergeQuery(String url, String queryString) throws MalformedURLException { + String ret = url; + if (queryString != null) { + URL u = new URL(ret); + if (u.getQuery() == null) { + ret += "?"; + } else { + ret += "&"; + } + ret += queryString; + } + return ret; + } + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + try { + if (verifyHost == null) { + verifyHost = true; + } + if (verifyChain == null) { + verifyChain = true; + } + if (trustManagerAlgorithm == null) { + trustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + } + if (trustStoreType == null) { + trustStoreType = KeyStore.getDefaultType(); + } + if (httpsProtocol == null) { + httpsProtocol = "TLSv1"; + } + } catch (Exception e) { + throw new ServletException(e); + } + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + if (url == null) { + response.sendError(response.SC_NOT_FOUND, "Cannot proxy, no URL is configured."); + } else { + URLConnection connection; + try { + connection = createConnection(new URL(mergeQuery(url, request.getQueryString()))); + } catch(Exception e) { + throw new ServletException(e); + } + connection.connect(); + try { + if (connection instanceof HttpURLConnection) { + response.setStatus(((HttpURLConnection)connection).getResponseCode()); + } + for (Map.Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) { + if (entry.getKey() != null) { + boolean first = true; + for (String value : entry.getValue()) { + if (first) { + first = false; + response.setHeader(entry.getKey(), value); + } else { + response.addHeader(entry.getKey(), value); + } + } + } + } + copy(connection.getInputStream(), response.getOutputStream()); + } finally { + if (connection instanceof HttpURLConnection) { + ((HttpURLConnection)connection).disconnect(); + } + } + } + } + +} diff --git a/backend/manager/modules/uutils/src/main/modules/org/ovirt/engine/core/uutils/main/module.xml b/backend/manager/modules/uutils/src/main/modules/org/ovirt/engine/core/uutils/main/module.xml index c8b8b95..55e8172 100644 --- a/backend/manager/modules/uutils/src/main/modules/org/ovirt/engine/core/uutils/main/module.xml +++ b/backend/manager/modules/uutils/src/main/modules/org/ovirt/engine/core/uutils/main/module.xml @@ -8,6 +8,7 @@ <dependencies> <module name="javax.api"/> + <module name="javax.servlet.api"/> <module name="org.apache.commons.codec"/> <module name="org.apache.commons.lang"/> <module name="org.apache.commons.logging"/> -- To view, visit http://gerrit.ovirt.org/32335 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia26768ec7a0e06a20f657cae40f6a51303970b44 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Ravi Nori <rn...@redhat.com> Gerrit-Reviewer: Alon Bar-Lev <alo...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches