classify CloudFront distributions

Custom domains commonly CNAME to <dist>.cloudfront.net, so CDN-hosted static
sites were invisible to CNAME discovery. Classify them as AWS/WebApp and probe
https://<dist>.cloudfront.net/ for readability.
This commit is contained in:
StasonJatham committed 2026-09-22 15:21:55 +02:00
1 parent e668429d1e
commit c90d5cc023
3 files changed
+20

No files matched your search

+17
View File
@@ -17,6 +17,23 @@ func aws(p model.Provider, s model.Service, sem model.PublicSemantic, resource,
} }
} }
// classifyCloudFront matches <distribution>.cloudfront.net. Custom domains
// almost always CNAME to a CloudFront distribution, so this is how CDN-hosted
// static sites get discovered via DNS enrichment.
func classifyCloudFront(s *scanner) (model.Match, bool) {
n := s.n
if n != 3 || s.label(n-1) != "net" || s.label(n-2) != "cloudfront" {
return model.Match{}, false
}
return model.Match{
Provider: model.ProviderAWS,
Service: model.ServiceWebApp,
ResourceSpecific: true,
PublicSemantic: model.PublicSemanticPublicEndpoint,
Resource: s.label(0),
}, true
}
func classifyAWS(s *scanner) (model.Match, bool) { func classifyAWS(s *scanner) (model.Match, bool) {
n := s.n n := s.n
if n < 4 || s.label(n-1) != "com" || s.label(n-2) != "amazonaws" { if n < 4 || s.label(n-1) != "com" || s.label(n-2) != "amazonaws" {
+2
View File
@@ -114,6 +114,8 @@ func Classify(host string) (model.Match, bool) {
switch { switch {
case strings.HasSuffix(host, ".amazonaws.com"): case strings.HasSuffix(host, ".amazonaws.com"):
return classifyAWS(&s) return classifyAWS(&s)
case strings.HasSuffix(host, ".cloudfront.net"):
return classifyCloudFront(&s)
case strings.HasSuffix(host, ".core.windows.net"): case strings.HasSuffix(host, ".core.windows.net"):
return classifyAzureCore(&s) return classifyAzureCore(&s)
case strings.HasSuffix(host, ".database.windows.net"): case strings.HasSuffix(host, ".database.windows.net"):
+1
View File
@@ -94,6 +94,7 @@ func TestClassifyMatches(t *testing.T) {
{"project.firebaseio.com", want{model.ProviderGCP, model.ServiceFirebaseDB, "project", "", true, 0}}, {"project.firebaseio.com", want{model.ProviderGCP, model.ServiceFirebaseDB, "project", "", true, 0}},
{"project.europe-west1.firebasedatabase.app", want{model.ProviderGCP, model.ServiceFirebaseDB, "project", "europe-west1", true, 0}}, {"project.europe-west1.firebasedatabase.app", want{model.ProviderGCP, model.ServiceFirebaseDB, "project", "europe-west1", true, 0}},
{"myproject.appspot.com", want{model.ProviderGCP, model.ServiceWebApp, "myproject", "", true, 0}}, {"myproject.appspot.com", want{model.ProviderGCP, model.ServiceWebApp, "myproject", "", true, 0}},
{"d111111abcdef8.cloudfront.net", want{model.ProviderAWS, model.ServiceWebApp, "d111111abcdef8", "", true, model.PublicSemanticPublicEndpoint}},
// Cloudflare // Cloudflare
{"acct.r2.cloudflarestorage.com", want{model.ProviderCloudflare, model.ServiceObjectStorage, "acct", "", true, 0}}, {"acct.r2.cloudflarestorage.com", want{model.ProviderCloudflare, model.ServiceObjectStorage, "acct", "", true, 0}},
{"mybucket.r2.dev", want{model.ProviderCloudflare, model.ServiceObjectStorage, "mybucket", "", true, model.PublicSemanticPublicURL}}, {"mybucket.r2.dev", want{model.ProviderCloudflare, model.ServiceObjectStorage, "mybucket", "", true, model.PublicSemanticPublicURL}},