beskar 0.0.1 → 0.0.2

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.
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ Beskar.configure do |config|
4
+ # ============================================================================
5
+ # Web Application Firewall (WAF) - ENABLED IN MONITOR MODE BY DEFAULT
6
+ # ============================================================================
7
+ # Detects and logs vulnerability scanning attempts (WordPress, phpMyAdmin, etc.)
8
+ # Start in monitor-only mode to observe patterns before enabling blocking.
9
+ #
10
+ config.waf = {
11
+ enabled: true, # Master switch for WAF
12
+ monitor_only: true, # LOG ONLY - does not block (recommended to start)
13
+ auto_block: true, # Auto-block IPs after threshold (when monitor_only=false)
14
+ block_threshold: 3, # Number of violations before blocking
15
+ violation_window: 1.hour, # Time window for counting violations
16
+ block_durations: [1.hour, 6.hours, 24.hours, 7.days], # Escalating ban durations
17
+ permanent_block_after: 5, # Permanent ban after N violations (nil = never)
18
+ create_security_events: true # Log violations to SecurityEvent table
19
+ }
20
+
21
+ # After monitoring for 24-48 hours, review logs and disable monitor_only:
22
+ # config.waf[:monitor_only] = false
23
+
24
+ # View WAF activity in logs:
25
+ # tail -f log/production.log | grep "Beskar::WAF"
26
+
27
+ # Query violations that would be blocked:
28
+ # Beskar::SecurityEvent.where(event_type: 'waf_violation')
29
+ # .where("metadata->>'would_be_blocked' = ?", 'true').count
30
+
31
+ # ============================================================================
32
+ # IP Whitelisting (RECOMMENDED)
33
+ # ============================================================================
34
+ # Trusted IPs bypass all blocking (bans, rate limits, WAF) while still
35
+ # logging activity for audit purposes.
36
+ #
37
+ # config.ip_whitelist = [
38
+ # "192.168.1.100", # Single IP address
39
+ # "10.0.0.0/24", # CIDR notation - entire subnet
40
+ # "172.16.0.0/16" # Larger CIDR range
41
+ # # Add your office IPs, monitoring services, trusted partners, etc.
42
+ # ]
43
+
44
+ # ============================================================================
45
+ # Security Event Tracking (OPTIONAL)
46
+ # ============================================================================
47
+ # Track authentication events for risk analysis and threat detection.
48
+ # Disable if you don't need historical security event data.
49
+ #
50
+ # config.security_tracking = {
51
+ # enabled: true, # Master switch for all tracking
52
+ # track_successful_logins: true, # Track successful authentications
53
+ # track_failed_logins: true, # Track failed authentication attempts
54
+ # auto_analyze_patterns: true # Enable automatic pattern analysis
55
+ # }
56
+
57
+ # ============================================================================
58
+ # Rate Limiting (OPTIONAL)
59
+ # ============================================================================
60
+ # Protect against brute force attacks by limiting authentication attempts.
61
+ #
62
+ # config.rate_limiting = {
63
+ # ip_attempts: {
64
+ # limit: 10, # Max attempts per IP
65
+ # period: 1.hour, # Time window
66
+ # exponential_backoff: true # Increase delay after each attempt
67
+ # },
68
+ # account_attempts: {
69
+ # limit: 5, # Max attempts per account
70
+ # period: 15.minutes,
71
+ # exponential_backoff: true
72
+ # },
73
+ # global_attempts: {
74
+ # limit: 100, # System-wide limit (DDoS protection)
75
+ # period: 1.minute,
76
+ # exponential_backoff: false
77
+ # }
78
+ # }
79
+
80
+ # ============================================================================
81
+ # Risk-Based Account Locking (OPTIONAL)
82
+ # ============================================================================
83
+ # Automatically lock accounts when authentication risk score is too high.
84
+ # Requires Devise :lockable module.
85
+ #
86
+ # config.risk_based_locking = {
87
+ # enabled: false, # Disabled by default
88
+ # risk_threshold: 75, # Lock if risk score >= this (0-100)
89
+ # lock_strategy: :devise_lockable, # Strategy: :devise_lockable, :custom, :none
90
+ # auto_unlock_time: 1.hour, # Time until automatic unlock
91
+ # notify_user: true, # Send notification on lock
92
+ # log_lock_events: true # Create security events for locks
93
+ # }
94
+
95
+ # ============================================================================
96
+ # IP Geolocation (OPTIONAL)
97
+ # ============================================================================
98
+ # Enhance risk assessment with geographic information.
99
+ # Requires MaxMind GeoLite2-City database (free with registration).
100
+ # Download from: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
101
+ #
102
+ # config.geolocation = {
103
+ # provider: :maxmind,
104
+ # maxmind_city_db_path: Rails.root.join('db', 'geoip', 'GeoLite2-City.mmdb').to_s,
105
+ # cache_ttl: 4.hours
106
+ # }
107
+ end
@@ -1,3 +1,3 @@
1
1
  module Beskar
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/beskar.rb CHANGED
@@ -1,6 +1,36 @@
1
1
  require "beskar/version"
