ai_root_shield 0.3.0 → 0.5.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.
data/exe/ai_root_shield CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "optparse"
5
5
  require "json"
6
+ require "fileutils"
6
7
  require_relative "../lib/ai_root_shield"
7
8
 
8
9
  # Command line interface for AI Root Shield
@@ -19,13 +20,42 @@ class AiRootShieldCLI
19
20
  enable_network_analysis: true,
20
21
  enable_ai_behavioral_analysis: true,
21
22
  enable_rasp_protection: false,
22
- rasp_monitoring_time: 5
23
+ rasp_monitoring_time: 5,
24
+ policy_file: nil,
25
+ enable_certificate_pinning: false,
26
+ enable_proxy_detection: false,
27
+ target_ip: nil,
28
+ target_url: nil,
29
+ # v0.5.0 new options
30
+ platform: nil,
31
+ safetynet_api_key: nil,
32
+ package_name: nil,
33
+ ci_mode: false,
34
+ artifacts_path: './security_test_artifacts',
35
+ siem_platform: nil,
36
+ siem_endpoint: nil,
37
+ siem_token: nil,
38
+ start_dashboard: false,
39
+ dashboard_port: 4567,
40
+ generate_ci_config: nil,
41
+ enable_unified_reporting: false
23
42
  }
24
43
  end
25
44
 
26
45
  def run(args)
27
46
  parse_options(args)
28
47
 
48
+ # Handle special commands first
49
+ if @options[:start_dashboard]
50
+ start_dashboard
51
+ return
52
+ end
53
+
54
+ if @options[:generate_ci_config]
55
+ generate_ci_config
56
+ return
57
+ end
58
+
29
59
  if args.empty?
30
60
  puts "Error: Please provide a device logs file path"
31
61
  puts "Usage: ai_root_shield [options] <device_logs.json>"
@@ -40,6 +70,33 @@ class AiRootShieldCLI
40
70
  end
41
71
 
42
72
  begin
73
+ # Configure SIEM if provided
74
+ if @options[:siem_platform] && @options[:siem_endpoint] && @options[:siem_token]
75
+ puts "Configuring SIEM integration (#{@options[:siem_platform]})..." if @options[:verbose]
76
+ AiRootShield.configure_siem(@options[:siem_platform].to_sym, {
77
+ api_endpoint: @options[:siem_endpoint],
78
+ api_key: @options[:siem_token]
79
+ })
80
+ end
81
+
82
+ # Configure enterprise policy if provided
83
+ if @options[:policy_file]
84
+ puts "Loading enterprise policy from #{@options[:policy_file]}..." if @options[:verbose]
85
+ AiRootShield.configure_policy(@options[:policy_file])
86
+ end
87
+
88
+ # Configure certificate pinning if enabled
89
+ if @options[:enable_certificate_pinning]
90
+ puts "Configuring certificate pinning..." if @options[:verbose]
91
+ AiRootShield.configure_certificate_pinning
92
+ end
93
+
94
+ # Configure proxy detection if enabled
95
+ if @options[:enable_proxy_detection]
96
+ puts "Configuring proxy detection..." if @options[:verbose]
97
+ AiRootShield.configure_proxy_detection
98
+ end
99
+
43
100
  # Start RASP protection if enabled
44
101
  if @options[:enable_rasp_protection]
45
102
  puts "Starting RASP protection..." if @options[:verbose]
@@ -60,13 +117,34 @@ class AiRootShieldCLI
60
117
  sleep(@options[:rasp_monitoring_time])
61
118
  end
62
119
 
63
- result = AiRootShield.scan_device_with_config(device_logs_path, @options)
120
+ # Run analysis based on mode
121
+ if @options[:ci_mode]
122
+ result = run_ci_cd_analysis(device_logs_path)
123
+ elsif @options[:platform]
124
+ result = run_platform_specific_analysis(device_logs_path)
125
+ else
126
+ result = AiRootShield.scan_device_with_config(device_logs_path, @options)
127
+ end
128
+
129
+ # Send to SIEM if configured
130
+ if @options[:siem_platform]
131
+ puts "Sending results to SIEM..." if @options[:verbose]
132
+ AiRootShield.send_to_siem(result, {
133
+ cli_version: AiRootShield::VERSION,
134
+ scan_timestamp: Time.now.utc.iso8601
135
+ })
136
+ end
64
137
 
