github-pages-health-check 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a1c13045e846da98ad6852b7e252863b2fff17b9
4
+ data.tar.gz: 1aab4822c1e5b5ac88a2ccf94460baf8b8eec981
5
+ SHA512:
6
+ metadata.gz: 397b3e0ccdd3fe29c49a4998fe8ee35799c4632f5c21459ed466689eddcc3f1cd755bde343bacc62c02d9de3f2fadb8bab7c52dd1ef397f9d51caa639dee28bb
7
+ data.tar.gz: 3fed5d309e7bc71fb44cda0dba972e8d63bfdda9234557dd0ee9ca487cdcde039bc14014798ff181c677272c298d796921ebc3c15cfc572650a77248b836acdf
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 GitHub, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ 199.27.128.0/21
2
+ 173.245.48.0/20
3
+ 103.21.244.0/22
4
+ 103.22.200.0/22
5
+ 103.31.4.0/22
6
+ 141.101.64.0/18
7
+ 108.162.192.0/18
8
+ 190.93.240.0/20
9
+ 188.114.96.0/20
10
+ 197.234.240.0/22
11
+ 198.41.128.0/17
12
+ 162.158.0.0/15
13
+ 104.16.0.0/12
@@ -0,0 +1,141 @@
1
+ require 'net/dns'
2
+ require 'net/dns/resolver'
3
+ require 'ipaddr'
4
+ require 'public_suffix'
5
+ require 'singleton'
6
+ require_relative 'github-pages-health-check/version'
7
+ require_relative 'github-pages-health-check/cloudflare'
8
+ require_relative 'github-pages-health-check/error'
9
+ require_relative 'github-pages-health-check/errors/deprecated_ip'
10
+ require_relative 'github-pages-health-check/errors/invalid_a_record'
11
+ require_relative 'github-pages-health-check/errors/invalid_cname'
12
+
13
+ class GitHubPages
14
+ class HealthCheck
15
+
16
+ attr_accessor :domain
17
+
18
+ LEGACY_IP_ADDRESSES = %w[
19
+ 207.97.227.245
20
+ 204.232.175.78
21
+ 199.27.73.133
22
+ ]
23
+
24
+ def initialize(domain)
25
+ @domain = domain
26
+ end
27
+
28
+ def cloudflare_ip?
29
+ dns.all? { |answer| answer.class == Net::DNS::RR::A && CloudFlare.controls_ip?(answer.address) }
30
+ end
31
+
32
+ # Returns an array of DNS answers
33
+ def dns
34
+ @dns ||= Net::DNS::Resolver.start(domain).answer if domain
35
+ rescue Exception => msg
36
+ false
37
+ end
38
+
39
+ # Does this domain have *any* A record that points to the legacy IPs?
40
+ def old_ip_address?
41
+ dns.any? { |answer| answer.class == Net::DNS::RR::A && LEGACY_IP_ADDRESSES.include?(answer.address.to_s) }
42
+ end
43
+
44
+ # Is this domain's first response an A record?
45
+ def a_record?
46
+ dns.first.class == Net::DNS::RR::A
47
+ end
48
+
49
+ # Is this domain's first response a CNAME record?
50
+ def cname_record?
51
+ dns.first.class == Net::DNS::RR::CNAME
52
+ end
53
+
54
+ # Is this a valid domain that PublicSuffix recognizes?
55
+ # Used as an escape hatch to prevent false positves on DNS checkes
56
+ def valid_domain?
57
+ PublicSuffix.valid? domain
58
+ end
59
+
60
+ # Is this domain an SLD, meaning a CNAME would be innapropriate
61
+ def apex_domain?
62
+ PublicSuffix.parse(domain).trd == nil
63
+ rescue
64
+ false
65
+ end
66
+
67
+ # Should the domain be an apex record?
68
+ def should_be_a_record?
69
+ !pages_domain? && apex_domain?
70
+ end
71
+
72
+ # Is the domain's first response a CNAME to a pages domain?
73
+ def pointed_to_github_user_domain?
74
+ dns.first.class == Net::DNS::RR::CNAME && pages_domain?(dns.first.cname.to_s)
75
+ end
76
+
77
+ # Is the given cname a pages domain?
78
+ #
79
+ # domain - the domain to check, generaly the target of a cname
80
+ def pages_domain?(domain = domain)
81
+ !!domain.match(/^[\w-]+\.github\.(io|com)\.?$/i)
82
+ end
83
+
84
+ def to_hash
85
+ {
86
+ :cloudflare_ip? => cloudflare_ip?,
87
+ :old_ip_address? => old_ip_address?,
88
+ :a_record? => a_record?,
89
+ :cname_record? => cname_record?,
90
+ :valid_domain? => valid_domain?,
91
+ :apex_domain? => apex_domain?,
92
+ :should_be_a_record? => should_be_a_record?,
93
+ :pointed_to_github_user_domain? => pointed_to_github_user_domain?,
94
+ :pages_domain? => pages_domain?,
95
+ :valid? => valid?,
96
+ :reason => reason
97
+ }
98
+ end
99
+
100
+ def to_json
101
+ to_hash.to_json
102
+ end
103
+
104
+ # Runs all checks, raises an error if invalid
105
+ def check!
106
+ return unless dns
107
+ return if cloudflare_ip?
108
+ raise DeprecatedIP if a_record? && old_ip_address?
109
+ raise InvalidARecord if valid_domain? && a_record? && !should_be_a_record?
110
+ raise InvalidCNAME if valid_domain? && !apex_domain? && !pointed_to_github_user_domain?
111
+ true
112
+ end
113
+ alias_method :valid!, :check!
114
+
115
+ # Runs all checks, returns true if valid, otherwise false
116
+ def valid?
117
+ check!
118
+ true
119
+ rescue
120
+ false
121
+ end
122
+
123
+ # Return the error, if any
124
+ def reason
125
+ check!
126
+ nil
127
+ rescue GitHubPages::HealthCheck::Error => e
128
+ e
129
+ end
130
+
131
+ def inspect
132
+ "#<GitHubPages::HealthCheck @domain=\"#{domain}\" valid?=#{valid?}>"
133
+ end
134
+
135
+ def to_s
136
+ to_hash.inject(Array.new) do |all, pair|
137
+ all.push pair.join(": ")
138
+ end.join("\n")
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,37 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ class CloudFlare
4
+ include Singleton
5
+
6
+ CONFIG_PATH = File.expand_path("../../config/cloudflare-ips.txt", File.dirname(__FILE__))
7
+
8
+ # Public: Does cloudflare control this address?
9
+ def self.controls_ip?(address)
10
+ instance.controls_ip?(address)
11
+ end
12
+
13
+ # Internal: Create a new cloudflare info instance.
14
+ def initialize(options = {})
15
+ @path = options.fetch(:path) { CONFIG_PATH }
16
+ end
17
+
18
+ # Internal: The path of the config file.
19
+ attr_reader :path
20
+
21
+ # Internal: Does cloudflare control this address?
22
+ def controls_ip?(address)
23
+ ranges.any? { |range| range.include?(address) }
24
+ end
25
+
26
+ # Internal: The IP address ranges that cloudflare controls.
27
+ def ranges
28
+ @ranges ||= load_ranges
29
+ end
30
+
31
+ # Internal: Load IPAddr ranges from #path
32
+ def load_ranges
33
+ File.read(path).lines.map { |line| IPAddr.new(line.chomp) }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ class Error < StandardError
4
+ def message
5
+ "Invalid domain"
6
+ end
7
+ def to_s
8
+ message
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ class DeprecatedIP < Error
4
+ def message
5
+ "A record points to deprecated IP address"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ class InvalidARecord < Error
4
+ def message
5
+ "Should not be an A record"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ class InvalidCNAME < Error
4
+ def message
5
+ "CNAME does not point to GitHub Pages"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class GitHubPages
2
+ class HealthCheck
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: github-pages-health-check
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - GitHub, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-dns
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: public_suffix
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gem-release
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Checks your GitHub Pages site for commons DNS configuration issues.
84
+ email: support@github.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - LICENSE.md
90
+ - config/cloudflare-ips.txt
91
+ - lib/github-pages-health-check.rb
92
+ - lib/github-pages-health-check/cloudflare.rb
93
+ - lib/github-pages-health-check/error.rb
94
+ - lib/github-pages-health-check/errors/deprecated_ip.rb
95
+ - lib/github-pages-health-check/errors/invalid_a_record.rb
96
+ - lib/github-pages-health-check/errors/invalid_cname.rb
97
+ - lib/github-pages-health-check/version.rb
98
+ homepage: https://github.com/github/github-pages-health-check
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.9.3
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.2
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Checks your GitHub Pages site for commons DNS configuration issues
122
+ test_files: []