You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2022/07/29 13:53:39 UTC

[brooklyn-server] 06/06: allow use of trust all to be configured via brooklyn properties and entity config

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

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 21da50685935380be46a6819c0441f97b879a752
Author: Alex Heneveld <al...@cloudsoft.io>
AuthorDate: Fri Jul 29 14:26:13 2022 +0100

    allow use of trust all to be configured via brooklyn properties and entity config
    
    see BrooklynHttpConfig
---
 .../catalog/internal/BasicBrooklynCatalog.java     |   2 +-
 .../PropertiesFileExternalConfigSupplier.java      |   4 +-
 .../vault/VaultExternalConfigSupplier.java         |   3 +-
 .../core/effector/http/HttpCommandEffector.java    |  54 +++----
 .../core/location/LocationConfigUtils.java         |  35 +++--
 .../mgmt/ha/BrooklynBomOsgiArchiveInstaller.java   |   2 +-
 .../org/apache/brooklyn/feed/http/HttpFeed.java    |  60 +++-----
 .../brooklyn/location/ssh/SshMachineLocation.java  |   2 +-
 .../apache/brooklyn/util/core/ResourceUtils.java   |  38 ++++-
 .../util/core/javalang/BrooklynHttpConfig.java     | 155 +++++++++++++++++++++
 .../brooklyn/util/core/osgi/BundleMaker.java       |   2 +-
 .../util/core/task/ssh/SshPutTaskFactory.java      |   7 +
 .../util/executor/HttpExecutorFactoryImpl.java     |  10 +-
 .../brooklyn/util/core/ResourceUtilsTest.java      |   2 +-
 .../location/jclouds/CreateUserStatements.java     |   3 +-
 .../brooklyn/location/jclouds/JcloudsLocation.java |   6 +-
 .../jclouds/JcloudsSshMachineLocation.java         |   3 +-
 .../entity/brooklynnode/DeployBlueprintTest.java   |   4 +-
 .../brooklyn/rest/BrooklynRestApiLauncherTest.java |   2 +-
 .../entity/brooklynnode/EntityHttpClientImpl.java  |   6 +-
 .../brooklynnode/BrooklynNodeIntegrationTest.java  |  23 ++-
 .../org/apache/brooklyn/test/HttpTestUtils.java    | 138 +++++-------------
 .../org/apache/brooklyn/test/WebAppMonitor.java    |   3 +-
 .../org/apache/brooklyn/util/http/HttpAsserts.java |  16 +--
 .../org/apache/brooklyn/util/http/HttpTool.java    |  50 ++++---
 .../util/http/TrustingSslSocketFactory.java        |   6 +-
 .../executor/apacheclient/HttpExecutorImpl.java    |   7 +
 .../brooklyn/util/jmx/jmxmp/JmxmpClient.java       |  11 +-
 28 files changed, 394 insertions(+), 260 deletions(-)

diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 8e742eb6cf..b8d37a3257 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -1233,7 +1233,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         // org.reflections requires the URL to be "file:" containg ".jar"
         File fJar = Os.newTempFile(containingBundle.getVersionedName().toOsgiString(), ".jar");
         try {
-            Streams.copy(ResourceUtils.create().getResourceFromUrl(url), new FileOutputStream(fJar));
+            Streams.copy(ResourceUtils.create(mgmt).getResourceFromUrl(url), new FileOutputStream(fJar));
             subCatalog.addToClasspath(new String[] { "file:"+fJar.getAbsolutePath() });
             Collection<CatalogItemDtoAbstract<?, ?>> result = scanAnnotationsInternal(mgmt, subCatalog, MutableMap.of("version", containingBundle.getSuppliedVersionString()), containingBundle);
             return result;
diff --git a/core/src/main/java/org/apache/brooklyn/core/config/external/PropertiesFileExternalConfigSupplier.java b/core/src/main/java/org/apache/brooklyn/core/config/external/PropertiesFileExternalConfigSupplier.java
index e9db17ea5b..eb640bcf34 100644
--- a/core/src/main/java/org/apache/brooklyn/core/config/external/PropertiesFileExternalConfigSupplier.java
+++ b/core/src/main/java/org/apache/brooklyn/core/config/external/PropertiesFileExternalConfigSupplier.java
@@ -54,10 +54,10 @@ public class PropertiesFileExternalConfigSupplier extends AbstractExternalConfig
         return properties.getProperty(key);
     }
 
