diff --git a/SOURCES/ci-azure-Filter-list-of-ssh-keys-pulled-from-fabric.patch b/SOURCES/ci-azure-Filter-list-of-ssh-keys-pulled-from-fabric.patch
new file mode 100644
index 0000000..04ae155
--- /dev/null
+++ b/SOURCES/ci-azure-Filter-list-of-ssh-keys-pulled-from-fabric.patch
@@ -0,0 +1,571 @@
+From a584b587a61e7fb7b29f915600021ce51d0ab558 Mon Sep 17 00:00:00 2001
+From: Eduardo Otubo <otubo@redhat.com>
+Date: Wed, 6 Mar 2019 14:18:01 +0100
+Subject: [PATCH] azure: Filter list of ssh keys pulled from fabric
+
+RH-Author: Eduardo Otubo <otubo@redhat.com>
+Message-id: <20190306141801.8647-1-otubo@redhat.com>
+Patchwork-id: 84806
+O-Subject: [RHEL-7.6.z cloud-init PATCH] azure: Filter list of ssh keys pulled from fabric
+Bugzilla: 1684038
+RH-Acked-by: Cathy Avery <cavery@redhat.com>
+RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+From: "Jason Zions (MSFT)" <jasonzio@microsoft.com>
+
+commit 34f54360fcc1e0f805002a0b639d0a84eb2cb8ee
+Author: Jason Zions (MSFT) <jasonzio@microsoft.com>
+Date:   Fri Feb 22 13:26:31 2019 +0000
+
+    azure: Filter list of ssh keys pulled from fabric
+
+    The Azure data source is expected to expose a list of
+    ssh keys for the user-to-be-provisioned in the crawled
+    metadata. When configured to use the __builtin__ agent
+    this list is built by the WALinuxAgentShim. The shim
+    retrieves the full set of certificates and public keys
+    exposed to the VM from the wireserver, extracts any
+    ssh keys it can, and returns that list.
+
+    This fix reduces that list of ssh keys to just the
+    ones whose fingerprints appear in the "administrative
+    user" section of the ovf-env.xml file. The Azure
+    control plane exposes other ssh keys to the VM for
+    other reasons, but those should not be added to the
+    authorized_keys file for the provisioned user.
+
+Signed-off-by: Eduardo Otubo <otubo@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ cloudinit/sources/DataSourceAzure.py               |  13 +-
+ cloudinit/sources/helpers/azure.py                 | 109 ++++++++++-----
+ tests/data/azure/parse_certificates_fingerprints   |   4 +
+ tests/data/azure/parse_certificates_pem            | 152 +++++++++++++++++++++
+ tests/data/azure/pubkey_extract_cert               |  13 ++
+ tests/data/azure/pubkey_extract_ssh_key            |   1 +
+ .../unittests/test_datasource/test_azure_helper.py |  71 +++++++++-
+ 7 files changed, 322 insertions(+), 41 deletions(-)
+ create mode 100644 tests/data/azure/parse_certificates_fingerprints
+ create mode 100644 tests/data/azure/parse_certificates_pem
+ create mode 100644 tests/data/azure/pubkey_extract_cert
+ create mode 100644 tests/data/azure/pubkey_extract_ssh_key
+
+diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
+index 46d5744..4ebe6af 100644
+--- a/cloudinit/sources/DataSourceAzure.py
++++ b/cloudinit/sources/DataSourceAzure.py
+@@ -522,9 +522,11 @@ class DataSourceAzure(sources.DataSource):
+         if self.ds_cfg['agent_command'] == AGENT_START_BUILTIN:
+             self.bounce_network_with_azure_hostname()
+ 
++            pubkey_info = self.cfg.get('_pubkeys', None)
+             metadata_func = partial(get_metadata_from_fabric,
+                                     fallback_lease_file=self.
+-                                    dhclient_lease_file)
++                                    dhclient_lease_file,
++                                    pubkey_info=pubkey_info)
+         else:
+             metadata_func = self.get_metadata_from_agent
+ 
+@@ -537,6 +539,7 @@ class DataSourceAzure(sources.DataSource):
+                 "Error communicating with Azure fabric; You may experience."
+                 "connectivity issues.", exc_info=True)
+             return False
++
+         util.del_file(REPORTED_READY_MARKER_FILE)
+         util.del_file(REPROVISION_MARKER_FILE)
+         return fabric_data
+@@ -807,13 +810,15 @@ def find_child(node, filter_func):
+ def load_azure_ovf_pubkeys(sshnode):
+     # This parses a 'SSH' node formatted like below, and returns
+     # an array of dicts.
+-    #  [{'fp': '6BE7A7C3C8A8F4B123CCA5D0C2F1BE4CA7B63ED7',
+-    #    'path': 'where/to/go'}]
++    #  [{'fingerprint': '6BE7A7C3C8A8F4B123CCA5D0C2F1BE4CA7B63ED7',
++    #    'path': '/where/to/go'}]
+     #
+     # <SSH><PublicKeys>
+-    #   <PublicKey><Fingerprint>ABC</FingerPrint><Path>/ABC</Path>
++    #   <PublicKey><Fingerprint>ABC</FingerPrint><Path>/x/y/z</Path>
+     #   ...
+     # </PublicKeys></SSH>
++    # Under some circumstances, there may be a <Value> element along with the
++    # Fingerprint and Path. Pass those along if they appear.
+     results = find_child(sshnode, lambda n: n.localName == "PublicKeys")
+     if len(results) == 0:
+         return []
+diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
+index 90c12df..4b4f0e0 100644
+--- a/cloudinit/sources/helpers/azure.py
++++ b/cloudinit/sources/helpers/azure.py
+@@ -137,9 +137,36 @@ class OpenSSLManager(object):
+             self.certificate = certificate
+         LOG.debug('New certificate generated.')
+ 
+-    def parse_certificates(self, certificates_xml):
+-        tag = ElementTree.fromstring(certificates_xml).find(
+-            './/Data')
++    @staticmethod
++    def _run_x509_action(action, cert):
++        cmd = ['openssl', 'x509', '-noout', action]
++        result, _ = util.subp(cmd, data=cert)
++        return result
++
++    def _get_ssh_key_from_cert(self, certificate):
++        pub_key = self._run_x509_action('-pubkey', certificate)
++        keygen_cmd = ['ssh-keygen', '-i', '-m', 'PKCS8', '-f', '/dev/stdin']
++        ssh_key, _ = util.subp(keygen_cmd, data=pub_key)
++        return ssh_key
++
++    def _get_fingerprint_from_cert(self, certificate):
++        """openssl x509 formats fingerprints as so:
++        'SHA1 Fingerprint=07:3E:19:D1:4D:1C:79:92:24:C6:A0:FD:8D:DA:\
++        B6:A8:BF:27:D4:73\n'
++
++        Azure control plane passes that fingerprint as so:
++        '073E19D14D1C799224C6A0FD8DDAB6A8BF27D473'
++        """
++        raw_fp = self._run_x509_action('-fingerprint', certificate)
++        eq = raw_fp.find('=')
++        octets = raw_fp[eq+1:-1].split(':')
++        return ''.join(octets)
++
++    def _decrypt_certs_from_xml(self, certificates_xml):
++        """Decrypt the certificates XML document using the our private key;
++           return the list of certs and private keys contained in the doc.
++        """
++        tag = ElementTree.fromstring(certificates_xml).find('.//Data')
+         certificates_content = tag.text
+         lines = [
+             b'MIME-Version: 1.0',
+@@ -150,32 +177,30 @@ class OpenSSLManager(object):
+             certificates_content.encode('utf-8'),
+         ]
+         with cd(self.tmpdir):
+-            with open('Certificates.p7m', 'wb') as f:
+-                f.write(b'\n'.join(lines))
+             out, _ = util.subp(
+-                'openssl cms -decrypt -in Certificates.p7m -inkey'
++                'openssl cms -decrypt -in /dev/stdin -inkey'
+                 ' {private_key} -recip {certificate} | openssl pkcs12 -nodes'
+                 ' -password pass:'.format(**self.certificate_names),
+-                shell=True)
+-        private_keys, certificates = [], []
++                shell=True, data=b'\n'.join(lines))
++        return out
++
++    def parse_certificates(self, certificates_xml):
++        """Given the Certificates XML document, return a dictionary of
++           fingerprints and associated SSH keys derived from the certs."""
++        out = self._decrypt_certs_from_xml(certificates_xml)
+         current = []
++        keys = {}
+         for line in out.splitlines():
+             current.append(line)
+             if re.match(r'[-]+END .*?KEY[-]+$', line):
+-                private_keys.append('\n'.join(current))
++                # ignore private_keys
+                 current = []
+             elif re.match(r'[-]+END .*?CERTIFICATE[-]+$', line):
+-                certificates.append('\n'.join(current))
++                certificate = '\n'.join(current)
++                ssh_key = self._get_ssh_key_from_cert(certificate)
++                fingerprint = self._get_fingerprint_from_cert(certificate)
++                keys[fingerprint] = ssh_key
+                 current = []
+-        keys = []
+-        for certificate in certificates:
+-            with cd(self.tmpdir):
+-                public_key, _ = util.subp(
+-                    'openssl x509 -noout -pubkey |'
+-                    'ssh-keygen -i -m PKCS8 -f /dev/stdin',
+-                    data=certificate,
+-                    shell=True)
+-            keys.append(public_key)
+         return keys
+ 
+ 
+@@ -205,7 +230,6 @@ class WALinuxAgentShim(object):
+         self.dhcpoptions = dhcp_options
+         self._endpoint = None
+         self.openssl_manager = None
+-        self.values = {}
+         self.lease_file = fallback_lease_file
+ 
+     def clean_up(self):
+@@ -327,8 +351,9 @@ class WALinuxAgentShim(object):
+         LOG.debug('Azure endpoint found at %s', endpoint_ip_address)
+         return endpoint_ip_address
+ 
+-    def register_with_azure_and_fetch_data(self):
+-        self.openssl_manager = OpenSSLManager()
++    def register_with_azure_and_fetch_data(self, pubkey_info=None):
++        if self.openssl_manager is None:
++            self.openssl_manager = OpenSSLManager()
+         http_client = AzureEndpointHttpClient(self.openssl_manager.certificate)
+         LOG.info('Registering with Azure...')
+         attempts = 0
+@@ -346,16 +371,37 @@ class WALinuxAgentShim(object):
+             attempts += 1
+         LOG.debug('Successfully fetched GoalState XML.')
+         goal_state = GoalState(response.contents, http_client)
+-        public_keys = []
+-        if goal_state.certificates_xml is not None:
++        ssh_keys = []
++        if goal_state.certificates_xml is not None and pubkey_info is not None:
+             LOG.debug('Certificate XML found; parsing out public keys.')
+-            public_keys = self.openssl_manager.parse_certificates(
++            keys_by_fingerprint = self.openssl_manager.parse_certificates(
+                 goal_state.certificates_xml)
+-        data = {
+-            'public-keys': public_keys,
+-        }
++            ssh_keys = self._filter_pubkeys(keys_by_fingerprint, pubkey_info)
+         self._report_ready(goal_state, http_client)
+-        return data
++        return {'public-keys': ssh_keys}
++
++    def _filter_pubkeys(self, keys_by_fingerprint, pubkey_info):
++        """cloud-init expects a straightforward array of keys to be dropped
++           into the user's authorized_keys file. Azure control plane exposes
++           multiple public keys to the VM via wireserver. Select just the
++           user's key(s) and return them, ignoring any other certs.
++        """
++        keys = []
++        for pubkey in pubkey_info:
++            if 'value' in pubkey and pubkey['value']:
++                keys.append(pubkey['value'])
++            elif 'fingerprint' in pubkey and pubkey['fingerprint']:
++                fingerprint = pubkey['fingerprint']
++                if fingerprint in keys_by_fingerprint:
++                    keys.append(keys_by_fingerprint[fingerprint])
++                else:
++                    LOG.warning("ovf-env.xml specified PublicKey fingerprint "
++                                "%s not found in goalstate XML", fingerprint)
++            else:
++                LOG.warning("ovf-env.xml specified PublicKey with neither "
++                            "value nor fingerprint: %s", pubkey)
++
++        return keys
+ 
+     def _report_ready(self, goal_state, http_client):
+         LOG.debug('Reporting ready to Azure fabric.')
+@@ -372,11 +418,12 @@ class WALinuxAgentShim(object):
+         LOG.info('Reported ready to Azure fabric.')
+ 
+ 
+-def get_metadata_from_fabric(fallback_lease_file=None, dhcp_opts=None):
++def get_metadata_from_fabric(fallback_lease_file=None, dhcp_opts=None,
++                             pubkey_info=None):
+     shim = WALinuxAgentShim(fallback_lease_file=fallback_lease_file,
+                             dhcp_options=dhcp_opts)
+     try:
+-        return shim.register_with_azure_and_fetch_data()
++        return shim.register_with_azure_and_fetch_data(pubkey_info=pubkey_info)
+     finally:
+         shim.clean_up()
+ 
+diff --git a/tests/data/azure/parse_certificates_fingerprints b/tests/data/azure/parse_certificates_fingerprints
+new file mode 100644
+index 0000000..f7293c5
+--- /dev/null
++++ b/tests/data/azure/parse_certificates_fingerprints
+@@ -0,0 +1,4 @@
++ECEDEB3B8488D31AF3BC4CCED493F64B7D27D7B1
++073E19D14D1C799224C6A0FD8DDAB6A8BF27D473
++4C16E7FAD6297D74A9B25EB8F0A12808CEBE293E
++929130695289B450FE45DCD5F6EF0CDE69865867
+diff --git a/tests/data/azure/parse_certificates_pem b/tests/data/azure/parse_certificates_pem
+new file mode 100644
+index 0000000..3521ea3
+--- /dev/null
++++ b/tests/data/azure/parse_certificates_pem
+@@ -0,0 +1,152 @@
++Bag Attributes
++    localKeyID: 01 00 00 00
++    Microsoft CSP Name: Microsoft Enhanced Cryptographic Provider v1.0
++Key Attributes
++    X509v3 Key Usage: 10
++-----BEGIN PRIVATE KEY-----
++MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDlEe5fUqwdrQTP
++W2oVlGK2f31q/8ULT8KmOTyUvL0RPdJQ69vvHOc5Q2CKg2eviHC2LWhF8WmpnZj6
++61RL0GeFGizwvU8Moebw5p3oqdcgoGpHVtxf+mr4QcWF58/Fwez0dA4hcsimVNBz
++eNpBBUIKNBMTBG+4d6hcQBUAGKUdGRcCGEyTqXLU0MgHjxC9JgVqWJl+X2LcAGj5
++7J+tGYGTLzKJmeCeGVNN5ZtJ0T85MYHCKQk1/FElK+Kq5akovXffQHjlnCPcx0NJ
++47NBjlPaFp2gjnAChn79bT4iCjOFZ9avWpqRpeU517UCnY7djOr3fuod/MSQyh3L
++Wuem1tWBAgMBAAECggEBAM4ZXQRs6Kjmo95BHGiAEnSqrlgX+dycjcBq3QPh8KZT
++nifqnf48XhnackENy7tWIjr3DctoUq4mOp8AHt77ijhqfaa4XSg7fwKeK9NLBGC5
++lAXNtAey0o2894/sKrd+LMkgphoYIUnuI4LRaGV56potkj/ZDP/GwTcG/R4SDnTn
++C1Nb05PNTAPQtPZrgPo7TdM6gGsTnFbVrYHQLyg2Sq/osHfF15YohB01esRLCAwb
++EF8JkRC4hWIZoV7BsyQ39232zAJQGGla7+wKFs3kObwh3VnFkQpT94KZnNiZuEfG
++x5pW4Pn3gXgNsftscXsaNe/M9mYZqo//Qw7NvUIvAvECgYEA9AVveyK0HOA06fhh
+++3hUWdvw7Pbrl+e06jO9+bT1RjQMbHKyI60DZyVGuAySN86iChJRoJr5c6xj+iXU
++cR6BVJDjGH5t1tyiK2aYf6hEpK9/j8Z54UiVQ486zPP0PGfT2TO4lBLK+8AUmoaH
++gk21ul8QeVCeCJa/o+xEoRFvzcUCgYEA8FCbbvInrUtNY+9eKaUYoNodsgBVjm5X
++I0YPUL9D4d+1nvupHSV2NVmQl0w1RaJwrNTafrl5LkqjhQbmuWNta6QgfZzSA3LB
++lWXo1Mm0azKdcD3qMGbvn0Q3zU+yGNEgmB/Yju3/NtgYRG6tc+FCWRbPbiCnZWT8
++v3C2Y0XggI0CgYEA2/jCZBgGkTkzue5kNVJlh5OS/aog+pCvL6hxCtarfBuTT3ed
++Sje+p46cz3DVpmUpATc+Si8py7KNdYQAm/BJ2be6X+woi9Xcgo87zWgcaPCjZzId
++0I2jsIE/Gl6XvpRCDrxnGWRPgt3GNP4szbPLrDPiH9oie8+Y9eYYf7G+PZkCgYEA
++nRSzZOPYV4f/QDF4pVQLMykfe/iH9B/fyWjEHg3He19VQmRReIHCMMEoqBziPXAe
++onpHj8oAkeer1wpZyhhZr6CKtFDLXgGm09bXSC/IRMHC81klORovyzU2HHfZfCtG
++WOmIDnU2+0xpIGIP8sztJ3qnf97MTJSkOSadsWo9gwkCgYEAh5AQmJQmck88Dff2
++qIfJIX8d+BDw47BFJ89OmMFjGV8TNB+JO+AV4Vkodg4hxKpLqTFZTTUFgoYfy5u1
++1/BhAjpmCDCrzubCFhx+8VEoM2+2+MmnuQoMAm9+/mD/IidwRaARgXgvEmp7sfdt
++RyWd+p2lYvFkC/jORQtDMY4uW1o=
++-----END PRIVATE KEY-----
++Bag Attributes
++    localKeyID: 02 00 00 00
++    Microsoft CSP Name: Microsoft Strong Cryptographic Provider
++Key Attributes
++    X509v3 Key Usage: 10
++-----BEGIN PRIVATE KEY-----
++MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDlQhPrZwVQYFV4
++FBc0H1iTXYaznMpwZvEITKtXWACzTdguUderEVOkXW3HTi5HvC2rMayt0nqo3zcd
++x1eGiqdjpZQ/wMrkz9wNEM/nNMsXntEwxk0jCVNKB/jz6vf+BOtrSI01SritAGZW
++dpKoTUyztT8C2mA3X6D8g3m4Dd07ltnzxaDqAQIU5jBHh3f/Q14tlPNZWUIiqVTC
++gDxgAe7MDmfs9h3CInTBX1XM5J4UsLTL23/padgeSvP5YF5qr1+0c7Tdftxr2lwA
++N3rLkisf5EiLAToVyJJlgP/exo2I8DaIKe7DZzD3Y1CrurOpkcMKYu5kM1Htlbua
++tDkAa2oDAgMBAAECggEAOvdueS9DyiMlCKAeQb1IQosdQOh0l0ma+FgEABC2CWhd
++0LgjQTBRM6cGO+urcq7/jhdWQ1UuUG4tVn71z7itCi/F/Enhxc2C22d2GhFVpWsn
++giSXJYpZ/mIjkdVfWNo6FRuRmmHwMys1p0qTOS+8qUJWhSzW75csqJZGgeUrAI61
++LBV5F0SGR7dR2xZfy7PeDs9xpD0QivDt5DpsZWPaPvw4QlhdLgw6/YU1h9vtm6ci
++xLjnPRLZ7JMpcQHO8dUDl6FiEI7yQ11BDm253VQAVMddYRPQABn7SpEF8kD/aZVh
++2Clvz61Rz80SKjPUthMPLWMCRp7zB0xDMzt3/1i+tQKBgQD6Ar1/oD3eFnRnpi4u
++n/hdHJtMuXWNfUA4dspNjP6WGOid9sgIeUUdif1XyVJ+afITzvgpWc7nUWIqG2bQ
++WxJ/4q2rjUdvjNXTy1voVungR2jD5WLQ9DKeaTR0yCliWlx4JgdPG7qGI5MMwsr+
++R/PUoUUhGeEX+o/sCSieO3iUrQKBgQDqwBEMvIdhAv/CK2sG3fsKYX8rFT55ZNX3
++Tix9DbUGY3wQColNuI8U1nDlxE9U6VOfT9RPqKelBLCgbzB23kdEJnjSlnqlTxrx
++E+Hkndyf2ckdJAR3XNxoQ6SRLJNBsgoBj/z5tlfZE9/Jc+uh0mYy3e6g6XCVPBcz
++MgoIc+ofbwKBgQCGQhZ1hR30N+bHCozeaPW9OvGDIE0qcEqeh9xYDRFilXnF6pK9
++SjJ9jG7KR8jPLiHb1VebDSl5O1EV/6UU2vNyTc6pw7LLCryBgkGW4aWy1WZDXNnW
++EG1meGS9GghvUss5kmJ2bxOZmV0Mi0brisQ8OWagQf+JGvtS7BAt+Q3l+QKBgAb9
++8YQPmXiqPjPqVyW9Ntz4SnFeEJ5NApJ7IZgX8GxgSjGwHqbR+HEGchZl4ncE/Bii
++qBA3Vcb0fM5KgYcI19aPzsl28fA6ivLjRLcqfIfGVNcpW3iyq13vpdctHLW4N9QU
++FdTaOYOds+ysJziKq8CYG6NvUIshXw+HTgUybqbBAoGBAIIOqcmmtgOClAwipA17
++dAHsI9Sjk+J0+d4JU6o+5TsmhUfUKIjXf5+xqJkJcQZMEe5GhxcCuYkgFicvh4Hz
++kv2H/EU35LcJTqC6KTKZOWIbGcn1cqsvwm3GQJffYDiO8fRZSwCaif2J3F2lfH4Y
++R/fA67HXFSTT+OncdRpY1NOn
++-----END PRIVATE KEY-----
++Bag Attributes: <Empty Attributes>
++subject=/CN=CRP/OU=AzureRT/O=Microsoft Corporation/L=Redmond/ST=WA/C=US
++issuer=/CN=Root Agency
++-----BEGIN CERTIFICATE-----
++MIIB+TCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDDAtSb290
++IEFnZW5jeTAeFw0xOTAyMTUxOTA0MDRaFw0yOTAyMTUxOTE0MDRaMGwxDDAKBgNV
++BAMMA0NSUDEQMA4GA1UECwwHQXp1cmVSVDEeMBwGA1UECgwVTWljcm9zb2Z0IENv
++cnBvcmF0aW9uMRAwDgYDVQQHDAdSZWRtb25kMQswCQYDVQQIDAJXQTELMAkGA1UE
++BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIlPjJXzrRih4C
++k/XsoI01oqo7IUxH3dA2F7vHGXQoIpKCp8Qe6Z6cFfdD8Uj+s+B1BX6hngwzIwjN
++jE/23X3SALVzJVWzX4Y/IEjbgsuao6sOyNyB18wIU9YzZkVGj68fmMlUw3LnhPbe
++eWkufZaJCaLyhQOwlRMbOcn48D6Ys8fccOyXNzpq3rH1OzeQpxS2M8zaJYP4/VZ/
++sf6KRpI7bP+QwyFvNKfhcaO9/gj4kMo9lVGjvDU20FW6g8UVNJCV9N4GO6mOcyqo
++OhuhVfjCNGgW7N1qi0TIVn0/MQM4l4dcT2R7Z/bV9fhMJLjGsy5A4TLAdRrhKUHT
++bzi9HyDvAgMBAAEwDQYJKoZIhvcNAQEFBQADAQA=
++-----END CERTIFICATE-----
++Bag Attributes
++    localKeyID: 01 00 00 00
++subject=/C=US/ST=WASHINGTON/L=Seattle/O=Microsoft/OU=Azure/CN=AnhVo/emailAddress=redacted@microsoft.com
++issuer=/C=US/ST=WASHINGTON/L=Seattle/O=Microsoft/OU=Azure/CN=AnhVo/emailAddress=redacted@microsoft.com
++-----BEGIN CERTIFICATE-----
++MIID7TCCAtWgAwIBAgIJALQS3yMg3R41MA0GCSqGSIb3DQEBCwUAMIGMMQswCQYD
++VQQGEwJVUzETMBEGA1UECAwKV0FTSElOR1RPTjEQMA4GA1UEBwwHU2VhdHRsZTES
++MBAGA1UECgwJTWljcm9zb2Z0MQ4wDAYDVQQLDAVBenVyZTEOMAwGA1UEAwwFQW5o
++Vm8xIjAgBgkqhkiG9w0BCQEWE2FuaHZvQG1pY3Jvc29mdC5jb20wHhcNMTkwMjE0
++MjMxMjQwWhcNMjExMTEwMjMxMjQwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgM
++CldBU0hJTkdUT04xEDAOBgNVBAcMB1NlYXR0bGUxEjAQBgNVBAoMCU1pY3Jvc29m
++dDEOMAwGA1UECwwFQXp1cmUxDjAMBgNVBAMMBUFuaFZvMSIwIAYJKoZIhvcNAQkB
++FhNhbmh2b0BtaWNyb3NvZnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
++CgKCAQEA5RHuX1KsHa0Ez1tqFZRitn99av/FC0/Cpjk8lLy9ET3SUOvb7xznOUNg
++ioNnr4hwti1oRfFpqZ2Y+utUS9BnhRos8L1PDKHm8Oad6KnXIKBqR1bcX/pq+EHF
++hefPxcHs9HQOIXLIplTQc3jaQQVCCjQTEwRvuHeoXEAVABilHRkXAhhMk6ly1NDI
++B48QvSYFaliZfl9i3ABo+eyfrRmBky8yiZngnhlTTeWbSdE/OTGBwikJNfxRJSvi
++quWpKL1330B45Zwj3MdDSeOzQY5T2hadoI5wAoZ+/W0+IgozhWfWr1qakaXlOde1
++Ap2O3Yzq937qHfzEkMody1rnptbVgQIDAQABo1AwTjAdBgNVHQ4EFgQUPvdgLiv3
++pAk4r0QTPZU3PFOZJvgwHwYDVR0jBBgwFoAUPvdgLiv3pAk4r0QTPZU3PFOZJvgw
++DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVUHZT+h9+uCPLTEl5IDg
++kqd9WpzXA7PJd/V+7DeDDTkEd06FIKTWZLfxLVVDjQJnQqubQb//e0zGu1qKbXnX
++R7xqWabGU4eyPeUFWddmt1OHhxKLU3HbJNJJdL6XKiQtpGGUQt/mqNQ/DEr6hhNF
++im5I79iA8H/dXA2gyZrj5Rxea4mtsaYO0mfp1NrFtJpAh2Djy4B1lBXBIv4DWG9e
++mMEwzcLCOZj2cOMA6+mdLMUjYCvIRtnn5MKUHyZX5EmX79wsqMTvVpddlVLB9Kgz
++Qnvft9+SBWh9+F3ip7BsL6Q4Q9v8eHRbnP0ya7ddlgh64uwf9VOfZZdKCnwqudJP
++3g==
++-----END CERTIFICATE-----
++Bag Attributes
++    localKeyID: 02 00 00 00
++subject=/CN=/subscriptions/redacted/resourcegroups/redacted/providers/Microsoft.Compute/virtualMachines/redacted
++issuer=/CN=Microsoft.ManagedIdentity
++-----BEGIN CERTIFICATE-----
++MIIDnTCCAoWgAwIBAgIUB2lauSRccvFkoJybUfIwOUqBN7MwDQYJKoZIhvcNAQEL
++BQAwJDEiMCAGA1UEAxMZTWljcm9zb2Z0Lk1hbmFnZWRJZGVudGl0eTAeFw0xOTAy
++MTUxOTA5MDBaFw0xOTA4MTQxOTA5MDBaMIGUMYGRMIGOBgNVBAMTgYYvc3Vic2Ny
++aXB0aW9ucy8yN2I3NTBjZC1lZDQzLTQyZmQtOTA0NC04ZDc1ZTEyNGFlNTUvcmVz
++b3VyY2Vncm91cHMvYW5oZXh0cmFzc2gvcHJvdmlkZXJzL01pY3Jvc29mdC5Db21w
++dXRlL3ZpcnR1YWxNYWNoaW5lcy9hbmh0ZXN0Y2VydDCCASIwDQYJKoZIhvcNAQEB
++BQADggEPADCCAQoCggEBAOVCE+tnBVBgVXgUFzQfWJNdhrOcynBm8QhMq1dYALNN
++2C5R16sRU6RdbcdOLke8LasxrK3SeqjfNx3HV4aKp2OllD/AyuTP3A0Qz+c0yxee
++0TDGTSMJU0oH+PPq9/4E62tIjTVKuK0AZlZ2kqhNTLO1PwLaYDdfoPyDebgN3TuW
++2fPFoOoBAhTmMEeHd/9DXi2U81lZQiKpVMKAPGAB7swOZ+z2HcIidMFfVczknhSw
++tMvbf+lp2B5K8/lgXmqvX7RztN1+3GvaXAA3esuSKx/kSIsBOhXIkmWA/97GjYjw
++Nogp7sNnMPdjUKu6s6mRwwpi7mQzUe2Vu5q0OQBragMCAwEAAaNWMFQwDgYDVR0P
++AQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYD
++VR0jBBgwFoAUOJvzEsriQWdJBndPrK+Me1bCPjYwDQYJKoZIhvcNAQELBQADggEB
++AFGP/g8o7Hv/to11M0UqfzJuW/AyH9RZtSRcNQFLZUndwweQ6fap8lFsA4REUdqe
++7Quqp5JNNY1XzKLWXMPoheIDH1A8FFXdsAroArzlNs9tO3TlIHE8A7HxEVZEmR4b
++7ZiixmkQPS2RkjEoV/GM6fheBrzuFn7X5kVZyE6cC5sfcebn8xhk3ZcXI0VmpdT0
++jFBsf5IvFCIXXLLhJI4KXc8VMoKFU1jT9na/jyaoGmfwovKj4ib8s2aiXGAp7Y38
++UCmY+bJapWom6Piy5Jzi/p/kzMVdJcSa+GqpuFxBoQYEVs2XYVl7cGu/wPM+NToC
++pkSoWwF1QAnHn0eokR9E1rU=
++-----END CERTIFICATE-----
++Bag Attributes: <Empty Attributes>
++subject=/CN=CRP/OU=AzureRT/O=Microsoft Corporation/L=Redmond/ST=WA/C=US
++issuer=/CN=Root Agency
++-----BEGIN CERTIFICATE-----
++MIIB+TCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDDAtSb290
++IEFnZW5jeTAeFw0xOTAyMTUxOTA0MDRaFw0yOTAyMTUxOTE0MDRaMGwxDDAKBgNV
++BAMMA0NSUDEQMA4GA1UECwwHQXp1cmVSVDEeMBwGA1UECgwVTWljcm9zb2Z0IENv
++cnBvcmF0aW9uMRAwDgYDVQQHDAdSZWRtb25kMQswCQYDVQQIDAJXQTELMAkGA1UE
++BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHU9IDclbKVYVb
++Yuv0+zViX+wTwlKspslmy/uf3hkWLh7pyzyrq70S7qtSW2EGixUPxZS/R8pOLHoi
++nlKF9ILgj0gVTCJsSwnWpXRg3rhZwIVoYMHN50BHS1SqVD0lsWNMXmo76LoJcjmW
++vwIznvj5C/gnhU+K7+c3m7AlCyU2wjwpBAEYj7PQs6l/wTqpEiaqC5NytNBd7qp+
++lYYysVrpa1PFL0Nj4MMZARIfjkiJtL9qDhy9YZeJRQ6q/Fhz0kjvkZnfxixfKF4y
++WzOfhBrAtpF6oOnuYKk3hxjh9KjTTX4/U8zdLojalX09iyHyEjwJKGlGEpzh1aY7
++t5btUyvpAgMBAAEwDQYJKoZIhvcNAQEFBQADAQA=
++-----END CERTIFICATE-----
+diff --git a/tests/data/azure/pubkey_extract_cert b/tests/data/azure/pubkey_extract_cert
+new file mode 100644
+index 0000000..ce9b852
+--- /dev/null
++++ b/tests/data/azure/pubkey_extract_cert
+@@ -0,0 +1,13 @@
++-----BEGIN CERTIFICATE-----
++MIIB+TCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDDAtSb290
++IEFnZW5jeTAeFw0xOTAyMTUxOTA0MDRaFw0yOTAyMTUxOTE0MDRaMGwxDDAKBgNV
++BAMMA0NSUDEQMA4GA1UECwwHQXp1cmVSVDEeMBwGA1UECgwVTWljcm9zb2Z0IENv
++cnBvcmF0aW9uMRAwDgYDVQQHDAdSZWRtb25kMQswCQYDVQQIDAJXQTELMAkGA1UE
++BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHU9IDclbKVYVb
++Yuv0+zViX+wTwlKspslmy/uf3hkWLh7pyzyrq70S7qtSW2EGixUPxZS/R8pOLHoi
++nlKF9ILgj0gVTCJsSwnWpXRg3rhZwIVoYMHN50BHS1SqVD0lsWNMXmo76LoJcjmW
++vwIznvj5C/gnhU+K7+c3m7AlCyU2wjwpBAEYj7PQs6l/wTqpEiaqC5NytNBd7qp+
++lYYysVrpa1PFL0Nj4MMZARIfjkiJtL9qDhy9YZeJRQ6q/Fhz0kjvkZnfxixfKF4y
++WzOfhBrAtpF6oOnuYKk3hxjh9KjTTX4/U8zdLojalX09iyHyEjwJKGlGEpzh1aY7
++t5btUyvpAgMBAAEwDQYJKoZIhvcNAQEFBQADAQA=
++-----END CERTIFICATE-----
+diff --git a/tests/data/azure/pubkey_extract_ssh_key b/tests/data/azure/pubkey_extract_ssh_key
+new file mode 100644
+index 0000000..54d749e
+--- /dev/null
++++ b/tests/data/azure/pubkey_extract_ssh_key
+@@ -0,0 +1 @@
++ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHU9IDclbKVYVbYuv0+zViX+wTwlKspslmy/uf3hkWLh7pyzyrq70S7qtSW2EGixUPxZS/R8pOLHoinlKF9ILgj0gVTCJsSwnWpXRg3rhZwIVoYMHN50BHS1SqVD0lsWNMXmo76LoJcjmWvwIznvj5C/gnhU+K7+c3m7AlCyU2wjwpBAEYj7PQs6l/wTqpEiaqC5NytNBd7qp+lYYysVrpa1PFL0Nj4MMZARIfjkiJtL9qDhy9YZeJRQ6q/Fhz0kjvkZnfxixfKF4yWzOfhBrAtpF6oOnuYKk3hxjh9KjTTX4/U8zdLojalX09iyHyEjwJKGlGEpzh1aY7t5btUyvp
+diff --git a/tests/unittests/test_datasource/test_azure_helper.py b/tests/unittests/test_datasource/test_azure_helper.py
+index b42b073..5eb26eb 100644
+--- a/tests/unittests/test_datasource/test_azure_helper.py
++++ b/tests/unittests/test_datasource/test_azure_helper.py
+@@ -1,11 +1,13 @@
+ # This file is part of cloud-init. See LICENSE file for license information.
+ 
+ import os
++import unittest2
+ from textwrap import dedent
+ 
+ from cloudinit.sources.helpers import azure as azure_helper
+ from cloudinit.tests.helpers import CiTestCase, ExitStack, mock, populate_dir
+ 
++from cloudinit.util import load_file
+ from cloudinit.sources.helpers.azure import WALinuxAgentShim as wa_shim
+ 
+ GOAL_STATE_TEMPLATE = """\
+@@ -287,6 +289,50 @@ class TestOpenSSLManager(CiTestCase):
+         self.assertEqual([mock.call(manager.tmpdir)], del_dir.call_args_list)
+ 
+ 
++class TestOpenSSLManagerActions(CiTestCase):
++
++    def setUp(self):
++        super(TestOpenSSLManagerActions, self).setUp()
++
++        self.allowed_subp = True
++
++    def _data_file(self, name):
++        path = 'tests/data/azure'
++        return os.path.join(path, name)
++
++    @unittest2.skip("todo move to cloud_test")
++    def test_pubkey_extract(self):
++        cert = load_file(self._data_file('pubkey_extract_cert'))
++        good_key = load_file(self._data_file('pubkey_extract_ssh_key'))
++        sslmgr = azure_helper.OpenSSLManager()
++        key = sslmgr._get_ssh_key_from_cert(cert)
++        self.assertEqual(good_key, key)
++
++        good_fingerprint = '073E19D14D1C799224C6A0FD8DDAB6A8BF27D473'
++        fingerprint = sslmgr._get_fingerprint_from_cert(cert)
++        self.assertEqual(good_fingerprint, fingerprint)
++
++    @unittest2.skip("todo move to cloud_test")
++    @mock.patch.object(azure_helper.OpenSSLManager, '_decrypt_certs_from_xml')
++    def test_parse_certificates(self, mock_decrypt_certs):
++        """Azure control plane puts private keys as well as certificates
++           into the Certificates XML object. Make sure only the public keys
++           from certs are extracted and that fingerprints are converted to
++           the form specified in the ovf-env.xml file.
++        """
++        cert_contents = load_file(self._data_file('parse_certificates_pem'))
++        fingerprints = load_file(self._data_file(
++            'parse_certificates_fingerprints')
++        ).splitlines()
++        mock_decrypt_certs.return_value = cert_contents
++        sslmgr = azure_helper.OpenSSLManager()
++        keys_by_fp = sslmgr.parse_certificates('')
++        for fp in keys_by_fp.keys():
++            self.assertIn(fp, fingerprints)
++        for fp in fingerprints:
++            self.assertIn(fp, keys_by_fp)
++
++
+ class TestWALinuxAgentShim(CiTestCase):
+ 
+     def setUp(self):
+@@ -327,18 +373,31 @@ class TestWALinuxAgentShim(CiTestCase):
+ 
+     def test_certificates_used_to_determine_public_keys(self):
+         shim = wa_shim()
+-        data = shim.register_with_azure_and_fetch_data()
++        """if register_with_azure_and_fetch_data() isn't passed some info about
++           the user's public keys, there's no point in even trying to parse
++           the certificates
++        """
++        mypk = [{'fingerprint': 'fp1', 'path': 'path1'},
++                {'fingerprint': 'fp3', 'path': 'path3', 'value': ''}]
++        certs = {'fp1': 'expected-key',
++                 'fp2': 'should-not-be-found',
++                 'fp3': 'expected-no-value-key',
++                 }
++        sslmgr = self.OpenSSLManager.return_value
++        sslmgr.parse_certificates.return_value = certs
++        data = shim.register_with_azure_and_fetch_data(pubkey_info=mypk)
+         self.assertEqual(
+             [mock.call(self.GoalState.return_value.certificates_xml)],
+-            self.OpenSSLManager.return_value.parse_certificates.call_args_list)
+-        self.assertEqual(
+-            self.OpenSSLManager.return_value.parse_certificates.return_value,
+-            data['public-keys'])
++            sslmgr.parse_certificates.call_args_list)
++        self.assertIn('expected-key', data['public-keys'])
++        self.assertIn('expected-no-value-key', data['public-keys'])
++        self.assertNotIn('should-not-be-found', data['public-keys'])
+ 
+     def test_absent_certificates_produces_empty_public_keys(self):
++        mypk = [{'fingerprint': 'fp1', 'path': 'path1'}]
+         self.GoalState.return_value.certificates_xml = None
+         shim = wa_shim()
+-        data = shim.register_with_azure_and_fetch_data()
++        data = shim.register_with_azure_and_fetch_data(pubkey_info=mypk)
+         self.assertEqual([], data['public-keys'])
+ 
+     def test_correct_url_used_for_report_ready(self):
+-- 
+1.8.3.1
+
diff --git a/SOURCES/cloud-init-centos-user.patch b/SOURCES/cloud-init-centos-user.patch
deleted file mode 100644
index 3ebaa88..0000000
--- a/SOURCES/cloud-init-centos-user.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -uNrp cloud-init-18.2.orig/rhel/cloud.cfg cloud-init-18.2/rhel/cloud.cfg
---- cloud-init-18.2.orig/rhel/cloud.cfg	2018-11-04 15:38:13.763701007 +0000
-+++ cloud-init-18.2/rhel/cloud.cfg	2018-11-04 15:41:06.934576619 +0000
-@@ -52,7 +52,7 @@ cloud_final_modules:
- 
- system_info:
-   default_user:
--    name: cloud-user
-+    name: centos
-     lock_passwd: true
-     gecos: Cloud User
-     groups: [wheel, adm, systemd-journal]
diff --git a/SPECS/cloud-init.spec b/SPECS/cloud-init.spec
index 4f3b5a0..34efcd4 100644
--- a/SPECS/cloud-init.spec
+++ b/SPECS/cloud-init.spec
@@ -7,7 +7,7 @@
 
 Name:           cloud-init
 Version:        18.2
-Release:        1%{?dist}.1
+Release:        1%{?dist}.2
 Summary:        Cloud instance init scripts
 
 Group:          System Environment/Base
@@ -33,8 +33,8 @@ Patch11: ci-Azure-Ignore-NTFS-mount-errors-when-checking-ephemer.patch
 Patch12: ci-azure-Add-reported-ready-marker-file.patch
 # For bz#1633282 - [Azure] cloud-init fails to mount /dev/sdb1 after stop(deallocate)&&start VM
 Patch13: ci-Adding-disk_setup-to-rhel-cloud.cfg.patch
-
-Patch9999: cloud-init-centos-user.patch 
+# For bz#1684038 - EMBARGOED cloud-init: wrong list of ssh keys added to authorized_keys [rhel-7.6.z]
+Patch14: ci-azure-Filter-list-of-ssh-keys-pulled-from-fabric.patch
 
 # Deal with noarch -> arch
 # https://bugzilla.redhat.com/show_bug.cgi?id=1067089
@@ -187,6 +187,11 @@ fi
 %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
 
 %changelog
+* Thu Mar 07 2019 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-1.el7_6.2
+- ci-azure-Filter-list-of-ssh-keys-pulled-from-fabric.patch [bz#1684038]
+- Resolves: bz#1684038
+  (EMBARGOED cloud-init: wrong list of ssh keys added to authorized_keys [rhel-7.6.z])
+
 * Thu Sep 27 2018 Miroslav Rezanina <mrezanin@redhat.com> - 18.2-1.el7_6.1
 - ci-Adding-systemd-mount-options-to-wait-for-cloud-init.patch [bz#1633282]
 - ci-Azure-Ignore-NTFS-mount-errors-when-checking-ephemer.patch [bz#1633282]