Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions citrix_hypervisor/changelog.d/24909.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply ``tls_verify`` to the XML-RPC session login, previously only applied to the RRD metrics HTTP client.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def _get_master_session(self, session):
def open_session(self):
# type: () -> Dict[str, str]
try:
self.xenserver = ServerProxy(self._base_url)
self.xenserver = ServerProxy(self._base_url, context=self.get_tls_context())
except Exception as e:
self.log.warning(str(e))
return {}
Expand Down
53 changes: 53 additions & 0 deletions citrix_hypervisor/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import os
import ssl
import subprocess
import tempfile
import threading
from xmlrpc.server import SimpleXMLRPCServer

import mock
import pytest

from datadog_checks.dev import docker_run
from datadog_checks.dev.http import MockResponse
from datadog_checks.dev.utils import find_free_port

from . import common

Expand Down Expand Up @@ -52,3 +58,50 @@ def mock_requests_get(url, *args, **kwargs):
def mock_responses():
with mock.patch('requests.Session.get', side_effect=mock_requests_get):
yield


@pytest.fixture
def tls_xenserver():
"""Real HTTPS XML-RPC server backed by a fresh self-signed cert, for TLS behavior tests."""
cert_file = tempfile.NamedTemporaryFile(delete=False, suffix='.crt')
key_file = tempfile.NamedTemporaryFile(delete=False, suffix='.key')
cert_file.close()
key_file.close()
subprocess.run(
[
'openssl',
'req',
'-x509',
'-newkey',
'rsa:2048',
'-keyout',
key_file.name,
'-out',
cert_file.name,
'-days',
'1',
'-nodes',
'-subj',
'/CN=localhost',
],
check=True,
)

port = find_free_port('127.0.0.1')
server = SimpleXMLRPCServer(('127.0.0.1', port), logRequests=False)
server.register_function(lambda username, password: common.SESSION_MASTER, 'session.login_with_password')

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=cert_file.name, keyfile=key_file.name)
server.socket = context.wrap_socket(server.socket, server_side=True)

thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()

yield 'https://localhost:{}'.format(port)

server.shutdown()
server.server_close()
thread.join()
os.unlink(cert_file.name)
os.unlink(key_file.name)
14 changes: 14 additions & 0 deletions citrix_hypervisor/tests/test_citrix_hypervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ def test_open_session(instance, side_effect, expected_session, tag):
assert tag == check._additional_tags


def test_open_session_fails_on_self_signed_cert_by_default(tls_xenserver):
# Regression test: the XML-RPC login used to ignore `tls_verify`, always using Python's
# default verifying SSL context regardless of instance config.
check = CitrixHypervisorCheck('citrix_hypervisor', {}, [{'url': tls_xenserver}])

assert check.open_session() == {}


def test_open_session_succeeds_with_tls_verify_false(tls_xenserver):
check = CitrixHypervisorCheck('citrix_hypervisor', {}, [{'url': tls_xenserver, 'tls_verify': False}])

assert check.open_session() == SESSION_MASTER


@pytest.mark.usefixtures('mock_responses')
@pytest.mark.parametrize('server_type', [pytest.param('master'), pytest.param('slave')])
def test_check(aggregator, dd_run_check, instance, server_type):
Expand Down
Loading