65
138
  # Add RASP status to result if enabled
66
139
  if @options[:enable_rasp_protection] && AiRootShield.rasp_active?
67
140
  result[:rasp_status] = AiRootShield.rasp_protection.protection_status
68
141
  end
69
142
 
143
+ # Add security status if verbose
144
+ if @options[:verbose]
145
+ result[:security_status] = AiRootShield.security_status
146
+ end
147
+
70
148
  output_result(result)
71
149
 
72
150
  rescue AiRootShield::Error => e
@@ -136,6 +214,90 @@ class AiRootShieldCLI
136
214
  @options[:rasp_monitoring_time] = time
137
215
  end
138
216
 
217
+ opts.on("--policy FILE", "Enterprise policy file path") do |file|
218
+ @options[:policy_file] = file
219
+ end
220
+
221
+ opts.on("--enable-cert-pinning", "Enable certificate pinning validation") do
222
+ @options[:enable_certificate_pinning] = true
223
+ end
224
+
225
+ opts.on("--enable-proxy-detection", "Enable advanced proxy detection") do
226
+ @options[:enable_proxy_detection] = true
227
+ end
228
+
229
+ opts.on("--target-ip IP", "Target IP address for network analysis") do |ip|
230
+ @options[:target_ip] = ip
231
+ end
232
+
233
+ opts.on("--target-url URL", "Target URL for certificate pinning validation") do |url|
234
+ @options[:target_url] = url
235
+ end
236
+
237
+ # v0.5.0 Platform-specific options
238
+ opts.separator ""
239
+ opts.separator "Platform-specific Analysis (v0.5.0):"
240
+
241
+ opts.on("--platform PLATFORM", ["android", "ios"], "Platform-specific analysis (android, ios)") do |platform|
242
+ @options[:platform] = platform
243
+ end
244
+
245
+ opts.on("--safetynet-key KEY", "Google SafetyNet API key for Android analysis") do |key|
246
+ @options[:safetynet_api_key] = key
247
+ end
248
+
249
+ opts.on("--package-name NAME", "Android package name for analysis") do |name|
250
+ @options[:package_name] = name
251
+ end
252
+
253
+ opts.on("--unified-report", "Generate unified cross-platform report") do
254
+ @options[:enable_unified_reporting] = true
255
+ end
256
+
257
+ # CI/CD Integration options
258
+ opts.separator ""
259
+ opts.separator "CI/CD Integration (v0.5.0):"
260
+
261
+ opts.on("--ci-mode", "Run in CI/CD mode with test artifacts") do
262
+ @options[:ci_mode] = true
263
+ end
264
+
265
+ opts.on("--artifacts-path PATH", "Path for CI/CD test artifacts (default: ./security_test_artifacts)") do |path|
266
+ @options[:artifacts_path] = path
267
+ end
268
+
269
+ opts.on("--generate-ci-config PLATFORM", ["github", "gitlab", "jenkins", "azure"], "Generate CI config for platform") do |platform|
270
+ @options[:generate_ci_config] = platform
271
+ end
272
+
273
+ # SIEM Integration options
274
+ opts.separator ""
275
+ opts.separator "SIEM Integration (v0.5.0):"
276
+
277
+ opts.on("--siem-platform PLATFORM", ["splunk", "elastic", "qradar", "sentinel", "datadog", "chronicle", "arcsight"], "SIEM platform") do |platform|
278
+ @options[:siem_platform] = platform
279
+ end
280
+
281
+ opts.on("--siem-endpoint URL", "SIEM API endpoint URL") do |url|
282
+ @options[:siem_endpoint] = url
283
+ end
284
+
285
+ opts.on("--siem-token TOKEN", "SIEM API authentication token") do |token|
286
+ @options[:siem_token] = token
287
+ end
288
+
289
+ # Dashboard options
290
+ opts.separator ""
291
+ opts.separator "Dashboard (v0.5.0):"
292
+
293
+ opts.on("--start-dashboard", "Start web dashboard server") do
294
+ @options[:start_dashboard] = true
295
+ end
296
+
297
+ opts.on("--dashboard-port PORT", Integer, "Dashboard port (default: 4567)") do |port|
298
+ @options[:dashboard_port] = port
299
+ end
300
+
139
301
  opts.on("-h", "--help", "Show this help message") do
