enfcli 3.3.2.pre.alpha

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.
data/lib/enfcli.rb ADDED
@@ -0,0 +1,390 @@
1
+ #
2
+ # Copyright 2018 Xaptum,Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ require 'openssl'
17
+ require 'enfapi'
18
+ require 'enfthor'
19
+ require 'readline'
20
+ require 'singleton'
21
+ require 'ipaddr'
22
+
23
+ require 'rubygems/commands/update_command'
24
+ require 'rubygems/commands/search_command'
25
+
26
+
27
+ require 'enfcli/version'
28
+ require 'enfcli/commands/xcr'
29
+ require 'enfcli/commands/xiam'
30
+ require 'enfcli/commands/xfw'
31
+ require 'enfcli/commands/user'
32
+
33
+ module EnfCli
34
+ FIREWALL_CMD = "firewall"
35
+ IAM_CMD = "iam"
36
+ NETWORK_CMD = "network"
37
+ USER_CMD = "user"
38
+
39
+ class IPV6
40
+ def initialize(ipv6)
41
+ begin
42
+ # create IPAddr object
43
+ ip = IPAddr.new ipv6
44
+
45
+ # make sure it is an ipv6 address
46
+ raise EnfCli::ERROR, "#{ipv6} is not a valid Ipv6 address." unless ip.ipv6?
47
+
48
+ @ip = ip
49
+ rescue IPAddr::InvalidAddressError
50
+ raise EnfCli::ERROR, "#{ipv6} is not a valid Ipv6 address."
51
+ end
52
+ end
53
+
54
+ def to_s
55
+ @ip.to_s
56
+ end
57
+
58
+ def hton
59
+ @ip.hton
60
+ end
61
+
62
+ def self.ntoh ipv6_bytes
63
+ ip = IPAddr::new_ntoh( ipv6_bytes )
64
+ EnfCli::IPV6.new ip.to_s
65
+ end
66
+
67
+ private
68
+
69
+ attr_accessor :ip
70
+ end
71
+
72
+ class IPV6Cidr
73
+ def initialize(ipv6cidr)
74
+ # split on /
75
+ tokens = ipv6cidr.split("/")
76
+
77
+ # raise exception if not cidr format
78
+ raise EnfCli::ERROR, "#{ipv6cidr} is not a valid CIDR notation." unless tokens.length == 2
79
+
80
+ # store in prefix/len
81
+ @prefix = EnfCli::IPV6.new tokens[0]
82
+ @len = tokens[1].to_i
83
+
84
+ # raise if len is not 0
85
+ raise EnfCli::ERROR, "#{ipv6cidr} is not a valid CIDR notation." unless len > 2
86
+
87
+ end
88
+
89
+ def prefix_bytes
90
+ @prefix.hton
91
+ end
92
+
93
+ def prefix_len
94
+ @len
95
+ end
96
+
97
+ def to_s
98
+ "#{@prefix.to_s}/#{@len}"
99
+ end
100
+
101
+ private
102
+ attr_accessor :prefix, :len
103
+ end
104
+
105
+ def self.ask_password(prompt = nil)
106
+ begin
107
+ prompt = 'Enter Password:' unless prompt
108
+ print prompt
109
+ # We hide the entered characters before to ask for the password
110
+ system 'stty -echo'
111
+ password = $stdin.gets.chomp
112
+ system 'stty echo'
113
+ puts ""
114
+ return password
115
+
116
+ rescue NoMethodError, Interrupt
117
+ # When the process is exited, we display the characters again
118
+ # And we exit
119
+ system 'stty echo'
120
+ exit
121
+ end
122
+ end
123
+
124
+ def self.generate_ec_cert(key, ipv6)
125
+ # monkey patch
126
+ OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?)
127
+
128
+ # Generate cert
129
+ cert = OpenSSL::X509::Certificate.new
130
+ cert.subject = cert.issuer = OpenSSL::X509::Name.new([['CN', "#{ipv6}"]])
131
+ cert.not_before = Time.now
132
+ cert.not_after = Time.now + 365 * 24 * 60 * 60
133
+ cert.public_key = key
134
+ cert.serial = 0x0
135
+ cert.version = 2
136
+
137
+ cert.sign key, OpenSSL::Digest::SHA1.new
138
+ cert
139
+ end
140
+
141
+ def self.expand_path(file)
142
+ new_file = File.expand_path(EnfCli::expand_env(file))
143
+ end
144
+
145
+ def self.expand_env(str)
146
+ str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) { ENV[$1] }
147
+ end
148
+
149
+ def self.to_canonical_ipv6(ipv6)
150
+ ip = EnfCli::IPV6.new ipv6
151
+ ip.to_s
152
+ end
153
+
154
+ ##
155
+ # EnfCli error
156
+ #
157
+ class ERROR < StandardError
158
+ def initialize(msg = "Cli Error")
159
+ super
160
+ end
161
+ end
162
+
163
+ ##
164
+ # EnfCli Context
165
+ #
166
+ class CTX
167
+ include Singleton
168
+
169
+ attr_accessor :session
170
+
171
+ def initialize
172
+ @prompt = "enfcli"
173
+ @host = ''
174
+ end
175
+
176
+ def xaptum_admin?
177
+ self.user_role == "XAPTUM_ADMIN"
178
+ end
179
+
180
+ def user_role
181
+ @session[:type]
182
+ end
183
+
184
+ def host
185
+ "#{@host}"
186
+ end
187
+
188
+ def host=(value)
189
+ @host = value
190
+ end
191
+
192
+ def prompt
193
+ "\001\033[1;32m\002#{@prompt}>\001\033[0m\002 "
194
+ end
195
+
196
+ def prompt=(value)
197
+ if value
198
+ @prompt = "enfcli-#{value}"
199
+ else
200
+ @prompt= "enfcli"
201
+ end
202
+
203
+ end
204
+
205
+ end
206
+
207
+ ##
208
+ # CLI for launching shell
209
+ #
210
+ class CLI < EnfThor
211
+ no_commands {
212
+ def execute_gem_cmd cmd
213
+ begin
214
+ cmd.execute
215
+ rescue Gem::SystemExitException => e
216
+ say "Unable to execute commnad. Please try again!", :red
217
+ end
218
+ end
219
+ }
220
+
221
+ desc "connect", "Connect to ENF Controller"
222
+ method_option :host, :type => :string, :required => true
223
+ method_option :user, :type => :string, :required => true
224
+ method_option :password, :type => :string
225
+ def connect(*names)
226
+ host = options[:host]
227
+ user = options[:user]
228
+
229
+ try_with_rescue do
230
+ # Make sure to use https as default
231
+ host = "https://#{host}" unless host =~ /^(http|https):\/\//
232
+
233
+ # Ask for password
234
+ say "Connecting to '#{host}'.....", :bold
235
+ password = EnfCli::ask_password()
236
+
237
+ # Authenticate
238
+ resp = EnfApi::API.instance.authenticate(host, user, password)
239
+
240
+ # set session
241
+ EnfCli::CTX.instance.session = resp[:data][0]
242
+
243
+ # launch shell/exec cmd
244
+ if names.empty?
245
+ EnfCli::Shell::Console::start host, user
246
+ else
247
+ EnfCli::Shell::CLI.start names
248
+ end
249
+ end
250
+ end
251
+
252
+ map %w[--version -v] => :__print_version
253
+ desc "--version, -v", "print the version"
254
+ def __print_version
255
+ puts EnfCli::VERSION
256
+ end
257
+
258
+ desc "update", "", :hide => true
259
+ def update
260
+ cmd = Gem::Commands::UpdateCommand.new
261
+ cmd.handle_options ['enfcli']
262
+ execute_gem_cmd cmd
263
+ end
264
+
265
+ desc "search", "", :hide => true
266
+ def search
267
+ cmd = Gem::Commands::SearchCommand.new
268
+ cmd.handle_options ["enfcli"]
269
+ execute_gem_cmd cmd
270
+ end
271
+
272
+ default_task :connect
273
+
274
+ end
275
+
276
+ ##
277
+ # Shell Module
278
+ #
279
+ module Shell
280
+
281
+ class Console
282
+ class << self
283
+ def execute(input)
284
+ argv = input.split(" ")
285
+ EnfCli::Shell::CLI.start( argv )
286
+ end
287
+
288
+ def start(host, user)
289
+ # Set prompt
290
+ EnfCli::CTX.instance.prompt = user
291
+
292
+ # Set host
293
+ EnfCli::CTX.instance.host = host
294
+
295
+ # Read each line
296
+ comp = proc { |s| Readline::HISTORY.grep(/^#{Regexp.escape(s)}/) }
297
+ Readline.completion_append_character = " "
298
+ Readline.completion_proc = comp
299
+
300
+ stty_save = `stty -g`.chomp
301
+ trap('INT') { system('stty', stty_save); exit }
302
+
303
+ while input = Readline.readline(EnfCli::CTX.instance.prompt, true)
304
+ break if input == "exit" or input == "\\q" or input == "quit"
305
+
306
+ # Remove blank lines from history
307
+ Readline::HISTORY.pop if input == ""
308
+
309
+ execute(input) unless input == ""
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ # Shell CLI class
316
+ class CLI < EnfThor
317
+
318
+ desc "ls [<dir>]", "List files in a directory", :hide => true
319
+ method_option :dir, :type => :string, :required => false
320
+ def ls(dir = nil)
321
+ try_with_rescue do
322
+ dir = "." unless dir
323
+ dir = EnfCli::expand_path( dir )
324
+
325
+ Dir.entries( dir ).each{ |f|
326
+ puts f unless f.start_with?('.')
327
+ }
328
+ end
329
+ end
330
+
331
+ desc "cat <file>", "Display contents of a file", :hide => true
332
+ def cat(file)
333
+ try_with_rescue do
334
+ # expand path
335
+ file = EnfCli::expand_path(file)
336
+
337
+ ## return if keyfile not found
338
+ raise EnfCli::ERROR, "#{file} not found!" unless File.exists?(file)
339
+
340
+ say File.readlines(file).join
341
+ end
342
+ end
343
+
344
+ desc "pwd", "Current Working Directory", :hide => true
345
+ def pwd
346
+ try_with_rescue do
347
+ say Dir.pwd
348
+ end
349
+ end
350
+
351
+ desc "cd [<dir>]", "Change working directory", :hide => true
352
+ def cd(dir = "~")
353
+ try_with_rescue do
354
+ dir = EnfCli::expand_path( dir )
355
+ raise EnfCli::ERROR, "No such directory #{dir}" unless Dir.exist?(dir)
356
+ Dir.chdir(dir)
357
+ end
358
+ end
359
+
360
+ desc "host", "Display ENF Controller host", :hide => true
361
+ def host
362
+ try_with_rescue do
363
+ say EnfCli::CTX.instance.host, :bold
364
+ end
365
+ end
366
+
367
+ desc "clear", "Clear Terminal Screen", :hide => true
368
+ def clear
369
+ try_with_rescue do
370
+ clear_code = %x{clear}
371
+ print clear_code or system("cls")
372
+ end
373
+ end
374
+
375
+ desc "#{EnfCli::NETWORK_CMD} COMMANDS", "#{EnfCli::NETWORK_CMD} commands"
376
+ subcommand EnfCli::NETWORK_CMD, EnfCli::Cmd::Xcr
377
+
378
+ desc "#{EnfCli::IAM_CMD} COMMANDS", "#{EnfCli::IAM_CMD} commands"
379
+ subcommand EnfCli::IAM_CMD, EnfCli::Cmd::Xiam
380
+
381
+ desc "#{EnfCli::FIREWALL_CMD} COMMANDS", "#{EnfCli::FIREWALL_CMD} commands"
382
+ subcommand EnfCli::FIREWALL_CMD, EnfCli::Cmd::Xfw
383
+
384
+ desc "#{EnfCli::USER_CMD} COMMANDS", "#{EnfCli::USER_CMD} commands"
385
+ subcommand EnfCli::USER_CMD, EnfCli::Cmd::User
386
+
387
+ end
388
+ end
389
+
390
+ end
data/lib/enfthor.rb ADDED
@@ -0,0 +1,118 @@
1
+ #
2
+ # Copyright 2018 Xaptum,Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ require 'thor'
17
+ require 'terminal-table'
18
+
19
+ module EnfCli
20
+ class EnfThor < Thor
21
+ # check for unknow of misspelt options
22
+ check_unknown_options!
23
+
24
+ # helper functions
25
+ no_commands {
26
+
27
+ def format_date(date)
28
+ DateTime.strptime("#{date}",'%s') if date
29
+ end
30
+
31
+ def render_table(headings, rows, file = nil)
32
+ table = Terminal::Table.new
33
+ table.headings = headings
34
+ table.rows = rows
35
+ if file
36
+ open(expand_path(file), 'w') { |f|
37
+ f.puts table
38
+ }
39
+ say "#{rows.length} rows written to file #{file}", :yellow
40
+ else
41
+ say table
42
+ say "#{rows.length} rows in set", :yellow
43
+ end
44
+ end
45
+
46
+ def try_with_rescue_in_session
47
+ try_with_rescue do
48
+ # Verify domain context is set
49
+ session = EnfCli::CTX.instance.session
50
+ raise EnfCli::ERROR, "User Session not establised!" if !session
51
+
52
+ yield
53
+ end
54
+ end
55
+
56
+ def try_with_rescue
57
+ begin
58
+ yield
59
+ rescue EnfApi::ERROR => e
60
+ say e, :red
61
+
62
+ rescue OpenSSL::SSL::SSLError => e
63
+ say e, :red
64
+ say "Host may not support https. Try http instead", :bold
65
+
66
+ rescue => e
67
+ say e, :red
68
+ end
69
+ end
70
+
71
+
72
+ }
73
+
74
+ # override help methods
75
+ class << self
76
+ def capture_stdout
77
+ $stdout = StringIO.new
78
+ yield
79
+ text = $stdout.string
80
+ $stdout = STDOUT
81
+ text
82
+ end
83
+
84
+ def help(shell, subcommand = false)
85
+ list = printable_commands(true, subcommand)
86
+ Thor::Util.thor_classes_in(self).each do |klass|
87
+ list += klass.printable_commands(false)
88
+ end
89
+
90
+ # Remove this line to disable alphabetical sorting
91
+ list.sort! { |a, b| a[0] <=> b[0] }
92
+
93
+ # Add this line to remove the help-command itself from the output
94
+ list.reject! {|l| l[0].split[1] == 'help' or l[0].split[2] == 'help'}
95
+
96
+
97
+ # Capture help message in a variable
98
+ help_text = capture_stdout {
99
+ shell.say "Commands:"
100
+ shell.print_table(list, :indent => 2, :truncate => true)
101
+ shell.say
102
+ class_options_help(shell)
103
+ }
104
+
105
+ ## HACK: format to display proper help message for help command run from shell
106
+ help_text = help_text.gsub(/enfcli /,"") unless self == EnfCli::CLI
107
+
108
+ # Print the actual help message
109
+ shell.say help_text
110
+
111
+ # Add this line if you want to print custom text at the end of your help output.
112
+ # (similar to how Rails does it)
113
+ shell.say 'All commands can be run with -h (or --help) for more information.'
114
+ end
115
+ end
116
+
117
+ end
118
+ end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enfcli
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.3.2.pre.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Venkatakumar Srinivasan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-03-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.20.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.20.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: terminal-table
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bump
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec_junit_formatter
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: fuubar
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: vcr
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email:
169
+ - venkat@xaptum.com
170
+ executables:
171
+ - enfcli
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - ".circleci/Dockerfile"
176
+ - ".circleci/build.sh"
177
+ - ".circleci/config.yml"
178
+ - ".circleci/setup-rubygems.sh"
179
+ - ".gitignore"
180
+ - Gemfile
181
+ - Gemfile.lock
182
+ - LICENSE
183
+ - Makefile
184
+ - README.md
185
+ - Rakefile
186
+ - bin/enfcli
187
+ - enfcli.gemspec
188
+ - lib/enfapi.rb
189
+ - lib/enfcli.rb
190
+ - lib/enfcli/commands/user.rb
191
+ - lib/enfcli/commands/xcr.rb
192
+ - lib/enfcli/commands/xfw.rb
193
+ - lib/enfcli/commands/xiam.rb
194
+ - lib/enfcli/version.rb
195
+ - lib/enfthor.rb
196
+ homepage: https://www.xaptum.com
197
+ licenses: []
198
+ metadata: {}
199
+ post_install_message:
200
+ rdoc_options: []
201
+ require_paths:
202
+ - lib
203
+ required_ruby_version: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ required_rubygems_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - ">"
211
+ - !ruby/object:Gem::Version
212
+ version: 1.3.1
213
+ requirements: []
214
+ rubygems_version: 3.0.1
215
+ signing_key:
216
+ specification_version: 4
217
+ summary: Xaptum ENF CLI.
218
+ test_files: []