use gossan_origin::{util, OriginCandidate, ValidationState};
use std::net::IpAddr;
use std::sync::Arc;
use wiremock::{
matchers::{method, path_regex},
Mock, MockServer, ResponseTemplate,
};
#[tokio::test]
async fn validator_confirms_known_good_origin() {
let cdn = MockServer::start().await;
let origin = MockServer::start().await;
Mock::given(method("GET"))
.and(path_regex("/.*"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Hello Origin</title></head><body>Hello Origin</body></html>",
))
.mount(&cdn)
.await;
Mock::given(method("GET"))
.and(path_regex("/.*"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Hello Origin</title></head><body>Hello Origin</body></html>",
))
.mount(&origin)
.await;
let domain = cdn.address().to_string();
let ip: IpAddr = origin.address().ip();
let port: u16 = origin.address().port();
let candidate = OriginCandidate::new_with_port(ip, port, "ssl_cert_ct_log", 70);
let config = gossan_core::Config::default();
let resolver =
Arc::new(hickory_resolver::TokioResolver::builder_tokio().unwrap().build());
let client = gossan_core::ScanClient::from_config(&config, resolver).unwrap();
let validated =
gossan_origin::validator::validate(vec![candidate], &domain, &config, &client).await;
assert_eq!(validated.len(), 1);
assert_eq!(validated[0].validated, ValidationState::Confirmed);
assert_eq!(validated[0].confidence, 100);
assert_eq!(validated[0].method, "validated_origin");
}
#[tokio::test]
async fn validator_rejects_generic_nginx_page() {
let cdn = MockServer::start().await;
let origin = MockServer::start().await;
Mock::given(method("GET"))
.and(path_regex("/.*"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Real Site</title></head><body>Real Site</body></html>",
))
.mount(&cdn)
.await;
Mock::given(method("GET"))
.and(path_regex("/.*"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Welcome to nginx!</title></head><body>Welcome to nginx!</body></html>",
))
.mount(&origin)
.await;
let domain = cdn.address().to_string();
let ip: IpAddr = origin.address().ip();
let candidate = OriginCandidate::new_with_port(ip, origin.address().port(), "dns_history", 85);
let config = gossan_core::Config::default();
let resolver =
Arc::new(hickory_resolver::TokioResolver::builder_tokio().unwrap().build());
let client = gossan_core::ScanClient::from_config(&config, resolver).unwrap();
let validated =
gossan_origin::validator::validate(vec![candidate], &domain, &config, &client).await;
assert_eq!(validated.len(), 1);
assert_eq!(validated[0].validated, ValidationState::Rejected);
}
#[tokio::test]
async fn validator_does_not_confirm_by_404_divergence() {
let cdn = MockServer::start().await;
let origin = MockServer::start().await;
Mock::given(method("GET"))
.and(path_regex("^/$"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Real Site</title></head><body>Real Site</body></html>",
))
.mount(&cdn)
.await;
Mock::given(method("GET"))
.and(path_regex("^/$"))
.respond_with(ResponseTemplate::new(200).set_body_string(
"<html><head><title>Different</title></head><body>Different</body></html>",
))
.mount(&origin)
.await;
Mock::given(method("GET"))
.and(path_regex("/nonexistent-.*"))
.respond_with(
ResponseTemplate::new(404).set_body_string("<html><body>Cloudflare 404</body></html>"),
)
.mount(&cdn)
.await;
Mock::given(method("GET"))
.and(path_regex("/nonexistent-.*"))
.respond_with(
ResponseTemplate::new(404).set_body_string("<html><body>nginx 404</body></html>"),
)
.mount(&origin)
.await;
let domain = cdn.address().to_string();
let ip: IpAddr = origin.address().ip();
let candidate = OriginCandidate::new_with_port(ip, origin.address().port(), "favicon_hash", 80);
let config = gossan_core::Config::default();
let resolver =
Arc::new(hickory_resolver::TokioResolver::builder_tokio().unwrap().build());
let client = gossan_core::ScanClient::from_config(&config, resolver).unwrap();
let validated =
gossan_origin::validator::validate(vec![candidate], &domain, &config, &client).await;
assert_eq!(validated.len(), 1);
assert_eq!(validated[0].validated, ValidationState::Speculative);
assert_ne!(validated[0].method, "validated_origin_404");
}