rspec-pgp_matchers 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|