Escape the password for WinRM certificate XML
This patch escapes the password formatted into a hand-crafted XML for the WinRM certificate mapping. Without it, using passwords such as 'P@ssw&d' will make the WinRM certificate auth plugin to fail with a "The WS-Management service cannot process the request because the XML is invalid.", which is actually true, since the resulting XML is not valid, due to the unescaped and sign. Change-Id: Ia93ab13a4ae5783c1fed5fbb748902bda84e9b65 Closes-Bug: #1441884
This commit is contained in:
parent
a118f260ce
commit
917fef98ce
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
import unittest
|
import unittest
|
||||||
|
from xml.sax import saxutils
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import unittest.mock as mock
|
import unittest.mock as mock
|
||||||
@ -267,10 +268,14 @@ class WinRMConfigTests(unittest.TestCase):
|
|||||||
'subject': 'subject',
|
'subject': 'subject',
|
||||||
'uri': 'fake:\\uri'}
|
'uri': 'fake:\\uri'}
|
||||||
mock_get_xml_bool.return_value = True
|
mock_get_xml_bool.return_value = True
|
||||||
|
fake_password = "Pa&ssw0rd!"
|
||||||
|
fake_username = 'fake user'
|
||||||
|
expected_password = saxutils.escape(fake_password)
|
||||||
|
expected_username = saxutils.escape(fake_username)
|
||||||
|
|
||||||
self._winrmconfig.create_cert_mapping(
|
self._winrmconfig.create_cert_mapping(
|
||||||
issuer='issuer', subject='subject', username='fake user',
|
issuer='issuer', subject='subject', username=fake_username,
|
||||||
password='fake password', uri='fake:\\uri', enabled=True)
|
password=fake_password, uri='fake:\\uri', enabled=True)
|
||||||
|
|
||||||
mock_get_xml_bool.assert_called_once_with(True)
|
mock_get_xml_bool.assert_called_once_with(True)
|
||||||
mock_create_resource.assert_called_once_with(
|
mock_create_resource.assert_called_once_with(
|
||||||
@ -281,8 +286,8 @@ class WinRMConfigTests(unittest.TestCase):
|
|||||||
'<p:Password>%(password)s</p:Password>'
|
'<p:Password>%(password)s</p:Password>'
|
||||||
'<p:UserName>%(username)s</p:UserName>'
|
'<p:UserName>%(username)s</p:UserName>'
|
||||||
'</p:certmapping>' % {'enabled': True,
|
'</p:certmapping>' % {'enabled': True,
|
||||||
'username': 'fake user',
|
'username': expected_username,
|
||||||
'password': 'fake password'})
|
'password': expected_password})
|
||||||
|
|
||||||
@mock.patch('cloudbaseinit.utils.windows.winrmconfig.WinRMConfig.'
|
@mock.patch('cloudbaseinit.utils.windows.winrmconfig.WinRMConfig.'
|
||||||
'_get_resource')
|
'_get_resource')
|
||||||
|
@ -17,6 +17,7 @@ import re
|
|||||||
|
|
||||||
from win32com import client
|
from win32com import client
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
from xml.sax import saxutils
|
||||||
|
|
||||||
|
|
||||||
CBT_HARDENING_LEVEL_NONE = "none"
|
CBT_HARDENING_LEVEL_NONE = "none"
|
||||||
@ -127,6 +128,8 @@ class WinRMConfig(object):
|
|||||||
resource_uri = self._SERVICE_CERTMAPPING_URI % {'issuer': issuer,
|
resource_uri = self._SERVICE_CERTMAPPING_URI % {'issuer': issuer,
|
||||||
'subject': subject,
|
'subject': subject,
|
||||||
'uri': uri}
|
'uri': uri}
|
||||||
|
escaped_password = saxutils.escape(password)
|
||||||
|
escaped_username = saxutils.escape(username)
|
||||||
self._create_resource(
|
self._create_resource(
|
||||||
resource_uri,
|
resource_uri,
|
||||||
'<p:certmapping xmlns:p="http://schemas.microsoft.com/wbem/wsman/'
|
'<p:certmapping xmlns:p="http://schemas.microsoft.com/wbem/wsman/'
|
||||||
@ -135,8 +138,8 @@ class WinRMConfig(object):
|
|||||||
'<p:Password>%(password)s</p:Password>'
|
'<p:Password>%(password)s</p:Password>'
|
||||||
'<p:UserName>%(username)s</p:UserName>'
|
'<p:UserName>%(username)s</p:UserName>'
|
||||||
'</p:certmapping>' % {'enabled': self._get_xml_bool(enabled),
|
'</p:certmapping>' % {'enabled': self._get_xml_bool(enabled),
|
||||||
'username': username,
|
'username': escaped_username,
|
||||||
'password': password})
|
'password': escaped_password})
|
||||||
|
|
||||||
def get_listener(self, protocol=LISTENER_PROTOCOL_HTTPS, address="*"):
|
def get_listener(self, protocol=LISTENER_PROTOCOL_HTTPS, address="*"):
|
||||||
resource_uri = self._SERVICE_LISTENER_URI % {'protocol': protocol,
|
resource_uri = self._SERVICE_LISTENER_URI % {'protocol': protocol,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user