2
+ require "beskar/configuration"
3
+ require "beskar/middleware"
4
+ require "beskar/middleware/request_analyzer"
5
+ require "beskar/models/security_trackable_generic"
6
+ require "beskar/models/security_trackable_devise"
7
+ require "beskar/models/security_trackable_authenticable"
8
+ require "beskar/models/security_trackable"
9
+ require "beskar/services/rate_limiter"
10
+ require "beskar/services/device_detector"
11
+ require "beskar/services/geolocation_service"
12
+ require "beskar/services/account_locker"
13
+ require "beskar/services/ip_whitelist"
14
+ require "beskar/services/waf"
2
15
  require "beskar/engine"
3
16
 
4
17
  module Beskar
5
- # Your code goes here...
18
+ class << self
19
+ attr_accessor :configuration
20
+ end
21
+
22
+ def self.configure
23
+ self.configuration ||= Configuration.new
24
+ yield(configuration)
25
+ end
26
+
27
+ # Convenience method to access the rate limiter
28
+ def self.rate_limiter
29
+ Services::RateLimiter
30
+ end
31
+
32
+ # Check if a request should be rate limited
33
+ def self.rate_limited?(request, user = nil)
34
+ Services::RateLimiter.is_rate_limited?(request, user)
35
+ end
6
36
  end
@@ -1,4 +1,112 @@
1
- # desc "Explaining what the task does"
2
- # task :beskar do
3
- # # Task goes here
4
- # end
1
+ # frozen_string_literal: true
2
+
3
+ namespace :beskar do
4
+ desc "Install Beskar: copy migrations and create initializer"
5
+ task install: :environment do
6
+ puts "=" * 80
7
+ puts "Installing Beskar Security..."
8
+ puts "=" * 80
9
+ puts
10
+
11
+ # Copy migrations
12
+ puts "📦 Copying migrations..."
13
+ begin
14
+ Rake::Task["beskar:install:migrations"].invoke
15
+ rescue RuntimeError
16
+ # In development/test within the gem, this task might not exist
17
+ # In a real app using the gem, it will work fine
18
+ puts " (Skipping migration copy in gem development mode)"
19
+ end
20
+ puts "✓ Migrations ready"
21
+ puts
22
+
23
+ # Create initializer
24
+ initializer_path = Rails.root.join("config/initializers/beskar.rb")
25
+
26
+ if File.exist?(initializer_path)
27
+ puts "⚠️ Initializer already exists at config/initializers/beskar.rb"
28
+ print " Overwrite? (y/N): "
29
+ response = $stdin.gets.chomp.downcase
30
+
31
+ unless response == 'y' || response == 'yes'
32
+ puts " Skipping initializer creation"
33
+ puts
34
+ next_steps
35
+ exit
36
+ end
37
+ end
38
+
39
+ puts "📝 Creating initializer..."
40
+ template_path = File.expand_path("../beskar/templates/beskar_initializer.rb", __dir__)
41
+ FileUtils.cp(template_path, initializer_path)
42
+ puts "✓ Created config/initializers/beskar.rb"
43
+ puts
44
+
45
+ next_steps
46
+ end
47
+
48
+ def next_steps
49
+ puts "=" * 80
50
+ puts "Beskar Security has been installed!"
51
+ puts "=" * 80
52
+ puts
53
+ puts "Next steps:"
54
+ puts
55
+ puts "1. Run migrations to create the security tables:"
56
+ puts
57
+ puts " bin/rails db:migrate"
58
+ puts
59
+ puts "2. Add the SecurityTrackable concern to your User model:"
60
+ puts
61
+ puts " # app/models/user.rb"
62
+ puts " class User < ApplicationRecord"
63
+ puts " include Beskar::SecurityTrackable"
64
+ puts " "
65
+ puts " devise :database_authenticatable, :registerable,"
66
+ puts " :recoverable, :rememberable, :validatable"
67
+ puts " # ... rest of your Devise modules"
68
+ puts " end"
69
+ puts
70
+ puts "3. Review the configuration file:"
71
+ puts
72
+ puts " config/initializers/beskar.rb"
73
+ puts
74
+ puts " By default, WAF is enabled in MONITOR-ONLY MODE. This means:"
75
+ puts " - Vulnerability scans are detected and logged"
76
+ puts " - No requests are blocked yet"
77
+ puts " - Security events are created for analysis"
78
+ puts
79
+ puts "4. Monitor WAF activity (recommended for 24-48 hours):"
80
+ puts
81
+ puts " # View all WAF logs"
82
+ puts " tail -f log/production.log | grep \"Beskar::WAF\""
83
+ puts " "
84
+ puts " # Check what would be blocked"
85
+ puts " rails console"
86
+ puts " > Beskar::SecurityEvent.where(event_type: 'waf_violation')"
87
+ puts " .where(\"metadata->>'would_be_blocked' = ?\", 'true').count"
88
+ puts
89
+ puts "5. When ready to enable blocking:"
90
+ puts
91
+ puts " # config/initializers/beskar.rb"
92
+ puts " config.waf = {"
93
+ puts " enabled: true,"
94
+ puts " monitor_only: false, # <-- Change this to false"
95
+ puts " # ... rest of config"
96
+ puts " }"
97
+ puts
98
+ puts "6. Optional: Add IP whitelist for trusted sources:"
99
+ puts
100
+ puts " # config/initializers/beskar.rb"
101
+ puts " config.ip_whitelist = ["
102
+ puts " \"YOUR_OFFICE_IP\","
103
+ puts " \"YOUR_MONITORING_SERVICE_IP\""
104
+ puts " ]"
105
+ puts
106
+ puts "=" * 80
107
+ puts "Documentation:"
108
+ puts " - README: https://github.com/humadroid-io/beskar"
109
+ puts " - WAF Monitor Mode: See MONITOR_ONLY_MODE.md"
110
+ puts "=" * 80
111
+ end
112
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beskar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Litwiniuk
@@ -23,6 +23,90 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 8.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: maxminddb
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: debug
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: devise
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: ostruct
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: factory_bot_rails
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: mocha
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
26
110
  description: |-
