sailesh1993 / rpms / cloud-init

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