rspec-pgp_matchers 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +25 -0
- data/ci/gemfiles/common.gemfile +1 -1
- data/lib/rspec/pgp_matchers/be_a_pgp_encrypted_message.rb +1 -19
- data/lib/rspec/pgp_matchers/be_a_valid_pgp_signature_of.rb +1 -21
- data/lib/rspec/pgp_matchers/gpg_matcher_helper.rb +4 -11
- data/lib/rspec/pgp_matchers/gpg_runner.rb +58 -0
- data/lib/rspec/pgp_matchers/version.rb +1 -1
- data/lib/rspec/pgp_matchers.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1880492b5a4864c566a6fa6004a9646d930d1ad232044384d3e6412b1e796891
|
4
|
+
data.tar.gz: ae2aadaa6617b9243f1625f2e6b1b990ce00efd9b3da67c1d9a93d12f723092c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f40aa2b0c66764c28b155e9540d581a89452b31fba2ecde2adf66a98e57ee3f6da210de4bebac78c3a62da8422aa1fc127f110c212045353b0f98abf0a047702
|
7
|
+
data.tar.gz: 160c8706ecb7c149594faba75351ca6ff7c9c1a0ca1270a0aa17921902469baf30eff5fcb0bf28dc38e7d38a5826ef7c16426d682d25fbc5c1ef911e5520448e
|
data/README.adoc
CHANGED
@@ -11,6 +11,9 @@ image:https://img.shields.io/codeclimate/maintainability/riboseinc/rspec-pgp_mat
|
|
11
11
|
|
12
12
|
RSpec matchers for testing PGP-encrypted messages, and signatures.
|
13
13
|
|
14
|
+
CAUTION: This gem is not meant to bridge GnuPG executables to production
|
15
|
+
environments. Use it in developments and tests only.
|
16
|
+
|
14
17
|
IMPORTANT: This gem calls GnuPG executables internally. However, it does not
|
15
18
|
rely on machine-readable interface yet, and may easily break when they change
|
16
19
|
something in GnuPG's human-readable output. As long as it is not resolved in
|
@@ -86,6 +89,28 @@ expect(encrypted).to be_a_pgp_encrypted_message.encrypted_for(recipient1_uid, re
|
|
86
89
|
expect(encrypted).to be_a_pgp_encrypted_message.encrypted_for(someones_uid)
|
87
90
|
----
|
88
91
|
|
92
|
+
=== Running arbitrary GnuPG commands
|
93
|
+
|
94
|
+
An `RSpec::PGPMatchers::GPGRunner` module can be used to run arbitrary GnuPG
|
95
|
+
commands:
|
96
|
+
|
97
|
+
[source,ruby]
|
98
|
+
----
|
99
|
+
RSpec::PGPMatchers::GPGRunner.run_command("--decrypt PATH_TO_FILE")
|
100
|
+
RSpec::PGPMatchers::GPGRunner.run_command("--list-keys")
|
101
|
+
----
|
102
|
+
|
103
|
+
Also, convenient helpers are defined for two common commands:
|
104
|
+
|
105
|
+
[source,ruby]
|
106
|
+
----
|
107
|
+
RSpec::PGPMatchers::GPGRunner.run_decrypt("encrypted_string")
|
108
|
+
RSpec::PGPMatchers::GPGRunner.run_verify("cleartext", "signature_string")
|
109
|
+
----
|
110
|
+
|
111
|
+
In all above cases, a triple consisting of captured standard output, captured
|
112
|
+
standard error, and `Process::Status` instance is returned.
|
113
|
+
|
89
114
|
== Development
|
90
115
|
|
91
116
|
After checking out the repo, run `bin/setup` to install dependencies.
|
data/ci/gemfiles/common.gemfile
CHANGED
@@ -43,7 +43,7 @@ RSpec::Matchers.define :be_a_pgp_encrypted_message do
|
|
43
43
|
|
44
44
|
# Returns +nil+ if signature is valid, or an error message otherwise.
|
45
45
|
def validate_encrypted_message(encrypted_string)
|
46
|
-
cmd_output =
|
46
|
+
cmd_output = run_decrypt(encrypted_string)
|
47
47
|
cmd_result = analyse_decrypt_output(*cmd_output)
|
48
48
|
|
49
49
|
if cmd_result[:well_formed_pgp_data]
|
@@ -53,12 +53,6 @@ RSpec::Matchers.define :be_a_pgp_encrypted_message do
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def run_gpg_decrypt(encrypted_string)
|
57
|
-
enc_file = make_tempfile_containing(encrypted_string)
|
58
|
-
cmd = gpg_decrypt_command(enc_file)
|
59
|
-
run_command(cmd)
|
60
|
-
end
|
61
|
-
|
62
56
|
def analyse_decrypt_output(stdout_str, stderr_str, status)
|
63
57
|
{
|
64
58
|
well_formed_pgp_data: (status.exitstatus != 2),
|
@@ -76,18 +70,6 @@ RSpec::Matchers.define :be_a_pgp_encrypted_message do
|
|
76
70
|
].detect { |x| x }
|
77
71
|
end
|
78
72
|
|
79
|
-
def gpg_decrypt_command(enc_file)
|
80
|
-
homedir_path = Shellwords.escape(RSpec::PGPMatchers.homedir)
|
81
|
-
enc_path = Shellwords.escape(enc_file.path)
|
82
|
-
|
83
|
-
<<~SH
|
84
|
-
gpg \
|
85
|
-
--homedir #{homedir_path} \
|
86
|
-
--no-permission-warning \
|
87
|
-
--decrypt #{enc_path}
|
88
|
-
SH
|
89
|
-
end
|
90
|
-
|
91
73
|
def msg_mismatch(text)
|
92
74
|
"expected given Open PGP message to contain following " +
|
93
75
|
"text:\n#{expected_cleartext}\nbut was:\n#{text}"
|
@@ -37,7 +37,7 @@ RSpec::Matchers.define :be_a_valid_pgp_signature_of do |text|
|
|
37
37
|
|
38
38
|
# Returns +nil+ if first signature is valid, or an error message otherwise.
|
39
39
|
def verify_signature(cleartext, signature_string)
|
40
|
-
cmd_output =
|
40
|
+
cmd_output = run_verify(cleartext, signature_string)
|
41
41
|
cmd_result = analyse_verify_output(*cmd_output)
|
42
42
|
|
43
43
|
if cmd_result[:well_formed_pgp_data]
|
@@ -47,13 +47,6 @@ RSpec::Matchers.define :be_a_valid_pgp_signature_of do |text|
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def run_gpg_verify(cleartext, signature_string)
|
51
|
-
sig_file = make_tempfile_containing(signature_string)
|
52
|
-
data_file = make_tempfile_containing(cleartext)
|
53
|
-
cmd = gpg_verify_command(sig_file, data_file)
|
54
|
-
run_command(cmd)
|
55
|
-
end
|
56
|
-
|
57
50
|
def analyse_verify_output(_stdout_str, stderr_str, status)
|
58
51
|
{
|
59
52
|
well_formed_pgp_data: (status.exitstatus != 2),
|
@@ -65,19 +58,6 @@ RSpec::Matchers.define :be_a_valid_pgp_signature_of do |text|
|
|
65
58
|
match_signature(signature)
|
66
59
|
end
|
67
60
|
|
68
|
-
def gpg_verify_command(sig_file, data_file)
|
69
|
-
homedir_path = Shellwords.escape(RSpec::PGPMatchers.homedir)
|
70
|
-
sig_path = Shellwords.escape(sig_file.path)
|
71
|
-
data_path = Shellwords.escape(data_file.path)
|
72
|
-
|
73
|
-
<<~SH
|
74
|
-
gpg \
|
75
|
-
--homedir #{homedir_path} \
|
76
|
-
--no-permission-warning \
|
77
|
-
--verify #{sig_path} #{data_path}
|
78
|
-
SH
|
79
|
-
end
|
80
|
-
|
81
61
|
def msg_mismatch(text)
|
82
62
|
"expected given signature to be a valid Open PGP signature " +
|
83
63
|
"of following text:\n#{text}"
|
@@ -7,6 +7,10 @@ require "tempfile"
|
|
7
7
|
module RSpec
|
8
8
|
module PGPMatchers
|
9
9
|
module GPGMatcherHelper
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegators :"RSpec::PGPMatchers::GPGRunner", :run_verify, :run_decrypt
|
13
|
+
|
10
14
|
def detect_signers(stderr_str)
|
11
15
|
rx = /(?<ok>Good|BAD) signature from .*\<(?<email>[^>]+)\>/
|
12
16
|
|
@@ -47,17 +51,6 @@ module RSpec
|
|
47
51
|
msg_wrong_signer(signature[:email])
|
48
52
|
end
|
49
53
|
end
|
50
|
-
|
51
|
-
def make_tempfile_containing(file_content)
|
52
|
-
tempfile = Tempfile.new
|
53
|
-
tempfile.write(file_content)
|
54
|
-
tempfile.flush
|
55
|
-
end
|
56
|
-
|
57
|
-
def run_command(cmd)
|
58
|
-
env = { "LC_ALL" => "C" } # Gettext English locale
|
59
|
-
Open3.capture3(env, cmd)
|
60
|
-
end
|
61
54
|
end
|
62
55
|
end
|
63
56
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# (c) Copyright 2018 Ribose Inc.
|
2
|
+
#
|
3
|
+
|
4
|
+
require "open3"
|
5
|
+
require "tempfile"
|
6
|
+
|
7
|
+
module RSpec
|
8
|
+
module PGPMatchers
|
9
|
+
module GPGRunner
|
10
|
+
class << self
|
11
|
+
def run_command(gpg_cmd)
|
12
|
+
env = { "LC_ALL" => "C" } # Gettext English locale
|
13
|
+
|
14
|
+
homedir_path = Shellwords.escape(RSpec::PGPMatchers.homedir)
|
15
|
+
|
16
|
+
Open3.capture3(env, <<~SH)
|
17
|
+
gpg \
|
18
|
+
--homedir #{homedir_path} \
|
19
|
+
--no-permission-warning \
|
20
|
+
#{gpg_cmd}
|
21
|
+
SH
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_decrypt(encrypted_string)
|
25
|
+
enc_file = make_tempfile_containing(encrypted_string)
|
26
|
+
cmd = gpg_decrypt_command(enc_file)
|
27
|
+
run_command(cmd)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_verify(cleartext, signature_string)
|
31
|
+
sig_file = make_tempfile_containing(signature_string)
|
32
|
+
data_file = make_tempfile_containing(cleartext)
|
33
|
+
cmd = gpg_verify_command(sig_file, data_file)
|
34
|
+
run_command(cmd)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def make_tempfile_containing(file_content)
|
40
|
+
tempfile = Tempfile.new
|
41
|
+
tempfile.write(file_content)
|
42
|
+
tempfile.flush
|
43
|
+
end
|
44
|
+
|
45
|
+
def gpg_decrypt_command(enc_file)
|
46
|
+
enc_path = Shellwords.escape(enc_file.path)
|
47
|
+
"--decrypt #{enc_path}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def gpg_verify_command(sig_file, data_file)
|
51
|
+
sig_path = Shellwords.escape(sig_file.path)
|
52
|
+
data_path = Shellwords.escape(data_file.path)
|
53
|
+
"--verify #{sig_path} #{data_path}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/rspec/pgp_matchers.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-pgp_matchers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-expectations
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- lib/rspec/pgp_matchers/be_a_pgp_encrypted_message.rb
|
136
136
|
- lib/rspec/pgp_matchers/be_a_valid_pgp_signature_of.rb
|
137
137
|
- lib/rspec/pgp_matchers/gpg_matcher_helper.rb
|
138
|
+
- lib/rspec/pgp_matchers/gpg_runner.rb
|
138
139
|
- lib/rspec/pgp_matchers/version.rb
|
139
140
|
- rspec-pgp_matchers.gemspec
|
140
141
|
homepage: https://github.com/riboseinc/rspec-pgp_matchers
|