27
111
  Rails Security Shield is a comprehensive, Rails-native security engine designed to provide multi-layered protection for modern web applications. It actively defends against common threats by integrating a powerful Web Application Firewall (WAF) to block attacks like SQLi and XSS, an advanced bot detection system using JavaScript challenges and honeypots, and robust account takeover prevention to stop brute-force and credential stuffing attacks.
28
112
 
@@ -38,22 +122,42 @@ files:
38
122
  - Rakefile
39
123
  - app/assets/stylesheets/beskar/application.css
40
124
  - app/controllers/beskar/application_controller.rb
125
+ - app/controllers/concerns/beskar/controllers/security_tracking.rb
41
126
  - app/helpers/beskar/application_helper.rb
42
127
  - app/jobs/beskar/application_job.rb
43
128
  - app/mailers/beskar/application_mailer.rb
44
129
  - app/models/beskar/application_record.rb
130
+ - app/models/beskar/banned_ip.rb
131
+ - app/models/beskar/security_event.rb
45
132
  - app/views/layouts/beskar/application.html.erb
133
+ - config/locales/en.yml
46
134
  - config/routes.rb
135
+ - db/migrate/20251016000001_create_beskar_security_events.rb
136
+ - db/migrate/20251016000002_create_beskar_banned_ips.rb
47
137
  - lib/beskar.rb
138
+ - lib/beskar/configuration.rb
48
139
  - lib/beskar/engine.rb
140
+ - lib/beskar/middleware.rb
141
+ - lib/beskar/middleware/request_analyzer.rb
142
+ - lib/beskar/models/security_trackable.rb
143
+ - lib/beskar/models/security_trackable_authenticable.rb
144
+ - lib/beskar/models/security_trackable_devise.rb
145
+ - lib/beskar/models/security_trackable_generic.rb
146
+ - lib/beskar/services/account_locker.rb
147
+ - lib/beskar/services/device_detector.rb
148
+ - lib/beskar/services/geolocation_service.rb
149
+ - lib/beskar/services/ip_whitelist.rb
150
+ - lib/beskar/services/rate_limiter.rb
151
+ - lib/beskar/services/waf.rb
152
+ - lib/beskar/templates/beskar_initializer.rb
49
153
  - lib/beskar/version.rb
50
154
  - lib/tasks/beskar_tasks.rake
51
- homepage: https://humadroid.io/
155
+ homepage: https://humadroid.io/beskar
52
156
  licenses:
53
157
  - MIT
54
158
  metadata:
55
- homepage_uri: https://humadroid.io/
56
- source_code_uri: https://github.com/prograils/beskar
159
+ homepage_uri: https://humadroid.io/beskar
160
+ source_code_uri: https://github.com/humadroid-io/beskar
57
161
  rdoc_options: []
58
162
  require_paths:
59
163
  - lib