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

Reply via email to