diff --git a/lib/github-pages-health-check/domain.rb b/lib/github-pages-health-check/domain.rb index 5fc0d3f..e0e2a2e 100644 --- a/lib/github-pages-health-check/domain.rb +++ b/lib/github-pages-health-check/domain.rb @@ -85,7 +85,7 @@ class Domain < Checkable cname_to_fastly? pointed_to_github_pages_ip? non_github_pages_ip_present? pages_domain? served_by_pages? valid? reason valid_domain? https? - enforces_https? https_error https_eligible? caa_error + enforces_https? https_error https_eligible? caa_error dns_zone_soa? ].freeze def self.redundant(host) @@ -164,6 +164,7 @@ def valid_domain? # Is this domain an apex domain, meaning a CNAME would be innapropriate def apex_domain? return @apex_domain if defined?(@apex_domain) + return unless valid_domain? # PublicSuffix.domain pulls out the apex-level domain name. @@ -177,6 +178,20 @@ def apex_domain? :ignore_private => true) == unicode_host end + # Does the domain have an SOA record published? + # + # Callers should be aware that this can return truthy for domains that + # are not apex-level (i.e. subdomain.apex.com). + def dns_zone_soa? + return @soa_records if defined?(@soa_records) + return false unless dns? + + @soa_records = begin + soa_records = dns.select { |answer| answer.type == Dnsruby::Types::SOA } + soa_records.any? + end + end + # Should the domain use an A record? def should_be_a_record? !pages_io_domain? && (apex_domain? || mx_records_present?) @@ -278,7 +293,8 @@ def proxied? Dnsruby::Types::A, Dnsruby::Types::AAAA, Dnsruby::Types::CNAME, - Dnsruby::Types::MX + Dnsruby::Types::MX, + Dnsruby::Types::SOA ].freeze # Returns an array of DNS answers diff --git a/spec/github_pages_health_check/domain_spec.rb b/spec/github_pages_health_check/domain_spec.rb index 81625ea..9bb29b3 100644 --- a/spec/github_pages_health_check/domain_spec.rb +++ b/spec/github_pages_health_check/domain_spec.rb @@ -23,6 +23,9 @@ let(:caa_packet) do Dnsruby::RR.create("#{domain}. 1000 IN CAA 0 issue #{caa_domain.inspect}") end + let(:soa_packet) do + Dnsruby::RR.create("#{domain}. 1000 IN SOA ns.example.com. #{domain.inspect}") + end context "constructor" do it "can handle bare domains" do @@ -257,6 +260,21 @@ end end + ["private.dns.zone"].each do |soa_domain| + context "given #{soa_domain}" do + before(:each) { allow(subject).to receive(:dns) { [soa_packet] } } + let(:domain) { soa_domain } + + it "disallows child zones with an SOA to be an Apex" do + expect(subject.should_be_a_record?).to be_falsy + end + + it "reports whether child zones publish an SOA record" do + expect(subject.dns_zone_soa?).to be_truthy + end + end + end + context "a domain with an MX record" do let(:domain) { "blog.parkermoore.de" } before(:each) do