From 0def71378dc7abf682727c600b696f7313cdcf60 Mon Sep 17 00:00:00 2001 From: Anh Vo Date: Tue, 27 Apr 2021 13:40:59 -0400 Subject: [PATCH 7/7] Azure: adding support for consuming userdata from IMDS (#884) RH-Author: Eduardo Otubo RH-MergeRequest: 18: Add support for userdata on Azure from IMDS RH-Commit: [7/7] 1e7ab925162ed9ef2c9b5b9f5c6d5e6ec6e623dd (otubo/cloud-init-src) RH-Bugzilla: 2042351 RH-Acked-by: Miroslav Rezanina RH-Acked-by: Emanuele Giuseppe Esposito --- cloudinit/sources/DataSourceAzure.py | 23 ++++++++- tests/unittests/test_datasource/test_azure.py | 50 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index d0be6d84..a66f023d 100755 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -83,7 +83,7 @@ AGENT_SEED_DIR = '/var/lib/waagent' IMDS_TIMEOUT_IN_SECONDS = 2 IMDS_URL = "http://169.254.169.254/metadata" IMDS_VER_MIN = "2019-06-01" -IMDS_VER_WANT = "2020-10-01" +IMDS_VER_WANT = "2021-01-01" # This holds SSH key data including if the source was @@ -539,6 +539,20 @@ class DataSourceAzure(sources.DataSource): imds_disable_password ) crawled_data['metadata']['disable_password'] = imds_disable_password # noqa: E501 + + # only use userdata from imds if OVF did not provide custom data + # userdata provided by IMDS is always base64 encoded + if not userdata_raw: + imds_userdata = _userdata_from_imds(imds_md) + if imds_userdata: + LOG.debug("Retrieved userdata from IMDS") + try: + crawled_data['userdata_raw'] = base64.b64decode( + ''.join(imds_userdata.split())) + except Exception: + report_diagnostic_event( + "Bad userdata in IMDS", + logger_func=LOG.warning) found = cdev report_diagnostic_event( @@ -1512,6 +1526,13 @@ def _username_from_imds(imds_data): return None +def _userdata_from_imds(imds_data): + try: + return imds_data['compute']['userData'] + except KeyError: + return None + + def _hostname_from_imds(imds_data): try: return imds_data['compute']['osProfile']['computerName'] diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py index c4a8e08d..f8433690 100644 --- a/tests/unittests/test_datasource/test_azure.py +++ b/tests/unittests/test_datasource/test_azure.py @@ -1899,6 +1899,56 @@ scbus-1 on xpt0 bus 0 dsrc.get_data() self.assertTrue(dsrc.metadata["disable_password"]) + @mock.patch(MOCKPATH + 'get_metadata_from_imds') + def test_userdata_from_imds(self, m_get_metadata_from_imds): + sys_cfg = {'datasource': {'Azure': {'apply_network_config': True}}} + odata = {'HostName': "myhost", 'UserName': "myuser"} + data = { + 'ovfcontent': construct_valid_ovf_env(data=odata), + 'sys_cfg': sys_cfg + } + userdata = "userdataImds" + imds_data = copy.deepcopy(NETWORK_METADATA) + imds_data["compute"]["osProfile"] = dict( + adminUsername="username1", + computerName="hostname1", + disablePasswordAuthentication="true", + ) + imds_data["compute"]["userData"] = b64e(userdata) + m_get_metadata_from_imds.return_value = imds_data + dsrc = self._get_ds(data) + ret = dsrc.get_data() + self.assertTrue(ret) + self.assertEqual(dsrc.userdata_raw, userdata.encode('utf-8')) + + @mock.patch(MOCKPATH + 'get_metadata_from_imds') + def test_userdata_from_imds_with_customdata_from_OVF( + self, m_get_metadata_from_imds): + userdataOVF = "userdataOVF" + odata = { + 'HostName': "myhost", 'UserName': "myuser", + 'UserData': {'text': b64e(userdataOVF), 'encoding': 'base64'} + } + sys_cfg = {'datasource': {'Azure': {'apply_network_config': True}}} + data = { + 'ovfcontent': construct_valid_ovf_env(data=odata), + 'sys_cfg': sys_cfg + } + + userdataImds = "userdataImds" + imds_data = copy.deepcopy(NETWORK_METADATA) + imds_data["compute"]["osProfile"] = dict( + adminUsername="username1", + computerName="hostname1", + disablePasswordAuthentication="true", + ) + imds_data["compute"]["userData"] = b64e(userdataImds) + m_get_metadata_from_imds.return_value = imds_data + dsrc = self._get_ds(data) + ret = dsrc.get_data() + self.assertTrue(ret) + self.assertEqual(dsrc.userdata_raw, userdataOVF.encode('utf-8')) + class TestAzureBounce(CiTestCase): -- 2.27.0