keepass_kpscript 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +6 -0
- data/README.md +180 -0
- data/lib/keepass_kpscript.rb +22 -0
- data/lib/keepass_kpscript/database.rb +186 -0
- data/lib/keepass_kpscript/kpscript.rb +111 -0
- data/lib/keepass_kpscript/pass_encryptor.kdbx +0 -0
- data/lib/keepass_kpscript/select.rb +110 -0
- data/lib/keepass_kpscript/version.rb +5 -0
- data/spec/keepass_kpscript_test/helpers.rb +56 -0
- data/spec/keepass_kpscript_test/tests/keepass_kpscript/database_spec.rb +240 -0
- data/spec/keepass_kpscript_test/tests/keepass_kpscript/kpscript_spec.rb +117 -0
- data/spec/keepass_kpscript_test/tests/keepass_kpscript/select_spec.rb +61 -0
- data/spec/keepass_kpscript_test/tests/rubocop_spec.rb +31 -0
- data/spec/spec_helper.rb +102 -0
- metadata +129 -0
Binary file
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module KeepassKpscript
|
2
|
+
|
3
|
+
# Define rules to select entries from a Keepass database.
|
4
|
+
# Those rules are taken from https://keepass.info/help/v2_dev/scr_sc_index.html#editentry
|
5
|
+
class Select
|
6
|
+
|
7
|
+
# Constructor
|
8
|
+
def initialize
|
9
|
+
@selectors = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Select a set of given field values
|
13
|
+
#
|
14
|
+
# Parameters::
|
15
|
+
# * *selection* (Hash<String or Symbol, String>): Set of { field_name => field_value } to be selected.
|
16
|
+
# Result::
|
17
|
+
# * self: The selector itself, useful for chaining
|
18
|
+
def fields(selection)
|
19
|
+
selection.each do |field_name, field_value|
|
20
|
+
@selectors << "-ref-#{field_name}:\"#{field_value}\""
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
# Select a UUID
|
26
|
+
#
|
27
|
+
# Parameters::
|
28
|
+
# * *id* (String): The UUID
|
29
|
+
# Result::
|
30
|
+
# * self: The selector itself, useful for chaining
|
31
|
+
def uuid(id)
|
32
|
+
@selectors << "-refx-UUID:#{id}"
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Select a list of tags
|
37
|
+
#
|
38
|
+
# Parameters::
|
39
|
+
# * *lst_tags* (Array<String>): List of tags to select
|
40
|
+
# Result::
|
41
|
+
# * self: The selector itself, useful for chaining
|
42
|
+
def tags(*lst_tags)
|
43
|
+
@selectors << "-refx-Tags:\"#{lst_tags.flatten.join(',')}\""
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Select entries that expire
|
48
|
+
#
|
49
|
+
# Parameters:
|
50
|
+
# * *switch* (Boolean): Do we select entries that expire? [default = true]
|
51
|
+
# Result::
|
52
|
+
# * self: The selector itself, useful for chaining
|
53
|
+
def expires(switch = true)
|
54
|
+
@selectors << "-refx-Expires:#{switch ? 'true' : 'false'}"
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Select entries that have expired
|
59
|
+
#
|
60
|
+
# Parameters:
|
61
|
+
# * *switch* (Boolean): Do we select entries that have expired? [default = true]
|
62
|
+
# Result::
|
63
|
+
# * self: The selector itself, useful for chaining
|
64
|
+
def expired(switch = true)
|
65
|
+
@selectors << "-refx-Expired:#{switch ? 'true' : 'false'}"
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Select entries that have a given parent group
|
70
|
+
#
|
71
|
+
# Parameters:
|
72
|
+
# * *group_name* (String): Name of the parent group
|
73
|
+
# Result::
|
74
|
+
# * self: The selector itself, useful for chaining
|
75
|
+
def group(group_name)
|
76
|
+
@selectors << "-refx-Group:\"#{group_name}\""
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Select entries that have a given group path
|
81
|
+
#
|
82
|
+
# Parameters:
|
83
|
+
# * *group_path_entries* (Array<String>): Group path
|
84
|
+
# Result::
|
85
|
+
# * self: The selector itself, useful for chaining
|
86
|
+
def group_path(*group_path_entries)
|
87
|
+
@selectors << "-refx-GroupPath:\"#{group_path_entries.flatten.join('/')}\""
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
# Select all entries
|
92
|
+
#
|
93
|
+
# Result::
|
94
|
+
# * self: The selector itself, useful for chaining
|
95
|
+
def all
|
96
|
+
@selectors << '-refx-All'
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return the command-line string selecting the entries
|
101
|
+
#
|
102
|
+
# Result::
|
103
|
+
# * String: The command-line string
|
104
|
+
def to_s
|
105
|
+
@selectors.join(' ')
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'keepass_kpscript'
|
3
|
+
|
4
|
+
module KeepassKpscriptTest
|
5
|
+
|
6
|
+
module Helpers
|
7
|
+
|
8
|
+
# Expect some calls to be done on KPScript
|
9
|
+
#
|
10
|
+
# Parameters::
|
11
|
+
# * *expected_calls* (Array<[String, String or Hash]>): The list of calls and their corresponding mocked response:
|
12
|
+
# * String: Mocked stdout
|
13
|
+
# * Hash<Symbol,Object>: More complete structure defining the mocked response:
|
14
|
+
# * *exit_status* (Integer): The command exit status [default: 0]
|
15
|
+
# * *stdout* (String): The command stdout
|
16
|
+
def expect_calls_to_kpscript(expected_calls)
|
17
|
+
if expected_calls.empty?
|
18
|
+
expect(Open3).not_to receive(:popen3)
|
19
|
+
else
|
20
|
+
expected_calls.each do |(expected_call, mocked_call)|
|
21
|
+
mocked_call = { stdout: mocked_call } if mocked_call.is_a?(String)
|
22
|
+
mocked_call[:exit_status] = 0 unless mocked_call.key?(:exit_status)
|
23
|
+
expect(Open3).to receive(:popen3).with(expected_call) do |_cmd, &block|
|
24
|
+
wait_thr_double = instance_double(Process::Waiter)
|
25
|
+
allow(wait_thr_double).to receive(:value) do
|
26
|
+
wait_thr_value_double = instance_double(Process::Status)
|
27
|
+
allow(wait_thr_value_double).to receive(:exitstatus) do
|
28
|
+
mocked_call[:exit_status]
|
29
|
+
end
|
30
|
+
wait_thr_value_double
|
31
|
+
end
|
32
|
+
block.call(
|
33
|
+
StringIO.new,
|
34
|
+
StringIO.new(mocked_call[:stdout]),
|
35
|
+
StringIO.new,
|
36
|
+
wait_thr_double
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
RSpec.configure do |config|
|
48
|
+
config.include KeepassKpscriptTest::Helpers
|
49
|
+
|
50
|
+
config.before do
|
51
|
+
# Make sure log debugs are not output on screen during tests
|
52
|
+
# rubocop:disable RSpec/AnyInstance
|
53
|
+
allow_any_instance_of(KeepassKpscript::Kpscript).to receive(:log_debug).and_yield
|
54
|
+
# rubocop:enable RSpec/AnyInstance
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
describe KeepassKpscript::Database do
|
2
|
+
|
3
|
+
shared_examples 'a database' do
|
4
|
+
|
5
|
+
subject(:database) { kpscript.open('/path/to/my_db.kdbx', password: 'MyPassword') }
|
6
|
+
|
7
|
+
let(:kpscript) { KeepassKpscript.use('/path/to/KPScript.exe', debug: debug) }
|
8
|
+
|
9
|
+
it 'gets a simple password for an entry title' do
|
10
|
+
expect_calls_to_kpscript [
|
11
|
+
[
|
12
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
13
|
+
<<~EO_STDOUT
|
14
|
+
MyEntryPassword
|
15
|
+
OK: Operation completed successfully.
|
16
|
+
EO_STDOUT
|
17
|
+
]
|
18
|
+
]
|
19
|
+
expect(database.password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'fails with an error silencing secrets when KPScript returns a non-zero exit status' do
|
23
|
+
expect_calls_to_kpscript [
|
24
|
+
[
|
25
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
26
|
+
{
|
27
|
+
stdout: '',
|
28
|
+
exit_status: 1
|
29
|
+
}
|
30
|
+
]
|
31
|
+
]
|
32
|
+
expect { database.password_for('MyEntryTitle') }.to raise_error 'Error while executing /path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"XXXXX" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password" (exit status: 1)'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'fails with an error silencing secrets when KPScript returns an error message' do
|
36
|
+
expect_calls_to_kpscript [
|
37
|
+
[
|
38
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
39
|
+
'E: Error reading database.'
|
40
|
+
]
|
41
|
+
]
|
42
|
+
expect { database.password_for('MyEntryTitle') }.to raise_error 'Error returned by /path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"XXXXX" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password": E: Error reading database.'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'reads entries string' do
|
46
|
+
expect_calls_to_kpscript [
|
47
|
+
[
|
48
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -refx-All -Field:"Field"',
|
49
|
+
<<~EO_STDOUT
|
50
|
+
Value1
|
51
|
+
Value2
|
52
|
+
Value3
|
53
|
+
OK: Operation completed successfully.
|
54
|
+
EO_STDOUT
|
55
|
+
]
|
56
|
+
]
|
57
|
+
expect(database.entries_string(kpscript.select.all, 'Field')).to eq %w[Value1 Value2 Value3]
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'reads entries string in a secured way with secret strings' do
|
61
|
+
expect_calls_to_kpscript [
|
62
|
+
[
|
63
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -refx-All -Field:"Field"',
|
64
|
+
<<~EO_STDOUT
|
65
|
+
Value1
|
66
|
+
Value2
|
67
|
+
Value3
|
68
|
+
OK: Operation completed successfully.
|
69
|
+
EO_STDOUT
|
70
|
+
]
|
71
|
+
]
|
72
|
+
leaked_values = nil
|
73
|
+
expect do
|
74
|
+
database.with_entries_string(kpscript.select.all, 'Field') do |values|
|
75
|
+
expect(values.map(&:to_s)).to eq %w[XXXXX XXXXX XXXXX]
|
76
|
+
expect(values.map(&:to_unprotected)).to eq %w[Value1 Value2 Value3]
|
77
|
+
leaked_values = values
|
78
|
+
end
|
79
|
+
end.not_to raise_error
|
80
|
+
expect(leaked_values.map(&:to_s)).to eq %w[XXXXX XXXXX XXXXX]
|
81
|
+
expect(leaked_values.map(&:to_unprotected)).to eq ["\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00"]
|
82
|
+
end
|
83
|
+
|
84
|
+
{
|
85
|
+
fail_if_not_exists: '-FailIfNotExists',
|
86
|
+
fail_if_no_entry: '-FailIfNoEntry',
|
87
|
+
spr: '-Spr'
|
88
|
+
}.each do |keyword, kpscript_flag|
|
89
|
+
|
90
|
+
it "reads entries string with #{keyword} flag" do
|
91
|
+
expect_calls_to_kpscript [
|
92
|
+
[
|
93
|
+
"/path/to/KPScript.exe \"/path/to/my_db.kdbx\" -pw:\"MyPassword\" -c:GetEntryString -refx-All -Field:\"Field\" #{kpscript_flag}",
|
94
|
+
<<~EO_STDOUT
|
95
|
+
Value1
|
96
|
+
Value2
|
97
|
+
Value3
|
98
|
+
OK: Operation completed successfully.
|
99
|
+
EO_STDOUT
|
100
|
+
]
|
101
|
+
]
|
102
|
+
expect(database.entries_string(kpscript.select.all, 'Field', **{ keyword => true })).to eq %w[Value1 Value2 Value3]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "reads entries string in a secured way with secret strings with #{keyword} flag" do
|
106
|
+
expect_calls_to_kpscript [
|
107
|
+
[
|
108
|
+
"/path/to/KPScript.exe \"/path/to/my_db.kdbx\" -pw:\"MyPassword\" -c:GetEntryString -refx-All -Field:\"Field\" #{kpscript_flag}",
|
109
|
+
<<~EO_STDOUT
|
110
|
+
Value1
|
111
|
+
Value2
|
112
|
+
Value3
|
113
|
+
OK: Operation completed successfully.
|
114
|
+
EO_STDOUT
|
115
|
+
]
|
116
|
+
]
|
117
|
+
leaked_values = nil
|
118
|
+
expect do
|
119
|
+
database.with_entries_string(kpscript.select.all, 'Field', **{ keyword => true }) do |values|
|
120
|
+
expect(values.map(&:to_s)).to eq %w[XXXXX XXXXX XXXXX]
|
121
|
+
expect(values.map(&:to_unprotected)).to eq %w[Value1 Value2 Value3]
|
122
|
+
leaked_values = values
|
123
|
+
end
|
124
|
+
end.not_to raise_error
|
125
|
+
expect(leaked_values.map(&:to_s)).to eq %w[XXXXX XXXXX XXXXX]
|
126
|
+
expect(leaked_values.map(&:to_unprotected)).to eq ["\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00"]
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
# All edit entries test cases
|
132
|
+
{
|
133
|
+
{ fields: { Field: 'Value' } } => '-set-Field:"Value"',
|
134
|
+
{ fields: { Field1: 'Value1', Field2: 'Value2' } } => '-set-Field1:"Value1" -set-Field2:"Value2"',
|
135
|
+
{ icon_idx: 7 } => '-setx-Icon:7',
|
136
|
+
{ custom_icon_idx: 11 } => '-setx-CustomIcon:11',
|
137
|
+
{ expires: true } => '-setx-Expires:true',
|
138
|
+
{ expiry_time: Time.parse('2021-06-30 15:12:11') } => '-setx-ExpiryTime:"2021-06-30T15:12:11"',
|
139
|
+
{ fields: { Field: 'Value' }, create_backup: true } => '-set-Field:"Value" -CreateBackup',
|
140
|
+
{
|
141
|
+
fields: { Field1: 'Value1', Field2: 'Value2' },
|
142
|
+
expiry_time: Time.parse('2021-06-30 15:12:11'),
|
143
|
+
icon_idx: 7,
|
144
|
+
create_backup: true
|
145
|
+
} => '-set-Field1:"Value1" -set-Field2:"Value2" -setx-Icon:7 -setx-ExpiryTime:"2021-06-30T15:12:11" -CreateBackup'
|
146
|
+
}.each do |kwargs, expected_args|
|
147
|
+
|
148
|
+
it "edit entries using #{kwargs}" do
|
149
|
+
expect_calls_to_kpscript [
|
150
|
+
[
|
151
|
+
"/path/to/KPScript.exe \"/path/to/my_db.kdbx\" -pw:\"MyPassword\" -c:EditEntry -refx-All #{expected_args}",
|
152
|
+
'OK: Operation completed successfully.'
|
153
|
+
]
|
154
|
+
]
|
155
|
+
expect { database.edit_entries(kpscript.select.all, **kwargs) }.not_to raise_error
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'detaches binaries' do
|
161
|
+
expect_calls_to_kpscript [
|
162
|
+
[
|
163
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:DetachBins',
|
164
|
+
'OK: Operation completed successfully.'
|
165
|
+
]
|
166
|
+
]
|
167
|
+
expect { database.detach_bins }.not_to raise_error
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'detaches binaries in another directory' do
|
171
|
+
tmpdir = "#{Dir.tmpdir}/keepass_kpscript_test"
|
172
|
+
FileUtils.mkdir_p tmpdir
|
173
|
+
begin
|
174
|
+
database_file = "#{tmpdir}/my_db.kdbx"
|
175
|
+
File.write(database_file, 'Dummy database')
|
176
|
+
bins_dir = "#{tmpdir}/bins_dir"
|
177
|
+
expect_calls_to_kpscript [
|
178
|
+
[
|
179
|
+
"/path/to/KPScript.exe \"#{bins_dir}/my_db.kdbx.tmp.kdbx\" -pw:\"MyPassword\" -c:DetachBins",
|
180
|
+
'OK: Operation completed successfully.'
|
181
|
+
]
|
182
|
+
]
|
183
|
+
expect { kpscript.open(database_file, password: 'MyPassword').detach_bins(copy_to_dir: bins_dir) }.not_to raise_error
|
184
|
+
expect(File.exist?(bins_dir)).to eq true
|
185
|
+
# Check that no database copy is remaining
|
186
|
+
expect(Dir.glob("#{bins_dir}/*")).to eq []
|
187
|
+
ensure
|
188
|
+
FileUtils.rm_rf tmpdir
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'exports the database' do
|
193
|
+
expect_calls_to_kpscript [
|
194
|
+
[
|
195
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:Export -Format:"Export Format" -OutFile:"/path/to/export_file"',
|
196
|
+
'OK: Operation completed successfully.'
|
197
|
+
]
|
198
|
+
]
|
199
|
+
expect { database.export('Export Format', '/path/to/export_file') }.not_to raise_error
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'exports the database with a group path selected' do
|
203
|
+
expect_calls_to_kpscript [
|
204
|
+
[
|
205
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:Export -Format:"Export Format" -OutFile:"/path/to/export_file" -GroupPath:"Group1/Group2/Group3"',
|
206
|
+
'OK: Operation completed successfully.'
|
207
|
+
]
|
208
|
+
]
|
209
|
+
expect { database.export('Export Format', '/path/to/export_file', group_path: %w[Group1 Group2 Group3]) }.not_to raise_error
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'exports the database with an XSL file specified' do
|
213
|
+
expect_calls_to_kpscript [
|
214
|
+
[
|
215
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:Export -Format:"Export Format" -OutFile:"/path/to/export_file" -XslFile:"/path/to/xsl_file.xsl"',
|
216
|
+
'OK: Operation completed successfully.'
|
217
|
+
]
|
218
|
+
]
|
219
|
+
expect { database.export('Export Format', '/path/to/export_file', xsl_file: '/path/to/xsl_file.xsl') }.not_to raise_error
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'without debug' do
|
225
|
+
|
226
|
+
it_behaves_like 'a database' do
|
227
|
+
let(:debug) { false }
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
context 'with debug' do
|
233
|
+
|
234
|
+
it_behaves_like 'a database' do
|
235
|
+
let(:debug) { true }
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
describe KeepassKpscript::Kpscript do
|
2
|
+
|
3
|
+
shared_examples 'a kpscript instance' do
|
4
|
+
|
5
|
+
subject(:kpscript) { KeepassKpscript.use('/path/to/KPScript.exe', debug: debug) }
|
6
|
+
|
7
|
+
it 'gives an instance wrapping a KPScript installation' do
|
8
|
+
expect_calls_to_kpscript [['/path/to/KPScript.exe -example-arg', 'OK: Operation completed successfully.']]
|
9
|
+
kpscript.run('-example-arg')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'encrypts passwords' do
|
13
|
+
expect_calls_to_kpscript [
|
14
|
+
[
|
15
|
+
'/path/to/KPScript.exe "/tmp/keepass_kpscript.tmp.kdbx" -pw:"pass_encryptor" -c:EditEntry -ref-Title:"pass_encryptor" -set-Password:"MyPassword"',
|
16
|
+
'OK: Operation completed successfully.'
|
17
|
+
],
|
18
|
+
[
|
19
|
+
'/path/to/KPScript.exe "/tmp/keepass_kpscript.tmp.kdbx" -pw:"pass_encryptor" -c:GetEntryString -ref-Title:"pass_encryptor" -Field:"URL" -Spr',
|
20
|
+
<<~EO_STDOUT
|
21
|
+
ENCRYPTED_PASSWORD
|
22
|
+
OK: Operation completed successfully.
|
23
|
+
EO_STDOUT
|
24
|
+
]
|
25
|
+
]
|
26
|
+
expect(kpscript.encrypt_password('MyPassword')).to eq 'ENCRYPTED_PASSWORD'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'opens a database with a password' do
|
30
|
+
expect_calls_to_kpscript [
|
31
|
+
[
|
32
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
33
|
+
<<~EO_STDOUT
|
34
|
+
MyEntryPassword
|
35
|
+
OK: Operation completed successfully.
|
36
|
+
EO_STDOUT
|
37
|
+
]
|
38
|
+
]
|
39
|
+
expect(kpscript.open('/path/to/my_db.kdbx', password: 'MyPassword').password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'opens a database with an encrypted password' do
|
43
|
+
expect_calls_to_kpscript [
|
44
|
+
[
|
45
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw-enc:"MyEncryptedPassword" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
46
|
+
<<~EO_STDOUT
|
47
|
+
MyEntryPassword
|
48
|
+
OK: Operation completed successfully.
|
49
|
+
EO_STDOUT
|
50
|
+
]
|
51
|
+
]
|
52
|
+
expect(kpscript.open('/path/to/my_db.kdbx', password_enc: 'MyEncryptedPassword').password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'opens a database with a key file' do
|
56
|
+
expect_calls_to_kpscript [
|
57
|
+
[
|
58
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -keyfile:"/path/to/key_file" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
59
|
+
<<~EO_STDOUT
|
60
|
+
MyEntryPassword
|
61
|
+
OK: Operation completed successfully.
|
62
|
+
EO_STDOUT
|
63
|
+
]
|
64
|
+
]
|
65
|
+
expect(kpscript.open('/path/to/my_db.kdbx', key_file: '/path/to/key_file').password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'opens a database with a key file and password' do
|
69
|
+
expect_calls_to_kpscript [
|
70
|
+
[
|
71
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw:"MyPassword" -keyfile:"/path/to/key_file" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
72
|
+
<<~EO_STDOUT
|
73
|
+
MyEntryPassword
|
74
|
+
OK: Operation completed successfully.
|
75
|
+
EO_STDOUT
|
76
|
+
]
|
77
|
+
]
|
78
|
+
expect(kpscript.open('/path/to/my_db.kdbx', password: 'MyPassword', key_file: '/path/to/key_file').password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'opens a database with a key file and encrypted password' do
|
82
|
+
expect_calls_to_kpscript [
|
83
|
+
[
|
84
|
+
'/path/to/KPScript.exe "/path/to/my_db.kdbx" -pw-enc:"MyEncryptedPassword" -keyfile:"/path/to/key_file" -c:GetEntryString -ref-Title:"MyEntryTitle" -Field:"Password"',
|
85
|
+
<<~EO_STDOUT
|
86
|
+
MyEntryPassword
|
87
|
+
OK: Operation completed successfully.
|
88
|
+
EO_STDOUT
|
89
|
+
]
|
90
|
+
]
|
91
|
+
expect(kpscript.open('/path/to/my_db.kdbx', password_enc: 'MyEncryptedPassword', key_file: '/path/to/key_file').password_for('MyEntryTitle')).to eq 'MyEntryPassword'
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'gives a selector' do
|
95
|
+
expect_calls_to_kpscript []
|
96
|
+
expect(kpscript.select.fields(Title: 'MyEntryTitle').to_s).to eq '-ref-Title:"MyEntryTitle"'
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'without debug' do
|
102
|
+
|
103
|
+
it_behaves_like 'a kpscript instance' do
|
104
|
+
let(:debug) { false }
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with debug' do
|
110
|
+
|
111
|
+
it_behaves_like 'a kpscript instance' do
|
112
|
+
let(:debug) { true }
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|