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