140
302
  puts opts
141
303
  exit
@@ -149,7 +311,7 @@ class AiRootShieldCLI
149
311
  end
150
312
 
151
313
  def output_result(result)
152
- case @options[:output_format]
314
+ case @options[:format]
153
315
  when "json"
154
316
  puts JSON.pretty_generate(result)
155
317
  when "text"
@@ -167,6 +329,42 @@ class AiRootShieldCLI
167
329
  puts "Version: #{result[:version]}"
168
330
  puts ""
169
331
 
332
+ # Display compliance status if available
333
+ if result[:compliance]
334
+ puts "Policy Compliance:"
335
+ puts " Status: #{result[:compliance][:compliant] ? 'COMPLIANT' : 'NON-COMPLIANT'}"
336
+ puts " Policy Version: #{result[:compliance][:policy_version]}"
337
+
338
+ if result[:compliance][:violations].any?
339
+ puts " Violations:"
340
+ result[:compliance][:violations].each do |violation|
341
+ puts " • #{violation[:message]} (#{violation[:severity]})"
342
+ end
343
+ end
344
+ puts ""
345
+ end
346
+
347
+ # Display network analysis if available
348
+ if result[:network_analysis]
349
+ puts "Network Security Analysis:"
350
+
351
+ if result[:network_analysis][:proxy_detection]
352
+ proxy = result[:network_analysis][:proxy_detection]
353
+ puts " Proxy Detection: #{proxy[:proxy_detected] ? 'DETECTED' : 'Clean'}"
354
+ if proxy[:proxy_detected]
355
+ puts " Types: #{proxy[:proxy_types].join(', ')}"
356
+ puts " Confidence: #{(proxy[:confidence_score] * 100).round}%"
357
+ end
358
+ end
359
+
360
+ if result[:network_analysis][:certificate_pinning]
361
+ pinning = result[:network_analysis][:certificate_pinning]
362
+ puts " Certificate Pinning: #{pinning[:valid] ? 'VALID' : 'FAILED'}"
363
+ puts " Reason: #{pinning[:reason]}" unless pinning[:valid]
364
+ end
365
+ puts ""
366
+ end
367
+
170
368
  if result[:factors].any?
171
369
  puts "Detected Security Factors:"
172
370
  result[:factors].each do |factor|
@@ -184,17 +382,125 @@ class AiRootShieldCLI
184
382
  else
185
383
  puts "No security threats detected."
186
384
  end
385
+
386
+ # Display RASP status if available
387
+ if result[:rasp_status]
388
+ puts ""
389
+ puts "RASP Protection Status:"
390
+ puts " Active: #{result[:rasp_status][:active] ? 'YES' : 'NO'}"
391
+ puts " Events Detected: #{result[:rasp_status][:events_detected] || 0}"
392
+ puts " Protection Level: #{result[:rasp_status][:protection_level] || 'Standard'}"
393
+ end
187
394
  end
188
395
 
189
396
  def output_summary_format(result)
190
- risk_level = AiRootShield::RiskCalculator.risk_level_description(result[:risk_score])
397
+ # Handle unified report format
398
+ if result[:executive_summary]
399
+ risk_level = result[:executive_summary][:overall_risk_level]
400
+ security_score = result[:executive_summary][:security_posture_score]
401
+ threat_count = result[:executive_summary][:critical_findings]&.length || 0
402
+
403
+ puts "Risk Level: #{risk_level} (Security Score: #{security_score}/100)"
404
+ puts "Threats: #{threat_count} critical findings detected"
405
+
406
+ if result[:executive_summary][:key_recommendations]&.any?
407
+ puts "Primary Concerns: #{result[:executive_summary][:key_recommendations].first(3).join(', ')}"
408
+ end
409
+ else
410
+ # Handle regular analysis format
411
+ risk_level = AiRootShield::RiskCalculator.risk_level_description(result[:risk_score])
412
+
413
+ puts "Risk Level: #{risk_level} (#{result[:risk_score]}/100)"
414
+ puts "Threats: #{result[:factors]&.length || 0} detected"
415
+
416
+ if result[:factors]&.any?
417
+ puts "Primary Concerns: #{result[:factors].first(3).join(', ')}"
418
+ end
419
+ end
420
+ end
421
+
422
+ # v0.5.0 New Methods
423
+ def run_platform_specific_analysis(device_logs_path)
424
+ puts "Running #{@options[:platform]} platform-specific analysis..." if @options[:verbose]
191
425
 
