Skip to content

Commit 6b14685

Browse files
dkirov-ddiliakur
andauthored
Allow HTTPS requests to use tls_ciphers (DataDog#20179)
* Add core TLS context changes * Fix base package tests * Run formatter * Turn requests.X mocks into requests.Session.X * Fix airflow unit tests * Run formatter * Add tls_ciphers to TLS Remote fetch_intermediate_certs * Rework Adapter class * Revert TLS protocol change * Fix error in TlsContextAdapter * Stop using TlsContextWrapper in RequestsWrapper * Run formatter * Add test for ciphers, switch naming to SSL and fix hole in persistent session logic * Run formatter * Naming * Naming and test fixes * Add unit test for debugging * Fix consul test * Fix consul config assertion * Fail SSLContext certificate loading with WARNING instead of ERROR * Lint * Change mocks from requests.method to requests.Session.method * Lint * Fix couchbase tests * Fix amazon_msk tests - mocking requests.get because the boto3 lib uses it * Fix apache tests by reworking mock with requests.Session * Fix arangodb tests by updating mock side effect * Fix couch tests by updating mock with requests.Session * Fix remaining occurrences of mock.patch("datadog_checks.base.utils.http.requests") * Fix gitlab tests * Fix harbor tests * Fix hdfs_namenode tests * Fix http_check test * Fix mapreduce tests * Fix proxysql test * Fix spark tests * Fix spark ssl test by fixing REMAPPER * Fix twistlock tests * Fix vault tests * Fix vertica tests * Fix yarn tests * Fix avi_vantage test * Fix http warning test * Extract options to tls_config logic in separate function * Add test for ssl_context initialization * Run linter * Fix falco test * Fix `tls_verify` parsing in SSL context creation logic * Add tests with custom server * Fix request method use * Fixing vsphere tests WIP * Fix vsphere tests * Run formatter * Fix vault tests again * Try fixing amazon_msk tests as they do not fail locally * Try fixing amazon_msk tests as they do not fail locally 2 * Run formatter * Try fixing amazon_msk tests as they do not fail locally 3 * Try fixing amazon_msk tests as they do not fail locally 4 * Try fixing amazon_msk tests as they do not fail locally 5 * Try fixing amazon_msk tests as they do not fail locally 6 * Try fixing http_check test * Fix datadog_checks_dev test * Fix datadog_checks_base test * Try fixing tls_cipher test * Run formatter * Fix datadog_checks_base test 2 * Fix datadog_checks_base test 3 * Run formatter * Fix datadog_checks_base test final * Add changelog * Update base.py * Use create_ssl_context in tls_remote * Apply suggestions from code review Co-authored-by: Ilia Kurenkov <ilia.kurenkov@datadoghq.com> * Add _mount_new_ssl_adapter method * Implement suggestions from code review * Use ChainMaps * Implement caching for HTTPS adapters * Use pydantic for TlsConfig class * Minor improvements and fixes * Add tests * Run formatter * Allow tls_ca_cert to be bool for legacy compatibility * Fix datadog_checks_base tests * Fix default tls_verify value in go_expvar * Fix proxysql and vertica tests * Run formatter and fix linting * Add go_expvar changelog * Fix base tests * Fix intermediate_certs_tests for windows * Fix intermediate_certs_tests for windows in a better way * tweak how we create session and mount adapter * Remove unused func and mounting https adapters when creating session * Mount default https adapter in property * Apply suggestions from code review Co-authored-by: Ilia Kurenkov <ilia.kurenkov@datadoghq.com> * Update datadog_checks_base/datadog_checks/base/utils/http.py Co-authored-by: Ilia Kurenkov <ilia.kurenkov@datadoghq.com> * Add TypeError for wrong TLS option types * Run formatter * Fix kubelet typo in test * Run the ACTUAL formatter * remove shallow network module * Update datadog_checks_base/datadog_checks/base/utils/http.py Co-authored-by: Ilia Kurenkov <ilia.kurenkov@datadoghq.com> * Make SSLContextAdapter private and simplify super() calls --------- Co-authored-by: Ilia Kurenkov <ilia.kurenkov@datadoghq.com>
1 parent dc2258e commit 6b14685

119 files changed

Lines changed: 1116 additions & 639 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

airflow/tests/test_unit.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ def test_service_checks_healthy_exp(aggregator, json_resp, expected_healthy_stat
3131
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
3232

3333
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value=None):
34-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
34+
mock_session = mock.MagicMock()
35+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=mock_session):
3536
mock_resp = mock.MagicMock(status_code=200)
3637
mock_resp.json.side_effect = [json_resp]
37-
req.get.return_value = mock_resp
38+
mock_session.get.return_value = mock_resp
3839

3940
check.check(None)
4041

@@ -59,13 +60,14 @@ def test_service_checks_healthy_stable(
5960
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
6061

6162
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
62-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
63+
mock_session = mock.MagicMock()
64+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=mock_session):
6365
mock_resp = mock.MagicMock(status_code=200)
6466
mock_resp.json.side_effect = [
6567
{'metadatabase': {'status': metadb_status}, 'scheduler': {'status': scheduler_status}},
6668
{'status': 'OK'},
6769
]
68-
req.get.return_value = mock_resp
70+
mock_session.get.return_value = mock_resp
6971

