keepass_kpscript 1.0.0
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 +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
|