1require 'rubygems/test_case' 2 3class TestGemSecuritySigner < Gem::TestCase 4 5 ALTERNATE_KEY = load_key 'alternate' 6 CHILD_KEY = load_key 'child' 7 GRANDCHILD_KEY = load_key 'grandchild' 8 9 CHILD_CERT = load_cert 'child' 10 GRANDCHILD_CERT = load_cert 'grandchild' 11 EXPIRED_CERT = load_cert 'expired' 12 13 def setup 14 super 15 16 @cert_file = PUBLIC_CERT 17 end 18 19 def test_initialize 20 signer = Gem::Security::Signer.new nil, nil 21 22 assert_nil signer.key 23 assert_nil signer.cert_chain 24 end 25 26 def test_initialize_cert_chain_empty 27 signer = Gem::Security::Signer.new PUBLIC_KEY, [] 28 29 assert_empty signer.cert_chain 30 end 31 32 def test_initialize_cert_chain_mixed 33 signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT] 34 35 assert_equal [PUBLIC_CERT, CHILD_CERT].map { |c| c.to_pem }, 36 signer.cert_chain.map { |c| c.to_pem } 37 end 38 39 def test_initialize_cert_chain_invalid 40 assert_raises OpenSSL::X509::CertificateError do 41 Gem::Security::Signer.new nil, ['garbage'] 42 end 43 end 44 45 def test_initialize_cert_chain_path 46 signer = Gem::Security::Signer.new nil, [@cert_file] 47 48 assert_equal [PUBLIC_CERT].map { |c| c.to_pem }, 49 signer.cert_chain.map { |c| c.to_pem } 50 end 51 52 def test_initialize_default 53 FileUtils.mkdir_p File.join(Gem.user_home, '.gem') 54 55 private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem' 56 Gem::Security.write PRIVATE_KEY, private_key_path 57 58 public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem' 59 Gem::Security.write PUBLIC_CERT, public_cert_path 60 61 signer = Gem::Security::Signer.new nil, nil 62 63 assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem 64 assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map { |c| c.to_pem } 65 end 66 67 def test_initialize_key_path 68 key_file = PRIVATE_KEY_PATH 69 70 signer = Gem::Security::Signer.new key_file, nil 71 72 assert_equal PRIVATE_KEY.to_s, signer.key.to_s 73 end 74 75 def test_load_cert_chain 76 Gem::Security.trust_dir.trust_cert PUBLIC_CERT 77 78 signer = Gem::Security::Signer.new nil, [] 79 signer.cert_chain.replace [CHILD_CERT] 80 81 signer.load_cert_chain 82 83 assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem], 84 signer.cert_chain.map { |c| c.to_pem } 85 end 86 87 def test_load_cert_chain_broken 88 Gem::Security.trust_dir.trust_cert CHILD_CERT 89 90 signer = Gem::Security::Signer.new nil, [] 91 signer.cert_chain.replace [GRANDCHILD_CERT] 92 93 signer.load_cert_chain 94 95 assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem], 96 signer.cert_chain.map { |c| c.to_pem } 97 end 98 99 def test_sign 100 signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT] 101 102 signature = signer.sign 'hello' 103 104 expected = <<-EXPECTED 105pxSf9ScaghbMNmNp8fqSJj7BiIGpbuoOVYCOM3TJNH9STLILA5z3xKp3gM6w 106VJ7aGsh9KCP485ftS3J9Kb/lKJsyoSkkRSQ5QG+LnyZwMuWlThPDR5o7q6al 1070oxE7vvbbqxFqcT4ojWIkwxJxOluFWmt2D8I6QTX2vLAn09y+Kl66AOrT7R5 108UinbXkz04VwcNvkBqJyko3yWxFKiGNpntZQg4jIw4L+h97EOaZp8H96udzQH 109Da3K0YZ6FsqLDFNnWAFhve3kmpE3CludpvDqH0piq0zKqnOiqAcvICIpPaJP 110c7NM7KZZjj7G++SXjYTEI1PHSA7aFQ/i/+qSUvx+Pg== 111 EXPECTED 112 113 assert_equal expected, [signature].pack('m') 114 end 115 116 def test_sign_expired 117 signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT] 118 119 assert_raises Gem::Security::Exception do 120 signer.sign 'hello' 121 end 122 end 123 124 def test_sign_expired_auto_update 125 FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700 126 127 private_key_path = File.join(Gem.user_home, '.gem', 'gem-private_key.pem') 128 Gem::Security.write PRIVATE_KEY, private_key_path 129 130 cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem' 131 Gem::Security.write EXPIRED_CERT, cert_path 132 133 signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT] 134 135 signer.sign 'hello' 136 137 cert = OpenSSL::X509::Certificate.new File.read cert_path 138 139 refute_equal EXPIRED_CERT.to_pem, cert.to_pem 140 assert_in_delta Time.now, cert.not_before, 10 141 142 expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S" 143 144 expired_path = 145 File.join Gem.user_home, '.gem', "gem-public_cert.pem.expired.#{expiry}" 146 147 assert_path_exists expired_path 148 assert_equal EXPIRED_CERT.to_pem, File.read(expired_path) 149 end 150 151 def test_sign_expired_auto_update_exists 152 FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700 153 154 expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S" 155 expired_path = 156 File.join Gem.user_home, "gem-public_cert.pem.expired.#{expiry}" 157 158 Gem::Security.write EXPIRED_CERT, expired_path 159 160 private_key_path = File.join(Gem.user_home, 'gem-private_key.pem') 161 Gem::Security.write PRIVATE_KEY, private_key_path 162 163 cert_path = File.join Gem.user_home, 'gem-public_cert.pem' 164 Gem::Security.write EXPIRED_CERT, cert_path 165 166 signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT] 167 168 e = assert_raises Gem::Security::Exception do 169 signer.sign 'hello' 170 end 171 172 assert_match %r%certificate /CN=nobody/DC=example not valid%, e.message 173 end 174 175 def test_sign_no_key 176 signer = Gem::Security::Signer.new nil, nil 177 178 assert_nil signer.sign 'stuff' 179 end 180 181 def test_sign_wrong_key 182 signer = Gem::Security::Signer.new ALTERNATE_KEY, [PUBLIC_CERT] 183 184 assert_raises Gem::Security::Exception do 185 signer.sign 'hello' 186 end 187 end 188 189end 190 191