7072
check.check(None)
7173

@@ -80,7 +82,8 @@ def test_dag_total_tasks(aggregator, task_instance):
8082
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
8183

8284
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
83-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
85+
req = mock.MagicMock()
86+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
8487
mock_resp = mock.MagicMock(status_code=200)
8588
mock_resp.json.side_effect = [
8689
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
@@ -98,7 +101,8 @@ def test_dag_task_ongoing_duration(aggregator, task_instance):
98101
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
99102

100103
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
101-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
104+
req = mock.MagicMock()
105+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
102106
mock_resp = mock.MagicMock(status_code=200)
103107
mock_resp.json.side_effect = [
104108
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},
@@ -142,7 +146,8 @@ def test_config_collect_ongoing_duration(collect_ongoing_duration, should_call_m
142146
check = AirflowCheck('airflow', common.FULL_CONFIG, [instance])
143147

144148
with mock.patch('datadog_checks.airflow.airflow.AirflowCheck._get_version', return_value='2.6.2'):
145-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
149+
req = mock.MagicMock()
150+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
146151
mock_resp = mock.MagicMock(status_code=200)
147152
mock_resp.json.side_effect = [
148153
{'metadatabase': {'status': 'healthy'}, 'scheduler': {'status': 'healthy'}},

amazon_msk/tests/conftest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ def mock_requests_get(url, *args, **kwargs):
3232

3333
@pytest.fixture
3434
def mock_data():
35-
with mock.patch('requests.get', side_effect=mock_requests_get, autospec=True):
35+
# Mock requests.get because it is used internally within boto3
36+
with (
37+
mock.patch('requests.get', side_effect=mock_requests_get, autospec=True),
38+
mock.patch('requests.Session.get', side_effect=mock_requests_get),
39+
):
3640
yield
3741

3842

apache/tests/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def check_status_page_ready():
4949

5050
@pytest.fixture
5151
def mock_hide_server_version():
52-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
52+
req = mock.MagicMock()
53+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=req):
5354

5455
def mock_requests_get_headers(*args, **kwargs):
5556
r = requests.get(*args, **kwargs)

arangodb/tests/test_arangodb.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ def test_invalid_endpoint(aggregator, instance_invalid_endpoint, dd_run_check):
5252
def test_check(instance, dd_run_check, aggregator, tag_condition, base_tags):
5353
check = ArangodbCheck('arangodb', {}, [instance])
5454

55-
def mock_requests_get(url, *args, **kwargs):
55+
def mock_requests_get(session, url, *args, **kwargs):
5656
fixture = url.rsplit('/', 1)[-1]
5757
return MockResponse(file_path=os.path.join(os.path.dirname(__file__), 'fixtures', tag_condition, fixture))
5858

59-
with mock.patch('requests.get', side_effect=mock_requests_get, autospec=True):
59+
with mock.patch('requests.Session.get', side_effect=mock_requests_get, autospec=True):
6060
dd_run_check(check)
6161

6262
aggregator.assert_service_check(

avi_vantage/tests/conftest.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,31 @@ def _get_metrics(metrics_folder=NO_TENANT_METRICS_FOLDER, endpoint=None):
5858

5959
@pytest.fixture
6060
def mock_client():
61-
with mock.patch('datadog_checks.base.utils.http.requests') as req:
61+
def mock_get(url: AnyStr, *__: Any, **___: Any):
62+
parsed = urlparse(url)
63+
resource = [part for part in parsed.path.split('/') if len(part) > 0][-1]
64+
query_params = parsed.query
6265

63-
def get(url: AnyStr, *_: Any, **__: Any):
64-
parsed = urlparse(url)
65-
resource = [part for part in parsed.path.split('/') if len(part) > 0][-1]
66-
query_params = parsed.query
66+
path = {}
6767

68-
path = {}
69-
70-
path['tenant=admin'] = ADMIN_TENANT_METRICS_FOLDER
71-
path['tenant=admin%2Ctenant_a%2Ctenant_b'] = MULTIPLE_TENANTS_METRICS_FOLDER
72-
73-
if query_params:
74-
return MockResponse(
75-
file_path=os.path.join(HERE, 'compose', 'fixtures', path[query_params], f'{resource}_metrics')
76-
)
68+
path['tenant=admin'] = ADMIN_TENANT_METRICS_FOLDER
69+
path['tenant=admin%2Ctenant_a%2Ctenant_b'] = MULTIPLE_TENANTS_METRICS_FOLDER
7770

71+
if query_params:
7872
return MockResponse(
79-
file_path=os.path.join(HERE, 'compose', 'fixtures', NO_TENANT_METRICS_FOLDER, f'{resource}_metrics')
73+
file_path=os.path.join(HERE, 'compose', 'fixtures', path[query_params], f'{resource}_metrics')
8074
)
8175

82-
req.Session = mock.MagicMock(return_value=mock.MagicMock(get=get))
83-
yield
76+
return MockResponse(
77+
file_path=os.path.join(HERE, 'compose', 'fixtures', NO_TENANT_METRICS_FOLDER, f'{resource}_metrics')
78+
)
79+
80+
def mock_post(url: AnyStr, *__: Any, **___: Any):
81+
return mock.MagicMock(status_code=200, content=b'{"results": []}')
82+
83+
with mock.patch('datadog_checks.base.utils.http.RequestsWrapper.get', side_effect=mock_get):
84+
with mock.patch('datadog_checks.base.utils.http.RequestsWrapper.post', new=mock_post):
85+
yield
8486

8587

8688
@pytest.fixture(scope='session')

cert_manager/tests/test_cert_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@pytest.fixture()
1616
def error_metrics():
1717
with mock.patch(
18-
'requests.get',
18+
'requests.Session.get',
1919
return_value=mock.MagicMock(status_code=502, headers={'Content-Type': "text/plain"}),
2020
):
2121
yield
@@ -34,7 +34,7 @@ def test_check(aggregator, dd_run_check):
3434
def mock_requests_get(url, *args, **kwargs):
3535
return MockResponse(file_path=os.path.join(os.path.dirname(__file__), 'fixtures', 'cert_manager.txt'))
3636

37-
with mock.patch('requests.get', side_effect=mock_requests_get, autospec=True):
37+
with mock.patch('requests.Session.get', side_effect=mock_requests_get, autospec=True):
3838
dd_run_check(check)
3939

4040
expected_metrics = dict(CERT_METRICS)

cilium/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def mock_agent_data():
203203
with open(f_name, "r") as f:
204204
text_data = f.read()
205205
with mock.patch(
206-
"requests.get",
206+
'requests.Session.get',
207207
return_value=mock.MagicMock(
208208
status_code=200, iter_lines=lambda **kwargs: text_data.split("\n"), headers={"Content-Type": "text/plain"}
209209
),
@@ -217,7 +217,7 @@ def mock_operator_data():
217217
with open(f_name, "r") as f:
218218
text_data = f.read()
219219
with mock.patch(
220-
"requests.get",
220+
'requests.Session.get',
221221
return_value=mock.MagicMock(
222222
status_code=200, iter_lines=lambda **kwargs: text_data.split("\n"), headers={"Content-Type": "text/plain"}
223223
),

citrix_hypervisor/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ def mock_requests_get(url, *args, **kwargs):
5050

5151
@pytest.fixture
5252
def mock_responses():
53-
with mock.patch('requests.get', side_effect=mock_requests_get):
53+
with mock.patch('requests.Session.get', side_effect=mock_requests_get):
5454
yield

consul/tests/test_unit.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def test_get_nodes_with_service_critical(aggregator):
158158
def test_consul_request(aggregator, instance, mocker):
159159
consul_check = ConsulCheck(common.CHECK_NAME, {}, [consul_mocks.MOCK_CONFIG])
160160
mocker.patch("datadog_checks.base.utils.serialization.json.loads")
161-
with mock.patch("datadog_checks.consul.consul.requests.get") as mock_requests_get:
161+
with mock.patch("datadog_checks.consul.consul.requests.Session.get") as mock_requests_get:
162162
consul_check.consul_request("foo")
163163
url = "{}/{}".format(instance["url"], "foo")
164164
aggregator.assert_service_check("consul.can_connect", ConsulCheck.OK, tags=["url:{}".format(url)], count=1)
@@ -549,8 +549,10 @@ def test_config(test_case, extra_config, expected_http_kwargs, mocker):
549549
check = ConsulCheck(common.CHECK_NAME, {}, instances=[instance])
550550
mocker.patch("datadog_checks.base.utils.serialization.json.loads")
551551

552-
with mock.patch('datadog_checks.base.utils.http.requests') as r:
553-
r.get.return_value = mock.MagicMock(status_code=200)
552+
with mock.patch('datadog_checks.base.utils.http.requests.Session') as session:
553+
mock_session = mock.MagicMock()
554+
session.return_value = mock_session
555+
mock_session.get.return_value = mock.MagicMock(status_code=200)
554556

555557
check.check(None)
556558

@@ -564,4 +566,4 @@ def test_config(test_case, extra_config, expected_http_kwargs, mocker):
564566
'allow_redirects': mock.ANY,
565567
}
566568
http_wargs.update(expected_http_kwargs)
567-
r.get.assert_called_with('/v1/status/leader', **http_wargs)
569+
mock_session.get.assert_called_with('/v1/status/leader', **http_wargs)

couch/tests/test_unit.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ def test_config(test_case, extra_config, expected_http_kwargs):
3030
instance.update(extra_config)
3131
check = CouchDb(common.CHECK_NAME, {}, instances=[instance])
3232

33-
with mock.patch('datadog_checks.base.utils.http.requests') as r:
33+
r = mock.MagicMock()
34+
with mock.patch('datadog_checks.base.utils.http.requests.Session', return_value=r):
3435
r.get.return_value = mock.MagicMock(status_code=200, content='{}')
3536

3637
check.check(instance)

0 commit comments

Comments
 (0)