From 11741d85b9f5417257c1e520553b700e8fdfa242 Mon Sep 17 00:00:00 2001 From: Martin Harris Date: Fri, 10 Jun 2016 14:21:40 +0100 Subject: [PATCH] Prevents premature resolving of external config --- .../camp/brooklyn/ExternalConfigYamlTest.java | 25 ++++ ...JcloudsLocationExternalConfigYamlTest.java | 124 ++++++++++++++++++ ...tractCloudMachineProvisioningLocation.java | 12 +- .../location/ssh/SshMachineLocation.java | 16 +-- .../brooklyn/util/core/config/ConfigBag.java | 50 ++++++- .../location/jclouds/JcloudsLocation.java | 48 +++++-- .../jclouds/JcloudsSshMachineLocation.java | 3 +- 7 files changed, 250 insertions(+), 28 deletions(-) create mode 100644 camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsLocationExternalConfigYamlTest.java diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java index a5f98b3622..f8285af4cf 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java @@ -27,6 +27,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType; import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.mgmt.ExecutionContext; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.config.ConfigKey; @@ -37,14 +38,17 @@ import org.apache.brooklyn.core.location.cloud.CloudLocationConfig; import org.apache.brooklyn.core.mgmt.internal.CampYamlParser; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.objs.BrooklynObjectInternal; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; import org.apache.brooklyn.core.test.entity.TestApplication; import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; import org.apache.brooklyn.util.core.task.DeferredSupplier; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.base.Joiner; @@ -217,6 +221,27 @@ public void testNonExternalisedCatalogConfigReferencedFromYaml() throws Exceptio assertEquals(Iterables.getOnlyElement(item.getLibraries()).getUrl(), LIBRARY_URL); } + @Test(groups="Integration") + public void testExternalisedLocationConfigInheritanceReferencedFromYaml() throws Exception { + ConfigKey MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key"); + + String yaml = Joiner.on("\n").join( + "services:", + "- type: "+EmptySoftwareProcess.class.getName(), + "location:", + " localhost:", + " my.config.key: $brooklyn:external(\"myprovider\", \"mykey\")"); + + Entity app = createAndStartApplication(yaml); + waitForApplicationTasks(app); + Entity entity = Iterables.getOnlyElement( app.getChildren() ); + Location l = Iterables.getOnlyElement( entity.getLocations() ); + assertEquals(l.config().get(MY_CONFIG_KEY), "myval"); + Maybe rawConfig = ((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(MY_CONFIG_KEY); + Assert.assertTrue(rawConfig.isPresentAndNonNull()); + Assert.assertTrue(rawConfig.get() instanceof DeferredSupplier, "Expected deferred raw value; got "+rawConfig.get()); + } + @Test(groups="Integration") public void testExternalisedLocationConfigSetViaProvisioningPropertiesReferencedFromYaml() throws Exception { String yaml = Joiner.on("\n").join( diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsLocationExternalConfigYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsLocationExternalConfigYamlTest.java new file mode 100644 index 0000000000..7e993289c2 --- /dev/null +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsLocationExternalConfigYamlTest.java @@ -0,0 +1,124 @@ +/* + * 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.camp.brooklyn; + +import static org.testng.Assert.assertEquals; + +import java.io.File; +import java.io.StringReader; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.camp.brooklyn.ExternalConfigYamlTest.MyExternalConfigSupplier; +import org.apache.brooklyn.camp.brooklyn.ExternalConfigYamlTest.MyExternalConfigSupplierWithoutMapArg; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.StartableApplication; +import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils; +import org.apache.brooklyn.core.objs.BrooklynObjectInternal; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.util.core.internal.ssh.SshTool; +import org.apache.brooklyn.util.core.task.DeferredSupplier; +import org.apache.brooklyn.util.guava.Maybe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; + +// also see ExternalConfigYamlTest +public class JcloudsLocationExternalConfigYamlTest extends AbstractYamlRebindTest { + + private static final Logger log = LoggerFactory.getLogger(ExternalConfigYamlTest.class); + + private static final ConfigKey MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key"); + + @Override + protected BrooklynProperties createBrooklynProperties() { + BrooklynProperties props = BrooklynProperties.Factory.newDefault(); + props.put("brooklyn.external.myprovider", MyExternalConfigSupplier.class.getName()); + props.put("brooklyn.external.myprovider.mykey", "myval"); + props.put("brooklyn.external.myproviderWithoutMapArg", MyExternalConfigSupplierWithoutMapArg.class.getName()); + return props; + } + + @Test(groups="Live") + public void testJcloudsInheritanceAndPasswordSecret() throws Exception { + String yaml = Joiner.on("\n").join( + "services:", + "- type: "+EmptySoftwareProcess.class.getName(), + "location:", + " jclouds:aws-ec2:", + " password: $brooklyn:external(\"myprovider\", \"mykey\")", + " my.config.key: $brooklyn:external(\"myprovider\", \"mykey\")"); + + origApp = (StartableApplication) createAndStartApplication(new StringReader(yaml)); + + Entity entity = Iterables.getOnlyElement( origApp.getChildren() ); + Location l = Iterables.getOnlyElement( entity.getLocations() ); + log.info("Location: "+l); + assertEquals(l.config().get(MY_CONFIG_KEY), "myval"); + + Maybe rawConfig = ((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(MY_CONFIG_KEY); + log.info("Raw config: "+rawConfig); + Assert.assertTrue(rawConfig.isPresentAndNonNull()); + Assert.assertTrue(rawConfig.get() instanceof DeferredSupplier, "Expected deferred raw value; got "+rawConfig.get()); + + rawConfig = ((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(SshTool.PROP_PASSWORD); + log.info("Raw config password: "+rawConfig); + Assert.assertTrue(rawConfig.isPresentAndNonNull()); + Assert.assertTrue(rawConfig.get() instanceof DeferredSupplier, "Expected deferred raw value; got "+rawConfig.get()); + } + + @Test(groups="Live") + public void testProvisioningPropertyInheritance() throws Exception { + String yaml = Joiner.on("\n").join( + "services:", + "- type: "+EmptySoftwareProcess.class.getName(), + " provisioning.properties:", + " password: $brooklyn:external(\"myprovider\", \"mykey\")", + // note that these 2 do not get transferred -- see below + " simple: 42", + " my.config.key: $brooklyn:external(\"myprovider\", \"mykey\")", + "location: aws-ec2"); + + origApp = (StartableApplication) createAndStartApplication(new StringReader(yaml)); + + Entity entity = Iterables.getOnlyElement( origApp.getChildren() ); + Location l = Iterables.getOnlyElement( entity.getLocations() ); + log.info("Location: "+l); + assertEquals(l.config().get(JcloudsLocation.PASSWORD), "myval"); + + Maybe rawConfig = ((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(ConfigKeys.newStringConfigKey("password")); + log.info("Raw config password: "+rawConfig); + Assert.assertTrue(rawConfig.isPresentAndNonNull()); + Assert.assertTrue(rawConfig.get() instanceof DeferredSupplier, "Expected deferred raw value; got "+rawConfig.get()); + + // these are null as only recognised provisioning properties are transmitted by jclouds + log.info("my config key: "+l.getConfig(MY_CONFIG_KEY)); + log.info("my config key raw: "+((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(MY_CONFIG_KEY)); + log.info("simple: "+l.getConfig(ConfigKeys.builder(Integer.class, "simple").build())); + log.info("simple raw: "+((BrooklynObjectInternal.ConfigurationSupportInternal)l.config()).getRaw(ConfigKeys.builder(Integer.class, "simple").build())); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/apache/brooklyn/core/location/cloud/AbstractCloudMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/core/location/cloud/AbstractCloudMachineProvisioningLocation.java index 504033a533..90d9f8b4d8 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/cloud/AbstractCloudMachineProvisioningLocation.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/cloud/AbstractCloudMachineProvisioningLocation.java @@ -71,22 +71,22 @@ protected ConfigBag extractSshConfig(ConfigBag setup, ConfigBag alt) { ConfigBag sshConfig = new ConfigBag(); if (setup.containsKey(PASSWORD)) { - sshConfig.put(SshTool.PROP_PASSWORD, setup.get(PASSWORD)); + sshConfig.copyKeyAs(setup, PASSWORD, SshTool.PROP_PASSWORD); } else if (alt.containsKey(PASSWORD)) { - sshConfig.put(SshTool.PROP_PASSWORD, alt.get(PASSWORD)); + sshConfig.copyKeyAs(alt, PASSWORD, SshTool.PROP_PASSWORD); } if (setup.containsKey(PRIVATE_KEY_DATA)) { - sshConfig.put(SshTool.PROP_PRIVATE_KEY_DATA, setup.get(PRIVATE_KEY_DATA)); + sshConfig.copyKeyAs(setup, PRIVATE_KEY_DATA, SshTool.PROP_PRIVATE_KEY_DATA); } else if (setup.containsKey(PRIVATE_KEY_FILE)) { - sshConfig.put(SshTool.PROP_PRIVATE_KEY_FILE, setup.get(PRIVATE_KEY_FILE)); + sshConfig.copyKeyAs(setup, PRIVATE_KEY_FILE, SshTool.PROP_PRIVATE_KEY_FILE); } else if (alt.containsKey(PRIVATE_KEY_DATA)) { - sshConfig.put(SshTool.PROP_PRIVATE_KEY_DATA, alt.get(PRIVATE_KEY_DATA)); + sshConfig.copyKeyAs(setup, PRIVATE_KEY_DATA, SshTool.PROP_PRIVATE_KEY_DATA); } if (setup.containsKey(PRIVATE_KEY_PASSPHRASE)) { // NB: not supported in jclouds (but it is by our ssh tool) - sshConfig.put(SshTool.PROP_PRIVATE_KEY_PASSPHRASE, setup.get(PRIVATE_KEY_PASSPHRASE)); + sshConfig.copyKeyAs(setup, PRIVATE_KEY_PASSPHRASE, SshTool.PROP_PRIVATE_KEY_PASSPHRASE); } // TODO extract other SshTool properties ? 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 b66c94c5aa..54bd6485c3 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 @@ -630,20 +630,20 @@ protected SshTool connectSsh(Map props) { // default value of host, overridden if SSH_HOST is supplied .configure(SshTool.PROP_HOST, address.getHostName()); - for (Map.Entry entry: config().getBag().getAllConfig().entrySet()) { + for (Map.Entry, ?> entry: config().getBag().getAllConfigAsConfigKeyMap().entrySet()) { boolean include = false; - String key = entry.getKey(); - if (key.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) { - key = Strings.removeFromStart(key, SshTool.BROOKLYN_CONFIG_KEY_PREFIX); + String keyName = entry.getKey().getName(); + if (keyName.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) { + keyName = Strings.removeFromStart(keyName, SshTool.BROOKLYN_CONFIG_KEY_PREFIX); include = true; } - if (key.startsWith(SSH_TOOL_CLASS_PROPERTIES_PREFIX)) { - key = Strings.removeFromStart(key, SSH_TOOL_CLASS_PROPERTIES_PREFIX); + if (keyName.startsWith(SSH_TOOL_CLASS_PROPERTIES_PREFIX)) { + keyName = Strings.removeFromStart(keyName, SSH_TOOL_CLASS_PROPERTIES_PREFIX); include = true; } - if (ALL_SSH_CONFIG_KEY_NAMES.contains(entry.getKey())) { + if (ALL_SSH_CONFIG_KEY_NAMES.contains(keyName)) { // key should be included, and does not need to be changed // TODO make this config-setting mechanism more universal @@ -655,7 +655,7 @@ protected SshTool connectSsh(Map props) { } if (include) { - args.putStringKey(key, entry.getValue()); + args.putStringKey(keyName, config().get(entry.getKey())); } } diff --git a/core/src/main/java/org/apache/brooklyn/util/core/config/ConfigBag.java b/core/src/main/java/org/apache/brooklyn/util/core/config/ConfigBag.java index 23a7485c47..96d2428b68 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/config/ConfigBag.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/config/ConfigBag.java @@ -30,7 +30,6 @@ import org.apache.brooklyn.config.ConfigKey.HasConfigKey; import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.JavaClassNames; @@ -367,6 +366,45 @@ public Maybe getObjKeyMaybe(Object key) { } } + /** gets a {@link Maybe}-wrapped value from a key, inferring the type of that key (e.g. {@link ConfigKey} or {@link String}) */ + @Beta + private Maybe getRawObjKeyMaybe(Object key) { + if (key instanceof HasConfigKey) key = ((HasConfigKey)key).getConfigKey(); + if (key instanceof ConfigKey) key = ((ConfigKey)key).getName(); + if (key instanceof String) { + return this.getRawStringKeyMaybe((String)key, true); + } else { + logInvalidKey(key); + return Maybe.absent(); + } + } + + /** Puts into this bag the raw value for the given key in the given bag, if it was present. */ + @Beta + public ConfigBag copyKey(ConfigBag source, ConfigKey key) { + return copyKeyAs(source, key, key); + } + + /** Puts into this bag the raw value for the given key in the given bag, if it was present. */ + @Beta + public ConfigBag copyKeys(ConfigBag source, ConfigKey ...keys) { + for (ConfigKey key : keys) { + copyKey(source, key); + } + return this; + } + + /** As {@link #copyKey(ConfigBag, ConfigKey)} but allowing a different key name to be used when writing here. */ + @Beta + @SuppressWarnings("unchecked") + public ConfigBag copyKeyAs(ConfigBag source, ConfigKey sourceKey, ConfigKey targetKey) { + Maybe sourceValue = source.getRawObjKeyMaybe(sourceKey); + if (sourceValue.isPresent()) { + put(targetKey, (T) sourceValue.get()); + } + return this; + } + /** like get, but without marking it as used */ public T peek(ConfigKey key) { return get(key, false); @@ -468,7 +506,8 @@ public static T coerceFirstNonNullKeyValue(ConfigKey key, Object ...value protected Object getStringKey(String key, boolean markUsed) { return getStringKeyMaybe(key, markUsed).orNull(); } - protected synchronized Maybe getStringKeyMaybe(String key, boolean markUsed) { + + private synchronized Maybe getRawStringKeyMaybe(String key, boolean markUsed) { if (config.containsKey(key)) { if (markUsed) markUsed(key); return Maybe.of(config.get(key)); @@ -476,6 +515,13 @@ protected synchronized Maybe getStringKeyMaybe(String key, boolean markU return Maybe.absent(); } + /** + * @return Unresolved configuration value. May be overridden to provide resolution - @see {@link ResolvingConfigBag#getStringKeyMaybe(String, boolean)} + */ + protected synchronized Maybe getStringKeyMaybe(String key, boolean markUsed) { + return getRawStringKeyMaybe(key, markUsed); + } + /** indicates that a string key in the config map has been accessed */ public synchronized void markUsed(String key) { unusedConfig.remove(key); 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 51e9d6aec2..4862e474ec 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 @@ -569,7 +569,7 @@ protected MachineManagementMixins.MachineMetadata getMachineMetadata(ComputeMeta @Override public MachineManagementMixins.MachineMetadata getMachineMetadata(MachineLocation l) { if (l instanceof JcloudsSshMachineLocation) { - return getMachineMetadata( ((JcloudsSshMachineLocation)l).node ); + return getMachineMetadata(getComputeService().getNodeMetadata(((JcloudsSshMachineLocation) l).getJcloudsId())); } return null; } @@ -813,8 +813,8 @@ protected MachineLocation obtainOnce(ConfigBag setup) throws NoMachinesAvailable userCredentials = LoginCredentials.fromCredentials(node.getCredentials()); } // store the credentials, in case they have changed - setup.putIfNotNull(JcloudsLocationConfig.PASSWORD, userCredentials.getOptionalPassword().orNull()); - setup.putIfNotNull(JcloudsLocationConfig.PRIVATE_KEY_DATA, userCredentials.getOptionalPrivateKey().orNull()); + putIfPresentButDifferent(setup, JcloudsLocationConfig.PASSWORD, userCredentials.getOptionalPassword().orNull()); + putIfPresentButDifferent(setup, JcloudsLocationConfig.PRIVATE_KEY_DATA, userCredentials.getOptionalPrivateKey().orNull()); // Wait for the VM to be reachable over SSH if (waitForSshable && !windows) { @@ -822,10 +822,13 @@ protected MachineLocation obtainOnce(ConfigBag setup) throws NoMachinesAvailable } else { LOG.debug("Skipping ssh check for {} ({}) due to config waitForSshable=false", node, setup.getDescription()); } + + // Do not store the credentials on the node as this may leak the credentials if they + // are obtained from an external supplier + node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(null).build(); + usableTimestamp = Duration.of(provisioningStopwatch); -// JcloudsSshMachineLocation jcloudsSshMachineLocation = null; -// WinRmMachineLocation winRmMachineLocation = null; // Create a JcloudsSshMachineLocation, and register it if (windows) { machineLocation = registerWinRmMachineLocation(computeService, node, userCredentials, sshHostAndPortOverride, setup); @@ -1151,6 +1154,21 @@ private void executeCommandWarningOnError(SshMachineLocation loc, String name, L // ------------- suspend and resume ------------------------------------ + private void putIfPresentButDifferent(ConfigBag setup, ConfigKey key, String expectedValue) { + if (expectedValue==null) return; + String currentValue = setup.get(key); + if (Objects.equal(currentValue, expectedValue)) { + // no need to write -- and good reason not to -- + // the currentValue may come from an external supplier, + // so we prefer to keep the secret in that supplier + return; + } + // either current value is null, or + // current value is different (possibly password coming from a one-time source) + // in either case prefer the expected value + setup.put(key, expectedValue); + } + /** * Suspends the given location. *

@@ -2375,7 +2393,7 @@ protected JcloudsSshMachineLocation registerJcloudsSshMachineLocation(ComputeSer if (userCredentials == null) userCredentials = node.getCredentials(); - String vmHostname = getPublicHostname(node, sshHostAndPort, setup); + String vmHostname = getPublicHostname(node, sshHostAndPort, userCredentials, setup); JcloudsSshMachineLocation machine = createJcloudsSshMachineLocation(computeService, node, template, vmHostname, sshHostAndPort, userCredentials, setup); registerJcloudsMachineLocation(node.getId(), machine); @@ -2442,8 +2460,12 @@ protected JcloudsSshMachineLocation createJcloudsSshMachineLocation(ComputeServi // FIXME remove "config" -- inserted directly, above .configure("config", sshConfig) .configure("user", userCredentials.getUser()) - .configure(SshMachineLocation.PASSWORD, userCredentials.getOptionalPassword().orNull()) - .configure(SshMachineLocation.PRIVATE_KEY_DATA, userCredentials.getOptionalPrivateKey().orNull()) + .configure(SshMachineLocation.PASSWORD.getName(), sshConfig.get(SshMachineLocation.PASSWORD.getName()) != null ? + sshConfig.get(SshMachineLocation.PASSWORD.getName()) : + userCredentials.getOptionalPassword().orNull()) + .configure(SshMachineLocation.PRIVATE_KEY_DATA.getName(), sshConfig.get(SshMachineLocation.PRIVATE_KEY_DATA.getName()) != null ? + sshConfig.get(SshMachineLocation.PRIVATE_KEY_DATA.getName()) : + userCredentials.getOptionalPrivateKey().orNull()) .configure("jcloudsParent", this) .configure("node", node) .configure("template", template.orNull()) @@ -2466,8 +2488,12 @@ protected JcloudsSshMachineLocation createJcloudsSshMachineLocation(ComputeServi // FIXME remove "config" -- inserted directly, above .put("config", sshConfig) .put("user", userCredentials.getUser()) - .putIfNotNull(SshMachineLocation.PASSWORD.getName(), userCredentials.getOptionalPassword().orNull()) - .putIfNotNull(SshMachineLocation.PRIVATE_KEY_DATA.getName(), userCredentials.getOptionalPrivateKey().orNull()) + .putIfNotNull(SshMachineLocation.PASSWORD.getName(), sshConfig.get(SshMachineLocation.PASSWORD.getName()) != null ? + SshMachineLocation.PASSWORD.getName() : + userCredentials.getOptionalPassword().orNull()) + .putIfNotNull(SshMachineLocation.PRIVATE_KEY_DATA.getName(), sshConfig.get(SshMachineLocation.PRIVATE_KEY_DATA.getName()) != null ? + SshMachineLocation.PRIVATE_KEY_DATA.getName() : + userCredentials.getOptionalPrivateKey().orNull()) .put("callerContext", setup.get(CALLER_CONTEXT)) .putIfNotNull(CLOUD_AVAILABILITY_ZONE_ID.getName(), nodeAvailabilityZone) .putIfNotNull(CLOUD_REGION_ID.getName(), nodeRegion) @@ -2509,7 +2535,7 @@ protected JcloudsWinRmMachineLocation createWinRmMachineLocation(ComputeService .configure(WinRmMachineLocation.WINRM_CONFIG_PORT, sshHostAndPort.isPresent() ? sshHostAndPort.get().getPort() : node.getLoginPort()) .configure("user", getUser(setup)) .configure(WinRmMachineLocation.USER, setup.get(USER)) - .configure(WinRmMachineLocation.PASSWORD, setup.get(PASSWORD)) + .configure(ConfigBag.newInstance().copyKeyAs(setup, PASSWORD, WinRmMachineLocation.PASSWORD).getAllConfigRaw()) .configure("node", node) .configureIfNotNull(CLOUD_AVAILABILITY_ZONE_ID, nodeAvailabilityZone) .configureIfNotNull(CLOUD_REGION_ID, nodeRegion) 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 51a476fd92..3318ba19a7 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 @@ -38,6 +38,7 @@ 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.config.ResolvingConfigBag; import org.apache.brooklyn.util.core.flags.SetFromFlag; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.net.Networking; @@ -480,7 +481,7 @@ public String waitForPassword() { } private LoginCredentials getLoginCredentials() { - OsCredential creds = LocationConfigUtils.getOsCredential(config().getBag()); + OsCredential creds = LocationConfigUtils.getOsCredential(new ResolvingConfigBag(getManagementContext(), config().getBag())); return LoginCredentials.builder() .user(getUser())