192
- puts "Risk Level: #{risk_level} (#{result[:risk_score]}/100)"
193
- puts "Threats: #{result[:factors].length} detected"
426
+ case @options[:platform]
427
+ when 'android'
428
+ config = {}
429
+ config[:safetynet_api_key] = @options[:safetynet_api_key] if @options[:safetynet_api_key]
430
+ config[:package_name] = @options[:package_name] if @options[:package_name]
431
+
432
+ result = AiRootShield.analyze_android_device(device_logs_path, config)
433
+ when 'ios'
434
+ result = AiRootShield.analyze_ios_device(device_logs_path)
435
+ else
436
+ raise "Unsupported platform: #{@options[:platform]}"
437
+ end
194
438
 
195
- if result[:factors].any?
196
- puts "Primary Concerns: #{result[:factors].first(3).join(', ')}"
439
+ if @options[:enable_unified_reporting]
440
+ puts "Generating unified cross-platform report..." if @options[:verbose]
441
+ case @options[:platform]
442
+ when 'android'
443
+ unified_result = AiRootShield.generate_unified_report(android_results: result)
444
+ when 'ios'
445
+ unified_result = AiRootShield.generate_unified_report(ios_results: result)
446
+ end
447
+ return unified_result
197
448
  end
449
+
450
+ result
451
+ end
452
+
453
+ def run_ci_cd_analysis(device_logs_path)
454
+ puts "Running CI/CD security analysis..." if @options[:verbose]
455
+
456
+ # Create artifacts directory
457
+ Dir.mkdir(@options[:artifacts_path]) unless Dir.exist?(@options[:artifacts_path])
458
+
459
+ # Run CI/CD tests
460
+ result = AiRootShield.run_ci_cd_tests(device_logs_path, {
461
+ artifacts_path: @options[:artifacts_path],
462
+ verbose: @options[:verbose]
463
+ })
464
+
465
+ puts "CI/CD test artifacts saved to: #{@options[:artifacts_path]}" if @options[:verbose]
466
+ result
467
+ end
468
+
469
+ def start_dashboard
470
+ puts "Starting AI Root Shield Dashboard on port #{@options[:dashboard_port]}..."
471
+ puts "Dashboard will be available at: http://localhost:#{@options[:dashboard_port]}"
472
+ puts "Press Ctrl+C to stop the dashboard"
473
+
474
+ begin
475
+ AiRootShield.start_dashboard(@options[:dashboard_port])
476
+ rescue Interrupt
477
+ puts "\nDashboard stopped."
478
+ end
479
+ end
480
+
481
+ def generate_ci_config
482
+ puts "Generating CI/CD configuration for #{@options[:generate_ci_config]}..."
483
+
484
+ config_content = AiRootShield.generate_ci_config(@options[:generate_ci_config].to_sym)
485
+
486
+ filename = case @options[:generate_ci_config]
487
+ when 'github'
488
+ '.github/workflows/security-scan.yml'
489
+ when 'gitlab'
490
+ '.gitlab-ci.yml'
491
+ when 'jenkins'
492
+ 'Jenkinsfile'
493
+ when 'azure'
494
+ 'azure-pipelines.yml'
495
+ end
496
+
497
+ # Create directory if needed
498
+ dir = File.dirname(filename)
499
+ FileUtils.mkdir_p(dir) unless Dir.exist?(dir) || dir == '.'
500
+
501
+ File.write(filename, config_content)
502
+ puts "CI/CD configuration saved to: #{filename}"
503
+ puts "Please review and customize the configuration as needed."
198
504
  end
199
505
  end
200
506