-    private static Properties loadProperties(String propertiesUrl) throws IOException {
+    private Properties loadProperties(String propertiesUrl) throws IOException {
         InputStream is = null;
         try {
-            is = ResourceUtils.create().getResourceFromUrl(propertiesUrl);
+            is = ResourceUtils.create(getManagementContext()).getResourceFromUrl(propertiesUrl);
             Properties p = new Properties();
             p.load(is);
             return p;
diff --git a/core/src/main/java/org/apache/brooklyn/core/config/external/vault/VaultExternalConfigSupplier.java b/core/src/main/java/org/apache/brooklyn/core/config/external/vault/VaultExternalConfigSupplier.java
index 2a976f10ed..28f9c84362 100644
--- a/core/src/main/java/org/apache/brooklyn/core/config/external/vault/VaultExternalConfigSupplier.java
+++ b/core/src/main/java/org/apache/brooklyn/core/config/external/vault/VaultExternalConfigSupplier.java
@@ -29,6 +29,7 @@ import com.google.gson.JsonObject;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.core.config.external.AbstractExternalConfigSupplier;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.http.HttpTool;
 import org.apache.brooklyn.util.http.HttpToolResponse;
@@ -69,7 +70,7 @@ public abstract class VaultExternalConfigSupplier extends AbstractExternalConfig
         super(managementContext, name);
         this.config = config;
         this.name = name;
-        httpClient = HttpTool.httpClientBuilder().build();
+        httpClient = BrooklynHttpConfig.httpClientBuilder(managementContext, true).build();
         gson = new GsonBuilder().create();
 
         List<String> errors = Lists.newArrayListWithCapacity(2);
diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
index 6a3fddfe11..ea21e2ca5f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
+++ b/core/src/main/java/org/apache/brooklyn/core/effector/http/HttpCommandEffector.java
@@ -18,21 +18,14 @@
  */
 package org.apache.brooklyn.core.effector.http;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import java.util.concurrent.Callable;
-
+import com.google.common.annotations.Beta;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.google.common.io.ByteStreams;
+import com.google.common.net.HttpHeaders;
+import com.jayway.jsonpath.JsonPath;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
@@ -45,26 +38,27 @@ import org.apache.brooklyn.core.entity.EntityInitializers;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.util.collections.Jsonya;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.http.executor.HttpConfig;
+import org.apache.brooklyn.util.http.auth.UsernamePassword;
 import org.apache.brooklyn.util.http.executor.HttpExecutor;
 import org.apache.brooklyn.util.http.executor.HttpRequest;
 import org.apache.brooklyn.util.http.executor.HttpResponse;
-import org.apache.brooklyn.util.http.auth.UsernamePassword;
-import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Enums;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.base.Throwables;
-import com.google.common.io.ByteStreams;
-import com.google.common.net.HttpHeaders;
-import com.jayway.jsonpath.JsonPath;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * An {@link Effector} to invoke REST endpoints.
@@ -141,7 +135,7 @@ public final class HttpCommandEffector extends AddEffectorInitializerAbstract {
             if(!Strings.isEmpty(jsonPath) && !pathsAndSensors.isEmpty()) {
                 throw new IllegalArgumentException("Both jsonPath and pathsAndSensors are defined, please pick just one to resolve the ambiguity");
             }
-            final HttpExecutor httpExecutor = HttpExecutorImpl.newInstance();
+            final HttpExecutor httpExecutor = BrooklynHttpConfig.newHttpExecutor(entity());
 
             final HttpRequest request = buildHttpRequest(httpVerb, uri, headers, httpUsername, httpPassword, payload);
             Task t = Tasks.builder().displayName(effector.getName()).body(new Callable<Object>() {
@@ -205,11 +199,7 @@ public final class HttpCommandEffector extends AddEffectorInitializerAbstract {
             HttpRequest.Builder httpRequestBuilder = new HttpRequest.Builder()
                     .uri(uri)
                     .method(httpVerb)
-                    .config(HttpConfig.builder()
-                            .trustSelfSigned(true)
-                            .trustAll(true)
-                            .laxRedirect(true)
-                            .build());
+                    .config(BrooklynHttpConfig.httpConfigBuilder(entity()).build());
 
             if (headers != null) {
                 httpRequestBuilder.headers(headers);
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/LocationConfigUtils.java b/core/src/main/java/org/apache/brooklyn/core/location/LocationConfigUtils.java
index 73607af8cc..3011d8baf0 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/LocationConfigUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/LocationConfigUtils.java
@@ -63,12 +63,18 @@ public class LocationConfigUtils {
      * {@link LocationConfigKeys#PRIVATE_KEY_DATA} and {@link LocationConfigKeys#PRIVATE_KEY_FILE}
      * (defaulting to the private key file + ".pub"). 
      **/
+    public static OsCredential getOsCredential(ConfigBag config, ResourceUtils ru) {
+        return OsCredential.newInstance(config).withResourceUtils(ru);
+    }
+
+    @Deprecated /** @deprecated since 1.1, pass a ResourceUtils for external lookup */
+    // only used in tests
     public static OsCredential getOsCredential(ConfigBag config) {
         return OsCredential.newInstance(config);
     }
     
     /** Convenience class for holding private/public keys and passwords, inferring from config keys.
-     * See {@link LocationConfigUtils#getOsCredential(ConfigBag)}. */
+     * See {@link LocationConfigUtils#getOsCredential(ConfigBag, ResourceUtils)}. */
     @Beta // would be nice to replace with a builder pattern 
     public static class OsCredential {
         private final ConfigBag config;
@@ -84,11 +90,17 @@ public class LocationConfigUtils {
         private String privateKeyData;
         private String publicKeyData;
         private String password;
+        private ResourceUtils resourceUtils;
         
         private OsCredential(ConfigBag config) {
             this.config = config;
         }
 
+        public OsCredential withResourceUtils(ResourceUtils ru) {
+            this.resourceUtils = ru;
+            return this;
+        }
+
         /** throws if there are any problems */
         public OsCredential checkNotEmpty() {
             checkNoErrors();
@@ -200,7 +212,12 @@ public class LocationConfigUtils {
         public static OsCredential newInstance(ConfigBag config) {
             return new OsCredential(config);
         }
-        
+
+        private ResourceUtils getResourceUtils() {
+            if (resourceUtils==null) resourceUtils = ResourceUtils.create("OsCredentials-uninitialized");  //shouldn't be used
+            return resourceUtils;
+        }
+
         private synchronized void infer() {
             if (!dirty) return;
             warningMessages.clear(); 
@@ -208,7 +225,7 @@ public class LocationConfigUtils {
             log.debug("Inferring OS credentials");
             privateKeyData = config.get(LocationConfigKeys.PRIVATE_KEY_DATA);
             password = config.get(LocationConfigKeys.PASSWORD);
-            publicKeyData = getKeyDataFromDataKeyOrFileKey(config, LocationConfigKeys.PUBLIC_KEY_DATA, LocationConfigKeys.PUBLIC_KEY_FILE);
+            publicKeyData = getKeyDataFromDataKeyOrFileKey(config, LocationConfigKeys.PUBLIC_KEY_DATA, LocationConfigKeys.PUBLIC_KEY_FILE, getResourceUtils());
 
             KeyPair privateKey = null;
             
@@ -228,7 +245,7 @@ public class LocationConfigUtils {
                                 // not real important, but we get it for free if "files" is a list instead.
                                 // using ResourceUtils is useful for classpath resources
                                 if (file!=null)
-                                    privateKeyData = ResourceUtils.create().getResourceAsString(file);
+                                    privateKeyData = getResourceUtils().getResourceAsString(file);
                                 // else use data already set
                                 
                                 privateKey = getValidatedPrivateKey(file);
@@ -241,7 +258,7 @@ public class LocationConfigUtils {
                                 } else {
                                     String publicKeyFile = (file!=null ? file+".pub" : "(data)");
                                     try {
-                                        publicKeyData = ResourceUtils.create().getResourceAsString(publicKeyFile);
+                                        publicKeyData = getResourceUtils().getResourceAsString(publicKeyFile);
                                         
                                         log.debug("Loaded private key data from "+file+
                                             " and public key data from "+publicKeyFile);
@@ -363,7 +380,7 @@ public class LocationConfigUtils {
         }
     }
 
-    private static String getKeyDataFromDataKeyOrFileKey(ConfigBag config, ConfigKey<String> dataKey, ConfigKey<String> fileKey) {
+    private static String getKeyDataFromDataKeyOrFileKey(ConfigBag config, ConfigKey<String> dataKey, ConfigKey<String> fileKey, ResourceUtils ru) {
         boolean unused = config.isUnused(dataKey);
         String data = config.get(dataKey);
         if (Strings.isNonBlank(data) && !unused) {
@@ -374,7 +391,7 @@ public class LocationConfigUtils {
         if (groovyTruth(file)) {
             List<String> files = Arrays.asList(file.split(File.pathSeparator));
             List<String> filesTidied = tidyFilePaths(files);
-            String fileData = getFileContents(filesTidied);
+            String fileData = getFileContents(filesTidied, ru);
             if (fileData == null) {
                 log.warn("Invalid file" + (files.size() > 1 ? "s" : "") + " for " + fileKey + " (given " + files + 
                         (files.equals(filesTidied) ? "" : "; converted to " + filesTidied) + ") " +
@@ -398,14 +415,14 @@ public class LocationConfigUtils {
      *  
      * @param files             list of file paths
      */
-    private static String getFileContents(Iterable<String> files) {
+    private static String getFileContents(Iterable<String> files, ResourceUtils ru) {
         Iterator<String> fi = files.iterator();
         while (fi.hasNext()) {
             String file = fi.next();
             if (groovyTruth(file)) {
                 try {
                     // see comment above
-                    String result = ResourceUtils.create().getResourceAsString(file);
+                    String result = ru.getResourceAsString(file);
                     if (result!=null) return result;
                     log.debug("Invalid file "+file+" ; " + (!fi.hasNext() ? "no more files to try" : "trying next file")+" (null)");
                 } catch (Exception e) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
index fc1440738d..bccc8d0d50 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
@@ -330,7 +330,7 @@ public class BrooklynBomOsgiArchiveInstaller {
                             // get a handle on the zip file (although we could skip if not doing persistence - but that feels even worse than this!)
                             try {
                                 url = Strings.removeFromStart(url, "system:");
-                                File zipTemp = new BundleMaker(ResourceUtils.create()).createJarFromClasspathDir(url);
+                                File zipTemp = new BundleMaker(ResourceUtils.create(mgmt)).createJarFromClasspathDir(url);
                                 zipIn = new FileInputStream(zipTemp);
                             } catch (FileNotFoundException e) {
                                 throw Exceptions.propagate(e);
diff --git a/core/src/main/java/org/apache/brooklyn/feed/http/HttpFeed.java b/core/src/main/java/org/apache/brooklyn/feed/http/HttpFeed.java
index c1897173a2..2f0247bc8b 100644
--- a/core/src/main/java/org/apache/brooklyn/feed/http/HttpFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/feed/http/HttpFeed.java
@@ -18,20 +18,11 @@
  */
 package org.apache.brooklyn.feed.http;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
+import com.google.common.base.*;
+import com.google.common.collect.*;
+import com.google.common.io.BaseEncoding;
+import com.google.common.io.ByteStreams;
+import com.google.common.reflect.TypeToken;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.location.Location;
@@ -46,15 +37,14 @@ import org.apache.brooklyn.core.feed.Poller;
 import org.apache.brooklyn.core.location.Locations;
 import org.apache.brooklyn.core.location.Machines;
 import org.apache.brooklyn.core.location.internal.LocationInternal;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.executor.HttpExecutorFactory;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.http.HttpToolResponse;
-import org.apache.brooklyn.util.http.executor.HttpConfig;
+import org.apache.brooklyn.util.http.auth.UsernamePassword;
 import org.apache.brooklyn.util.http.executor.HttpExecutor;
 import org.apache.brooklyn.util.http.executor.HttpRequest;
 import org.apache.brooklyn.util.http.executor.HttpResponse;
-import org.apache.brooklyn.util.http.auth.UsernamePassword;
-import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.http.auth.Credentials;
@@ -62,20 +52,19 @@ import org.apache.http.auth.UsernamePasswordCredentials;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.base.Throwables;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
-import com.google.common.io.ByteStreams;
-import com.google.common.reflect.TypeToken;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Provides a feed of attribute values, by polling over http.
@@ -346,7 +335,8 @@ public class HttpFeed extends AbstractFeed {
                 Map<String, Object> httpExecutorProps = ((LocationInternal)location.get()).config().getBag().getAllConfig();
                 httpExecutor = httpExecutorFactory.getHttpExecutor(httpExecutorProps);
             } else {
-                httpExecutor = HttpExecutorImpl.newInstance();
+                httpExecutor = BrooklynHttpConfig.newHttpExecutor(
+                        Preconditions.checkNotNull(location.isPresent() ? location.get() : builder.entity, "feed requires a location or entity") );
             }
         }
 
@@ -423,11 +413,7 @@ public class HttpFeed extends AbstractFeed {
                             .credentials(creds)
                             .method(pollInfo.method)
                             .body(pollInfo.body)
-                            .config(HttpConfig.builder()
-                                    .trustSelfSigned(true)
-                                    .trustAll(true)
-                                    .laxRedirect(true)
-                                    .build())
+                            .config(BrooklynHttpConfig.httpConfigBuilder(getEntity()).build())
                             .build());
                     return createHttpToolRespose(response, startTime);
                 }};
diff --git a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
index 9f7a8e3d1d..a1619b7e00 100644
--- a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
@@ -1018,7 +1018,7 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
 
     /** returns the un-passphrased key-pair info if a key is being used, or else null */
     public KeyPair findKeyPair() {
-        OsCredential creds = LocationConfigUtils.getOsCredential(config().getBag());
+        OsCredential creds = LocationConfigUtils.getOsCredential(config().getBag(), ResourceUtils.create(this));
         if (creds.hasKey()) {
             String data = creds.getPrivateKeyData();
             return SecureKeys.readPem(data.getBytes(), getConfig(SshTool.PROP_PRIVATE_KEY_PASSPHRASE));
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
index b5bb384440..1191b05125 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
@@ -32,20 +32,26 @@ import java.net.URL;
 import java.net.URLDecoder;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.annotation.Nullable;
 
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.OsgiBrooklynClassLoadingContext;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
+import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.core.text.DataUriSchemeParser;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.http.HttpTool;
@@ -139,9 +145,9 @@ public class ResourceUtils {
 
     public static final ResourceUtils create(RegisteredType type, ManagementContext mgmt, boolean includeThreadAndJavaClassLoader) {
         if (includeThreadAndJavaClassLoader) {
-            return create(CatalogUtils.newClassLoadingContext(mgmt, type), type.getId());
+            return create(CatalogUtils.newClassLoadingContext(mgmt, type), type.getId()).withHttpClientBuilder(() -> BrooklynHttpConfig.httpClientBuilder(mgmt, true));
         } else {
-            return create(new OsgiBrooklynClassLoadingContext(mgmt, type.getId(), type.getLibraries()), type.getId());
+            return create(new OsgiBrooklynClassLoadingContext(mgmt, type.getId(), type.getLibraries()), type.getId()).withHttpClientBuilder(() -> BrooklynHttpConfig.httpClientBuilder(mgmt, true));
         }
     }
 
@@ -149,6 +155,7 @@ public class ResourceUtils {
      * Creates a {@link ResourceUtils} object with itself as the context.
      *
      * @see ResourceUtils#create(Object)
+     * @deprecated since 1.1, supply an object such as an entity or adjunct to use the correct classpaths and correct certificate trust settings
      */
     public static final ResourceUtils create() {
         return new ResourceUtils(null);
@@ -165,7 +172,7 @@ public class ResourceUtils {
     }
 
     public ResourceUtils(Object contextObject, String contextMessage) {
-        this(contextObject==null ? null : getClassLoadingContextInternal(null, contextObject), contextObject, contextMessage);
+        this(contextObject==null || contextObject instanceof String ? null : getClassLoadingContextInternal(null, contextObject), contextObject, contextMessage);
     }
 
     public ResourceUtils(Object contextObject) {
@@ -203,7 +210,7 @@ public class ResourceUtils {
      * Better for callers use {@link CatalogUtils#getClassLoadingContext(org.apache.brooklyn.api.entity.Entity)} or similar. }.
      */
     private BrooklynClassLoadingContext getLoader() {
-        return (loader!=null ? loader : getClassLoadingContextInternal(null, contextObject!=null ? contextObject : this));
+        return (loader!=null ? loader : getClassLoadingContextInternal(null, contextObject!=null && !(contextObject instanceof String) ? contextObject : this));
     }
 
     /**
@@ -430,11 +437,28 @@ public class ResourceUtils {
         }
     }
 
+    Supplier<HttpClientBuilder> httpClientBuilderSupplier;
+
+    public ResourceUtils withHttpClientBuilder(Supplier<HttpClientBuilder> httpClientBuilderSupplier) {
+        this.httpClientBuilderSupplier = httpClientBuilderSupplier;
+        return this;
+    }
+
+    protected HttpClientBuilder newHttpClientBuilder() {
+        if (httpClientBuilderSupplier!=null) return httpClientBuilderSupplier.get();
+
+        if (contextObject instanceof ManagementContext) return BrooklynHttpConfig.httpClientBuilder( (ManagementContext) contextObject, true );
+        else if (contextObject instanceof BrooklynObject) return BrooklynHttpConfig.httpClientBuilder((BrooklynObject) contextObject);
+
+        Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+        if (entity!=null) return BrooklynHttpConfig.httpClientBuilder(entity);
+
+        return BrooklynHttpConfig.httpClientBuilderDefaultStrict();
+    }
+
     private InputStream getResourceViaHttp(String resource, @Nullable String username, @Nullable String password) throws IOException {
         URI uri = URI.create(resource);
-        HttpClientBuilder builder = HttpTool.httpClientBuilder()
-                .laxRedirect(true)
-                .uri(uri);
+        HttpClientBuilder builder = newHttpClientBuilder().uri(uri);
         Credentials credentials;
         if (username != null) {
             credentials = new UsernamePasswordCredentials(username, password);
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/javalang/BrooklynHttpConfig.java b/core/src/main/java/org/apache/brooklyn/util/core/javalang/BrooklynHttpConfig.java
new file mode 100644
index 0000000000..db470eb5e9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/javalang/BrooklynHttpConfig.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.util.core.javalang;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.http.HttpTool;
+import org.apache.brooklyn.util.http.executor.HttpConfig;
+import org.apache.brooklyn.util.http.executor.HttpExecutor;
+import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class BrooklynHttpConfig {
+
+    public static final String HTTPS_CONFIG = "brooklyn.https.config.";
+    public static final ConfigKey<Boolean> TRUST_ALL = ConfigKeys.newBooleanConfigKey(HTTPS_CONFIG + "trustAll",
+        "Whether HTTPS and TLS connections should trust all certificates");
+    public static final ConfigKey<Boolean> TRUST_SELF_SIGNED = ConfigKeys.newBooleanConfigKey(HTTPS_CONFIG + "trustSelfSigned",
+            "Whether HTTPS and TLS connections should trust self-signed certificates");
+    public static final ConfigKey<Boolean> LAX_REDIRECT = ConfigKeys.newBooleanConfigKey(HTTPS_CONFIG + "laxRedirect",
+            "Whether HTTPS and TLS connections should be lax about redirecting");
+
+    private static final boolean DEFAULT_FOR_MGMT_LAX_AND_TRUSTING = true;
+
+    public static HttpConfig.Builder httpConfigBuilder(ManagementContext mgmt, boolean lookForContextEntity) {
+        return httpConfigBuilder(mgmt, DEFAULT_FOR_MGMT_LAX_AND_TRUSTING, lookForContextEntity);
+    }
+    public static HttpConfig.Builder httpConfigBuilder(ManagementContext mgmt, boolean defaultLaxAndTrusting, boolean lookForContextEntity) {
+        HttpConfig.Builder hcb = httpConfigBuilderDefault(defaultLaxAndTrusting, false);
+        apply(hcb, mgmt.getConfig()::getConfig);
+        if (lookForContextEntity) applyContextEntity(hcb);
+        return hcb;
+    }
+
+    private static void apply(HttpConfig.Builder hcb, Function<ConfigKey<Boolean>,Boolean> getter) {
+        applyIfNonNull(getter.apply(TRUST_ALL), hcb::trustAll);
+        applyIfNonNull(getter.apply(TRUST_SELF_SIGNED), hcb::trustSelfSigned);
+        applyIfNonNull(getter.apply(LAX_REDIRECT), hcb::laxRedirect);
+    }
+
+    private static void applyContextEntity(HttpConfig.Builder hcb) {
+        BrooklynObject entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+        if (entity!=null) apply(hcb, entity.config()::get);
+    }
+
+    private static void applyIfNonNull(Boolean v, Consumer<Boolean> target) {
+        if (v!=null) target.accept(v);
+    }
+
+    public static HttpConfig.Builder httpConfigBuilder(BrooklynObject entity) {
+        return httpConfigBuilder(entity, DEFAULT_FOR_MGMT_LAX_AND_TRUSTING);
+    }
+    public static HttpConfig.Builder httpConfigBuilder(BrooklynObject entity, boolean defaultLaxAndTrusting) {
+        HttpConfig.Builder hcb = httpConfigBuilder(((BrooklynObjectInternal)entity).getManagementContext(), defaultLaxAndTrusting, false);
+        apply(hcb, entity.config()::get);
+        return hcb;
+    }
+
+    private static HttpConfig.Builder httpConfigBuilderDefault(boolean laxAndTrusting, boolean lookForContextEntities) {
+        HttpConfig.Builder hcb = HttpConfig.builder().laxRedirect(laxAndTrusting).trustAll(laxAndTrusting).trustSelfSigned(laxAndTrusting);
+        if (lookForContextEntities) applyContextEntity(hcb);
+        return hcb;
+    }
+
+
+
+    public static HttpTool.HttpClientBuilder httpClientBuilder(ManagementContext mgmt, boolean lookForContextEntity) {
+        return httpClientBuilder(mgmt, DEFAULT_FOR_MGMT_LAX_AND_TRUSTING, lookForContextEntity);
+    }
+    public static HttpTool.HttpClientBuilder httpClientBuilder(ManagementContext mgmt, boolean defaultLaxAndTrusting, boolean lookForContextEntity) {
+        HttpTool.HttpClientBuilder hcb = httpClientBuilderDefault(defaultLaxAndTrusting, false);
+        apply(hcb, mgmt.getConfig()::getConfig);
+        if (lookForContextEntity) {
+            applyContextEntity(hcb);
+        }
+        return hcb;
+    }
+
+    private static void apply(HttpTool.HttpClientBuilder hcb, Function<ConfigKey<Boolean>,Boolean> getter) {
+        applyIfNonNull(getter.apply(TRUST_ALL), hcb::trustAll);
+        applyIfNonNull(getter.apply(TRUST_SELF_SIGNED), hcb::trustSelfSigned);
+        applyIfNonNull(getter.apply(LAX_REDIRECT), hcb::laxRedirect);
+    }
+
+    private static void applyContextEntity(HttpTool.HttpClientBuilder hcb) {
+        BrooklynObject entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+        if (entity!=null) apply(hcb, entity.config()::get);
+    }
+
+    public static HttpTool.HttpClientBuilder httpClientBuilderDefaultStrict() {
+        return httpClientBuilderDefault(false, false);
+    }
+
+    private static HttpTool.HttpClientBuilder httpClientBuilderDefault(boolean defaultLaxAndTrusting, boolean lookForContextEntity) {
+        HttpTool.HttpClientBuilder hcb = HttpTool.httpClientBuilder();
+        if (defaultLaxAndTrusting) {
+            hcb.trustAll(true);
+            hcb.trustSelfSigned(true);
+            hcb.laxRedirect(true);
+        }
+        if (lookForContextEntity) {
+            applyContextEntity(hcb);
+        }
+        return hcb;
+    }
+
+    public static HttpTool.HttpClientBuilder httpClientBuilder(BrooklynObject entity) {
+        return httpClientBuilder(entity, DEFAULT_FOR_MGMT_LAX_AND_TRUSTING);
+    }
+
+    public static HttpTool.HttpClientBuilder httpClientBuilder(BrooklynObject entity, boolean defaultLaxAndTrusting) {
+        HttpTool.HttpClientBuilder hcb = httpClientBuilder(((BrooklynObjectInternal)entity).getManagementContext(), defaultLaxAndTrusting, false);
+        apply(hcb, entity.config()::get);
+        return hcb;
+    }
+
+    public static HttpExecutor newHttpExecutor(BrooklynObject entity) {
+        return HttpExecutorImpl.newInstance().withConfig(httpConfigBuilder(entity, false).build());
+    }
+
+    public static HttpExecutor newHttpExecutorDefault() {
+        return HttpExecutorImpl.newInstance().withConfig(httpConfigBuilderDefault(false, true).build());
+    }
+
+    // SslTrustUtils.trustAll and TRUST_ALL -- only used in unsafe methods
+    // TrustingSslSocketFactory - only used in unsafe methods
+    // HttpTool and HttpTestUtils methods -- only used in tests and check code, methods marked unsafe, not for content
+    // HttpTool.TrustAllStrategy -- only used in unsafe methods above and by HttpClientBuilder which is routed above in production code
+    // HttpExecutorImpl -- only used with config supplied by above
+    // HttpExecutorFactory not set, except in tests; our HttpExecutorFactoryImpl only used in tests
+    // HttpConfig.Builder -- all uses routed through here
+}
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java b/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
index f2eeb0fb5c..1510e6d810 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/osgi/BundleMaker.java
@@ -75,7 +75,7 @@ public class BundleMaker {
     }
     
     public BundleMaker(@Nonnull ManagementContext mgmt) {
-        this(((ManagementContextInternal) mgmt).getOsgiManager().get().getFramework(), ResourceUtils.create());
+        this(((ManagementContextInternal) mgmt).getOsgiManager().get().getFramework(), ResourceUtils.create(mgmt));
     }
 
     /** if set, this will be used to resolve relative classpath fragments;
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/SshPutTaskFactory.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/SshPutTaskFactory.java
index 5e369d112c..5d65019ce8 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/SshPutTaskFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/SshPutTaskFactory.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.util.core.task.ssh;
 import java.io.InputStream;
 import java.io.Reader;
 
+import com.google.common.base.Supplier;
 import org.apache.brooklyn.api.mgmt.TaskFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -89,6 +90,12 @@ public class SshPutTaskFactory extends SshPutTaskStub implements TaskFactory<Ssh
         return self();
     }
 
+    public SshPutTaskFactory contents(Supplier<InputStream> stream) {
+        markDirty();
+        this.contents = stream;
+        return self();
+    }
+
     public SshPutTaskFactory contents(Reader reader) {
         markDirty();
         this.contents = Suppliers.ofInstance(new ReaderInputStream(reader));  
diff --git a/core/src/main/java/org/apache/brooklyn/util/executor/HttpExecutorFactoryImpl.java b/core/src/main/java/org/apache/brooklyn/util/executor/HttpExecutorFactoryImpl.java
index b652dba0b1..3a72fbc66e 100644
--- a/core/src/main/java/org/apache/brooklyn/util/executor/HttpExecutorFactoryImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/util/executor/HttpExecutorFactoryImpl.java
@@ -18,11 +18,10 @@
  */
 package org.apache.brooklyn.util.executor;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
+import com.google.common.collect.Maps;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.http.executor.HttpExecutor;
 import org.apache.brooklyn.util.http.executor.apacheclient.HttpExecutorImpl;
@@ -31,7 +30,8 @@ import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class HttpExecutorFactoryImpl implements HttpExecutorFactory {
     private static final Logger LOG = LoggerFactory.getLogger(HttpExecutorFactoryImpl.class);
@@ -62,7 +62,7 @@ public class HttpExecutorFactoryImpl implements HttpExecutorFactory {
 
         } else {
             LOG.info(HTTP_EXECUTOR_CLASS_CONFIG + " parameter not provided. Using the default implementation " + HttpExecutorImpl.class.getName());
-            httpExecutor = HttpExecutorImpl.newInstance();
+            httpExecutor = BrooklynHttpConfig.newHttpExecutorDefault();
         }
 
         return httpExecutor;
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsTest.java
index 11914f8aab..c45b5d3bc0 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsTest.java
@@ -182,7 +182,7 @@ public class ResourceUtilsTest {
 
     @Test
     public void testGetResources() {
-        Iterable<URL> manifests = ResourceUtils.create().getResources("META-INF/MANIFEST.MF");
+        Iterable<URL> manifests = ResourceUtils.create("test").getResources("META-INF/MANIFEST.MF");
         assertFalse(Iterables.isEmpty(manifests));
     }
 
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/CreateUserStatements.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/CreateUserStatements.java
index d275fc102f..994fd10613 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/CreateUserStatements.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/CreateUserStatements.java
@@ -26,6 +26,7 @@ import java.util.List;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.core.location.LocationConfigUtils;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.crypto.SecureKeys;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -129,7 +130,7 @@ public class CreateUserStatements {
                         : null;
         final boolean dontCreateUser = config.get(JcloudsLocation.DONT_CREATE_USER);
         final boolean grantUserSudo = config.get(JcloudsLocation.GRANT_USER_SUDO);
-        final LocationConfigUtils.OsCredential credential = LocationConfigUtils.getOsCredential(config);
+        final LocationConfigUtils.OsCredential credential = LocationConfigUtils.getOsCredential(config, ResourceUtils.create(location));
         credential.checkNoErrors().logAnyWarnings();
         final String passwordToSet =
                 Strings.isNonBlank(credential.getPassword()) ? credential.getPassword() : Identifiers.makeRandomId(12);
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index a7b3d13bf3..de1b09949b 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -1045,7 +1045,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
                     } else {
                         List<String> extraKeyDataToAuth = MutableList.of();
                         for (String keyUrl : extraKeyUrlsToAuth) {
-                            extraKeyDataToAuth.add(ResourceUtils.create().getResourceAsString(keyUrl));
+                            extraKeyDataToAuth.add(ResourceUtils.create(this).getResourceAsString(keyUrl));
                         }
                         executeCommandThrowingOnError(
                                 (SshMachineLocation)machineLocation,
@@ -1978,7 +1978,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
         }
         NodeMetadata node = Iterables.getOnlyElement(candidateNodes);
 
-        OsCredential osCredentials = LocationConfigUtils.getOsCredential(config).checkNoErrors().logAnyWarnings();
+        OsCredential osCredentials = LocationConfigUtils.getOsCredential(config, ResourceUtils.create(this)).checkNoErrors().logAnyWarnings();
         String pkd = osCredentials.getPrivateKeyData();
         String password = osCredentials.getPassword();
         LoginCredentials expectedCredentials = node.getCredentials();
@@ -2490,7 +2490,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
     protected LoginCredentials extractVmCredentials(ConfigBag setup, NodeMetadata node, LoginCredentials nodeCredentials) {
         boolean windows = isWindows(node, setup);
         String user = getUser(setup);
-        OsCredential localCredentials = LocationConfigUtils.getOsCredential(setup).checkNoErrors();
+        OsCredential localCredentials = LocationConfigUtils.getOsCredential(setup, ResourceUtils.create(this)).checkNoErrors();
         
         LOG.debug("Credentials extracted for {}: {}/{} with {}/{}", new Object[] {
                 node, user, nodeCredentials.getUser(), localCredentials, nodeCredentials });
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
index 68dd4924c2..199283ed61 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.core.location.BasicOsDetails;
 import org.apache.brooklyn.core.location.LocationConfigUtils;
 import org.apache.brooklyn.core.location.LocationConfigUtils.OsCredential;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.config.ResolvingConfigBag;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -458,7 +459,7 @@ public class JcloudsSshMachineLocation extends SshMachineLocation implements Jcl
     }
     
     private LoginCredentials getLoginCredentials() {
-        OsCredential creds = LocationConfigUtils.getOsCredential(new ResolvingConfigBag(getManagementContext(), config().getBag()));
+        OsCredential creds = LocationConfigUtils.getOsCredential(new ResolvingConfigBag(getManagementContext(), config().getBag()), ResourceUtils.create(this));
         
         return LoginCredentials.builder()
                 .user(getUser())
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
index 87d4604bba..4d1d3b6821 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
@@ -77,11 +77,11 @@ public class DeployBlueprintTest extends BrooklynRestResourceTest {
 
         log.info("got: "+id);
 
-        String apps = HttpTool.getContent(getEndpointAddress() + "/applications");
+        String apps = HttpTool.getContentUnsafe(getEndpointAddress() + "/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"), String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));
 
-        String status = HttpTool.getContent(getEndpointAddress()+"/applications/"+id+"/entities/"+id+"/sensors/service.status");
+        String status = HttpTool.getContentUnsafe(getEndpointAddress()+"/applications/"+id+"/entities/"+id+"/sensors/service.status");
         log.info("STATUS: "+status);
     }
 
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTest.java
index 26c8fb012d..f887ed3566 100644
--- a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTest.java
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTest.java
@@ -55,7 +55,7 @@ public class BrooklynRestApiLauncherTest extends BrooklynRestApiLauncherTestFixt
         int code = Asserts.succeedsEventually(new Callable<Integer>() {
             @Override
             public Integer call() throws Exception {
-                int code = HttpTool.getHttpStatusCode(rootUrl+"catalog/entities");
+                int code = HttpTool.getHttpStatusCodeUnsafe(rootUrl+"catalog/entities");
                 if (code == HttpStatus.SC_FORBIDDEN) {
                     throw new RuntimeException("Retry request");
                 } else {
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
index ab08924997..c6d649126b 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.http.HttpTool;
 import org.apache.brooklyn.util.http.HttpToolResponse;
 import org.apache.brooklyn.util.core.task.Tasks;
@@ -67,10 +68,7 @@ public class EntityHttpClientImpl implements EntityHttpClient {
     @Override
     public HttpTool.HttpClientBuilder getHttpClientForBrooklynNode() {
         String baseUrl = getEntityUrl();
-        HttpTool.HttpClientBuilder builder = HttpTool.httpClientBuilder()
-                .trustAll()
-                .laxRedirect(true)
-                .uri(baseUrl);
+        HttpTool.HttpClientBuilder builder = BrooklynHttpConfig.httpClientBuilder(entity).uri(baseUrl);
         if (entity.getConfig(BrooklynNode.MANAGEMENT_USER) != null) {
             UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
                     entity.getConfig(BrooklynNode.MANAGEMENT_USER),
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
index 7f2e6edab2..7506db7ead 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
@@ -57,6 +57,7 @@ import org.apache.brooklyn.test.HttpTestUtils;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.javalang.BrooklynHttpConfig;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Functionals;
 import org.apache.brooklyn.util.http.HttpAsserts;
@@ -253,7 +254,7 @@ services:
         app.start(locs);
         log.info("started "+app+" containing "+brooklynNode+" for "+JavaClassNames.niceClassAndMethod());
 
-        assertEquals(ResourceUtils.create().getResourceAsString(pseudoBrooklynCatalogFile.getAbsolutePath()), catalogContents);
+        assertEquals(ResourceUtils.create(app).getResourceAsString(pseudoBrooklynCatalogFile.getAbsolutePath()), catalogContents);
         
         // Confirm the catalog item has taken effect (by deploying an app)
         final URI webConsoleUri = brooklynNode.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
@@ -263,7 +264,7 @@ services:
             .configure(DeployBlueprintEffector.BLUEPRINT_TYPE, "BrooklynNodeIntegrationTest.mycatalog:1.0")
             .getAllConfig()).get();
         
-        String apps = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+        String apps = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"), String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));
         
@@ -465,7 +466,7 @@ services:
 
         URI webConsoleUri = brooklynNode.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
         waitForApps(webConsoleUri, 1);
-        String apps = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+        String apps = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"), String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));
     }
@@ -484,7 +485,7 @@ services:
             @Override
             public void run() {
                 //Wait all apps to become managed
-                String appsContent = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+                String appsContent = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
                 List<String> appIds = parseJsonList(appsContent, ImmutableList.of("id"), String.class);
                 assertEquals(appIds.size(), num);
                 
@@ -510,7 +511,7 @@ services:
             .configure(DeployBlueprintEffector.BLUEPRINT_TYPE, BasicApplication.class.getName())
             .getAllConfig()).get();
         
-        String apps = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+        String apps = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"), String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));
         
@@ -538,17 +539,17 @@ services:
         waitForApps(webConsoleUri, 1);
 
         // Check that "mynamedloc" has been picked up from the brooklyn.properties
-        String locsContent = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/locations");
+        String locsContent = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/locations");
         List<String> locNames = parseJsonList(locsContent, ImmutableList.of("name"), String.class);
         assertTrue(locNames.contains("mynamedloc"), "locNames="+locNames);
 
         // Find the id of the concrete location instance of the app
-        String appsContent = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+        String appsContent = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
         List<String[]> appLocationIds = parseJsonList(appsContent, ImmutableList.of("spec", "locations"), String[].class);
         String appLocationId = Iterables.getOnlyElement(appLocationIds)[0];  // app.getManagementContext().getLocationRegistry()
 
         // Check that the concrete location is of the required type
-        String locatedLocationsContent = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/locations/usage/LocatedLocations");
+        String locatedLocationsContent = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/locations/usage/LocatedLocations");
         assertEquals(parseJson(locatedLocationsContent, ImmutableList.of(appLocationId, "name"), String.class), "myname");
         assertEquals(parseJson(locatedLocationsContent, ImmutableList.of(appLocationId, "longitude"), Double.class), 45.6, 0.00001);
     }
@@ -576,10 +577,8 @@ services:
         Assert.assertTrue(webConsoleUri.toString().contains(""+httpsPort), "web console not using right https port ("+httpsPort+"): "+webConsoleUri);
         HttpTestUtils.assertHttpStatusCodeEquals(webConsoleUri.toString(), 401);
 
-        HttpClient http = HttpTool.httpClientBuilder()
-            .trustAll()
+        HttpClient http = BrooklynHttpConfig.httpClientBuilder(app)
             .uri(webConsoleUri)
-            .laxRedirect(true)
             .credentials(new UsernamePasswordCredentials("admin", adminPassword))
             .build();
         HttpToolResponse response = HttpTool.httpGet(http, webConsoleUri, MutableMap.<String,String>of());
@@ -653,7 +652,7 @@ services:
                 BrooklynNode.RestartSoftwareParameters.RESTART_MACHINE.getName(), "false")).getUnchecked();
 
         waitForApps(webConsoleUri.toString());
-        String apps = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
+        String apps = HttpTool.getContentUnsafe(webConsoleUri.toString()+"/v1/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"), String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));
     }
diff --git a/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java b/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
index 1006befda8..21bf1906aa 100644
--- a/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
+++ b/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
@@ -18,42 +18,30 @@
  */
 package org.apache.brooklyn.test;
 
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.http.HttpTool;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
-import java.net.URL;
 import java.net.URLConnection;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
 
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSession;
-
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.crypto.SslTrustUtils;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.http.HttpTool;
-import org.apache.brooklyn.util.http.TrustingSslSocketFactory;
-import org.apache.brooklyn.util.stream.Streams;
-import org.apache.brooklyn.util.time.Time;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 /**
  * Utility methods to aid testing HTTP.
@@ -69,76 +57,20 @@ public class HttpTestUtils {
     private static final Logger LOG = LoggerFactory.getLogger(HttpTestUtils.class);
 
     static final ExecutorService executor = Executors.newCachedThreadPool();
-    
-    /**
-     * Connects to the given url and returns the connection.
-     * Caller should {@code connection.getInputStream().close()} the result of this
-     * (especially if they are making heavy use of this method).
-     */
+
+    @Deprecated /** @deprecated since 1.1, refer to (and replace per) method in HttpTool */
     public static URLConnection connectToUrl(String u) throws Exception {
-        final URL url = new URL(u);
-        final AtomicReference<Exception> exception = new AtomicReference<Exception>();
-        
-        // sometimes openConnection hangs, so run in background
-        Future<URLConnection> f = executor.submit(new Callable<URLConnection>() {
-            @Override
-            public URLConnection call() {
-                try {
-                    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
-                        @Override public boolean verify(String s, SSLSession sslSession) {
-                            return true;
-                        }
-                    });
-                    URLConnection connection = url.openConnection();
-                    TrustingSslSocketFactory.configure(connection);
-                    connection.connect();
-    
-                    connection.getContentLength(); // Make sure the connection is made.
-                    return connection;
-                } catch (Exception e) {
-                    exception.set(e);
-                    LOG.debug("Error connecting to url "+url+" (propagating): "+e, e);
-                }
-                return null;
-            }
-        });
-        try {
-            URLConnection result = null;
-            try {
-                result = f.get(60, TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                throw e;
-            } catch (Exception e) {
-                LOG.debug("Error connecting to url "+url+", probably timed out (rethrowing): "+e);
-                throw new IllegalStateException("Connect to URL not complete within 60 seconds, for url "+url+": "+e);
-            }
-            if (exception.get() != null) {
-                LOG.debug("Error connecting to url "+url+", thread caller of "+exception, new Throwable("source of rethrown error "+exception));
-                throw exception.get();
-            } else {
-                return result;
-            }
-        } finally {
-            f.cancel(true);
-        }
+        return HttpTool.connectToUrlUnsafe(u);
     }
 
     public static void assertHealthyStatusCode(int code) {
         if (code>=200 && code<=299) return;
         Assert.fail("Wrong status code: "+code);
     }
-    
+
+    @Deprecated /** @deprecated since 1.1, refer to (and replace per) method in HttpTool */
     public static int getHttpStatusCode(String url) throws Exception {
-        URLConnection connection = connectToUrl(url);
-        long startTime = System.currentTimeMillis();
-        int status = ((HttpURLConnection) connection).getResponseCode();
-        
-        // read fully if possible, then close everything, trying to prevent cached threads at server
-        consumeAndCloseQuietly((HttpURLConnection) connection);
-        
-        if (LOG.isDebugEnabled())
-            LOG.debug("connection to {} ({}ms) gives {}", new Object[] { url, (System.currentTimeMillis()-startTime), status });
-        return status;
+        return HttpTool.getHttpStatusCodeUnsafe(url);
     }
 
     /**
@@ -147,7 +79,7 @@ public class HttpTestUtils {
      */
     public static void assertUrlReachable(String url) {
         try {
-            getHttpStatusCode(url);
+            HttpTool.getHttpStatusCodeUnsafe(url);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new RuntimeException("Interrupted for "+url+" (in assertion that is reachable)", e);
@@ -158,7 +90,7 @@ public class HttpTestUtils {
 
     public static void assertUrlUnreachable(String url) {
         try {
-            int statusCode = getHttpStatusCode(url);
+            int statusCode = HttpTool.getHttpStatusCodeUnsafe(url);
             fail("Expected url "+url+" unreachable, but got status code "+statusCode);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
@@ -192,7 +124,7 @@ public class HttpTestUtils {
             acceptableCodes.add(code);
         }
         try {
-            int actualCode = getHttpStatusCode(url);
+            int actualCode = HttpTool.getHttpStatusCodeUnsafe(url);
             assertTrue(acceptableCodes.contains(actualCode), "code="+actualCode+"; expected="+acceptableCodes+"; url="+url);
             
         } catch (InterruptedException e) {
@@ -218,7 +150,7 @@ public class HttpTestUtils {
 
     public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = getContent(url);
+            String contents = HttpTool.getContentUnsafe(url);
             Assert.assertTrue(contents != null && contents.length() > 0);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (!contents.contains(text)) {
@@ -233,7 +165,7 @@ public class HttpTestUtils {
 
     public static void assertContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = getContent(url);
+            String contents = HttpTool.getContentUnsafe(url);
             Assert.assertTrue(contents != null);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (contents.contains(text)) {
@@ -248,7 +180,7 @@ public class HttpTestUtils {
 
     public static void assertErrorContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = getErrorContent(url);
+            String contents = HttpTool.getErrorContent(url);
             Assert.assertTrue(contents != null && contents.length() > 0);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (!contents.contains(text)) {
@@ -264,7 +196,7 @@ public class HttpTestUtils {
 
     public static void assertErrorContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String err = getErrorContent(url);
+            String err = HttpTool.getErrorContent(url);
             Assert.assertTrue(err != null);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (err.contains(text)) {
@@ -291,7 +223,7 @@ public class HttpTestUtils {
     }
     
     public static void assertContentMatches(String url, String regex) {
-        String contents = getContent(url);
+        String contents = HttpTool.getContentUnsafe(url);
         Assert.assertNotNull(contents);
         Assert.assertTrue(contents.matches(regex), "Contents does not match expected regex ("+regex+"): "+contents);
     }
@@ -308,7 +240,8 @@ public class HttpTestUtils {
             }
         });
     }
-    
+
+    @Deprecated /** @deprecated since 1.1, refer to (and replace per) method in HttpTool */
     public static String getErrorContent(String url) {
         try {
             HttpURLConnection connection = (HttpURLConnection) connectToUrl(url);
@@ -332,13 +265,10 @@ public class HttpTestUtils {
             throw Exceptions.propagate(e);
         }
     }
-    
+
+    @Deprecated /** @deprecated since 1.1, refer to (and replace per) method in HttpTool */
     public static String getContent(String url) {
-        try {
-            return Streams.readFullyStringAndClose(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream());
-        } catch (Exception e) {
-            throw Throwables.propagate(e);
-        }
+        return HttpTool.getContentUnsafe(url);
     }
 
     /**
@@ -380,7 +310,7 @@ public class HttpTestUtils {
      * Ignores all exceptions completely, not even logging them!
      * 
      * Consuming the stream fully is useful for preventing idle TCP connections. 
-     * See {@linkplain http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html}.
+     * See http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html
      */
     public static void consumeAndCloseQuietly(HttpURLConnection connection) {
         try { Streams.readFully(connection.getInputStream()); } catch (Exception e) {}
diff --git a/test-support/src/main/java/org/apache/brooklyn/test/WebAppMonitor.java b/test-support/src/main/java/org/apache/brooklyn/test/WebAppMonitor.java
index 439013fd3b..1e59d867ed 100644
--- a/test-support/src/main/java/org/apache/brooklyn/test/WebAppMonitor.java
+++ b/test-support/src/main/java/org/apache/brooklyn/test/WebAppMonitor.java
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.http.HttpTool;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
 import org.testng.Assert;
@@ -80,7 +81,7 @@ public class WebAppMonitor implements Runnable {
             long startTime = System.currentTimeMillis();
             try {
                 if (preAttempt()) {
-                    int code = HttpTestUtils.getHttpStatusCode(url);
+                    int code = HttpTool.getHttpStatusCodeUnsafe(url);
                     lastTime.set(System.currentTimeMillis() - startTime);
                     lastStatus.set(code);
                     if (isResponseOkay(code)) {
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
index b4f253866b..afa368ee8f 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
@@ -89,7 +89,7 @@ public class HttpAsserts {
      */
     public static void assertUrlReachable(String url) {
         try {
-            HttpTool.getHttpStatusCode(url);
+            HttpTool.getHttpStatusCodeUnsafe(url);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new RuntimeException("Interrupted for "+url+" (in assertion that is reachable)", e);
@@ -106,7 +106,7 @@ public class HttpAsserts {
 
     public static void assertUrlUnreachable(String url) {
         try {
-            int statusCode = HttpTool.getHttpStatusCode(url);
+            int statusCode = HttpTool.getHttpStatusCodeUnsafe(url);
             Asserts.fail("Expected url " + url + " unreachable, but got status code " + statusCode);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
@@ -159,7 +159,7 @@ public class HttpAsserts {
             acceptableCodes.add(code);
         }
         try {
-            int actualCode = HttpTool.getHttpStatusCode(url);
+            int actualCode = HttpTool.getHttpStatusCodeUnsafe(url);
             Asserts.assertTrue(acceptableCodes.contains(actualCode), "code=" + actualCode + "; expected=" + acceptableCodes + "; url=" + url);
             
         } catch (InterruptedException e) {
@@ -185,7 +185,7 @@ public class HttpAsserts {
 
     public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = HttpTool.getContent(url);
+            String contents = HttpTool.getContentUnsafe(url);
             Asserts.assertTrue(contents != null && contents.length() > 0);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (!contents.contains(text)) {
@@ -200,7 +200,7 @@ public class HttpAsserts {
 
     public static void assertContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = HttpTool.getContent(url);
+            String contents = HttpTool.getContentUnsafe(url);
             Asserts.assertTrue(contents != null);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (contents.contains(text)) {
@@ -215,7 +215,7 @@ public class HttpAsserts {
 
     public static void assertErrorContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String contents = HttpTool.getErrorContent(url);
+            String contents = HttpTool.getErrorContentUnsafe(url);
             Asserts.assertTrue(contents != null && contents.length() > 0);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (!contents.contains(text)) {
@@ -231,7 +231,7 @@ public class HttpAsserts {
 
     public static void assertErrorContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
         try {
-            String err = HttpTool.getErrorContent(url);
+            String err = HttpTool.getErrorContentUnsafe(url);
             Asserts.assertTrue(err != null);
             for (String text: Lists.asList(phrase, additionalPhrases)) {
                 if (err.contains(text)) {
@@ -279,7 +279,7 @@ public class HttpAsserts {
     }
 
     public static void assertContentMatches(String url, String regex) {
-        String contents = HttpTool.getContent(url);
+        String contents = HttpTool.getContentUnsafe(url);
         Asserts.assertNotNull(contents);
         Asserts.assertTrue(contents.matches(regex), "Contents does not match expected regex ("+regex+"): "+contents);
     }
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpTool.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpTool.java
index 52b8d7a435..7a3d5ac022 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpTool.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpTool.java
@@ -103,12 +103,18 @@ public class HttpTool {
 
     static final ExecutorService executor = Executors.newCachedThreadPool();
 
+    @Deprecated /** @deprecated since 1.1, use #getContentUnsafe if you don't need to trust the remote endpoint, otherwise use a more sophisticated method */
+    public static URLConnection connectToUrl(String u) throws Exception {
+        return connectToUrlUnsafe(u);
+    }
     /**
      * Connects to the given url and returns the connection.
      * Caller should {@code connection.getInputStream().close()} the result of this
      * (especially if they are making heavy use of this method).
-     */
-    public static URLConnection connectToUrl(String u) throws Exception {
+     *
+     * trusts all connections, so the content could be hacked and should not be relied upon */
+    // only used in tests and test assertions
+    public static URLConnection connectToUrlUnsafe(String u) throws Exception {
         final URL url = new URL(u);
         final AtomicReference<Exception> exception = new AtomicReference<Exception>();
 
@@ -117,16 +123,8 @@ public class HttpTool {
             @Override
             public URLConnection call() {
                 try {
-                    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
-                        @Override
-                        public boolean verify(String s, SSLSession sslSession) {
-                            return true;
-                        }
-                    });
-                    URLConnection connection = url.openConnection();
-                    TrustingSslSocketFactory.configure(connection);
+                    URLConnection connection = SslTrustUtils.trustAll(url.openConnection());
                     connection.connect();
-
                     connection.getContentLength(); // Make sure the connection is made.
                     return connection;
                 } catch (Exception e) {
@@ -157,10 +155,14 @@ public class HttpTool {
         }
     }
 
-
-
+    @Deprecated /** @deprecated since 1.1, use #getContentUnsafe if you don't need to trust the remote endpoint, otherwise use a more sophisticated method */
     public static int getHttpStatusCode(String url) throws Exception {
-        URLConnection connection = connectToUrl(url);
+        return getHttpStatusCodeUnsafe(url);
+    }
+    /** trusts all connections, so the content could be hacked */
+    // only used in tests, test assertions, and pre-checks
+    public static int getHttpStatusCodeUnsafe(String url) throws Exception {
+        URLConnection connection = connectToUrlUnsafe(url);
         long startTime = System.currentTimeMillis();
         int status = ((HttpURLConnection) connection).getResponseCode();
 
@@ -172,8 +174,9 @@ public class HttpTool {
         return status;
     }
 
-
-    public static String getContent(String url) {
+    /** trusts all connections, so the content could be hacked */
+    // only used in tests and test assertions
+    public static String getContentUnsafe(String url) {
         try {
             return Streams.readFullyStringAndClose(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream());
         } catch (Exception e) {
@@ -181,9 +184,20 @@ public class HttpTool {
         }
     }
 
+    @Deprecated /** @deprecated since 1.1, use #getContentUnsafe if you don't need to trust the remote endpoint, otherwise use a more sophisticated method */
+    public static String getContent(String url) {
+        return getContentUnsafe(url);
+    }
+
+    @Deprecated /** @deprecated since 1.1, use #getErrorContentUnsafe if you don't need to trust the remote endpoint, otherwise use a more sophisticated method */
     public static String getErrorContent(String url) {
+        return getErrorContentUnsafe(url);
+    }
+    /** trusts all connections, so the content could be hacked */
+    // only used in tests and test assertions
+    public static String getErrorContentUnsafe(String url) {
         try {
-            HttpURLConnection connection = (HttpURLConnection) connectToUrl(url);
+            HttpURLConnection connection = (HttpURLConnection) connectToUrlUnsafe(url);
             long startTime = System.currentTimeMillis();
 
             String err;
@@ -242,7 +256,7 @@ public class HttpTool {
     public static HttpClientBuilder httpClientBuilder() {
         return new HttpClientBuilder();
     }
-    
+
     // TODO deprecate this and use the new Apache Commons HttpClientBuilder instead
     @SuppressWarnings("deprecation")
     public static class HttpClientBuilder {
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java
index 6b035361cc..5968ef6e5e 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java
@@ -36,8 +36,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Throwables;
 
-// FIXME copied from brooklyn-core because core not visible here
-
+@Deprecated /** since 1.1 use org.apache.brooklyn.util.crypto.TrustingSslSocketFactory */
 public class TrustingSslSocketFactory extends SSLSocketFactory {
     
     private static final Logger logger = LoggerFactory.getLogger(TrustingSslSocketFactory.class);
@@ -57,7 +56,8 @@ public class TrustingSslSocketFactory extends SSLSocketFactory {
         }
     }
 
-    /** configures a connection to accept all certificates, if it is for https */
+    /** configures a connection to accept all certificates, if it is for https
+     * @deprecated use {@link org.apache.brooklyn.util.crypto.SslTrustUtils#trustAll(URLConnection)} if required. */
     public static <T extends URLConnection> T configure(T connection) {
         if (connection instanceof HttpsURLConnection) {
             ((HttpsURLConnection)connection).setSSLSocketFactory(getInstance());
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/apacheclient/HttpExecutorImpl.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/apacheclient/HttpExecutorImpl.java
index 7642c901ff..79cd722366 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/apacheclient/HttpExecutorImpl.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/apacheclient/HttpExecutorImpl.java
@@ -59,6 +59,13 @@ public class HttpExecutorImpl implements HttpExecutor {
     public HttpExecutorImpl() {
     }
 
+    HttpConfig config = DEFAULT_CONFIG;
+
+    public HttpExecutorImpl withConfig(HttpConfig config) {
+        this.config = config;
+        return this;
+    }
+
     @Override
     public HttpResponse execute(HttpRequest request) throws IOException {
         HttpConfig config = (request.config() != null) ? request.config() : DEFAULT_CONFIG;
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
index 1d766ea6d5..b2375421e0 100644
--- a/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
+++ b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
@@ -40,6 +40,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 
+import com.google.common.base.Preconditions;
 import org.apache.brooklyn.util.core.crypto.SecureKeys;
 import org.apache.brooklyn.util.crypto.SslTrustUtils;
 import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
@@ -59,12 +60,16 @@ public class JmxmpClient {
         } 
 
         jmxc.close();
-    } 
+    }
+
+    public void connectTls(String urlString, KeyStore keyStore, String keyStorePass, KeyStore trustStore) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, CertificateException, SecurityException, SignatureException, IOException, KeyManagementException {
+        connectTls(urlString, keyStore, keyStorePass, SecureKeys.getTrustManager(Preconditions.checkNotNull(trustStore, "trust store must be provided or explicit TRUST ALL manager")));
+    }
 
     /** tries to connect to the given JMX url over tls, 
      * optionally using the given keystore (if null using a randomly generated key)
      * and optionally using the given truststore (if null trusting all) */
-    public void connectTls(String urlString, KeyStore keyStore, String keyStorePass, KeyStore trustStore) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, CertificateException, SecurityException, SignatureException, IOException, KeyManagementException { 
+    public void connectTls(String urlString, KeyStore keyStore, String keyStorePass, TrustManager tms) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, CertificateException, SecurityException, SignatureException, IOException, KeyManagementException {
         Map env = new LinkedHashMap(); 
 
         env.put("jmx.remote.profiles", JmxmpAgent.TLS_JMX_REMOTE_PROFILES);
@@ -73,8 +78,6 @@ public class JmxmpClient {
         KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); //"SunX509");
         kmf.init(keyStore, (keyStorePass!=null ? keyStorePass : "").toCharArray());
 
-        TrustManager tms = trustStore!=null ? SecureKeys.getTrustManager(trustStore) : SslTrustUtils.TRUST_ALL;
-
         SSLContext ctx = SSLContext.getInstance("TLSv1");
         ctx.init(kmf.getKeyManagers(), new TrustManager[] { tms }, null);
         SSLSocketFactory ssf = ctx.getSocketFactory();