appmap 0.33.0 → 0.34.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -56,10 +56,12 @@ class CLITest < Minitest::Test
56
56
  Class frequency:
57
57
  ----------------
58
58
  1 Main
59
+ 1 IO
59
60
 
60
61
  Method frequency:
61
62
  ----------------
62
63
  1 Main.say_hello
64
+ 1 IO#write
63
65
  OUTPUT
64
66
  end
65
67
 
@@ -80,12 +82,20 @@ class CLITest < Minitest::Test
80
82
  {
81
83
  "name": "Main",
82
84
  "count": 1
85
+ },
86
+ {
87
+ "name": "IO",
88
+ "count": 1
83
89
  }
84
90
  ],
85
91
  "method_frequency": [
86
92
  {
87
93
  "name": "Main.say_hello",
88
94
  "count": 1
95
+ },
96
+ {
97
+ "name": "IO#write",
98
+ "count": 1
89
99
  }
90
100
  ]
91
101
  }
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'appmap', git: 'applandinc/appmap-ruby', branch: `git rev-parse --abbrev-ref HEAD`.strip
@@ -0,0 +1,3 @@
1
+ name: openssl_recorder
2
+ packages:
3
+ - path: lib
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ # From the manual page https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL.html
4
+
5
+ require 'openssl'
6
+
7
+ module Example
8
+ def Example.sign
9
+ ca_key = OpenSSL::PKey::RSA.new 2048
10
+ pass_phrase = 'my secure pass phrase goes here'
11
+
12
+ cipher = OpenSSL::Cipher.new 'AES-256-CBC'
13
+
14
+ open 'tmp/ca_key.pem', 'w', 0644 do |io|
15
+ io.write ca_key.export(cipher, pass_phrase)
16
+ end
17
+
18
+ ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
19
+
20
+ ca_cert = OpenSSL::X509::Certificate.new
21
+ ca_cert.serial = 0
22
+ ca_cert.version = 2
23
+ ca_cert.not_before = Time.now
24
+ ca_cert.not_after = Time.now + 86400
25
+
26
+ ca_cert.public_key = ca_key.public_key
27
+ ca_cert.subject = ca_name
28
+ ca_cert.issuer = ca_name
29
+
30
+ extension_factory = OpenSSL::X509::ExtensionFactory.new
31
+ extension_factory.subject_certificate = ca_cert
32
+ extension_factory.issuer_certificate = ca_cert
33
+
34
+ ca_cert.add_extension extension_factory.create_extension('subjectKeyIdentifier', 'hash')
35
+ ca_cert.add_extension extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
36
+
37
+ ca_cert.add_extension extension_factory.create_extension(
38
+ 'keyUsage', 'cRLSign,keyCertSign', true)
39
+
40
+ ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
41
+
42
+ open 'tmp/ca_cert.pem', 'w' do |io|
43
+ io.write ca_cert.to_pem
44
+ end
45
+
46
+ csr = OpenSSL::X509::Request.new
47
+ csr.version = 0
48
+ csr.subject = OpenSSL::X509::Name.new([ ['CN', 'the name to sign', OpenSSL::ASN1::UTF8STRING] ])
49
+ csr.public_key = ca_key.public_key
50
+ csr.sign ca_key, OpenSSL::Digest::SHA1.new
51
+
52
+ open 'tmp/csr.pem', 'w' do |io|
53
+ io.write csr.to_pem
54
+ end
55
+
56
+ csr = OpenSSL::X509::Request.new File.read 'tmp/csr.pem'
57
+
58
+ raise 'CSR can not be verified' unless csr.verify csr.public_key
59
+
60
+ csr_cert = OpenSSL::X509::Certificate.new
61
+ csr_cert.serial = 0
62
+ csr_cert.version = 2
63
+ csr_cert.not_before = Time.now
64
+ csr_cert.not_after = Time.now + 600
65
+
66
+ csr_cert.subject = csr.subject
67
+ csr_cert.public_key = csr.public_key
68
+ csr_cert.issuer = ca_cert.subject
69
+
70
+ extension_factory = OpenSSL::X509::ExtensionFactory.new
71
+ extension_factory.subject_certificate = csr_cert
72
+ extension_factory.issuer_certificate = ca_cert
73
+
74
+ csr_cert.add_extension extension_factory.create_extension('basicConstraints', 'CA:FALSE')
75
+
76
+ csr_cert.add_extension extension_factory.create_extension(
77
+ 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
78
+
79
+ csr_cert.add_extension extension_factory.create_extension('subjectKeyIdentifier', 'hash')
80
+
81
+ csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
82
+
83
+ 'tmp/csr_cert.pem'.tap do |fname|
84
+ open fname, 'w' do |io|
85
+ io.write csr_cert.to_pem
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ if __FILE__ == $0
92
+ cert_file = Example.sign
93
+ puts "Wrote cert file #{cert_file}"
94
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # From the manual page https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL.html
4
+
5
+ require 'openssl'
6
+
7
+ module Example
8
+ def Example.encrypt
9
+ cipher = OpenSSL::Cipher.new 'AES-256-CBC'
10
+ cipher.encrypt
11
+ iv = cipher.random_iv
12
+
13
+ pwd = 'some hopefully not to easily guessable password'
14
+ salt = OpenSSL::Random.random_bytes 16
15
+ iter = 20000
16
+ key_len = cipher.key_len
17
+ digest = OpenSSL::Digest::SHA256.new
18
+
19
+ key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
20
+ cipher.key = key
21
+
22
+ document = 'the document'
23
+
24
+ encrypted = cipher.update document
25
+ encrypted << cipher.final
26
+ encrypted
27
+ end
28
+ end
29
+
30
+ if __FILE__ == $0
31
+ ciphertext = Example.encrypt
32
+ require 'base64'
33
+ puts "Computed ciphertext #{Base64.urlsafe_encode64(ciphertext)}"
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # From the manual page https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL.html
4
+
5
+ require 'appmap'
6
+ require 'openssl'
7
+ require 'openssl/digest'
8
+
9
+ module Example
10
+ def Example.sign
11
+ key = OpenSSL::PKey::RSA.new 2048
12
+
13
+ document = 'the document'
14
+
15
+ digest = OpenSSL::Digest::SHA256.new
16
+ key.sign digest, document
17
+ end
18
+ end
19
+
20
+ if __FILE__ == $0
21
+ appmap = AppMap.record do
22
+ Example.sign
23
+ puts 'Computed signature'
24
+ end
25
+ appmap['metadata'] = [ 'recorder' => __FILE__ ]
26
+
27
+ File.write('appmap.json', JSON.generate(appmap))
28
+ end
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'test_helper'
5
+ require 'English'
6
+
7
+ class OpenSSLTest < Minitest::Test
8
+ def perform_test(test_name)
9
+ Bundler.with_clean_env do
10
+ Dir.chdir 'test/fixtures/openssl_recorder' do
11
+ FileUtils.rm_rf 'tmp'
12
+ system 'bundle config --local local.appmap ../../..'
13
+ system 'bundle'
14
+ system({ 'APPMAP' => 'true', 'DEBUG' => 'true' }, %(bundle exec ruby lib/openssl_#{test_name}.rb))
15
+
16
+ yield
17
+ end
18
+ end
19
+ end
20
+
21
+ def test_key_sign
22
+ perform_test 'key_sign' do
23
+ appmap_file = 'appmap.json'
24
+
25
+ assert File.file?(appmap_file), 'appmap output file does not exist'
26
+ appmap = JSON.parse(File.read(appmap_file))
27
+ assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
28
+ assert_equal [ { 'recorder' => 'lib/openssl_key_sign.rb' } ], appmap['metadata']
29
+ assert_equal JSON.parse(<<~JSON), appmap['classMap']
30
+ [
31
+ {
32
+ "name": "lib",
33
+ "type": "package",
34
+ "children": [
35
+ {
36
+ "name": "Example",
37
+ "type": "class",
38
+ "children": [
39
+ {
40
+ "name": "sign",
41
+ "type": "function",
42
+ "location": "lib/openssl_key_sign.rb:10",
43
+ "static": true
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "name": "openssl",
51
+ "type": "package",
52
+ "children": [
53
+ {
54
+ "name": "OpenSSL",
55
+ "type": "class",
56
+ "children": [
57
+ {
58
+ "name": "PKey",
59
+ "type": "class",
60
+ "children": [
61
+ {
62
+ "name": "PKey",
63
+ "type": "class",
64
+ "children": [
65
+ {
66
+ "name": "sign",
67
+ "type": "function",
68
+ "location": "OpenSSL::PKey::PKey#sign",
69
+ "static": false,
70
+ "labels": [
71
+ "security",
72
+ "crypto"
73
+ ]
74
+ }
75
+ ]
76
+ }
77
+ ]
78
+ }
79
+ ]
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ "name": "io",
85
+ "type": "package",
86
+ "children": [
87
+ {
88
+ "name": "IO",
89
+ "type": "class",
90
+ "children": [
91
+ {
92
+ "name": "write",
93
+ "type": "function",
94
+ "location": "IO#write",
95
+ "static": false,
96
+ "labels": [
97
+ "io"
98
+ ]
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ }
104
+ ]
105
+ JSON
106
+ sanitized_events = appmap['events'].map(&:deep_symbolize_keys).map(&AppMap::Util.method(:sanitize_event)).map do |event|
107
+ delete_value = ->(obj) { (obj || {}).delete(:value) }
108
+ delete_value.call(event[:receiver])
109
+ delete_value.call(event[:return_value])
110
+ event
111
+ end
112
+
113
+ diff = Diffy::Diff.new(<<~JSON.strip, JSON.pretty_generate(sanitized_events).strip)
114
+ [
115
+ {
116
+ "id": 1,
117
+ "event": "call",
118
+ "defined_class": "Example",
119
+ "method_id": "sign",
120
+ "path": "lib/openssl_key_sign.rb",
121
+ "lineno": 10,
122
+ "static": true,
123
+ "parameters": [
124
+
125
+ ],
126
+ "receiver": {
127
+ "class": "Module"
128
+ }
129
+ },
130
+ {
131
+ "id": 2,
132
+ "event": "call",
133
+ "defined_class": "OpenSSL::PKey::PKey",
134
+ "method_id": "sign",
135
+ "path": "OpenSSL::PKey::PKey#sign",
136
+ "static": false,
137
+ "parameters": [
138
+ {
139
+ "name": "arg",
140
+ "class": "OpenSSL::Digest::SHA256",
141
+ "value": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
142
+ "kind": "req"
143
+ },
144
+ {
145
+ "name": "arg",
146
+ "class": "String",
147
+ "value": "the document",
148
+ "kind": "req"
149
+ }
150
+ ],
151
+ "receiver": {
152
+ "class": "OpenSSL::PKey::RSA"
153
+ }
154
+ },
155
+ {
156
+ "id": 3,
157
+ "event": "return",
158
+ "parent_id": 2,
159
+ "return_value": {
160
+ "class": "String"
161
+ }
162
+ },
163
+ {
164
+ "id": 4,
165
+ "event": "return",
166
+ "parent_id": 1,
167
+ "return_value": {
168
+ "class": "String"
169
+ }
170
+ },
171
+ {
172
+ "id": 5,
173
+ "event": "call",
174
+ "defined_class": "IO",
175
+ "method_id": "write",
176
+ "path": "IO#write",
177
+ "static": false,
178
+ "parameters": [
179
+ {
180
+ "name": "arg",
181
+ "class": "String",
182
+ "value": "Computed signature",
183
+ "kind": "rest"
184
+ }
185
+ ],
186
+ "receiver": {
187
+ "class": "IO"
188
+ }
189
+ },
190
+ {
191
+ "id": 6,
192
+ "event": "return",
193
+ "parent_id": 5,
194
+ "return_value": {
195
+ "class": "Integer"
196
+ }
197
+ }
198
+ ]
199
+ JSON
200
+ assert_equal '', diff.to_s
201
+ end
202
+ end
203
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.33.0
4
+ version: 0.34.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-15 00:00:00.000000000 Z
11
+ date: 2020-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake-compiler
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: climate_control
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -248,16 +262,46 @@ dependencies:
248
262
  - - "~>"
249
263
  - !ruby/object:Gem::Version
250
264
  version: '4.0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: timecop
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: hashie
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
251
293
  description:
252
294
  email:
253
295
  - kgilpin@gmail.com
254
296
  executables:
255
297
  - appmap
256
- extensions: []
298
+ extensions:
299
+ - ext/appmap/extconf.rb
257
300
  extra_rdoc_files: []
258
301
  files:
259
302
  - ".dockerignore"
260
303
  - ".gitignore"
304
+ - ".rbenv-gemsets"
261
305
  - ".rubocop.yml"
262
306
  - ".ruby-version"
263
307
  - ".travis.yml"
@@ -277,6 +321,8 @@ files:
277
321
  - examples/mock_webapp/lib/mock_webapp/request.rb
278
322
  - examples/mock_webapp/lib/mock_webapp/user.rb
279
323
  - exe/appmap
324
+ - ext/appmap/appmap.c
325
+ - ext/appmap/extconf.rb
280
326
  - lib/appmap.rb
281
327
  - lib/appmap/algorithm/prune_class_map.rb
282
328
  - lib/appmap/algorithm/stats.rb
@@ -503,6 +549,11 @@ files:
503
549
  - test/fixtures/minitest_recorder/appmap.yml
504
550
  - test/fixtures/minitest_recorder/lib/hello.rb
505
551
  - test/fixtures/minitest_recorder/test/hello_test.rb
552
+ - test/fixtures/openssl_recorder/Gemfile
553
+ - test/fixtures/openssl_recorder/appmap.yml
554
+ - test/fixtures/openssl_recorder/lib/openssl_cert_sign.rb
555
+ - test/fixtures/openssl_recorder/lib/openssl_encrypt.rb
556
+ - test/fixtures/openssl_recorder/lib/openssl_key_sign.rb
506
557
  - test/fixtures/process_recorder/appmap.yml
507
558
  - test/fixtures/process_recorder/hello.rb
508
559
  - test/fixtures/rspec_recorder/Gemfile
@@ -512,6 +563,7 @@ files:
512
563
  - test/fixtures/rspec_recorder/spec/labeled_hello_spec.rb
513
564
  - test/fixtures/rspec_recorder/spec/plain_hello_spec.rb
514
565
  - test/minitest_test.rb
566
+ - test/openssl_test.rb
515
567
  - test/record_process_test.rb
516
568
  - test/rspec_test.rb
517
569
  - test/test_helper.rb