mfa 0.0.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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +6 -0
  3. data/Onafile +254 -0
  4. data/bin/mfa +4 -0
  5. metadata +88 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: abc69612ca114cbc9b3735453b8602485cc4f95d8dd5d71ae2f4eb10c3cdc335
4
+ data.tar.gz: b6d3146f3318d006190f2f813b44533519203641b1bdf6b1d790c725f818156f
5
+ SHA512:
6
+ metadata.gz: 766faa173d7b177cbc932638cbcb87fc51cb204a6b6583789afe701abfed32e5420c226896c52d31f067a1d541fc7147c6a7707976ebc776b570b512440bc032
7
+ data.tar.gz: f9d668031f3e571e961be1283e49ded04eb259955c30cbaecd1c540a6d6eea4456dc50597e907a605c41b586a6162cb26fc93633735db96c373563de4c12618e
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'isna', '0.0.4'
4
+ gem 'abstract_command', '0.0.6'
5
+ gem 'ona', '1.0.0'
6
+
data/Onafile ADDED
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'abstract_command'
4
+ require 'isna'
5
+ require 'tmpdir'
6
+ require 'json'
7
+
8
+ module Command
9
+ class GetMfa < AbstractCommand
10
+ def template
11
+ 'security find-generic-password -w -a %<account>s -s %<service>s %<keychain>s'
12
+ end
13
+ end
14
+ class SetMfa < AbstractCommand
15
+ def template
16
+ 'security add-generic-password -a %<account>s -s %<service>s -w %<mfa>s %<keychain>s'
17
+ end
18
+ end
19
+ class RmMfa < AbstractCommand
20
+ def template
21
+ 'security delete-generic-password -a %<account>s -s %<service>s %<keychain>s'
22
+ end
23
+ end
24
+ class CreateKeychain < AbstractCommand
25
+ def template
26
+ 'security create-keychain %<keychain>s'
27
+ end
28
+ end
29
+ class DeleteKeychain < AbstractCommand
30
+ def template
31
+ 'security delete-keychain %<keychain>s'
32
+ end
33
+ end
34
+ class ListMfa < AbstractCommand
35
+ def template
36
+ "security dump-keychain %<keychain>s | awk -F'=' '/0x00000007/ { print $2 }'"
37
+ end
38
+ end
39
+ class ResolveMfa < AbstractCommand
40
+ def template
41
+ 'oathtool -b --totp %<seed>s'
42
+ end
43
+ end
44
+ end
45
+
46
+ KEYCHAIN = 'mfa'
47
+
48
+ Ona.prompt = 'Mfa'
49
+
50
+ Ona.resource(:mfa, [:service])
51
+
52
+ def load_mfa_list
53
+ Command::ListMfa.new(:keychain => KEYCHAIN).backtick.each_line do |line|
54
+ line.chomp!
55
+ next if line == ''
56
+ Ona.register(:mfa) do |mfa|
57
+ mfa.service = line.gsub(/^"|"$/, '')
58
+ end
59
+ end
60
+ end
61
+
62
+ def unload_mfa_list
63
+ Ona.class_eval do
64
+ puts @resources[:mfa][:entries] = []
65
+ end
66
+ end
67
+
68
+ def reset_mfa_list
69
+ unload_mfa_list
70
+ load_mfa_list
71
+ end
72
+
73
+ load_mfa_list
74
+
75
+ def print_command(command)
76
+ puts ''
77
+ puts "# Command: #{command.to_ansi.yellow.to_s}"
78
+ puts "# Executed at: #{Time.now.to_s}"
79
+ puts "# #{('=' * 76).to_ansi.cyan.to_s}"
80
+ puts ''
81
+ end
82
+
83
+ Ona.action(
84
+ :regex => /^create-keychain$/,
85
+ :resource => :mfa,
86
+ :text => 'Create the MFA Keychain.',
87
+ :example => 'create-keychain'
88
+ ) do |mfa, input, regex|
89
+ command = Command::CreateKeychain.new
90
+ command.keychain = KEYCHAIN
91
+ print_command command.to_s
92
+ command.system
93
+ end
94
+
95
+ Ona.action(
96
+ :regex => /^delete-keychain$/,
97
+ :resource => :mfa,
98
+ :text => 'Delete the MFA Keychain.',
99
+ :example => 'delete-keychain'
100
+ ) do |mfa, input, regex|
101
+ command = Command::DeleteKeychain.new
102
+ command.keychain = KEYCHAIN
103
+ print_command command.to_s
104
+ command.system
105
+ reset_mfa_list
106
+ end
107
+
108
+ Ona.action(
109
+ :regex => /(^)(set)(\s)([^ ]+)(\s)(.*)($)/,
110
+ :resource => :mfa,
111
+ :text => 'Add a new MFA entry.',
112
+ :example => 'set [SERVICE] [MFA]',
113
+ ) do |mfa, input, regex|
114
+ command = Command::SetMfa.new
115
+ command.account = KEYCHAIN
116
+ command.service = input.scan(regex)[0][3]
117
+ command.keychain = KEYCHAIN
118
+ command.mfa = input.scan(regex)[0][5]
119
+ print_command command.to_s
120
+ command.system
121
+ reset_mfa_list
122
+ end
123
+
124
+ Ona.action(
125
+ :regex => /(^)(get)(\s)(\d+)($)/,
126
+ :resource => :mfa,
127
+ :text => 'Get mfa from keychain and send to clipboard.',
128
+ :example => 'get [NUMBER]',
129
+ :find => true,
130
+ :token => proc { |scan| scan[0][3] }
131
+ ) do |mfa, id|
132
+ command = Command::GetMfa.new
133
+ command.account = KEYCHAIN
134
+ command.service = mfa.service
135
+ command.keychain = KEYCHAIN
136
+ seed = command.backtick.chomp
137
+ puts " #{id.to_s.to_ansi.cyan.to_s} - #{'service'.to_ansi.green.to_s} : #{mfa.service}"
138
+ command = Command::ResolveMfa.new(:seed => seed)
139
+ secret = command.backtick.chomp
140
+ puts " * Sent to clipboard!".to_ansi.yellow.to_s
141
+ puts " > ".to_ansi.cyan.blink.to_s + "#{secret}"
142
+ Dir.mktmpdir do |dir|
143
+ fname = "#{dir}/file.txt"
144
+ File.open(fname, 'w+') do |file|
145
+ file.print secret.chomp
146
+ end
147
+ system "cat #{fname} | pbcopy"
148
+ end
149
+ end
150
+
151
+ Ona.action(
152
+ :regex => /(^)(dump)(\s)(\d+)($)/,
153
+ :resource => :mfa,
154
+ :text => 'Dump seed, service, and code to STDOUT.',
155
+ :example => 'dump [NUMBER]',
156
+ :find => true,
157
+ :token => proc { |scan| scan[0][3] }
158
+ ) do |mfa, id|
159
+ command = Command::GetMfa.new
160
+ command.account = KEYCHAIN
161
+ command.service = mfa.service
162
+ command.keychain = KEYCHAIN
163
+ puts " #{id.to_s.to_ansi.cyan.to_s} - #{'service'.to_ansi.green.to_s} : #{mfa.service}"
164
+ puts " - mfa : #{command.backtick.chomp}"
165
+ end
166
+
167
+ Ona.action(
168
+ :regex => /(^)(rm)(\s)(\d+)($)/,
169
+ :resource => :mfa,
170
+ :text => 'Remove an existing mfa seed.',
171
+ :example => 'rm [NUMBER]',
172
+ :find => true,
173
+ :token => proc { |scan| scan[0][3] }
174
+ ) do |mfa, id|
175
+ command = Command::RmMfa.new
176
+ command.account = KEYCHAIN
177
+ command.service = mfa.service
178
+ command.keychain = KEYCHAIN
179
+ print_command command.to_s
180
+ command.system
181
+ end
182
+
183
+ Ona.action(
184
+ :regex => /(^)(ls)($)/,
185
+ :resource => :mfa,
186
+ :text => 'List all MFAs.',
187
+ :example => 'ls',
188
+ ) do |mfa, id|
189
+ mfa.each_with_index do |mfa, id|
190
+ puts " #{id.to_s.to_ansi.cyan.to_s} - #{'service'.to_ansi.green.to_s} : #{mfa.service}"
191
+ end
192
+ end
193
+
194
+ Ona.action(
195
+ :regex => /(^)(export)($)/,
196
+ :resource => :mfa,
197
+ :text => 'Export all MFAs.',
198
+ :example => 'export',
199
+ ) do |mfa, id|
200
+ mfa.each_with_index do |mfa, id|
201
+ command = Command::GetMfa.new
202
+ command.account = KEYCHAIN
203
+ command.service = mfa.service
204
+ command.keychain = KEYCHAIN
205
+ seed = command.backtick.chomp
206
+ object = {
207
+ :service => mfa.service,
208
+ :seed => seed
209
+ }
210
+ puts object.to_json
211
+ end
212
+ end
213
+
214
+ Ona.action(
215
+ :regex => /(^)(import)(\s)(.*\.json)($)/,
216
+ :resource => :mfa,
217
+ :text => 'Import MFAs from a json file.',
218
+ :example => 'import [FILE]',
219
+ ) do |mfa, command, regex|
220
+ file = regex.match(command)[4]
221
+ puts "Importing from #{file}"
222
+ unless File.exists?(file)
223
+ puts "File #{file} does not exist."
224
+ next
225
+ end
226
+ File.read(file).each_line do |line|
227
+ object = JSON.parse(line)
228
+ Ona.run("set #{object['service']} #{object['seed']}")
229
+ end
230
+ reset_mfa_list
231
+ puts "Import has completed."
232
+ end
233
+
234
+ Ona.action(
235
+ :regex => /(^)(s)(\s)(.*)($)/,
236
+ :resource => :mfa,
237
+ :text => 'Search by service.',
238
+ :example => 's [STRING]'
239
+ ) do |mfa, command, regex|
240
+ text = command.scan(regex)[0][3]
241
+ r = Regexp.new(text)
242
+ mfa.each_with_index do |mfa, id|
243
+ next unless r.match(mfa.to_s)
244
+ match = " #{id.to_s.to_ansi.cyan.to_s} - #{'service'.to_ansi.green.to_s} : #{mfa.service}"
245
+ puts match.gsub(text, text.to_ansi.red.to_s)
246
+ end
247
+ end
248
+
249
+ if ARGV.size > 0
250
+ Ona.defaults
251
+ Ona.run(ARGV.join(' '))
252
+ exit 0
253
+ end
254
+
data/bin/mfa ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ system "cd #{__dir__}/../ && ona #{ARGV.join(' ')}"
4
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mfa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kazuyoshi Tlacaelel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-07-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: isna
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: abstract_command
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: ona
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ description:
56
+ email: kazu.dev@gmail.com
57
+ executables:
58
+ - mfa
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - Onafile
64
+ - bin/mfa
65
+ homepage: https://github.com/ktlacaelel/mfa
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.3.7
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: mfa - mfa utility tool
88
+ test_files: []