Michael Pasternak has uploaded a new change for review. Change subject: sdk: implement SSL connection support (without host verification) ......................................................................
sdk: implement SSL connection support (without host verification) This is a partial support for the SSL based connections, it's enables working against SSL sites, but without validating the server identity by CA certificate. Change-Id: Ie35d89864f15b65b0daa03e74bccd6e60bdc6fac Signed-off-by: Michael Pasternak <[email protected]> --- M ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/Api.java M ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/ConnectionsPoolBuilder.java M ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxy.java M ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBroker.java M ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBuilder.java 5 files changed, 232 insertions(+), 226 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine-sdk-java refs/changes/31/12231/1 diff --git a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/Api.java b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/Api.java index 63c7be4..abe6977 100644 --- a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/Api.java +++ b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/Api.java @@ -58,7 +58,6 @@ private StorageDomains storageDomains; private Groups groups; - /** * @param url * oVirt api url @@ -66,7 +65,7 @@ * oVirt api username * @param password * oVirt api password - * + * * @throws ClientProtocolException * Signals that HTTP/S protocol error has occurred. * @throws ServerException @@ -92,9 +91,9 @@ * oVirt api username * @param password * oVirt api password - * @param insecure - * do not throw error when accessing SSL sites without certificate - * + * @param noHostVerification + * turns hostname verification off + * * @throws ClientProtocolException * Signals that HTTP/S protocol error has occurred. * @throws ServerException @@ -104,48 +103,14 @@ * @throws UnsecuredConnectionAttemptError * Signals that attempt of connecting to SSL secured site using HTTP protocol has occurred. */ - public Api(String url, String username, String password, boolean insecure) throws ClientProtocolException, - ServerException, UnsecuredConnectionAttemptError, IOException { - - ConnectionsPool pool = new ConnectionsPoolBuilder(url, username, password) - .build(); - HttpProxy httpProxy = new HttpProxyBuilder(pool) - .insecure(insecure) - .build(); - this.proxy = new HttpProxyBroker(httpProxy); - initResources(); - } - - /** - * @param url - * oVirt api url - * @param username - * oVirt api username - * @param password - * oVirt api password - * @param ca_file - * CA certificate to validate the server identity - * @param filter - * enables filtering based on user's permissions - * - * @throws ClientProtocolException - * Signals that HTTP/S protocol error has occurred. - * @throws ServerException - * Signals that an oVirt api error has occurred. - * @throws IOException - * Signals that an I/O exception of some sort has occurred. - * @throws UnsecuredConnectionAttemptError - * Signals that attempt of connecting to SSL secured site using HTTP protocol has occurred. - */ - public Api(String url, String username, String password, String ca_file, boolean filter) + public Api(String url, String username, String password, boolean noHostVerification) throws ClientProtocolException, ServerException, UnsecuredConnectionAttemptError, IOException { ConnectionsPool pool = new ConnectionsPoolBuilder(url, username, password) - .ca_file(ca_file) - .build(); + .noHostVerification(noHostVerification) + .build(); HttpProxy httpProxy = new HttpProxyBuilder(pool) - .filter(filter) - .build(); + .build(); this.proxy = new HttpProxyBroker(httpProxy); initResources(); } @@ -157,25 +122,53 @@ * oVirt api username * @param password * oVirt api password - * @param key_file - * user key file to validate client identity - * @param cert_file - * user certificate file to validate client identity - * @param ca_file - * CA certificate to validate the server identity + * @param noHostVerification + * turns hostname verification off + * @param filter + * enables filtering based on user's permissions + * + * @throws ClientProtocolException + * Signals that HTTP/S protocol error has occurred. + * @throws ServerException + * Signals that an oVirt api error has occurred. + * @throws IOException + * Signals that an I/O exception of some sort has occurred. + * @throws UnsecuredConnectionAttemptError + * Signals that attempt of connecting to SSL secured site using HTTP protocol has occurred. + */ + public Api(String url, String username, String password, Boolean noHostVerification, Boolean filter) + throws ClientProtocolException, ServerException, UnsecuredConnectionAttemptError, IOException { + + ConnectionsPool pool = new ConnectionsPoolBuilder(url, username, password) + .noHostVerification(noHostVerification) + .build(); + HttpProxy httpProxy = new HttpProxyBuilder(pool) + .filter(filter) + .build(); + this.proxy = new HttpProxyBroker(httpProxy); + initResources(); + } + + /** + * @param url + * oVirt api url + * @param username + * oVirt api username + * @param password + * oVirt api password * @param port * oVirt api port * @param timeout * request timeout * @param persistentAuth - * disable persistent authetication (will be used auth. per request) - * @param insecure - * do not throw error when accessing SSL sites without certificate + * disable persistent authentication (will be used auth. per request) + * @param noHostVerification + * turns hostname verification off * @param filter * enables filtering based on user's permissions * @param debug * enables debug mode - * + * * @throws ClientProtocolException * Signals that HTTP/S protocol error has occurred. * @throws ServerException @@ -185,24 +178,20 @@ * @throws UnsecuredConnectionAttemptError * Signals that attempt of connecting to SSL secured site using HTTP protocol has occurred. */ - public Api(String url, String username, String password, String key_file, - String cert_file, String ca_file, Integer port, Integer timeout, - Boolean persistentAuth, Boolean insecure, Boolean filter, Boolean debug) throws ClientProtocolException, - ServerException, UnsecuredConnectionAttemptError, IOException { + public Api(String url, String username, String password, Integer port, Integer timeout, + Boolean persistentAuth, Boolean noHostVerification, Boolean filter, Boolean debug) + throws ClientProtocolException, ServerException, UnsecuredConnectionAttemptError, IOException { ConnectionsPool pool = new ConnectionsPoolBuilder(url, username, password) - .key_file(key_file) - .cert_file(cert_file) - .ca_file(ca_file) - .port(port) - .timeout(timeout) - .build(); + .port(port) + .timeout(timeout) + .noHostVerification(noHostVerification) + .build(); HttpProxy httpProxy = new HttpProxyBuilder(pool) - .persistentAuth(persistentAuth) - .insecure(insecure) - .filter(filter) - .debug(debug) - .build(); + .persistentAuth(persistentAuth) + .filter(filter) + .debug(debug) + .build(); this.proxy = new HttpProxyBroker(httpProxy); initResources(); } @@ -248,15 +237,6 @@ } /** - * Enable/Disable accessing SSL sites without validating host identity (default is False) - * - * @param insecure - */ - public void setInsecure(boolean insecure) { - this.proxy.setInsecure(insecure); - } - - /** * Enable/Disable persistent authentication (default is True) * * @param persistentAuth @@ -270,13 +250,6 @@ */ public boolean isPersistentAuth() { return this.proxy.isPersistentAuth(); - } - - /** - * @return Insecure flag - */ - public boolean isInsecure() { - return this.proxy.isInsecure(); } /** @@ -294,11 +267,10 @@ } /** - * Gets the value of the Networks property. - * - * @return - * {@link Networks } - * + * Gets the value of the Networks property. + * + * @return {@link Networks } + * */ public synchronized Networks getNetworks() { if (this.networks == null) { @@ -306,12 +278,12 @@ } return networks; } + /** - * Gets the value of the Tags property. - * - * @return - * {@link Tags } - * + * Gets the value of the Tags property. + * + * @return {@link Tags } + * */ public synchronized Tags getTags() { if (this.tags == null) { @@ -319,12 +291,12 @@ } return tags; } + /** - * Gets the value of the Users property. - * - * @return - * {@link Users } - * + * Gets the value of the Users property. + * + * @return {@link Users } + * */ public synchronized Users getUsers() { if (this.users == null) { @@ -332,12 +304,12 @@ } return users; } + /** - * Gets the value of the Templates property. - * - * @return - * {@link Templates } - * + * Gets the value of the Templates property. + * + * @return {@link Templates } + * */ public synchronized Templates getTemplates() { if (this.templates == null) { @@ -345,12 +317,12 @@ } return templates; } + /** - * Gets the value of the Events property. - * - * @return - * {@link Events } - * + * Gets the value of the Events property. + * + * @return {@link Events } + * */ public synchronized Events getEvents() { if (this.events == null) { @@ -358,12 +330,12 @@ } return events; } + /** - * Gets the value of the Domains property. - * - * @return - * {@link Domains } - * + * Gets the value of the Domains property. + * + * @return {@link Domains } + * */ public synchronized Domains getDomains() { if (this.domains == null) { @@ -371,12 +343,12 @@ } return domains; } + /** - * Gets the value of the Disks property. - * - * @return - * {@link Disks } - * + * Gets the value of the Disks property. + * + * @return {@link Disks } + * */ public synchronized Disks getDisks() { if (this.disks == null) { @@ -384,12 +356,12 @@ } return disks; } + /** - * Gets the value of the Clusters property. - * - * @return - * {@link Clusters } - * + * Gets the value of the Clusters property. + * + * @return {@link Clusters } + * */ public synchronized Clusters getClusters() { if (this.clusters == null) { @@ -397,12 +369,12 @@ } return clusters; } + /** - * Gets the value of the DataCenters property. - * - * @return - * {@link DataCenters } - * + * Gets the value of the DataCenters property. + * + * @return {@link DataCenters } + * */ public synchronized DataCenters getDataCenters() { if (this.dataCenters == null) { @@ -410,12 +382,12 @@ } return dataCenters; } + /** - * Gets the value of the Roles property. - * - * @return - * {@link Roles } - * + * Gets the value of the Roles property. + * + * @return {@link Roles } + * */ public synchronized Roles getRoles() { if (this.roles == null) { @@ -423,12 +395,12 @@ } return roles; } + /** - * Gets the value of the Hosts property. - * - * @return - * {@link Hosts } - * + * Gets the value of the Hosts property. + * + * @return {@link Hosts } + * */ public synchronized Hosts getHosts() { if (this.hosts == null) { @@ -436,12 +408,12 @@ } return hosts; } + /** - * Gets the value of the VMs property. - * - * @return - * {@link VMs } - * + * Gets the value of the VMs property. + * + * @return {@link VMs } + * */ public synchronized VMs getVMs() { if (this.vMs == null) { @@ -449,12 +421,12 @@ } return vMs; } + /** - * Gets the value of the VmPools property. - * - * @return - * {@link VmPools } - * + * Gets the value of the VmPools property. + * + * @return {@link VmPools } + * */ public synchronized VmPools getVmPools() { if (this.vmPools == null) { @@ -462,12 +434,12 @@ } return vmPools; } + /** - * Gets the value of the StorageDomains property. - * - * @return - * {@link StorageDomains } - * + * Gets the value of the StorageDomains property. + * + * @return {@link StorageDomains } + * */ public synchronized StorageDomains getStorageDomains() { if (this.storageDomains == null) { @@ -475,12 +447,12 @@ } return storageDomains; } + /** - * Gets the value of the Groups property. - * - * @return - * {@link Groups } - * + * Gets the value of the Groups property. + * + * @return {@link Groups } + * */ public synchronized Groups getGroups() { if (this.groups == null) { @@ -489,12 +461,11 @@ return groups; } - /** * Gets the value of the Time property. - * + * * @return {@link javax.xml.datatype.XMLGregorianCalendar } - * + * * @throws ClientProtocolException * Signals that HTTP/S protocol error has occurred. * @throws ServerException @@ -508,11 +479,12 @@ UnsecuredConnectionAttemptError, IOException { return getEntryPoint().getTime(); } + /** * Gets the value of the Summary property. - * + * * @return {@link org.ovirt.engine.sdk.entities.ApiSummary } - * + * * @throws ClientProtocolException * Signals that HTTP/S protocol error has occurred. * @throws ServerException @@ -526,11 +498,12 @@ UnsecuredConnectionAttemptError, IOException { return getEntryPoint().getSummary(); } + /** * Gets the value of the SpecialObjects property. - * + * * @return {@link org.ovirt.engine.sdk.entities.SpecialObjects } - * + * */ public org.ovirt.engine.sdk.entities.SpecialObjects getSpecialObjects() { if (this.entryPoint != null) { @@ -538,11 +511,12 @@ } return null; } + /** * Gets the value of the ProductInfo property. - * + * * @return {@link org.ovirt.engine.sdk.entities.ProductInfo } - * + * */ public org.ovirt.engine.sdk.entities.ProductInfo getProductInfo() { if (this.entryPoint != null) { @@ -552,4 +526,3 @@ } } - diff --git a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/ConnectionsPoolBuilder.java b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/ConnectionsPoolBuilder.java index befb8de..284acac 100644 --- a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/ConnectionsPoolBuilder.java +++ b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/ConnectionsPoolBuilder.java @@ -18,6 +18,12 @@ import java.net.MalformedURLException; import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; @@ -35,6 +41,10 @@ * Provides ConnectionsPool building services */ public class ConnectionsPoolBuilder { + + private static final String BAD_PROTOCOL_ERROR = "Unsupported protocol "; + private static final String BAD_KEY_ERROR = "SSL context initiation has failed because of key error."; + private static final String NO_TLS_ERROR = "SSL context initiation has failed locating TLS slgorithm."; private static int MAX_CONNECTIONS = 20; private static int MAX_CONNECTIONS_PER_HOST = 50; @@ -54,6 +64,7 @@ private String ca_file; private int port = -1; private int timeout = -1; + private boolean noHostVerification = false; private URL urlobj = null; @@ -134,6 +145,7 @@ /** * @param port * oVirt API port + * */ public ConnectionsPoolBuilder port(Integer port) { if (port != null) { @@ -149,6 +161,17 @@ public ConnectionsPoolBuilder timeout(Integer timeout) { if (timeout != null) { this.timeout = timeout.intValue(); + } + return this; + } + + /** + * @param noHostVerification + * flag + */ + public ConnectionsPoolBuilder noHostVerification(Boolean noHostVerification) { + if (noHostVerification != null) { + this.noHostVerification = noHostVerification.booleanValue(); } return this; } @@ -170,11 +193,13 @@ private DefaultHttpClient createDefaultHttpClient(String url, String username, String password, String key_file, String cert_file, String ca_file, Integer port, Integer timeout) { + int port_ = getPort(url, port); + DefaultHttpClient client = - new DefaultHttpClient(createPoolingClientConnectionManager(url, port)); + new DefaultHttpClient(createPoolingClientConnectionManager(url, port_)); client.getCredentialsProvider().setCredentials( - new AuthScope(getHost(url), getPort(url, port)), + new AuthScope(getHost(url), port_), new UsernamePasswordCredentials(username, password)); // FIXME: use all .ctr params @@ -190,7 +215,7 @@ * * @return {@link ClientConnectionManager} */ - private ClientConnectionManager createPoolingClientConnectionManager(String url, Integer port) { + private ClientConnectionManager createPoolingClientConnectionManager(String url, int port) { SchemeRegistry schemeRegistry = createSchemeRegistry(url, port); PoolingClientConnectionManager cm = @@ -214,19 +239,48 @@ * * @return {@link SchemeRegistry} */ - private SchemeRegistry createSchemeRegistry(String url, Integer port) { + private SchemeRegistry createSchemeRegistry(String url, int port) { SchemeRegistry schemeRegistry = new SchemeRegistry(); String protocol = getProtocol(url); + SSLSocketFactory sf; + if (HTTP_PROTOCOL.equals(protocol)) { schemeRegistry.register( new Scheme(HTTP_PROTOCOL, - getPort(url, port), + port, PlainSocketFactory.getSocketFactory())); + } else if (HTTPS_PROTOCOL.equals(protocol)) { + SSLContext sslcontext; + try { + sslcontext = SSLContext.getInstance("TLS"); + + if (this.noHostVerification) { + sslcontext.init(null, new TrustManager[] { noCaTrustManager }, null); + sf = new SSLSocketFactory( + sslcontext, + SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } else { + sslcontext.init(null, null, null); + sf = new SSLSocketFactory( + sslcontext, + // This hostname verifier that works the same way as Curl and Firefox. The hostname must + // match either the first CN, or any of the subject-alts. A wildcard can occur in the CN, + // and in any of the subject-alts. The only difference between BrowserCompatHostnameVerifier + // and StrictHostnameVerifier is that a wildcard (such as "*.foo.com") with + // BrowserCompatHostnameVerifier matches all subdomains, including "a.b.foo.com". + SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + schemeRegistry.register( + new Scheme(HTTPS_PROTOCOL, port, sf)); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new RuntimeException(NO_TLS_ERROR, e); + } catch (KeyManagementException e) { + throw new RuntimeException(BAD_KEY_ERROR, e); + } } else { - schemeRegistry.register( - new Scheme(HTTPS_PROTOCOL, - getPort(url, port), - SSLSocketFactory.getSocketFactory())); + throw new RuntimeException(BAD_PROTOCOL_ERROR + protocol); } return schemeRegistry; @@ -265,4 +319,29 @@ cert_file, ca_file, port, timeout), this.urlobj); } + + /** + * This TrustManager used to ignore CA cert validation and should not be used unless user explicitly asks to ignore + * host identity validation. + */ + X509TrustManager noCaTrustManager = new X509TrustManager() { + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws java.security.cert.CertificateException { + // do nothing + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws java.security.cert.CertificateException { + // do nothing + + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + }; } diff --git a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxy.java b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxy.java index 88e1228..ce42e78 100644 --- a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxy.java +++ b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxy.java @@ -48,7 +48,6 @@ private ConnectionsPool pool; private List<Header> staticHeaders; private boolean persistentAuth = true; - private boolean insecure = false; private boolean filter = false; private boolean debug = false; @@ -65,13 +64,11 @@ * @param debug * flag */ - public HttpProxy(ConnectionsPool pool, boolean persistent_auth, boolean insecure, - boolean filter, boolean debug) { + public HttpProxy(ConnectionsPool pool, boolean persistent_auth, boolean filter, boolean debug) { super(); this.pool = pool; this.staticHeaders = HttpHeaderUtils.toHeaders(STATIC_HEADERS); this.persistentAuth = persistent_auth; - this.insecure = insecure; this.filter = filter; this.debug = debug; } @@ -195,21 +192,6 @@ */ public void setPersistentAuth(boolean persistentAuth) { this.persistentAuth = persistentAuth; - } - - /** - * @return Insecure flag - */ - public boolean isInsecure() { - return insecure; - } - - /** - * @param insecure - * sets Insecure flag - */ - public void setInsecure(boolean insecure) { - this.insecure = insecure; } /** diff --git a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBroker.java b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBroker.java index 28b07a0..ee39077 100644 --- a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBroker.java +++ b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBroker.java @@ -433,15 +433,6 @@ } /** - * Enable/Disable accessing SSL sites without validating host identity (default is False) - * - * @param insecure - */ - public void setInsecure(boolean insecure) { - this.proxy.setInsecure(insecure); - } - - /** * Enable/Disable persistent authentication (default is True) * * @param persistentAuth @@ -455,13 +446,6 @@ */ public boolean isPersistentAuth() { return this.proxy.isPersistentAuth(); - } - - /** - * @return Insecure flag - */ - public boolean isInsecure() { - return this.proxy.isInsecure(); } /** diff --git a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBuilder.java b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBuilder.java index e6f0f4c..628a370 100644 --- a/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBuilder.java +++ b/ovirt-engine-sdk-java/src/main/java/org/ovirt/engine/sdk/web/HttpProxyBuilder.java @@ -23,7 +23,6 @@ private ConnectionsPool pool; private boolean persistentAuth = true; - private boolean insecure = false; private boolean filter = false; private boolean debug = false; @@ -43,17 +42,6 @@ public HttpProxyBuilder persistentAuth(Boolean persistentAuth) { if (persistentAuth != null) { this.persistentAuth = persistentAuth.booleanValue(); - } - return this; - } - - /** - * @param insecure - * flag - */ - public HttpProxyBuilder insecure(Boolean insecure) { - if (insecure != null) { - this.insecure = insecure.booleanValue(); } return this; } @@ -84,6 +72,6 @@ * builds the proxy */ public HttpProxy build() { - return new HttpProxy(pool, persistentAuth, insecure, filter, debug); + return new HttpProxy(pool, persistentAuth, filter, debug); } } -- To view, visit http://gerrit.ovirt.org/12231 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie35d89864f15b65b0daa03e74bccd6e60bdc6fac Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine-sdk-java Gerrit-Branch: master Gerrit-Owner: Michael Pasternak <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
