Please review pull request #162: (#11660) Adds feature SSHFP opened by (grooverdan)

Description:

RFC4255 SSH fingerprints are now facts in the form SSHFP_RSA, SSHFP_DSA,
SSHFP_ECDSA.

This also performs SHA2 and ECDSA that are part of the draft:
http://tools.ietf.org/id/draft-os-ietf-sshfp-ecdsa-sha2

(www.iana.org/assignments/dns-sshfp-rr-parameters).

(#11659) Adds ssh spec
Adds test cases for the ssh fact module. Reworks a bit of the ssh fact
implementation so that the rspec mochs can work.

  • Opened: Wed Feb 01 07:44:09 UTC 2012
  • Based on: puppetlabs:master (d9128eb4830fd6911dd690c0c4a0f5a46a81446a)
  • Requested merge: grooverdan:ticket/11660-sshfp_and_ssh_rspec (2a862191137370cf16c2d284fe60cc9bed0e9cd8)

Diff follows:

diff --git a/lib/facter/ssh.rb b/lib/facter/ssh.rb
index 6aa7e08..23c6578 100644
--- a/lib/facter/ssh.rb
+++ b/lib/facter/ssh.rb
@@ -12,14 +12,14 @@
 ##
 
 ["/etc/ssh","/usr/local/etc/ssh","/etc","/usr/local/etc"].each do |dir|
-  {"SSHDSAKey" => "ssh_host_dsa_key.pub", "SSHRSAKey" => "ssh_host_rsa_key.pub", "SSHECDSAKey" => "ssh_host_ecdsa_key.pub"}.each do |name,file|
+  {"SSHDSAKey" => { :file => "ssh_host_dsa_key.pub", :sshfprrtype => 2 } , "SSHRSAKey" => { :file => "ssh_host_rsa_key.pub", :sshfprrtype => 1 }, "SSHECDSAKey" => { :file => "ssh_host_ecdsa_key.pub", :sshfprrtype => 3 } }.each do |name,key|
     Facter.add(name) do
       setcode do
         value = nil
-        filepath = File.join(dir,file)
+        filepath = File.join(dir,key[:file])
         if FileTest.file?(filepath)
           begin
-            File.open(filepath) { |f| value = f.read.chomp.split(/\s+/)[1] }
+            value = File.read(filepath).chomp.split(/\s+/)[1]
           rescue
             value = nil
           end
@@ -27,5 +27,27 @@
         value
       end # end of proc
     end # end of add
+    Facter.add('SSHFP_' + name[3..-4]) do
+      setcode do
+        ssh = Facter.fact(name).value
+        value = nil
+        if ssh && key[:sshfprrtype]
+          begin
+            require 'digest/sha1'
+            require 'base64'
+            digest = Base64.decode64(ssh)
+            value = 'SSHFP ' + key[:sshfprrtype].to_s + ' 1 ' + Digest::SHA1.hexdigest(digest)
+            begin
+              require 'digest/sha2'
+              value += "\nSSHFP " + key[:sshfprrtype].to_s + ' 2 ' + Digest::SHA256.hexdigest(digest)
+            rescue
+            end
+          rescue
+            value = nil
+          end
+        end # end of sshfp if
+        value
+      end # end of sshfp proc
+    end # end of sshfp add
   end # end of hash each
 end # end of dir each
diff --git a/spec/unit/ssh_spec.rb b/spec/unit/ssh_spec.rb
new file mode 100755
index 0000000..79dc025
--- /dev/null
+++ b/spec/unit/ssh_spec.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+require 'facter/ssh'
+require 'pathname'
+
+describe "SSH fact" do
+
+  before do
+   # We need these facts loaded, but they belong to a file with a
+   # different name, so load the file explicitly.
+   Facter.collection.loader.load(:ssh)
+  end
+   
+    # fingerprints extracted from ssh-keygen -r '' -f /etc/ssh/ssh_host_dsa_key.pub
+  { 'SSHRSAKey' => [ '/usr/local/etc/ssh_host_rsa_key.pub' , "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDrs+KtR8hjasELsyCiiBplUeIi77hEHzTSQt1ALG7N4IgtMg27ZAcq0tl2/O9ZarQuClc903pgionbM9Q98CtAIoqgJwdtsor7ETRmzwrcY/mvI7ne51UzQy4Eh9WrplfpNyg+EVO0FUC7mBcay6JY30QKasePp+g4MkwK5cuTzOCzd9up9KELonlH7tTm2L0YI4HhZugwVoTFulCAZvPICxSk1B/fEKyGSZVfY/UxZNqg9g2Wyvq5u40xQ5eO882UwhB3w4IbmRnPKcyotAcqOJxA7hToMKtEmFct+vjHE8T37w8axE/1X9mdvy8IZbkEBL1cupqqb8a8vU1QTg1z", "SSHFP 1 1 1e4f163a1747d0d1a08a29972c9b5d94ee5705d0\nSSHFP 1 2 4e834c91e423d6085ed6dfb880a59e2f1b04f17c1dc17da07708af67c5ab6045" ],
+    'SSHDSAKey' => [ '/etc/ssh/ssh_host_dsa_key.pub' , "ssh-dss AAAAB3NzaC1kc3MAAACBAKjmRez14aZT6OKhHrsw19s7u30AdghwHFQbtC+L781YjJ3UV0/WQoZ8NaDL4ovuvW23RuO49tsqSNcVHg+PtRiN2iTVAS2h55TFhaPKhTs+i0NH3p3Ze8LNSYuz8uK7a+nTxysz47GYTHiE1ke8KXe5wGKDO1TO/MUgpDbwx72LAAAAFQD9yMJCnZMiKzA7J1RNkwvgCyBKSQAAAIAtWBAsuRM0F2fdCe+F/JmgyryQmRIT5vP8E1ww3t3ywdLHklN7UMkaEKBW/TN/jj1JOGXtZ2v5XI+0VNoNKD/7dnCGzNViRT/jjfyVi6l5UMg4Q52Gv0RXJoBJpxNqFOU2niSsy8hioyE39W6LJYWJtQozGpH/KKgkCSvxBn5hlAAAAIB1yo/YD0kQICOO0KE+UMMaKtV7FwyedFJsxsWYwZfHXGwWskf0d2+lPhd9qwdbmSvySE8Qrlvu+W+X8AipwGkItSnj16ORF8kO3lfABa+7L4BLDtumt7ybjBPcHOy3n28dd07TmMtyWvLjOb0mcxPo+TwDLtHd3L/3C1Dh41jRPg==\n", "SSHFP 2 1 f63dfe8da99f50ffbcfa40a61161cee29d109f70\nSSHFP 2 2 5f57aa6be9baddd71b6049ed5d8639664a7ddf92ce293e3887f16ad0f2d459d9"  ],
+    'SSHECDSAKey' => [ '/etc/ssh_host_ecdsa_key.pub' , 'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIuKHtgXQUIrXSVNKC7uY+ZOF7jjfqYNU7Cb/IncDOZ7jW44dxsfBzRJwS5sTHERjBinJskY87mmwY07NFF5GoE=', "SSHFP 3 1 091a088fd3500ad9e35ce201c5101646cbf6ff98\nSSHFP 3 2 1dd2aa8f29b539337316e2862b28c196c68ffe0af78fccf9e50625635677e50f"]
+  }.each_pair do |fact, data|
+    filename, contents, fingerprint = data
+    pk = /AAAA\S+/.match(contents).to_s
+    it "'#{fact}' should be '#{pk}' based on '#{filename}' contents '#{contents}'" do
+      File.expects(:read).with(filename).at_least_once.returns contents
+      path, file = Pathname.new(filename).split
+      ["/etc/ssh","/usr/local/etc/ssh","/etc","/usr/local/etc"].each do |dir|
+        if dir != path.to_s
+          blockfile =  (Pathname.new(dir) + file).to_s
+          FileTest.expects(:file?).with( blockfile ).at_least(0).returns false
+        end
+      end
+      FileTest.expects(:file?).with( filename ).at_least_once.returns true
+
+      Facter.fact(fact).value.should == pk
+    end
+    fp_fact = 'SSHFP_' + fact[3..-4]
+    it "'#{fp_fact}' should have fingerprint '#{fingerprint}' based on '#{filename}' contents '#{contents}'" do
+      File.expects(:read).with(filename).at_least_once.returns contents
+      path, file = Pathname.new(filename).split
+      ["/etc/ssh","/usr/local/etc/ssh","/etc","/usr/local/etc"].each do |dir|
+        if dir != path.to_s
+          blockfile =  (Pathname.new(dir) + file).to_s
+          FileTest.expects(:file?).with( blockfile ).at_least(0).returns false
+        end
+      end
+      FileTest.expects(:file?).with( filename ).at_least_once.returns true
+
+      Facter.fact(fp_fact).value.should == fingerprint
+    end
+  end
+
+end

    

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to puppet-dev@googlegroups.com.
To unsubscribe from this group, send email to puppet-dev+unsubscr...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to