-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquickstart.sh
More file actions
1010 lines (896 loc) · 30.7 KB
/
Copy pathquickstart.sh
File metadata and controls
1010 lines (896 loc) · 30.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# bWall - Firewall Management Dashboard - Quickstart Script
# bWall by bunit.net
# This script automates the installation and setup process
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Log file
LOG_FILE="quickstart.log"
START_TIME=$(date +%s)
# Function to log messages
log() {
local level=$1
shift
local message="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# Function to print colored output
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
log "INFO" "$1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
log "SUCCESS" "$1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
log "WARNING" "$1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
log "ERROR" "$1"
}
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to detect OS
detect_os() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if command_exists apt-get; then
echo "debian"
elif command_exists yum; then
echo "rhel"
elif command_exists dnf; then
echo "fedora"
elif command_exists pacman; then
echo "arch"
else
echo "unknown"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo "macos"
else
echo "unknown"
fi
}
# Initialize log file
echo "=== bWall Quickstart Log ===" > "$LOG_FILE"
echo "Started: $(date)" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# Banner
clear
echo "=========================================="
echo " bWall - Firewall Management Dashboard"
echo " Quickstart Installation Script"
echo " by bunit.net"
echo "=========================================="
echo ""
print_info "Starting installation process..."
echo ""
# Check if running as root (will need for iptables)
if [ "$EUID" -ne 0 ]; then
print_warning "Not running as root. Some operations may require sudo."
SUDO_CMD="sudo"
else
SUDO_CMD=""
print_info "Running as root"
fi
# Step 1: Check Prerequisites
print_info "Step 1: Checking prerequisites..."
MISSING_PREREQS=()
# Check Python 3
if command_exists python3; then
PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
print_success "Python 3 found: $PYTHON_VERSION"
else
print_error "Python 3 not found"
MISSING_PREREQS+=("python3")
fi
# Check pip
if command_exists pip3 || command_exists pip; then
PIP_CMD=$(command_exists pip3 && echo "pip3" || echo "pip")
print_success "pip found: $PIP_CMD"
else
print_error "pip not found"
MISSING_PREREQS+=("python3-pip")
fi
# Check iptables
if command_exists iptables; then
IPTABLES_VERSION=$(iptables --version 2>&1 | head -n1)
print_success "iptables found: $IPTABLES_VERSION"
else
print_error "iptables not found"
MISSING_PREREQS+=("iptables")
fi
# Check MariaDB/MySQL client
if command_exists mysql; then
print_success "MySQL/MariaDB client found"
else
print_warning "MySQL/MariaDB client not found (will be installed with server)"
fi
if [ ${#MISSING_PREREQS[@]} -gt 0 ]; then
print_warning "Missing prerequisites: ${MISSING_PREREQS[*]}"
OS=$(detect_os)
if [ "$OS" == "debian" ] || [ "$OS" == "ubuntu" ]; then
print_info "To install missing prerequisites on Debian/Ubuntu, run:"
echo " $SUDO_CMD apt-get update && $SUDO_CMD apt-get install -y ${MISSING_PREREQS[*]}"
read -p "Install missing prerequisites now? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
$SUDO_CMD apt-get update
$SUDO_CMD apt-get install -y "${MISSING_PREREQS[@]}"
print_success "Prerequisites installed"
fi
elif [ "$OS" == "rhel" ] || [ "$OS" == "fedora" ]; then
print_info "To install missing prerequisites on RHEL/Fedora, run:"
echo " $SUDO_CMD yum install -y ${MISSING_PREREQS[*]}"
read -p "Install missing prerequisites now? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
$SUDO_CMD yum install -y "${MISSING_PREREQS[@]}"
print_success "Prerequisites installed"
fi
elif [ "$OS" == "macos" ]; then
print_info "On macOS, install prerequisites using Homebrew:"
echo " brew install python3"
read -p "Continue anyway? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
else
print_error "Unknown OS. Please install prerequisites manually."
exit 1
fi
fi
echo ""
# Step 2: Check MariaDB Server
print_info "Step 2: Checking MariaDB/MySQL server..."
MARIADB_RUNNING=false
if command_exists systemctl; then
if systemctl is-active --quiet mariadb 2>/dev/null || systemctl is-active --quiet mysql 2>/dev/null; then
MARIADB_RUNNING=true
print_success "MariaDB/MySQL server is running"
else
print_warning "MariaDB/MySQL server is not running"
fi
elif command_exists service; then
if service mariadb status >/dev/null 2>&1 || service mysql status >/dev/null 2>&1; then
MARIADB_RUNNING=true
print_success "MariaDB/MySQL server is running"
else
print_warning "MariaDB/MySQL server is not running"
fi
else
# Try to connect to check if running
if mysql -u root -e "SELECT 1" >/dev/null 2>&1; then
MARIADB_RUNNING=true
print_success "MariaDB/MySQL server is accessible"
else
print_warning "Cannot determine MariaDB/MySQL server status"
fi
fi
if [ "$MARIADB_RUNNING" = false ]; then
OS=$(detect_os)
print_warning "MariaDB/MySQL server not detected"
read -p "Would you like to install MariaDB server? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "Installing MariaDB server..."
if [ "$OS" == "debian" ] || [ "$OS" == "ubuntu" ]; then
$SUDO_CMD apt-get update
$SUDO_CMD apt-get install -y mariadb-server
$SUDO_CMD systemctl start mariadb
$SUDO_CMD systemctl enable mariadb
print_success "MariaDB server installed and started"
elif [ "$OS" == "rhel" ] || [ "$OS" == "fedora" ]; then
$SUDO_CMD yum install -y mariadb-server
$SUDO_CMD systemctl start mariadb
$SUDO_CMD systemctl enable mariadb
print_success "MariaDB server installed and started"
elif [ "$OS" == "macos" ]; then
if command_exists brew; then
brew install mariadb
brew services start mariadb
print_success "MariaDB server installed and started"
else
print_error "Homebrew not found. Please install MariaDB manually."
exit 1
fi
else
print_error "Cannot auto-install MariaDB on this OS. Please install manually."
exit 1
fi
# Secure installation
print_info "Running MariaDB secure installation..."
print_warning "You will be prompted to set a root password and configure security options"
$SUDO_CMD mysql_secure_installation
else
print_warning "Skipping MariaDB installation. You'll need to set it up manually."
fi
fi
echo ""
# Step 3: Install Python Requirements
print_info "Step 3: Installing Python requirements..."
if [ -f "requirements.txt" ]; then
PIP_CMD=$(command_exists pip3 && echo "pip3" || echo "pip")
# Ensure setuptools is installed first (required for pkg_resources)
print_info "Installing setuptools (required dependency)..."
$PIP_CMD install --upgrade setuptools >/dev/null 2>&1 || true
# Ensure future package is compatible with Python 3.13
print_info "Installing/upgrading future package (Python 3.13 compatibility)..."
$PIP_CMD install --upgrade 'future>=0.18.3' >/dev/null 2>&1 || true
print_info "Installing packages from requirements.txt..."
if $PIP_CMD install -r requirements.txt; then
print_success "Python requirements installed"
else
print_error "Failed to install Python requirements"
print_warning "If you encounter Python 3.13 compatibility issues, see FIX_PYTHON313.md"
exit 1
fi
else
print_error "requirements.txt not found"
exit 1
fi
echo ""
# Step 4: Database Setup
print_info "Step 4: Setting up database..."
# Get database configuration
read -p "Database host [localhost]: " DB_HOST
DB_HOST=${DB_HOST:-localhost}
read -p "Database root user [root]: " DB_ROOT_USER
DB_ROOT_USER=${DB_ROOT_USER:-root}
read -sp "Database root password: " DB_ROOT_PASSWORD
echo ""
read -p "Database name [iptables_db]: " DB_NAME
DB_NAME=${DB_NAME:-iptables_db}
read -p "Database user [iptables_user]: " DB_USER
DB_USER=${DB_USER:-iptables_user}
read -sp "Database user password: " DB_PASSWORD
echo ""
# Test database connection
print_info "Testing database connection..."
if mysql -h "$DB_HOST" -u "$DB_ROOT_USER" -p"$DB_ROOT_PASSWORD" -e "SELECT 1" >/dev/null 2>&1; then
print_success "Database connection successful"
else
print_error "Cannot connect to database. Please check credentials."
exit 1
fi
# Create database and user
print_info "Creating database and user..."
mysql -h "$DB_HOST" -u "$DB_ROOT_USER" -p"$DB_ROOT_PASSWORD" <<EOF
CREATE DATABASE IF NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost';
FLUSH PRIVILEGES;
EOF
if [ $? -eq 0 ]; then
print_success "Database and user created"
else
print_error "Failed to create database or user"
exit 1
fi
# Create database schema (tables)
print_info "Creating database schema..."
mysql -h "$DB_HOST" -u "$DB_ROOT_USER" -p"$DB_ROOT_PASSWORD" "$DB_NAME" <<EOF
-- Whitelist table
CREATE TABLE IF NOT EXISTS whitelist (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL UNIQUE,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_ip (ip_address),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Blacklist table
CREATE TABLE IF NOT EXISTS blacklist (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL UNIQUE,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_ip (ip_address),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Rules table
CREATE TABLE IF NOT EXISTS rules (
id INT AUTO_INCREMENT PRIMARY KEY,
chain VARCHAR(50),
target VARCHAR(50),
protocol VARCHAR(10),
source VARCHAR(45),
destination VARCHAR(45),
options TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_chain (chain),
INDEX idx_source (source)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Activity log table
CREATE TABLE IF NOT EXISTS activity_log (
id INT AUTO_INCREMENT PRIMARY KEY,
action VARCHAR(50) NOT NULL,
type VARCHAR(20),
entry VARCHAR(255),
status VARCHAR(20),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_timestamp (timestamp),
INDEX idx_type (type),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Sync log table
CREATE TABLE IF NOT EXISTS sync_log (
id INT AUTO_INCREMENT PRIMARY KEY,
direction VARCHAR(20),
whitelist_synced INT DEFAULT 0,
blacklist_synced INT DEFAULT 0,
rules_synced INT DEFAULT 0,
status VARCHAR(20),
message TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_timestamp (timestamp),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- AbuseIPDB report queue table
CREATE TABLE IF NOT EXISTS abuseipdb_queue (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL,
categories JSON NOT NULL,
comment TEXT,
service VARCHAR(50),
attack_type VARCHAR(50),
source VARCHAR(20) DEFAULT 'auto',
status VARCHAR(20) DEFAULT 'pending',
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
submitted_at TIMESTAMP NULL,
INDEX idx_status (status),
INDEX idx_ip (ip_address),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- URL-based IP lists table
CREATE TABLE IF NOT EXISTS url_lists (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
url TEXT NOT NULL,
list_type VARCHAR(20) NOT NULL,
enabled BOOLEAN DEFAULT TRUE,
auto_sync BOOLEAN DEFAULT FALSE,
sync_interval INT DEFAULT 3600,
last_sync TIMESTAMP NULL,
last_success TIMESTAMP NULL,
last_error TEXT,
entry_count INT DEFAULT 0,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_type (list_type),
INDEX idx_enabled (enabled),
INDEX idx_last_sync (last_sync)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Users table for local authentication
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(255),
full_name VARCHAR(255),
is_active BOOLEAN DEFAULT TRUE,
is_admin BOOLEAN DEFAULT FALSE,
failed_login_attempts INT DEFAULT 0,
locked_until TIMESTAMP NULL,
last_login TIMESTAMP NULL,
password_changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_active (is_active),
INDEX idx_locked (locked_until)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- User sessions table for secure session management
CREATE TABLE IF NOT EXISTS user_sessions (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
session_token VARCHAR(255) NOT NULL UNIQUE,
ip_address VARCHAR(45),
user_agent TEXT,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user (user_id),
INDEX idx_token (session_token),
INDEX idx_expires (expires_at),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- System settings table for customization
CREATE TABLE IF NOT EXISTS system_settings (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) NOT NULL UNIQUE,
setting_value TEXT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_key (setting_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Monitored services configuration table
CREATE TABLE IF NOT EXISTS monitored_services (
id INT AUTO_INCREMENT PRIMARY KEY,
service_name VARCHAR(50) NOT NULL UNIQUE,
enabled BOOLEAN DEFAULT TRUE,
threshold INT DEFAULT 5,
duration_minutes INT DEFAULT 60,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_enabled (enabled),
INDEX idx_service (service_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Permanent ban blacklist table
CREATE TABLE IF NOT EXISTS permaban_blacklist (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL UNIQUE,
abuse_count INT DEFAULT 0,
abuse_score INT DEFAULT 0,
first_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
reason TEXT,
INDEX idx_ip (ip_address),
INDEX idx_score (abuse_score),
INDEX idx_last_seen (last_seen)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Abuse history table for tracking all monitoring events
CREATE TABLE IF NOT EXISTS abuse_history (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL,
service VARCHAR(50),
attack_type VARCHAR(50),
severity VARCHAR(20) DEFAULT 'medium',
blocked BOOLEAN DEFAULT FALSE,
reported_to_abuseipdb BOOLEAN DEFAULT FALSE,
permabanned BOOLEAN DEFAULT FALSE,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_ip (ip_address),
INDEX idx_timestamp (timestamp),
INDEX idx_service (service),
INDEX idx_blocked (blocked)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
EOF
if [ $? -eq 0 ]; then
print_success "Database schema created"
else
print_error "Failed to create database schema"
exit 1
fi
# Create views
print_info "Creating database views..."
mysql -h "$DB_HOST" -u "$DB_ROOT_USER" -p"$DB_ROOT_PASSWORD" "$DB_NAME" <<EOF
-- View: Recent activity summary
CREATE OR REPLACE VIEW v_recent_activity AS
SELECT
DATE(timestamp) as date,
type,
status,
COUNT(*) as count
FROM activity_log
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(timestamp), type, status
ORDER BY date DESC, type, status;
-- View: Whitelist summary
CREATE OR REPLACE VIEW v_whitelist_summary AS
SELECT
COUNT(*) as total_entries,
COUNT(DISTINCT SUBSTRING_INDEX(ip_address, '/', 1)) as unique_ips,
MIN(created_at) as first_entry,
MAX(created_at) as last_entry
FROM whitelist;
-- View: Blacklist summary
CREATE OR REPLACE VIEW v_blacklist_summary AS
SELECT
COUNT(*) as total_entries,
COUNT(DISTINCT SUBSTRING_INDEX(ip_address, '/', 1)) as unique_ips,
MIN(created_at) as first_entry,
MAX(created_at) as last_entry
FROM blacklist;
-- View: Sync status
CREATE OR REPLACE VIEW v_sync_status AS
SELECT
direction,
SUM(whitelist_synced) as total_whitelist_synced,
SUM(blacklist_synced) as total_blacklist_synced,
SUM(rules_synced) as total_rules_synced,
COUNT(*) as sync_count,
MAX(timestamp) as last_sync
FROM sync_log
GROUP BY direction;
EOF
if [ $? -eq 0 ]; then
print_success "Database views created"
else
print_warning "Some views may not have been created (this is okay if they already exist)"
fi
# Create stored procedures for reports
print_info "Creating stored procedures for reports..."
mysql -h "$DB_HOST" -u "$DB_ROOT_USER" -p"$DB_ROOT_PASSWORD" "$DB_NAME" <<EOF
DELIMITER //
-- Procedure: Get daily activity report
CREATE PROCEDURE IF NOT EXISTS sp_daily_activity_report(IN days INT)
BEGIN
SELECT
DATE(timestamp) as date,
action,
type,
status,
COUNT(*) as count
FROM activity_log
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL days DAY)
GROUP BY DATE(timestamp), action, type, status
ORDER BY date DESC, action, type;
END //
-- Procedure: Get top blocked IPs
CREATE PROCEDURE IF NOT EXISTS sp_top_blocked_ips(IN limit_count INT)
BEGIN
SELECT
ip_address,
description,
created_at,
(SELECT COUNT(*) FROM activity_log
WHERE entry = blacklist.ip_address AND type = 'blacklist') as block_count
FROM blacklist
ORDER BY created_at DESC
LIMIT limit_count;
END //
-- Procedure: Get sync statistics
CREATE PROCEDURE IF NOT EXISTS sp_sync_statistics(IN days INT)
BEGIN
SELECT
direction,
COUNT(*) as total_syncs,
SUM(whitelist_synced) as total_whitelist,
SUM(blacklist_synced) as total_blacklist,
SUM(rules_synced) as total_rules,
AVG(whitelist_synced + blacklist_synced + rules_synced) as avg_entries_per_sync,
MAX(timestamp) as last_sync
FROM sync_log
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL days DAY)
GROUP BY direction;
END //
DELIMITER ;
EOF
if [ $? -eq 0 ]; then
print_success "Stored procedures created"
else
print_warning "Some procedures may not have been created (this is okay if they already exist)"
fi
echo ""
# Step 5: Authentication Configuration
print_info "Step 5: Authentication Configuration"
echo ""
echo "bWall supports multiple authentication types:"
echo " - ENV: Simple username/password from .env file (ADMIN_USERNAME, ADMIN_PASSWORD)"
echo " - OIDC: OpenID Connect (PocketID, etc.)"
echo " - LOCAL: Database-backed user accounts"
echo ""
echo "You can specify one or more (comma-separated), e.g., 'ENV,OIDC' will try ENV first, then OIDC"
echo ""
read -p "Authentication type(s) [ENV,OIDC,LOCAL or leave blank for auto-detect]: " AUTH_TYPE_INPUT
AUTH_TYPE_INPUT=${AUTH_TYPE_INPUT:-""}
# Step 5a: ENV Authentication Configuration
if [[ "$AUTH_TYPE_INPUT" == *"ENV"* ]] || [[ -z "$AUTH_TYPE_INPUT" ]]; then
print_info "Step 5a: ENV Authentication Configuration"
echo ""
read -p "Would you like to configure ENV authentication? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
read -p "Admin Username [bwall]: " ADMIN_USERNAME_INPUT
ADMIN_USERNAME_INPUT=${ADMIN_USERNAME_INPUT:-bwall}
read -sp "Admin Password [ReadGoodBooks&BadNetworks]: " ADMIN_PASSWORD_INPUT
echo ""
ADMIN_PASSWORD_INPUT=${ADMIN_PASSWORD_INPUT:-ReadGoodBooks&BadNetworks}
if [ -n "$ADMIN_USERNAME_INPUT" ] && [ -n "$ADMIN_PASSWORD_INPUT" ]; then
ADMIN_USERNAME="$ADMIN_USERNAME_INPUT"
ADMIN_PASSWORD="$ADMIN_PASSWORD_INPUT"
print_success "ENV authentication configured"
else
print_warning "ENV authentication skipped (missing username or password)"
ADMIN_USERNAME=""
ADMIN_PASSWORD=""
fi
else
ADMIN_USERNAME=""
ADMIN_PASSWORD=""
fi
else
ADMIN_USERNAME=""
ADMIN_PASSWORD=""
fi
# Step 5b: OIDC/PocketID Configuration
if [[ "$AUTH_TYPE_INPUT" == *"OIDC"* ]] || [[ -z "$AUTH_TYPE_INPUT" ]]; then
print_info "Step 5b: OIDC/PocketID Configuration"
echo ""
read -p "Would you like to configure PocketID OIDC authentication? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "PocketID OIDC Configuration"
echo "Please have the following information ready:"
echo " - PocketID Issuer URL"
echo " - Client ID"
echo " - Client Secret"
echo " - Redirect URI (callback URL)"
echo ""
read -p "PocketID Issuer URL: " OIDC_ISSUER
read -p "OIDC Client ID: " OIDC_CLIENT_ID
read -sp "OIDC Client Secret: " OIDC_CLIENT_SECRET
echo ""
read -p "Redirect URI [http://localhost:5000/oidc_callback]: " OIDC_REDIRECT_URI
OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI:-http://localhost:5000/oidc_callback}
read -p "Post-Logout Redirect URI [http://localhost:5000/]: " OIDC_POST_LOGOUT_URI
OIDC_POST_LOGOUT_URI=${OIDC_POST_LOGOUT_URI:-http://localhost:5000/}
print_success "OIDC configuration collected"
else
print_info "Skipping OIDC configuration. You can configure it later using environment variables."
OIDC_ISSUER=""
OIDC_CLIENT_ID=""
OIDC_CLIENT_SECRET=""
OIDC_REDIRECT_URI=""
OIDC_POST_LOGOUT_URI=""
fi
else
OIDC_ISSUER=""
OIDC_CLIENT_ID=""
OIDC_CLIENT_SECRET=""
OIDC_REDIRECT_URI=""
OIDC_POST_LOGOUT_URI=""
fi
# Determine AUTH_TYPE
if [ -z "$AUTH_TYPE_INPUT" ]; then
# Auto-detect based on what's configured
AUTH_TYPES_LIST=()
# Default to ENV if not explicitly configured
if [ -z "$ADMIN_USERNAME" ] && [ -z "$ADMIN_PASSWORD" ]; then
# Use defaults
ADMIN_USERNAME="bwall"
ADMIN_PASSWORD="ReadGoodBooks&BadNetworks"
fi
if [ -n "$ADMIN_USERNAME" ] && [ -n "$ADMIN_PASSWORD" ]; then
AUTH_TYPES_LIST+=("ENV")
fi
if [ -n "$OIDC_ISSUER" ] && [ -n "$OIDC_CLIENT_ID" ] && [ -n "$OIDC_CLIENT_SECRET" ]; then
AUTH_TYPES_LIST+=("OIDC")
fi
if [ ${#AUTH_TYPES_LIST[@]} -eq 0 ]; then
AUTH_TYPES_LIST+=("LOCAL")
fi
AUTH_TYPE=$(IFS=','; echo "${AUTH_TYPES_LIST[*]}")
else
AUTH_TYPE="$AUTH_TYPE_INPUT"
# If ENV is in AUTH_TYPE but credentials not set, use defaults
if [[ "$AUTH_TYPE" == *"ENV"* ]] && [ -z "$ADMIN_USERNAME" ] && [ -z "$ADMIN_PASSWORD" ]; then
ADMIN_USERNAME="bwall"
ADMIN_PASSWORD="ReadGoodBooks&BadNetworks"
fi
fi
# Generate secret key if not set
if [ -z "$SECRET_KEY" ]; then
if command_exists openssl; then
SECRET_KEY=$(openssl rand -hex 32)
else
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
fi
fi
echo ""
# Step 5b: AbuseIPDB Configuration
print_info "Step 5b: AbuseIPDB Configuration (Optional)"
echo "AbuseIPDB integration allows you to report and check abusive IPs."
echo "Get your API key from: https://www.abuseipdb.com/pricing"
echo ""
read -p "Would you like to configure AbuseIPDB integration? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
read -sp "AbuseIPDB API Key: " ABUSEIPDB_API_KEY
echo ""
if [ -n "$ABUSEIPDB_API_KEY" ]; then
print_success "AbuseIPDB API key collected"
echo ""
echo "AbuseIPDB Reporting Mode:"
echo " 1) automatic - Report immediately when IPs are blocked"
echo " 2) log_and_hold - Queue reports for review before submitting"
echo " 3) log_only - Only log events, do not report"
read -p "Select mode [1-3] (default: 1): " MODE_CHOICE
case $MODE_CHOICE in
2)
ABUSEIPDB_MODE="log_and_hold"
;;
3)
ABUSEIPDB_MODE="log_only"
;;
*)
ABUSEIPDB_MODE="automatic"
;;
esac
print_success "AbuseIPDB mode set to: $ABUSEIPDB_MODE"
else
print_warning "No API key provided, skipping AbuseIPDB configuration"
ABUSEIPDB_API_KEY=""
ABUSEIPDB_MODE="automatic"
fi
else
print_info "Skipping AbuseIPDB configuration. You can configure it later in the .env file."
ABUSEIPDB_API_KEY=""
ABUSEIPDB_MODE="automatic"
fi
echo ""
# Step 6: Create Environment File
print_info "Step 6: Creating environment configuration file..."
ENV_FILE=".env"
cat > "$ENV_FILE" <<EOF
# bWall Configuration
# Generated by quickstart.sh on $(date)
# Database Configuration
DB_HOST=$DB_HOST
DB_USER=$DB_USER
DB_PASSWORD=$DB_PASSWORD
DB_NAME=$DB_NAME
# Authentication Configuration
AUTH_TYPE=$AUTH_TYPE
EOF
# Add ENV auth if configured
if [ -n "$ADMIN_USERNAME" ] && [ -n "$ADMIN_PASSWORD" ]; then
cat >> "$ENV_FILE" <<EOF
# ENV Authentication (if AUTH_TYPE includes ENV)
ADMIN_USERNAME=$ADMIN_USERNAME
ADMIN_PASSWORD=$ADMIN_PASSWORD
EOF
fi
# Add OIDC if configured
if [ -n "$OIDC_ISSUER" ]; then
cat >> "$ENV_FILE" <<EOF
# OIDC Configuration (if AUTH_TYPE includes OIDC)
OIDC_ISSUER=$OIDC_ISSUER
OIDC_CLIENT_ID=$OIDC_CLIENT_ID
OIDC_CLIENT_SECRET=$OIDC_CLIENT_SECRET
OIDC_REDIRECT_URI=$OIDC_REDIRECT_URI
OIDC_POST_LOGOUT_REDIRECT_URI=$OIDC_POST_LOGOUT_URI
EOF
fi
# Add secret key (always needed)
cat >> "$ENV_FILE" <<EOF
# Application Secret Key
SECRET_KEY=$SECRET_KEY
EOF
# AbuseIPDB Configuration
if [ -n "$ABUSEIPDB_API_KEY" ]; then
cat >> "$ENV_FILE" <<EOF
# AbuseIPDB Configuration
ABUSEIPDB_API_KEY=$ABUSEIPDB_API_KEY
ABUSEIPDB_MODE=$ABUSEIPDB_MODE
EOF
else
cat >> "$ENV_FILE" <<EOF
# AbuseIPDB Configuration (optional)
# Get your API key from: https://www.abuseipdb.com/pricing
# ABUSEIPDB_API_KEY=
# ABUSEIPDB_MODE=automatic # Options: automatic, log_and_hold, log_only
EOF
fi
# Make .env file readable only by owner
chmod 600 "$ENV_FILE"
print_success "Environment file created: $ENV_FILE"
print_warning "Keep this file secure! It contains sensitive credentials."
echo ""
# Step 7: Create startup helper script
print_info "Step 7: Creating startup helper script..."
cat > "start_bwall.sh" <<'STARTER'
#!/bin/bash
# bWall Startup Script
# Loads environment variables and starts the application
# Load environment variables
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
else
echo "Error: .env file not found. Run quickstart.sh first."
exit 1
fi
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Warning: This application requires root privileges to manage iptables."
echo "Attempting to run with sudo..."
exec sudo -E python3 app.py
else
python3 app.py
fi
STARTER
chmod +x start_bwall.sh
print_success "Startup script created: start_bwall.sh"
# Step 8: Systemd Service Installation (Optional)
print_info "Step 8: Systemd Service Installation (Optional)"
echo ""
echo "Would you like to install bWall as a systemd service?"
echo "This will allow bWall to start automatically at boot time."
echo ""
read -p "Install systemd service? (y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [ -f "install_systemd_service.sh" ]; then
print_info "Installing systemd service..."
chmod +x install_systemd_service.sh
./install_systemd_service.sh
if [ $? -eq 0 ]; then
print_success "Systemd service installed and enabled"
else
print_warning "Systemd service installation had issues, but you can install it later with:"
echo " sudo ./install_systemd_service.sh"
fi
else
print_warning "install_systemd_service.sh not found. You can install the service later with:"
echo " sudo ./install_systemd_service.sh"
fi
else
print_info "Skipping systemd service installation."
echo "You can install it later with: sudo ./install_systemd_service.sh"
fi
echo ""
echo ""
# Summary
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
print_success "=========================================="
print_success "Installation Complete!"
print_success "=========================================="
echo ""
print_info "Summary:"
echo " - Prerequisites: ✓"
echo " - Python packages: ✓"
echo " - Database: ✓"
echo " - Database views: ✓"
echo " - Stored procedures: ✓"
echo " - Configuration: ✓"
echo ""
print_info "Next steps:"
echo " 1. Review the .env file and adjust if needed"
echo " 2. Start the application: ./start_bwall.sh"
echo " Or install systemd service: sudo ./install_systemd_service.sh"
echo " 3. Access the dashboard: http://localhost:5000"
echo ""
print_info "Log file: $LOG_FILE"
print_info "Installation time: ${DURATION} seconds"
echo ""
# Display database connection info
echo "Database Information:"
echo " Host: $DB_HOST"
echo " Database: $DB_NAME"
echo " User: $DB_USER"
echo ""
if [ -n "$OIDC_ISSUER" ]; then
echo "OIDC Configuration:"
echo " Issuer: $OIDC_ISSUER"
echo " Client ID: $OIDC_CLIENT_ID"
echo " ✓ OIDC authentication enabled"
echo ""
else
echo "OIDC Configuration:"
echo " ⚠ OIDC not configured (optional)"
echo " To configure later, edit .env file or set environment variables"
echo ""
fi
if [ -n "$ABUSEIPDB_API_KEY" ]; then
echo "AbuseIPDB Configuration:"
echo " ✓ AbuseIPDB integration enabled"
echo ""
else
echo "AbuseIPDB Configuration:"
echo " ⚠ AbuseIPDB not configured (optional)"
echo " To configure later, edit .env file and set ABUSEIPDB_API_KEY"
echo ""
fi