summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--cloudinit/sources/DataSourceAzure.py16
-rw-r--r--tests/unittests/test_datasource/test_azure.py52
3 files changed, 57 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index b7a66aa1..538ffda8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -63,6 +63,7 @@
- NoCloud: fix consumption of vendordata (LP: #1493453)
- power_state_change: support 'condition' to disable or enable poweroff
- ubuntu fan: support for config and installing of ubuntu fan (LP: #1504604)
+ - Azure: support extracting SSH key values from ovf-env.xml (LP: #1506244)
0.7.6:
- open 0.7.6
- Enable vendordata on CloudSigma datasource (LP: #1303986)
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index ff950deb..c6228e6c 100644
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -148,9 +148,15 @@ class DataSourceAzureNet(sources.DataSource):
wait_for = [shcfgxml]
fp_files = []
+ key_value = None
for pk in self.cfg.get('_pubkeys', []):
- bname = str(pk['fingerprint'] + ".crt")
- fp_files += [os.path.join(ddir, bname)]
+ if pk.get('value', None):
+ key_value = pk['value']
+ LOG.debug("ssh authentication: using value from fabric")
+ else:
+ bname = str(pk['fingerprint'] + ".crt")
+ fp_files += [os.path.join(ddir, bname)]
+ LOG.debug("ssh authentication: using fingerprint from fabirc")
missing = util.log_time(logfunc=LOG.debug, msg="waiting for files",
func=wait_for_files,
@@ -166,7 +172,8 @@ class DataSourceAzureNet(sources.DataSource):
metadata['instance-id'] = iid_from_shared_config(shcfgxml)
except ValueError as e:
LOG.warn("failed to get instance id in %s: %s", shcfgxml, e)
- metadata['public-keys'] = pubkeys_from_crt_files(fp_files)
+
+ metadata['public-keys'] = key_value or pubkeys_from_crt_files(fp_files)
return metadata
def get_data(self):
@@ -497,7 +504,8 @@ def load_azure_ovf_pubkeys(sshnode):
for pk_node in pubkeys:
if not pk_node.hasChildNodes():
continue
- cur = {'fingerprint': "", 'path': ""}
+
+ cur = {'fingerprint': "", 'path': "", 'value': ""}
for child in pk_node.childNodes:
if child.nodeType == text_node or not child.localName:
continue
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index 8952374f..ec0435f5 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -54,10 +54,13 @@ def construct_valid_ovf_env(data=None, pubkeys=None, userdata=None):
if pubkeys:
content += "<SSH><PublicKeys>\n"
- for fp, path in pubkeys:
+ for fp, path, value in pubkeys:
content += " <PublicKey>"
- content += ("<Fingerprint>%s</Fingerprint><Path>%s</Path>" %
- (fp, path))
+ if fp and path:
+ content += ("<Fingerprint>%s</Fingerprint><Path>%s</Path>" %
+ (fp, path))
+ if value:
+ content += "<Value>%s</Value>" % value
content += "</PublicKey>\n"
content += "</PublicKeys></SSH>"
content += """
@@ -297,10 +300,10 @@ class TestAzureDataSource(TestCase):
self.assertFalse(ret)
self.assertFalse('agent_invoked' in data)
- def test_cfg_has_pubkeys(self):
+ def test_cfg_has_pubkeys_fingerprint(self):
odata = {'HostName': "myhost", 'UserName': "myuser"}
- mypklist = [{'fingerprint': 'fp1', 'path': 'path1'}]
- pubkeys = [(x['fingerprint'], x['path']) for x in mypklist]
+ mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': ''}]
+ pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
data = {'ovfcontent': construct_valid_ovf_env(data=odata,
pubkeys=pubkeys)}
@@ -309,6 +312,39 @@ class TestAzureDataSource(TestCase):
self.assertTrue(ret)
for mypk in mypklist:
self.assertIn(mypk, dsrc.cfg['_pubkeys'])
+ self.assertIn('pubkey_from', dsrc.metadata['public-keys'][-1])
+
+ def test_cfg_has_pubkeys_value(self):
+ # make sure that provided key is used over fingerprint
+ odata = {'HostName': "myhost", 'UserName': "myuser"}
+ mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': 'value1'}]
+ pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
+ data = {'ovfcontent': construct_valid_ovf_env(data=odata,
+ pubkeys=pubkeys)}
+
+ dsrc = self._get_ds(data)
+ ret = dsrc.get_data()
+ self.assertTrue(ret)
+
+ for mypk in mypklist:
+ self.assertIn(mypk, dsrc.cfg['_pubkeys'])
+ self.assertIn(mypk['value'], dsrc.metadata['public-keys'])
+
+ def test_cfg_has_no_fingerprint_has_value(self):
+ # test value is used when fingerprint not provided
+ odata = {'HostName': "myhost", 'UserName': "myuser"}
+ mypklist = [{'fingerprint': None, 'path': 'path1', 'value': 'value1'}]
+ pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
+ data = {'ovfcontent': construct_valid_ovf_env(data=odata,
+ pubkeys=pubkeys)}
+
+ dsrc = self._get_ds(data)
+ ret = dsrc.get_data()
+ self.assertTrue(ret)
+
+ for mypk in mypklist:
+ self.assertIn(mypk['value'], dsrc.metadata['public-keys'])
+
def test_default_ephemeral(self):
# make sure the ephemeral device works
@@ -642,8 +678,8 @@ class TestReadAzureOvf(TestCase):
DataSourceAzure.read_azure_ovf, invalid_xml)
def test_load_with_pubkeys(self):
- mypklist = [{'fingerprint': 'fp1', 'path': 'path1'}]
- pubkeys = [(x['fingerprint'], x['path']) for x in mypklist]
+ mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': ''}]
+ pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
content = construct_valid_ovf_env(pubkeys=pubkeys)
(_md, _ud, cfg) = DataSourceAzure.read_azure_ovf(content)
for mypk in mypklist: