Module: Knowngithub

Defined in:
lib/knowngithub.rb,
lib/knowngithub/version.rb

Constant Summary collapse

VERSION =
'0.2.1'.freeze

Class Method Summary collapse

Class Method Details

.fingerprintsArray<String>

Queries and parses the GitHub help page for the SSH key fingerprints.

Since:

  • 0.1.0



29
30
31
32
33
34
35
# File 'lib/knowngithub.rb', line 29

def self.fingerprints
  pattern = /^(sha256:[a-z0-9\+\/]{43})|([0-9a-f\:]{32,47})$/i
  res = safe_call('https://help.github.com/articles/github-s-ssh-key-fingerprints/')
  output = Nokogiri::HTML(res.body)
  fields = output.xpath('//code')
  fields.children.map(&:content).select { |x| pattern =~ x }
end

.hostHash

Composes a hash with the properties required for composing a known host entry

Raises:

  • (SecurityError)

    If the host keys fail validation or if the https call fails, this will be raised.

Since:

  • 0.1.0



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/knowngithub.rb', line 50

def self.host
  s = session
  if fingerprints.any? { |f| f == s.host_keys.first.fingerprint }
    base64_key = [Net::SSH::Buffer.from(:key, s.host_keys.first).to_s].pack('m*').gsub(/\s/, '')
    return {
      'host_as_string' => s.host_as_string,
      'ssh_type' => s.host_keys.first.ssh_type,
      'base64_key' => base64_key
    }
  else
    raise SecurityError # while this is inappropriate, it sounds cool
  end
end

.known_hostString

Composes a known_hosts entry for the fqdn only

Since:

  • 0.1.0



67
68
69
70
# File 'lib/knowngithub.rb', line 67

def self.known_host
  h = host
  [h['host_as_string'], h['ssh_type'], h['base64_key']].join(' ')
end

.known_hostsArray<String>

Calls the ‘/meta` endpoint on GitHub’s API via a safe https call and composes an array of entries ready for appending to a known_hosts file.

Since:

  • 0.1.0



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/knowngithub.rb', line 75

def self.known_hosts
  h = host
  cidr_ranges = JSON.parse(safe_call('https://api.github.com/meta').body)['git']
  known_hosts = []
  cidr_ranges.each do |range|
    IPAddr.new(range).to_range.to_a.map(&:to_s).each do |ip|
      known_hosts << ["github.com,#{ip}", h['ssh_type'], h['base64_key']].join(' ')
    end
  end
  known_hosts
end

.safe_call(url) ⇒ Net::HTTP

Make a call enforcing the strict use of SSL.

Since:

  • 0.1.0



15
16
17
18
19
20
21
22
23
24
# File 'lib/knowngithub.rb', line 15

def self.safe_call(url)
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  request = Net::HTTP::Get.new(uri.request_uri)

  http.request(request)
end

.sessionNet:SSH

Instantiates a Net::SSH session with GitHub to get the host key and closes it.

Since:

  • 0.1.0



40
41
42
43
44
# File 'lib/knowngithub.rb', line 40

def self.session
  s = Net::SSH::Transport::Session.new('github.com', verify_host_key: true)
  s.close
  s
end