Skip to content

Commit ba4837c

Browse files
committed
add verify_ssl constructor param, bump version to 11.1.0
Adds a `verify_ssl` keyword argument to the CloudCheck constructor (Rust `with_config` + PyO3 binding) mapping to reqwest's `danger_accept_invalid_certs`. Lets callers disable SSL verification when fetching cloud provider signatures (corporate proxies, custom CAs, SSL-intercepting infrastructure). Defaults to True. Closes #272; unblocks bbot#3226 (ssl_verify_infrastructure passthrough). - src/lib.rs: verify_ssl field; build a reqwest::Client with danger_accept_invalid_certs(!verify_ssl) instead of the default client; warn when verification is disabled - src/python.rs: verify_ssl=None kwarg passed through to with_config - bump 11.0.0 -> 11.1.0 (Cargo.toml, pyproject.toml, lockfiles) - docker-tests.yml: image tags v11.0/v11.0.0 -> v11.1/v11.1.0 - tests: Rust + Python coverage for verify_ssl=False
1 parent b53324b commit ba4837c

8 files changed

Lines changed: 49 additions & 11 deletions

File tree

.github/workflows/docker-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ jobs:
6161
type=sha,prefix=sha-
6262
type=raw,value=latest,enable={{is_default_branch}}
6363
type=raw,value=v11
64-
type=raw,value=v11.0
65-
type=raw,value=v11.0.0
64+
type=raw,value=v11.1
65+
type=raw,value=v11.1.0
6666
6767
- name: Build and push Docker image
6868
uses: docker/build-push-action@v7

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cloudcheck"
3-
version = "11.0.0"
3+
version = "11.1.0"
44
edition = "2024"
55
description = "CloudCheck is a simple Rust tool to check whether an IP address or hostname belongs to a cloud provider."
66
license = "GPL-3.0"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "cloudcheck"
3-
version = "11.0.0"
3+
version = "11.1.0"
44
description = "Detailed database of cloud providers. Instantly look up a domain or IP address"
55
readme = "README.md"
66
requires-python = ">=3.10"

src/lib.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct CloudCheck {
4747
max_retries: u32,
4848
retry_delay_seconds: u64,
4949
force_refresh: bool,
50+
verify_ssl: bool,
5051
}
5152

5253
impl Default for CloudCheck {
@@ -57,14 +58,15 @@ impl Default for CloudCheck {
5758

5859
impl CloudCheck {
5960
pub fn new() -> Self {
60-
Self::with_config(None, None, None, None)
61+
Self::with_config(None, None, None, None, None)
6162
}
6263

6364
pub fn with_config(
6465
signature_url: Option<String>,
6566
max_retries: Option<u32>,
6667
retry_delay_seconds: Option<u64>,
6768
force_refresh: Option<bool>,
69+
verify_ssl: Option<bool>,
6870
) -> Self {
6971
let url = signature_url
7072
.or_else(|| std::env::var("CLOUDCHECK_SIGNATURE_URL").ok())
@@ -78,6 +80,7 @@ impl CloudCheck {
7880
max_retries: max_retries.unwrap_or(10),
7981
retry_delay_seconds: retry_delay_seconds.unwrap_or(1),
8082
force_refresh: force_refresh.unwrap_or(false),
83+
verify_ssl: verify_ssl.unwrap_or(true),
8184
}
8285
}
8386

@@ -95,17 +98,28 @@ impl CloudCheck {
9598
let max_retries = self.max_retries;
9699
let retry_delay_seconds = self.retry_delay_seconds;
97100
log::info!(
98-
"Fetching data from URL: {} (max_retries={}, retry_delay={}s)",
101+
"Fetching data from URL: {} (max_retries={}, retry_delay={}s, verify_ssl={})",
99102
url,
100103
max_retries,
101-
retry_delay_seconds
104+
retry_delay_seconds,
105+
self.verify_ssl
102106
);
103107

108+
if !self.verify_ssl {
109+
log::warn!(
110+
"SSL certificate verification is DISABLED for cloud provider signature fetch"
111+
);
112+
}
113+
let client = reqwest::Client::builder()
114+
.danger_accept_invalid_certs(!self.verify_ssl)
115+
.build()
116+
.map_err(|e| Box::new(e) as Error)?;
117+
104118
let mut last_error = None;
105119

106120
for attempt in 0..=max_retries {
107121
log::info!("Fetch attempt {}/{}", attempt + 1, max_retries + 1);
108-
let result = match reqwest::get(url).await {
122+
let result = match client.get(url).send().await {
109123
Ok(response) => {
110124
let status = response.status();
111125
log::info!(
@@ -479,6 +493,19 @@ mod tests {
479493
);
480494
}
481495

496+
#[tokio::test]
497+
async fn test_lookup_with_ssl_verification_disabled() {
498+
// verify_ssl=false should still succeed against a host with a valid cert
499+
let cloudcheck = CloudCheck::with_config(None, None, None, Some(true), Some(false));
500+
let results = cloudcheck.lookup("8.8.8.8").await.unwrap();
501+
let names: Vec<String> = results.iter().map(|p| p.name.clone()).collect();
502+
assert!(
503+
names.contains(&"Google".to_string()),
504+
"Expected Google in results: {:?}",
505+
names
506+
);
507+
}
508+
482509
#[tokio::test]
483510
async fn test_lookup_windows_blob_domain() {
484511
let cloudcheck = CloudCheck::new();

src/python.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ pub struct CloudCheck {
2020
#[pymethods]
2121
impl CloudCheck {
2222
#[new]
23-
#[pyo3(signature = (signature_url=None, max_retries=None, retry_delay_seconds=None, force_refresh=None))]
23+
#[pyo3(signature = (signature_url=None, max_retries=None, retry_delay_seconds=None, force_refresh=None, verify_ssl=None))]
2424
fn new(
2525
signature_url: Option<String>,
2626
max_retries: Option<u32>,
2727
retry_delay_seconds: Option<u64>,
2828
force_refresh: Option<bool>,
29+
verify_ssl: Option<bool>,
2930
) -> Self {
3031
CloudCheck {
3132
inner: RustCloudCheck::with_config(
3233
signature_url,
3334
max_retries,
3435
retry_delay_seconds,
3536
force_refresh,
37+
verify_ssl,
3638
),
3739
}
3840
}

test_cloudcheck.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ async def test_lookup_amazon_domain():
2020
assert "Amazon" in names, f"Expected Amazon in results: {names}"
2121

2222

23+
@pytest.mark.asyncio
24+
async def test_lookup_with_ssl_verification_disabled():
25+
"""verify_ssl=False should still succeed against a host with a valid cert"""
26+
cloudcheck = CloudCheck(verify_ssl=False)
27+
results = await cloudcheck.lookup("8.8.8.8")
28+
names = [provider["name"] for provider in results]
29+
assert "Google" in names, f"Expected Google in results: {names}"
30+
31+
2332
@pytest.mark.asyncio
2433
async def test_lookup_with_invalid_url():
2534
"""Test that lookup raises RuntimeError with proper message when URL is invalid"""

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)