mirror of https://github.com/Aidaho12/haproxy-wi
parent
b02acc475a
commit
1ae61a35bf
109
README.md
109
README.md
|
@ -1,4 +1,4 @@
|
|||
# ![alt text](https://roxy-wi.org/inc/images/logo_menu.png "Logo")
|
||||
# ![alt text](https://roxy-wi.org/static/images/logo_menu.png "Logo")
|
||||
Web interface(user-friendly web GUI, alerting, monitoring and secure) for managing HAProxy, Nginx and Keepalived servers. Leave your [feedback](https://github.com/hap-wi/roxy-wi/issues)
|
||||
|
||||
# Get involved
|
||||
|
@ -9,75 +9,76 @@ Web interface(user-friendly web GUI, alerting, monitoring and secure) for managi
|
|||
# Demo site
|
||||
[Demo site](https://demo.roxy-wi.org) Login/password: admin/admin. Server resets every hour.
|
||||
|
||||
![alt text](https://roxy-wi.org/inc/images/viewstat.png "HAProxy state page")
|
||||
![alt text](https://roxy-wi.org/static/images/viewstat.png "HAProxy state page")
|
||||
|
||||
# Features:
|
||||
1. Installing and updating HAProxy, Nginx and Keepalived with Roxy-WI as a system service
|
||||
1. Installing and updating HAProxy and Nginx with Roxy-WI as a Docker service
|
||||
2. Installing and updating Grafana, Prometheus servers with Roxy-WI
|
||||
3. Installing and updating HAProxy and Nginx exporters with Roxy-WI
|
||||
4. Server provisioning on AWS, DigitalOcean and G-Core Labs
|
||||
5. Downloading, updating and formatting GeoIP to the acceptable format for HAProxy with Roxy-WI
|
||||
6. Dynamic change of Maxconn, Black/white lists and backend's IP address and port with saving changes to the config file
|
||||
7. Configuring HAProxy, Nginx, Apache and Keepalived in a jiffy with Roxy-WI
|
||||
8. Viewing and analysing the status of all Frontend/backend servers via Roxy-WI from a single control panel
|
||||
9. Enabling/disabling servers through stats page without rebooting HAProxy
|
||||
1. Viewing/Analysing HAProxy, Nginx and Apache logs right from the Roxy-WI web interface
|
||||
1. Creating and visualizing the HAProxy workflow from Web Ui
|
||||
1. Pushing Your changes to your HAProxy, Nginx, Apache and Keepalived servers with a single click via the web interface
|
||||
1. Getting info on past changes, evaluating your config files and restoring the previous stable config at any time with a single click right from Web interface
|
||||
1. Adding/Editing Frontend or backend servers via the web interface with a click
|
||||
1. Editing the config of HAProxy, Nginx, Apache and Keepalived and push ingchanges to All Master/Slave servers by a single click
|
||||
1. Adding Multiple server to ensure the Config Sync between servers
|
||||
1. Managing the ports assigned to Frontend automatically
|
||||
1. Evaluating the changes of recent configs pushed to HAProxy, Nginx and Keepalived instances right from the Web UI
|
||||
1. Multiple User Roles support for privileged based Viewing and editing of Config
|
||||
1. Creating Groups and adding/removing servers to ensure the proper identification for your HAProxy and Nginx Clusters
|
||||
1. Sending notifications from Roxy-WI via Telegram, Slack and via the web interface
|
||||
1. Supporting high Availability to ensure uptime to all Master slave servers configured
|
||||
1. Support of SSL (including Let's Encrypt)
|
||||
1. Support of SSH Key for managing multiple HAProxy, Nginx, Apache and Keepalived Servers straight from Roxy-WI
|
||||
1. SYN flood protect
|
||||
1. Alerting about changes of the state of HAProxy backends
|
||||
1. Alerting about the state of HAProxy, Nginx, Apache and Keepalived service
|
||||
1. Gathering metrics for incoming connections
|
||||
1. Web acceleration settings
|
||||
1. Firewall for web application
|
||||
1. LDAP support
|
||||
1. Keep active HAProxy, Nginx and Keepalived services
|
||||
1. Possibility to hide parts of the config with tags for users with "guest" role: "HideBlockStart" and "HideBlockEnd"
|
||||
1. Mobile-ready design
|
||||
1. Simple port monitoring (SMON)
|
||||
1. Backup HAProxy, Nginx and Keepalived config files through Roxy-WI
|
||||
1. Managing OpenVPN3 as a client via Roxy-WI
|
||||
2. Installing and updating HAProxy and Nginx with Roxy-WI as a Docker service
|
||||
3. Installing and updating Grafana, Prometheus servers with Roxy-WI
|
||||
4. Installing and updating HAProxy and Nginx exporters with Roxy-WI
|
||||
5. Server provisioning on AWS, DigitalOcean and G-Core Labs
|
||||
6. Downloading, updating and formatting GeoIP to the acceptable format for HAProxy with Roxy-WI
|
||||
7. Dynamic change of Maxconn, Black/white lists and backend's IP address and port with saving changes to the config file
|
||||
8. Configuring HAProxy, Nginx, Apache and Keepalived in a jiffy with Roxy-WI
|
||||
9. Viewing and analysing the status of all Frontend/backend servers via Roxy-WI from a single control panel
|
||||
10. Enabling/disabling servers through stats page without rebooting HAProxy
|
||||
11. Viewing/Analysing HAProxy, Nginx and Apache logs right from the Roxy-WI web interface
|
||||
12. Creating and visualizing the HAProxy workflow from Web Ui
|
||||
13. Pushing Your changes to your HAProxy, Nginx, Apache and Keepalived servers with a single click via the web interface
|
||||
14. Getting info on past changes, evaluating your config files and restoring the previous stable config at any time with a single click right from Web interface
|
||||
15. Adding/Editing Frontend or backend servers via the web interface with a click
|
||||
16. Editing the config of HAProxy, Nginx, Apache and Keepalived and push ingchanges to All Master/Slave servers by a single click
|
||||
17. Adding Multiple server to ensure the Config Sync between servers
|
||||
18. Managing the ports assigned to Frontend automatically
|
||||
19. Evaluating the changes of recent configs pushed to HAProxy, Nginx, Apache and Keepalived instances right from the Web UI
|
||||
20. Multiple User Roles support for privileged based Viewing and editing of Config
|
||||
21. Creating Groups and adding/removing servers to ensure the proper identification for your HAProxy and Nginx Clusters
|
||||
22. Sending notifications from Roxy-WI via Telegram, Slack, Email and via the web interface
|
||||
23. Supporting high Availability to ensure uptime to all Master slave servers configured
|
||||
24. Support of SSL (including Let's Encrypt)
|
||||
25. Support of SSH Key for managing multiple HAProxy, Nginx, Apache and Keepalived Servers straight from Roxy-WI
|
||||
26. SYN flood protect
|
||||
27. Alerting about changes of the state of HAProxy backends
|
||||
28. Alerting about the state of HAProxy, Nginx, Apache and Keepalived service
|
||||
29. Gathering metrics for incoming connections
|
||||
30. Web acceleration settings
|
||||
31. Firewall for web application (WAF)
|
||||
32. LDAP support
|
||||
33. Keep active HAProxy, Nginx, Apache and Keepalived services
|
||||
34. Possibility to hide parts of the config with tags for users with "guest" role: "HideBlockStart" and "HideBlockEnd"
|
||||
35. Mobile-ready design
|
||||
36. Simple port monitoring (SMON)
|
||||
37. Backup HAProxy, Nginx, Apache and Keepalived config files through Roxy-WI
|
||||
38. Managing OpenVPN3 as a client via Roxy-WI
|
||||
|
||||
|
||||
|
||||
![alt text](https://Roxy-WI.org/inc/images/roxy-wi-metrics.png "Merics")
|
||||
![alt text](https://Roxy-WI.org/static/images/roxy-wi-metrics.png "Merics")
|
||||
|
||||
# Install
|
||||
|
||||
## RPM
|
||||
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation.py#rpm)
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation#rpm)
|
||||
|
||||
## DEB
|
||||
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation.py#deb)
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation#deb)
|
||||
|
||||
## Manual install
|
||||
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation.py#manual)
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation#manual)
|
||||
|
||||
# OS support
|
||||
Roxy-WI supports the following OSes:
|
||||
1. EL7(RPM installation and manual installation). It must be "Infrastructure Server" at least. x86_64 only
|
||||
2. EL8(RPM installation and manual installation). It must be "Infrastructure Server" at least. x86_64 only
|
||||
3. Amazon Linux 2(RPM installation and manual installation). x86_64 only
|
||||
4. Ubuntu(DEB installation and manual installation). x86_64 only
|
||||
5. Other Linux distributions (manual installation only). x86_64 only
|
||||
3. EL9(RPM installation and manual installation). It must be "Infrastructure Server" at least. x86_64 only
|
||||
4. Amazon Linux 2(RPM installation and manual installation). x86_64 only
|
||||
5. Ubuntu(DEB installation and manual installation). x86_64 only
|
||||
6. Other Linux distributions (manual installation only). x86_64 only
|
||||
|
||||
![alt text](https://roxy-wi.org/inc/images/smon_dashboard.png "SMON area")
|
||||
![alt text](https://roxy-wi.org/static/images/smon_dashboard.png "SMON area")
|
||||
|
||||
# Database support
|
||||
|
||||
|
@ -85,21 +86,21 @@ Default Roxy-WI use Sqlite, if you want use MySQL enable in config, and create d
|
|||
|
||||
### For MySQL support:
|
||||
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation.py#database)
|
||||
### Read instruction on the official [site](https://roxy-wi.org/installation#database)
|
||||
|
||||
![alt text](https://roxy-wi.org/inc/images/roxy-wi-overview.webp "Overview page")
|
||||
![alt text](https://roxy-wi.org/static/images/roxy-wi-overview.webp "Overview page")
|
||||
|
||||
# Settings
|
||||
|
||||
|
||||
Login https://roxy-wi-server/users.py, and add: users, groups and servers. Default: admin/admin
|
||||
|
||||
### Read instruction on the official [site](https://roxy-wi.org/settings.py)
|
||||
### Read instruction on the official [site](https://roxy-wi.org/settings)
|
||||
|
||||
![alt text](https://roxy-wi.org/inc/images/hapwi_overview.webp "HAProxy server overview page")
|
||||
![alt text](https://roxy-wi.org/static/images/hapwi_overview.webp "HAProxy server overview page")
|
||||
|
||||
|
||||
![alt text](https://roxy-wi.org/inc/images/add.png "Add proxy page")
|
||||
![alt text](https://roxy-wi.org/static/images/add.png "Add proxy page")
|
||||
|
||||
|
||||
|
||||
|
@ -122,8 +123,8 @@ Do this:
|
|||
$ cd /var/www/haproxy-wi/app
|
||||
$ ./create_db.py
|
||||
```
|
||||
and check executeble py files
|
||||
and check executable py files
|
||||
|
||||
If you see plain text, check section "Directory" in httpd conf
|
||||
|
||||
[Read more](https://roxy-wi.org/troubleshooting.py)
|
||||
[Read more](https://roxy-wi.org/troubleshooting)
|
||||
|
|
|
@ -943,8 +943,24 @@ def update_db_v_6_1_0(**kwargs):
|
|||
print("An error occurred:", e)
|
||||
|
||||
|
||||
def update_db_v_6_1_3(**kwargs):
|
||||
cursor = conn.cursor()
|
||||
sql = list()
|
||||
sql.append("ALTER TABLE `waf_rules` ADD COLUMN service VARCHAR ( 64 ) DEFAULT 'haproxy'")
|
||||
sql.append("ALTER TABLE `waf_rules` drop CONSTRAINT serv")
|
||||
sql.append("ALTER TABLE `waf_rules` ADD CONSTRAINT UNIQUE (serv, rule_name, service)")
|
||||
for i in sql:
|
||||
try:
|
||||
cursor.execute(i)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
if kwargs.get('silent') != 1:
|
||||
print('Updating... DB has been updated to version 6.1.3.0')
|
||||
|
||||
|
||||
def update_ver():
|
||||
query = Version.update(version='6.1.2.0')
|
||||
query = Version.update(version='6.1.3.0')
|
||||
try:
|
||||
query.execute()
|
||||
except Exception:
|
||||
|
@ -971,6 +987,7 @@ def update_all():
|
|||
update_db_v_6_0()
|
||||
update_db_v_6_0_1()
|
||||
update_db_v_6_1_0()
|
||||
update_db_v_6_1_3()
|
||||
update_ver()
|
||||
|
||||
|
||||
|
@ -993,6 +1010,7 @@ def update_all_silent():
|
|||
update_db_v_5_4_3_1(silent=1)
|
||||
update_db_v_6_0(silent=1)
|
||||
update_db_v_6_0_1(silent=1)
|
||||
update_db_v_6_1_3(silent=1)
|
||||
update_ver()
|
||||
|
||||
|
||||
|
|
|
@ -280,10 +280,11 @@ class WafRules(BaseModel):
|
|||
rule_file = CharField()
|
||||
desc = TextField(null=True)
|
||||
en = IntegerField(constraints=[SQL('DEFAULT 1')])
|
||||
service = CharField(constraints=[SQL('haproxy')])
|
||||
|
||||
class Meta:
|
||||
table_name = 'waf_rules'
|
||||
constraints = [SQL('UNIQUE (serv, rule_name)')]
|
||||
constraints = [SQL('UNIQUE (serv, rule_name, service)')]
|
||||
|
||||
|
||||
class PortScannerSettings(BaseModel):
|
||||
|
@ -550,10 +551,20 @@ class CheckerSetting(BaseModel):
|
|||
constraints = [SQL('UNIQUE (server_id, service_id)')]
|
||||
|
||||
|
||||
class WafNginx(BaseModel):
|
||||
id = AutoField()
|
||||
server_id = ForeignKeyField(Server, on_delete='Cascade')
|
||||
|
||||
class Meta:
|
||||
table_name = 'waf_nginx'
|
||||
constraints = [SQL('UNIQUE (server_id)')]
|
||||
|
||||
|
||||
def create_tables():
|
||||
with conn:
|
||||
conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion,
|
||||
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory,
|
||||
PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds, ServiceSetting,
|
||||
ProvisionedServers, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes, NginxMetrics,
|
||||
SystemInfo, Services, UserName, GitSetting, CheckerSetting, ApacheMetrics, ProvisionParam])
|
||||
SystemInfo, Services, UserName, GitSetting, CheckerSetting, ApacheMetrics, ProvisionParam,
|
||||
WafNginx])
|
||||
|
|
62
app/funct.py
62
app/funct.py
|
@ -448,7 +448,10 @@ def get_config(server_ip, cfg, **kwargs):
|
|||
):
|
||||
config_path = kwargs.get('config_file_name')
|
||||
elif kwargs.get("waf") or kwargs.get("service") == 'waf':
|
||||
config_path = sql.get_setting('haproxy_dir') + '/waf/rules/' + kwargs.get("waf_rule_file")
|
||||
if kwargs.get("waf") == 'haproxy':
|
||||
config_path = sql.get_setting('haproxy_dir') + '/waf/rules/' + kwargs.get("waf_rule_file")
|
||||
elif kwargs.get("waf") == 'nginx':
|
||||
config_path = sql.get_setting('nginx_dir') + '/waf/rules/' + kwargs.get("waf_rule_file")
|
||||
else:
|
||||
config_path = sql.get_setting('haproxy_config_path')
|
||||
|
||||
|
@ -783,14 +786,46 @@ def waf_install(server_ip):
|
|||
output, error = subprocess_execute(commands[0])
|
||||
|
||||
if show_installation_output(error, output, service):
|
||||
ssh_command(server_ip, commands, print_out="1")
|
||||
|
||||
sql.insert_waf_metrics_enable(server_ip, "0")
|
||||
sql.insert_waf_rules(server_ip)
|
||||
|
||||
os.system("rm -f %s" % script)
|
||||
|
||||
|
||||
def waf_nginx_install(server_ip):
|
||||
import sql
|
||||
script = "waf_nginx.sh"
|
||||
proxy = sql.get_setting('proxy')
|
||||
nginx_dir = sql.get_setting('nginx_dir')
|
||||
service = ' WAF'
|
||||
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = return_ssh_keys_path(server_ip)
|
||||
ssh_port = '22'
|
||||
|
||||
if ssh_enable == 0:
|
||||
ssh_key_name = ''
|
||||
|
||||
os.system("cp scripts/%s ." % script)
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
else:
|
||||
proxy_serv = ''
|
||||
|
||||
commands = [
|
||||
"chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " NGINX_PATH=" + nginx_dir
|
||||
+ " SSH_PORT=" + ssh_port + " HOST=" + server_ip
|
||||
+ " USER=" + ssh_user_name + " PASS='" + ssh_user_password + "' KEY=" + ssh_key_name
|
||||
]
|
||||
|
||||
output, error = subprocess_execute(commands[0])
|
||||
|
||||
if show_installation_output(error, output, service):
|
||||
sql.insert_nginx_waf_rules(server_ip)
|
||||
sql.insert_waf_nginx_server(server_ip)
|
||||
|
||||
os.system("rm -f %s" % script)
|
||||
|
||||
|
||||
def install_nginx(server_ip, **kwargs):
|
||||
import sql
|
||||
script = "install_nginx.sh"
|
||||
|
@ -1541,30 +1576,25 @@ def check_ver():
|
|||
return sql.get_ver()
|
||||
|
||||
|
||||
def check_new_version(**kwargs):
|
||||
def check_new_version(service):
|
||||
import requests
|
||||
import sql
|
||||
current_ver = check_ver()
|
||||
proxy = sql.get_setting('proxy')
|
||||
res = ''
|
||||
|
||||
if kwargs.get('service'):
|
||||
last_ver = '_' + kwargs.get('service')
|
||||
else:
|
||||
last_ver = ''
|
||||
|
||||
user_name = sql.select_user_name()
|
||||
|
||||
try:
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_dict = {"https": proxy, "http": proxy}
|
||||
response = requests.get('https://roxy-wi.org/update.py?last_ver' + last_ver + '=1', timeout=1, proxies=proxy_dict)
|
||||
requests.get('https://roxy-wi.org/update.py?ver_send=' + current_ver, timeout=1, proxies=proxy_dict)
|
||||
response_status = requests.get('https://roxy-wi.org/update.py?user_name=' + user_name, timeout=1, proxies=proxy_dict)
|
||||
response = requests.get(f'https://roxy-wi.org/version/get/{service}', timeout=1, proxies=proxy_dict)
|
||||
requests.get(f'https://roxy-wi.org/version/send/{current_ver}', timeout=1, proxies=proxy_dict)
|
||||
response_status = requests.get(f'https://roxy-wi.org/user-name/{user_name}', timeout=1, proxies=proxy_dict)
|
||||
else:
|
||||
response = requests.get('https://roxy-wi.org/update.py?last_ver' + last_ver + '=1', timeout=1)
|
||||
requests.get('https://roxy-wi.org/update.py?ver_send=' + current_ver, timeout=1)
|
||||
response_status = requests.get('https://roxy-wi.org/update.py?user_name=' + user_name, timeout=1)
|
||||
response = requests.get(f'https://roxy-wi.org/version/get/{service}', timeout=1)
|
||||
requests.get(f'https://roxy-wi.org/version/send/{current_ver}', timeout=1)
|
||||
response_status = requests.get(f'https://roxy-wi.org/user-name/{user_name}', timeout=1)
|
||||
|
||||
res = response.content.decode(encoding='UTF-8')
|
||||
try:
|
||||
|
@ -1595,7 +1625,7 @@ def versions():
|
|||
current_ver_without_dots = 0
|
||||
|
||||
try:
|
||||
new_ver = check_new_version()
|
||||
new_ver = check_new_version('roxy-wi')
|
||||
new_ver_without_dots = new_ver.split('.')
|
||||
new_ver_without_dots = ''.join(new_ver_without_dots)
|
||||
new_ver_without_dots = new_ver_without_dots.replace('\n', '')
|
||||
|
|
178
app/options.py
178
app/options.py
|
@ -41,6 +41,9 @@ try:
|
|||
except ValueError:
|
||||
print('error: Your token is not valid')
|
||||
sys.exit()
|
||||
except Exception:
|
||||
print('error: There is no token')
|
||||
sys.exit()
|
||||
|
||||
if not sql.check_token_exists(token):
|
||||
print('error: Your token has been expired')
|
||||
|
@ -504,10 +507,29 @@ if form.getvalue('action_waf') is not None and serv is not None:
|
|||
|
||||
funct.is_restarted(serv, action)
|
||||
|
||||
funct.logging(serv, 'WAF service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='haproxy')
|
||||
funct.logging(serv, 'HAProxy WAF service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='haproxy')
|
||||
commands = ["sudo systemctl %s waf" % action]
|
||||
funct.ssh_command(serv, commands)
|
||||
|
||||
if form.getvalue('action_waf_nginx') is not None and serv is not None:
|
||||
serv = form.getvalue('serv')
|
||||
action = form.getvalue('action_waf_nginx')
|
||||
config_dir = funct.return_nice_path(sql.get_setting('nginx_dir'))
|
||||
|
||||
if action not in ('start', 'stop'):
|
||||
print('error: wrong action')
|
||||
sys.exit()
|
||||
|
||||
funct.is_restarted(serv, action)
|
||||
|
||||
waf_new_state = 'on' if action == 'start' else 'off'
|
||||
waf_old_state = 'off' if action == 'start' else 'on'
|
||||
|
||||
funct.logging(serv, 'NGINX WAF service has been ' + action + 'ed', haproxywi=1, login=1, keep_history=1, service='nginx')
|
||||
commands = [ f"sudo sed -i 's/modsecurity {waf_old_state}/modsecurity {waf_new_state}/g' {config_dir}nginx.conf"
|
||||
f" && sudo systemctl reload nginx" ]
|
||||
funct.ssh_command(serv, commands)
|
||||
|
||||
if form.getvalue('action_apache') is not None and serv is not None:
|
||||
action = form.getvalue('action_apache')
|
||||
|
||||
|
@ -728,32 +750,44 @@ if act == "overviewwaf":
|
|||
)
|
||||
template = env.get_template('overivewWaf.html')
|
||||
|
||||
waf_service = form.getvalue('service')
|
||||
servers = sql.select_servers(server=serv)
|
||||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
||||
user_id = cookie.get('uuid')
|
||||
|
||||
haproxy_path = ''
|
||||
config_path = ''
|
||||
returned_servers = []
|
||||
waf = ''
|
||||
metrics_en = 0
|
||||
waf_process = ''
|
||||
waf_mode = ''
|
||||
is_waf_on_server = 0
|
||||
|
||||
for server in servers:
|
||||
haproxy = sql.select_haproxy(server[2])
|
||||
if haproxy == 1:
|
||||
haproxy_path = sql.get_setting('haproxy_dir')
|
||||
waf = sql.select_waf_servers(server[2])
|
||||
metrics_en = sql.select_waf_metrics_enable_server(server[2])
|
||||
if waf_service == 'haproxy':
|
||||
is_waf_on_server = sql.select_haproxy(server[2])
|
||||
elif waf_service == 'nginx':
|
||||
is_waf_on_server = sql.select_nginx(server[2])
|
||||
|
||||
if is_waf_on_server == 1:
|
||||
config_path = sql.get_setting(waf_service + '_dir')
|
||||
if waf_service == 'haproxy':
|
||||
waf = sql.select_waf_servers(server[2])
|
||||
metrics_en = sql.select_waf_metrics_enable_server(server[2])
|
||||
elif waf_service == 'nginx':
|
||||
waf = sql.select_waf_nginx_servers(server[2])
|
||||
try:
|
||||
waf_len = len(waf)
|
||||
except Exception:
|
||||
waf_len = 0
|
||||
|
||||
if waf_len >= 1:
|
||||
command = ["ps ax |grep waf/bin/modsecurity |grep -v grep |wc -l"]
|
||||
if waf_service == 'haproxy':
|
||||
command = ["ps ax |grep waf/bin/modsecurity |grep -v grep |wc -l"]
|
||||
elif waf_service == 'nginx':
|
||||
command = ["grep 'modsecurity on' %s* --exclude-dir=waf -Rs |wc -l" % funct.return_nice_path(config_path)]
|
||||
commands1 = [
|
||||
"grep SecRuleEngine %s/waf/modsecurity.conf |grep -v '#' |awk '{print $2}'" % haproxy_path]
|
||||
"grep SecRuleEngine %s/waf/modsecurity.conf |grep -v '#' |awk '{print $2}'" % config_path]
|
||||
waf_process = funct.ssh_command(server[2], command)
|
||||
waf_mode = funct.ssh_command(server[2], commands1).strip()
|
||||
|
||||
|
@ -774,7 +808,7 @@ if act == "overviewwaf":
|
|||
returned_servers.append(server_status)
|
||||
|
||||
servers_sorted = sorted(returned_servers, key=funct.get_key)
|
||||
template = template.render(service_status=servers_sorted, role=sql.get_user_role_by_uuid(user_id.value))
|
||||
template = template.render(service_status=servers_sorted, role=sql.get_user_role_by_uuid(user_id.value), waf_service=waf_service)
|
||||
print(template)
|
||||
|
||||
if act == "overviewServers":
|
||||
|
@ -1836,7 +1870,11 @@ if form.getvalue('haproxyaddserv'):
|
|||
hapver=form.getvalue('hapver'), docker=form.getvalue('docker'))
|
||||
|
||||
if form.getvalue('installwaf'):
|
||||
funct.waf_install(form.getvalue('installwaf'))
|
||||
service = form.getvalue('service')
|
||||
if service == 'haproxy':
|
||||
funct.waf_install(form.getvalue('installwaf'))
|
||||
else:
|
||||
funct.waf_nginx_install(form.getvalue('installwaf'))
|
||||
|
||||
if form.getvalue('update_roxy_wi'):
|
||||
service = form.getvalue('service')
|
||||
|
@ -2150,8 +2188,8 @@ if form.getvalue('get_lists'):
|
|||
lib_path = funct.get_config_var('main', 'lib_path')
|
||||
list_path = lib_path + "/" + sql.get_setting('lists_path') + "/" + form.getvalue('group') + "/" + form.getvalue('color')
|
||||
lists = funct.get_files(dir=list_path, format="lst")
|
||||
for list in lists:
|
||||
print(list)
|
||||
for l in lists:
|
||||
print(l)
|
||||
|
||||
if form.getvalue('get_ldap_email'):
|
||||
username = form.getvalue('get_ldap_email')
|
||||
|
@ -2191,11 +2229,17 @@ if form.getvalue('get_ldap_email'):
|
|||
ldap_bind.unbind()
|
||||
|
||||
if form.getvalue('change_waf_mode'):
|
||||
waf_mode = form.getvalue('change_waf_mode')
|
||||
waf_mode = funct.checkAjaxInput(form.getvalue('change_waf_mode'))
|
||||
server_hostname = form.getvalue('server_hostname')
|
||||
haproxy_dir = sql.get_setting('haproxy_dir')
|
||||
service = funct.checkAjaxInput(form.getvalue('service'))
|
||||
serv = sql.select_server_by_name(server_hostname)
|
||||
commands = ["sudo sed -i 's/^SecRuleEngine.*/SecRuleEngine %s/' %s/waf/modsecurity.conf " % (waf_mode, haproxy_dir)]
|
||||
|
||||
if service == 'haproxy':
|
||||
config_dir = sql.get_setting('haproxy_dir')
|
||||
elif service == 'nginx':
|
||||
config_dir = sql.get_setting('nginx_dir')
|
||||
|
||||
commands = ["sudo sed -i 's/^SecRuleEngine.*/SecRuleEngine %s/' %s/waf/modsecurity.conf " % (waf_mode, config_dir)]
|
||||
funct.ssh_command(serv, commands)
|
||||
funct.logging(serv, 'Has been changed WAF mod to ' + waf_mode, haproxywi=1, login=1)
|
||||
|
||||
|
@ -2259,6 +2303,8 @@ if form.getvalue('updateuser') is not None:
|
|||
|
||||
if form.getvalue('updatepassowrd') is not None:
|
||||
password = form.getvalue('updatepassowrd')
|
||||
username = ''
|
||||
|
||||
if form.getvalue('uuid'):
|
||||
user_id = sql.get_user_id_by_uuid(form.getvalue('uuid'))
|
||||
else:
|
||||
|
@ -2478,6 +2524,9 @@ if form.getvalue('new_ssh'):
|
|||
if form.getvalue('sshdel') is not None:
|
||||
lib_path = funct.get_config_var('main', 'lib_path')
|
||||
sshdel = funct.checkAjaxInput(form.getvalue('sshdel'))
|
||||
name = ''
|
||||
ssh_enable = 0
|
||||
ssh_key_name = ''
|
||||
|
||||
for sshs in sql.select_ssh(id=sshdel):
|
||||
ssh_enable = sshs.enable
|
||||
|
@ -2501,6 +2550,7 @@ if form.getvalue('updatessh'):
|
|||
group = form.getvalue('group')
|
||||
username = form.getvalue('ssh_user')
|
||||
password = form.getvalue('ssh_pass')
|
||||
new_ssh_key_name = ''
|
||||
|
||||
if username is None:
|
||||
print(error_mess)
|
||||
|
@ -2553,10 +2603,6 @@ if form.getvalue('ssh_cert'):
|
|||
ssh_keys = full_dir + name + '.pem'
|
||||
|
||||
try:
|
||||
# cloud = sql.is_cloud()
|
||||
# if cloud != '':
|
||||
# key.write_private_key_file(ssh_keys, password=cloud)
|
||||
# else:
|
||||
key.write_private_key_file(ssh_keys)
|
||||
except Exception as e:
|
||||
print('error: Cannot save SSH key file: ', str(e))
|
||||
|
@ -2829,17 +2875,17 @@ if form.getvalue('showBytes') is not None:
|
|||
port = sql.get_setting('haproxy_sock_port')
|
||||
bin_bout = []
|
||||
cmd = "echo 'show stat' |nc {} {} |cut -d ',' -f 1-2,9|grep -E '[0-9]'|awk -F',' '{{sum+=$3;}}END{{print sum;}}'".format(serv, port)
|
||||
bin, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bin[0])
|
||||
bit_in, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bit_in[0])
|
||||
cmd = "echo 'show stat' |nc {} {} |cut -d ',' -f 1-2,10|grep -E '[0-9]'|awk -F',' '{{sum+=$3;}}END{{print sum;}}'".format(serv, port)
|
||||
bin, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bin[0])
|
||||
bout, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bout[0])
|
||||
cmd = "echo 'show stat' |nc {} {} |cut -d ',' -f 1-2,5|grep -E '[0-9]'|awk -F',' '{{sum+=$3;}}END{{print sum;}}'".format(serv, port)
|
||||
bin, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bin[0])
|
||||
cin, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(cin[0])
|
||||
cmd = "echo 'show stat' |nc {} {} |cut -d ',' -f 1-2,8|grep -E '[0-9]'|awk -F',' '{{sum+=$3;}}END{{print sum;}}'".format(serv, port)
|
||||
bin, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(bin[0])
|
||||
cout, stderr = funct.subprocess_execute(cmd)
|
||||
bin_bout.append(cout[0])
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
|
@ -2883,7 +2929,8 @@ if form.getvalue('waf_rule_id'):
|
|||
haproxy_path = sql.get_setting('haproxy_dir')
|
||||
rule_file = sql.select_waf_rule_by_id(rule_id)
|
||||
conf_file_path = haproxy_path + '/waf/modsecurity.conf'
|
||||
rule_file_path = 'Include ' + haproxy_path + '//waf/rules/' + rule_file
|
||||
rule_file_path = 'Include ' + haproxy_path + '/waf/rules/' + rule_file
|
||||
print(rule_file_path)
|
||||
|
||||
if enable == '0':
|
||||
cmd = ["sudo sed -i 's!" + rule_file_path + "!#" + rule_file_path + "!' " + conf_file_path]
|
||||
|
@ -2901,6 +2948,32 @@ if form.getvalue('waf_rule_id'):
|
|||
print(funct.ssh_command(serv, cmd))
|
||||
sql.update_enable_waf_rules(rule_id, serv, enable)
|
||||
|
||||
if form.getvalue('new_waf_rule'):
|
||||
service = form.getvalue('service')
|
||||
new_waf_rule = form.getvalue('new_waf_rule')
|
||||
new_rule_desc = form.getvalue('new_rule_description')
|
||||
rule_file = form.getvalue('new_rule_file')
|
||||
rule_file = rule_file + '.conf'
|
||||
waf_path = ''
|
||||
|
||||
if service == 'haproxy':
|
||||
waf_path = funct.return_nice_path(sql.get_setting('haproxy_dir'))
|
||||
elif service == 'nginx':
|
||||
waf_path = funct.return_nice_path(sql.get_setting('nginx_dir'))
|
||||
|
||||
conf_file_path = waf_path + 'waf/modsecurity.conf'
|
||||
rule_file_path = waf_path + 'waf/rules/' + rule_file
|
||||
|
||||
cmd = [f"sudo echo Include {rule_file_path} >> {conf_file_path} && sudo touch {rule_file_path}"]
|
||||
print(funct.ssh_command(serv, cmd))
|
||||
print(sql.insert_new_waf_rule(new_waf_rule, rule_file, new_rule_desc, service, serv))
|
||||
|
||||
try:
|
||||
funct.logging('WAF', ' A new rule has been created ' + rule_file + ' on the server ' + serv,
|
||||
haproxywi=1, login=1)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if form.getvalue('lets_domain'):
|
||||
serv = form.getvalue('serv')
|
||||
lets_domain = form.getvalue('lets_domain')
|
||||
|
@ -3251,7 +3324,7 @@ if form.getvalue('show_versions'):
|
|||
if form.getvalue('get_group_name_by_id'):
|
||||
print(sql.get_group_name_by_id(form.getvalue('get_group_name_by_id')))
|
||||
|
||||
if form.getvalue('do_new_name') or form.getvalue('aws_new_name') or form.getvalue('gcore_new_name'):
|
||||
if any((form.getvalue('do_new_name'), form.getvalue('aws_new_name'), form.getvalue('gcore_new_name'))):
|
||||
funct.check_user_group()
|
||||
is_add = False
|
||||
if form.getvalue('do_new_name'):
|
||||
|
@ -3288,6 +3361,8 @@ if form.getvalue('do_new_name') or form.getvalue('aws_new_name') or form.getvalu
|
|||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
||||
user_uuid = cookie.get('uuid')
|
||||
role_id = sql.get_user_role_by_uuid(user_uuid.value)
|
||||
params = sql.select_provisioning_params()
|
||||
providers = sql.select_providers(provider_group, key=provider_token)
|
||||
|
||||
if role_id == 1:
|
||||
groups = sql.select_groups()
|
||||
|
@ -3296,7 +3371,7 @@ if form.getvalue('do_new_name') or form.getvalue('aws_new_name') or form.getvalu
|
|||
|
||||
env = Environment(loader=FileSystemLoader('templates'), autoescape=True)
|
||||
template = env.get_template('ajax/provisioning/providers.html')
|
||||
template = template.render(providers=sql.select_providers(provider_group, key=provider_token), role=role_id, groups=groups, user_group=provider_group, adding=1)
|
||||
template = template.render(providers=providers, role=role_id, groups=groups, user_group=provider_group, adding=1, params=params)
|
||||
print(template)
|
||||
|
||||
if form.getvalue('providerdel'):
|
||||
|
@ -3462,12 +3537,13 @@ if form.getvalue('doworkspace'):
|
|||
|
||||
user, user_id, role, token, servers, user_services = funct.get_users_params()
|
||||
new_server = sql.select_provisioned_servers(new=workspace, group=group, type='do')
|
||||
params = sql.select_provisioning_params()
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/provisioned_servers.html')
|
||||
template = template.render(
|
||||
servers=new_server, groups=sql.select_groups(), user_group=group,
|
||||
providers=sql.select_providers(group), role=role, adding=1
|
||||
providers=sql.select_providers(group), role=role, adding=1, params=params
|
||||
)
|
||||
print(template)
|
||||
|
||||
|
@ -3557,12 +3633,13 @@ if form.getvalue('awsworkspace'):
|
|||
|
||||
user, user_id, role, token, servers, user_services = funct.get_users_params()
|
||||
new_server = sql.select_provisioned_servers(new=workspace, group=group, type='aws')
|
||||
params = sql.select_provisioning_params()
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/provisioned_servers.html')
|
||||
template = template.render(
|
||||
servers=new_server, groups=sql.select_groups(), user_group=group,
|
||||
providers=sql.select_providers(group), role=role, adding=1
|
||||
providers=sql.select_providers(group), role=role, adding=1, params=params
|
||||
)
|
||||
print(template)
|
||||
|
||||
|
@ -3682,6 +3759,10 @@ if (
|
|||
for ip in output:
|
||||
ips += ip
|
||||
ips += ' '
|
||||
|
||||
if cloud == 'gcore':
|
||||
ips = ips.split(' ')[0]
|
||||
|
||||
print(ips)
|
||||
sql.update_provisioning_server_status('Created', group, workspace, provider_id, update_ip=ips)
|
||||
|
||||
|
@ -3826,6 +3907,7 @@ if form.getvalue('gcoreworkspace'):
|
|||
|
||||
user, user_id, role, token, servers, user_services = funct.get_users_params()
|
||||
new_server = sql.select_provisioned_servers(new=workspace, group=group, type='gcore')
|
||||
params = sql.select_provisioning_params()
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/provisioned_servers.html')
|
||||
|
@ -3834,7 +3916,8 @@ if form.getvalue('gcoreworkspace'):
|
|||
user_group=group,
|
||||
providers=sql.select_providers(group),
|
||||
role=role,
|
||||
adding=1)
|
||||
adding=1,
|
||||
params=params)
|
||||
print(template)
|
||||
|
||||
if form.getvalue('gcoreeditworkspace'):
|
||||
|
@ -3879,33 +3962,42 @@ if form.getvalue('editAwsServer'):
|
|||
funct.check_user_group()
|
||||
server_id = form.getvalue('editAwsServer')
|
||||
user_group = form.getvalue('editAwsGroup')
|
||||
params = sql.select_provisioning_params()
|
||||
providers = sql.select_providers(int(user_group))
|
||||
server = sql.select_gcore_server(server_id=server_id)
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/aws_edit_dialog.html')
|
||||
template = template.render(server=sql.select_aws_server(server_id=server_id), providers=sql.select_providers(int(user_group)))
|
||||
template = template.render(server=server, providers=providers, params=params)
|
||||
print(template)
|
||||
|
||||
if form.getvalue('editGcoreServer'):
|
||||
funct.check_user_group()
|
||||
server_id = form.getvalue('editGcoreServer')
|
||||
user_group = form.getvalue('editGcoreGroup')
|
||||
params = sql.select_provisioning_params()
|
||||
providers = sql.select_providers(int(user_group))
|
||||
server = sql.select_gcore_server(server_id=server_id)
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/gcore_edit_dialog.html')
|
||||
template = template.render(server=sql.select_gcore_server(server_id=server_id), providers=sql.select_providers(int(user_group)))
|
||||
template = template.render(server=server, providers=providers, params=params)
|
||||
print(template)
|
||||
|
||||
if form.getvalue('editDoServer'):
|
||||
funct.check_user_group()
|
||||
server_id = form.getvalue('editDoServer')
|
||||
user_group = form.getvalue('editDoGroup')
|
||||
params = sql.select_provisioning_params()
|
||||
providers = sql.select_providers(int(user_group))
|
||||
server = sql.select_do_server(server_id=server_id)
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
env = Environment(extensions=["jinja2.ext.do"], loader=FileSystemLoader('templates'))
|
||||
template = env.get_template('ajax/provisioning/do_edit_dialog.html')
|
||||
template = template.render(server=sql.select_do_server(server_id=server_id), providers=sql.select_providers(int(user_group)))
|
||||
template = template.render(server=server, providers=providers, params=params)
|
||||
print(template)
|
||||
|
||||
if form.getvalue('edit_do_provider'):
|
||||
|
@ -4009,12 +4101,12 @@ if form.getvalue('load_update_hapwi'):
|
|||
template = env.get_template('ajax/load_updatehapwi.html')
|
||||
|
||||
versions = funct.versions()
|
||||
checker_ver = funct.check_new_version(service='checker')
|
||||
smon_ver = funct.check_new_version(service='smon')
|
||||
metrics_ver = funct.check_new_version(service='metrics')
|
||||
keep_ver = funct.check_new_version(service='keep')
|
||||
portscanner_ver = funct.check_new_version(service='portscanner')
|
||||
socket_ver = funct.check_new_version(service='socket')
|
||||
checker_ver = funct.check_new_version('checker')
|
||||
smon_ver = funct.check_new_version('smon')
|
||||
metrics_ver = funct.check_new_version('metrics')
|
||||
keep_ver = funct.check_new_version('keep_alive')
|
||||
portscanner_ver = funct.check_new_version('portscanner')
|
||||
socket_ver = funct.check_new_version('socket')
|
||||
services = funct.get_services_status()
|
||||
|
||||
template = template.render(services=services,
|
||||
|
|
|
@ -15,6 +15,18 @@
|
|||
msg="info HAProxy WAF has already installed"
|
||||
when: stat_result.stat.exists
|
||||
|
||||
- name: erase the RPMS for HAProxy
|
||||
yum:
|
||||
name:
|
||||
- ssdeep
|
||||
- ssdeep-devel
|
||||
state: absent
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
- name: install the el7 RPMS for HAProxy
|
||||
yum:
|
||||
name:
|
||||
|
@ -65,6 +77,7 @@
|
|||
- libevent-devel
|
||||
- libtool
|
||||
- make
|
||||
- gcc-c++
|
||||
state: latest
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
|
@ -86,6 +99,7 @@
|
|||
- libyajl-dev
|
||||
- libxml2
|
||||
- automake
|
||||
- g++
|
||||
- make
|
||||
state: present
|
||||
when: ansible_facts['os_family'] == 'Debian' or ansible_facts['os_family'] == 'Ubuntu'
|
||||
|
@ -110,57 +124,41 @@
|
|||
become: false
|
||||
unarchive:
|
||||
src: /tmp/modsecurity.tar.gz
|
||||
dest: /tmp/modsecurity/
|
||||
dest: /tmp/modsecurity
|
||||
remote_src: true
|
||||
|
||||
- name: Copy modsecurity
|
||||
copy:
|
||||
src: "/tmp/modsecurity/modsecurity-{{ modsec_ver }}/"
|
||||
dest: /tmp/modsecurity/
|
||||
remote_src: yes
|
||||
|
||||
- name: Set execute permision to configure
|
||||
become: true
|
||||
command: chdir=/tmp/modsecurity/ chmod +x configure
|
||||
args:
|
||||
warn: no
|
||||
- name: Set ModSec src foleder
|
||||
set_fact:
|
||||
mod_sec_src: /tmp/modsecurity-{{ modsec_ver }}
|
||||
|
||||
- name: Re configure Modsecurity
|
||||
become: true
|
||||
command: chdir=/tmp/modsecurity/ autoreconf -f -i
|
||||
command: "chdir={{ mod_sec_src }} autoreconf -f -i"
|
||||
|
||||
- name: Configure Modsecurity
|
||||
become: true
|
||||
command: chdir=/tmp/modsecurity/ ./configure --prefix=/tmp/modsecurity --enable-standalone-module --disable-mlogc --enable-pcre-study --without-lua --enable-pcre-jit
|
||||
command: "chdir={{ mod_sec_src }} ./configure --prefix=/tmp/modsecurity --enable-standalone-module --disable-mlogc --enable-pcre-study --without-lua --enable-pcre-jit"
|
||||
|
||||
- name: Make Modsecurity
|
||||
command: chdir=/tmp/modsecurity/ make
|
||||
command: "chdir={{ mod_sec_src }} make"
|
||||
|
||||
- name: Make Install Modsecurity
|
||||
command: chdir=/tmp/modsecurity/ make -C standalone install
|
||||
command: "chdir={{ mod_sec_src }} make -C standalone install"
|
||||
|
||||
- name: Creates directory
|
||||
file:
|
||||
path: /tmp/modsecurity/INSTALL/include
|
||||
path: "{{ mod_sec_src }}INSTALL/include"
|
||||
state: directory
|
||||
|
||||
- name: Copy Modsec libs
|
||||
copy:
|
||||
src: /tmp/modsecurity/standalone/.libs/
|
||||
dest: /tmp/modsecurity/INSTALL/include/
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec files
|
||||
copy:
|
||||
src: /tmp/modsecurity/standalone/
|
||||
dest: /tmp/modsecurity/INSTALL/include/
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec apache files
|
||||
copy:
|
||||
src: /tmp/modsecurity/apache2/
|
||||
dest: /tmp/modsecurity/INSTALL/include/
|
||||
src: "{{ mod_sec_src }}/{{ item }}"
|
||||
dest: "{{ mod_sec_src }}/INSTALL/include/"
|
||||
remote_src: yes
|
||||
with_items:
|
||||
- standalone/.libs/
|
||||
- standalone/
|
||||
- apache2/
|
||||
|
||||
- name: Install git
|
||||
package:
|
||||
|
@ -175,22 +173,20 @@
|
|||
mod_sec_dir: /tmp/spoa-modsecurity
|
||||
|
||||
- name: Make APT Modsecurity module for HAProxy
|
||||
command: "chdir={{ mod_sec_dir }} make MODSEC_INC=/tmp/modsecurity/INSTALL/include MODSEC_LIB=/tmp/modsecurity/INSTALL/include APACHE2_INC=/usr/include/apache2/ APR_INC=/usr/include/apr-1.0"
|
||||
command: "chdir={{ mod_sec_dir }} make MODSEC_INC={{ mod_sec_src }}/INSTALL/include MODSEC_LIB={{ mod_sec_src }}/INSTALL/include APACHE2_INC=/usr/include/apache2/ APR_INC=/usr/include/apr-1.0"
|
||||
when: ansible_facts['os_family'] == 'Debian' or ansible_facts['os_family'] == 'Ubuntu'
|
||||
|
||||
- name: Make EL Modsecurity module for HAProxy
|
||||
command: "chdir={{ mod_sec_dir }} make MODSEC_INC=/tmp/modsecurity/INSTALL/include MODSEC_LIB=/tmp/modsecurity/INSTALL/include APACHE2_INC=/usr/include/httpd/ APR_INC=/usr/include/apr-1"
|
||||
command: "chdir={{ mod_sec_dir }} make MODSEC_INC={{ mod_sec_src }}/INSTALL/include MODSEC_LIB={{ mod_sec_src }}/INSTALL/include APACHE2_INC=/usr/include/httpd/ APR_INC=/usr/include/apr-1"
|
||||
when: ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
|
||||
- name: Make WAF rules directory
|
||||
file:
|
||||
path: "{{ HAPROXY_PATH }}/waf/rules"
|
||||
state: directory
|
||||
|
||||
- name: Make WAF bin directory
|
||||
file:
|
||||
path: "{{ HAPROXY_PATH }}/waf/bin"
|
||||
path: "{{ HAPROXY_PATH }}/waf/{{ item }}"
|
||||
state: directory
|
||||
with_items:
|
||||
- rules
|
||||
- bin
|
||||
|
||||
- name: Copy Modsec module to HAProxy dir
|
||||
copy:
|
||||
|
@ -269,9 +265,16 @@
|
|||
|
||||
- name: Copy owasp files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/owasp-modsecurity-crs-2.2.9/
|
||||
src: "/tmp/owasp-modsecurity-crs-2.2.9/{{ item }}"
|
||||
dest: /tmp/owasp-modsecurity-crs-2.2.9
|
||||
remote_src: yes
|
||||
with_items:
|
||||
- owasp-modsecurity-crs-2.2.9/
|
||||
- activated_rules/
|
||||
- base_rules/
|
||||
- experimental_rules/
|
||||
- optional_rules/
|
||||
- slr_rules/
|
||||
|
||||
- name: Copy Modsec crs conf file
|
||||
copy:
|
||||
|
@ -279,36 +282,6 @@
|
|||
dest: "{{ HAPROXY_PATH }}/waf/rules/modsecurity_crs_10_setup.conf"
|
||||
remote_src: true
|
||||
|
||||
- name: Copy Modsec crs activated_rules files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/activated_rules/
|
||||
dest: "{{ HAPROXY_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec crs base_rules files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/base_rules/
|
||||
dest: "{{ HAPROXY_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec crs experimental_rules files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/experimental_rules/
|
||||
dest: "{{ HAPROXY_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec crs optional_rules files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/optional_rules/
|
||||
dest: "{{ HAPROXY_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy Modsec crs slr_rules files
|
||||
copy:
|
||||
src: /tmp/owasp-modsecurity-crs-2.2.9/slr_rules/
|
||||
dest: "{{ HAPROXY_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Ensure ModSec engine mode on
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ HAPROXY_PATH }}/waf/modsecurity.conf"
|
||||
|
@ -367,42 +340,14 @@
|
|||
enabled: yes
|
||||
|
||||
always:
|
||||
- name: Remove modsecurity.tar.gz
|
||||
- name: Clean up
|
||||
ansible.builtin.file:
|
||||
path: /tmp/modsecurity.tar.gz
|
||||
state: absent
|
||||
|
||||
- name: Remove modsecurity-2.9.2
|
||||
ansible.builtin.file:
|
||||
path: /tmp/modsecurity-2.9.2
|
||||
state: absent
|
||||
|
||||
- name: Remove HAProxy
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/haproxy-{{ VERSION }}"
|
||||
state: absent
|
||||
|
||||
- name: Remove modsecurity
|
||||
ansible.builtin.file:
|
||||
path: /tmp/modsecurity
|
||||
state: absent
|
||||
|
||||
- name: Remove modsecurity.conf
|
||||
ansible.builtin.file:
|
||||
path: /tmp/modsecurity.conf
|
||||
state: absent
|
||||
|
||||
- name: Remove owasp.tar.gz
|
||||
ansible.builtin.file:
|
||||
path: /tmp/owasp.tar.gz
|
||||
state: absent
|
||||
|
||||
- name: Remove owasp-modsecurity-crs-2.2.9
|
||||
ansible.builtin.file:
|
||||
path: /tmp/owasp-modsecurity-crs-2.2.9
|
||||
state: absent
|
||||
|
||||
- name: Remove spoa-modsecurity
|
||||
ansible.builtin.file:
|
||||
path: /tmp/spoa-modsecurity
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- /tmp/modsecurity.tar.gz
|
||||
- "/tmp/modsecurity-{{ modsec_ver }}"
|
||||
- "/tmp/haproxy-{{ VERSION }}"
|
||||
- /tmp/owasp.tar.gz
|
||||
- /tmp/owasp-modsecurity-crs-2.2.9
|
||||
- /tmp/spoa-modsecurity
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
- name: Install WAF
|
||||
hosts: "{{ variable_host }}"
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
roles:
|
||||
- role: waf_nginx
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
|
@ -0,0 +1 @@
|
|||
coreruleset_ver: 3.3.2
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
- name: reload NGINX
|
||||
service: name=nginx state=reloaded
|
|
@ -0,0 +1,224 @@
|
|||
---
|
||||
- name: Installing WAF
|
||||
block:
|
||||
- name: Set SSH port
|
||||
set_fact:
|
||||
ansible_port: "{{SSH_PORT}}"
|
||||
|
||||
# - debug: msg="{{ ansible_facts }}"
|
||||
|
||||
- name: Check that WAF has been installed
|
||||
stat:
|
||||
path: "{{ NGINX_PATH }}/waf/modsecurity.conf"
|
||||
register: stat_result
|
||||
|
||||
- name: Fail if has been installed
|
||||
fail:
|
||||
msg="info NGINX WAF has already installed"
|
||||
when: stat_result.stat.exists
|
||||
|
||||
- name: install the common RPMS for NGINX
|
||||
yum:
|
||||
name:
|
||||
- libtool
|
||||
- libxml2-devel
|
||||
- gcc
|
||||
- curl-devel
|
||||
- pcre-devel
|
||||
- automake
|
||||
- autoconf
|
||||
- libevent-devel
|
||||
- libtool
|
||||
- make
|
||||
- gcc-c++
|
||||
- git
|
||||
- redhat-rpm-config
|
||||
- openssl-devel
|
||||
- libxslt-devel
|
||||
- gd-devel
|
||||
- perl-ExtUtils-Embed
|
||||
- GeoIP-devel
|
||||
- ssdeep-devel
|
||||
state: latest
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
- name: Install needed packages
|
||||
apt:
|
||||
name:
|
||||
- libtool
|
||||
- libevent-dev
|
||||
- libpcre3-dev
|
||||
- libxml2-dev
|
||||
- gcc
|
||||
- libpcre3-dev
|
||||
- libcurl4-nss-dev
|
||||
- libyajl-dev
|
||||
- libxml2
|
||||
- automake
|
||||
- autoconf
|
||||
- g++
|
||||
- make
|
||||
- openssl-dev
|
||||
- libxslt-dev
|
||||
- gd-dev
|
||||
- perl-modules
|
||||
- libmodsecurity3
|
||||
- libgeoip-dev
|
||||
- libfuzzy2
|
||||
state: present
|
||||
when: ansible_facts['os_family'] == 'Debian' or ansible_facts['os_family'] == 'Ubuntu'
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
- name: Download ModSec
|
||||
ansible.builtin.get_url:
|
||||
url: "http://repo.roxy-wi.org/modsec/modsecv3.0.7-{{ ansible_facts.distribution | lower }}{{ ansible_facts.distribution_major_version }}.tar.gz"
|
||||
dest: /usr/local/modsecv3.tar.gz
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
|
||||
- name: Untar ModSec
|
||||
unarchive:
|
||||
src: /usr/local/modsecv3.tar.gz
|
||||
dest: /usr/local/
|
||||
remote_src: true
|
||||
|
||||
- name: Get NGINX version
|
||||
shell: /usr/sbin/nginx -v
|
||||
register: nginx_version
|
||||
|
||||
- name: Get NGINX parameters
|
||||
shell: /usr/sbin/nginx -V 2>&1 |grep configu |awk -F":" '{print $2}'
|
||||
register: nginx_params
|
||||
|
||||
- name: Clone NGINX connector
|
||||
shell: git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git /tmp/nginx-connector
|
||||
|
||||
- name: Download NGINX
|
||||
ansible.builtin.get_url:
|
||||
url: "http://nginx.org/download/nginx-{{ nginx_version.stderr.split('/')[1] }}.tar.gz"
|
||||
dest: /tmp/nginx_src.tar.gz
|
||||
|
||||
- name: Create nginx_src directory
|
||||
become: false
|
||||
file:
|
||||
path: /tmp/nginx_src/
|
||||
state: directory
|
||||
|
||||
- name: Untar NGINX
|
||||
become: false
|
||||
unarchive:
|
||||
src: /tmp/nginx_src.tar.gz
|
||||
dest: /tmp/nginx_src/
|
||||
remote_src: true
|
||||
|
||||
- name: Configure NGINX
|
||||
become: true
|
||||
command: "chdir=/tmp/nginx_src/nginx-{{ nginx_version.stderr.split('/')[1] }} ./configure {{ nginx_params.stdout }} --add-dynamic-module=../../nginx-connector"
|
||||
environment:
|
||||
CFLAGS: -Wno-error
|
||||
|
||||
- name: Make NGINX modules
|
||||
become: true
|
||||
command: "chdir=/tmp/nginx_src/nginx-{{ nginx_version.stderr.split('/')[1] }} make modules"
|
||||
|
||||
- name: Copy module for CentOS
|
||||
become: true
|
||||
command: "chdir=/tmp/nginx_src/nginx-{{ nginx_version.stderr.split('/')[1] }} cp objs/ngx_http_modsecurity_module.so /usr/share/nginx/modules/"
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
|
||||
- name: Copy module for Ubuntu
|
||||
become: true
|
||||
command: "chdir=/tmp/nginx_src/nginx-{{ nginx_version.stderr.split('/')[1] }} cp objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules/"
|
||||
when: ansible_facts['os_family'] == 'Debian' or ansible_facts['os_family'] == 'Ubuntu'
|
||||
|
||||
- name: Enable module for Centos
|
||||
become: true
|
||||
shell: echo 'load_module "modules/ngx_http_modsecurity_module.so";' > /usr/share/nginx/modules/mod-waf-connector.conf
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
|
||||
- name: Enable module for Ubuntu
|
||||
lineinfile:
|
||||
path: "{{ NGINX_PATH }}/nginx.conf"
|
||||
line: load_module modules/ngx_http_modsecurity_module.so;
|
||||
insertbefore: BOF
|
||||
when: ansible_facts['os_family'] == 'Debian' or ansible_facts['os_family'] == 'Ubuntu'
|
||||
|
||||
- name: Create WAF directory
|
||||
become: false
|
||||
file:
|
||||
path: "{{ NGINX_PATH }}/waf/"
|
||||
state: directory
|
||||
|
||||
- name: Create WAF rules directory
|
||||
become: false
|
||||
file:
|
||||
path: "{{ NGINX_PATH }}/waf/rules"
|
||||
state: directory
|
||||
|
||||
- name: Download modsecurity.conf
|
||||
ansible.builtin.get_url:
|
||||
url: https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
|
||||
dest: "{{ NGINX_PATH }}/waf/modsecurity.conf"
|
||||
|
||||
- name: Download unicode.mapping
|
||||
ansible.builtin.get_url:
|
||||
url: https://github.com/SpiderLabs/ModSecurity/blob/v3/master/unicode.mapping
|
||||
dest: "{{ NGINX_PATH }}/waf/unicode.mapping"
|
||||
|
||||
- name: Create WAF config
|
||||
template:
|
||||
src: waf.conf.j2
|
||||
dest: "{{ NGINX_PATH }}/waf/waf.conf"
|
||||
|
||||
- name: Download OWASP rules
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/coreruleset/coreruleset/archive/v{{ coreruleset_ver }}.tar.gz"
|
||||
dest: /tmp/OWASP.tar.gz
|
||||
|
||||
- name: Untar NGINX
|
||||
become: false
|
||||
unarchive:
|
||||
src: /tmp/OWASP.tar.gz
|
||||
dest: /tmp/
|
||||
remote_src: true
|
||||
|
||||
- name: Copy Modsec crs activated_rules files
|
||||
copy:
|
||||
src: "/tmp/coreruleset-{{ coreruleset_ver }}/rules/"
|
||||
dest: "{{ NGINX_PATH }}/waf/rules/"
|
||||
remote_src: yes
|
||||
|
||||
- name: Copy module
|
||||
become: true
|
||||
command: "chdir=/tmp/coreruleset-{{ coreruleset_ver }} cp crs-setup.conf.example {{ NGINX_PATH }}/waf/rulescrs-setup.conf"
|
||||
|
||||
- name: Add waf Mod on
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ NGINX_PATH }}/nginx.conf"
|
||||
marker: "#-- {mark} WAF BLOCK --#"
|
||||
insertafter: "http {"
|
||||
block: |
|
||||
modsecurity off;
|
||||
modsecurity_rules_file /etc/nginx/waf/waf.conf;
|
||||
notify: reload NGINX
|
||||
|
||||
always:
|
||||
- name: Clean up
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- /tmp/nginx_src/
|
||||
- /tmp/nginx_src.tar.gz
|
||||
- /tmp/nginx-connector
|
||||
- /tmp/OWASP.tar.gz
|
||||
- /usr/local/modsecv3.tar.gz
|
||||
# - "/tmp/coreruleset-{{ coreruleset_ver }}"
|
|
@ -0,0 +1,31 @@
|
|||
Include {{ NGINX_PATH }}/waf/modsecurity.conf
|
||||
Include {{ NGINX_PATH }}/waf/rulescrs-setup.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-901-INITIALIZATION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-910-IP-REPUTATION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-912-DOS-PROTECTION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-913-SCANNER-DETECTION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-921-PROTOCOL-ATTACK.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/REQUEST-949-BLOCKING-EVALUATION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
|
||||
Include {{ NGINX_PATH }}/waf/rules/RESPONSE-980-CORRELATION.conf
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
|
||||
for ARGUMENT in "$@"
|
||||
do
|
||||
KEY=$(echo "$ARGUMENT" | cut -f1 -d=)
|
||||
VALUE=$(echo "$ARGUMENT" | cut -f2 -d=)
|
||||
|
||||
case "$KEY" in
|
||||
PROXY) PROXY=${VALUE} ;;
|
||||
NGINX_PATH) NGINX_PATH=${VALUE} ;;
|
||||
HOST) HOST=${VALUE} ;;
|
||||
USER) USER=${VALUE} ;;
|
||||
PASS) PASS=${VALUE} ;;
|
||||
KEY) KEY=${VALUE} ;;
|
||||
SSH_PORT) SSH_PORT=${VALUE} ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
|
||||
export ACTION_WARNINGS=False
|
||||
export LOCALHOST_WARNING=False
|
||||
export COMMAND_WARNINGS=False
|
||||
|
||||
PWD=$(pwd)
|
||||
PWD=$PWD/scripts/ansible/
|
||||
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
|
||||
|
||||
if [[ $KEY == "" ]]; then
|
||||
ansible-playbook $PWD/roles/waf_nginx.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST PROXY=$PROXY NGINX_PATH=$NGINX_PATH SSH_PORT=$SSH_PORT" -i $PWD/$HOST
|
||||
else
|
||||
ansible-playbook $PWD/roles/waf_nginx.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST PROXY=$PROXY NGINX_PATH=$NGINX_PATH SSH_PORT=$SSH_PORT" -i $PWD/$HOST
|
||||
fi
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
echo "error: Cannot install WAF"
|
||||
else
|
||||
echo "success"
|
||||
fi
|
||||
rm -f $PWD/$HOST
|
136
app/sql.py
136
app/sql.py
|
@ -1272,6 +1272,25 @@ def select_waf_servers(serv):
|
|||
return en.ip
|
||||
|
||||
|
||||
def select_waf_nginx_servers(serv):
|
||||
query = Server.select(Server.ip).join(WafNginx, on=(WafNginx.server_id == Server.server_id)).where(Server.ip == serv)
|
||||
try:
|
||||
query_res = query.execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
else:
|
||||
for en in query_res:
|
||||
return en.ip
|
||||
|
||||
|
||||
def insert_waf_nginx_server(server_ip):
|
||||
try:
|
||||
server_id = Server.get(Server.ip == server_ip).server_id
|
||||
WafNginx.insert(server_id=server_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_waf_servers_metrics_for_master():
|
||||
query = Server.select(Server.ip).join(
|
||||
Waf, on=(Waf.server_id == Server.server_id)
|
||||
|
@ -1390,8 +1409,105 @@ def insert_waf_rules(serv):
|
|||
return True
|
||||
|
||||
|
||||
def select_waf_rules(serv):
|
||||
query = WafRules.select(WafRules.id, WafRules.rule_name, WafRules.en, WafRules.desc).where(WafRules.serv == serv)
|
||||
def insert_nginx_waf_rules(serv):
|
||||
data_source = [
|
||||
{'serv': serv, 'rule_name': 'Initialization', 'rule_file': 'REQUEST-901-INITIALIZATION.conf',
|
||||
'desc': 'This file REQUEST-901-INITIALIZATION.conf initializes the Core Rules and performs preparatory actions. '
|
||||
'It also fixes errors and omissions of variable definitions in the file crs-setup.conf The setup.conf'
|
||||
'can and should be edited by the user, this file. is part of the CRS installation and should not be altered.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Drupal exclusion rules', 'rule_file': 'REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf',
|
||||
'desc': 'These exclusions remedy false positives in a default Drupal install. The exclusions are only active '
|
||||
'if crs_exclusions_drupal=1 is set. See rule 900130 in crs-setup.conf for instructions.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Nextcloud exclusion rules', 'rule_file': 'REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf',
|
||||
'desc': 'These exclusions remedy false positives in a default NextCloud install. They will likely work with OwnCloud '
|
||||
'too, but you may have to modify them. The exclusions are only active if crs_exclusions_nextcloud=1 is set. '
|
||||
'See rule 900130 in crs-setup.conf for instructions.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Dokuwiki exclusion rules', 'rule_file': 'REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf',
|
||||
'desc': 'These exclusions remedy false positives in a default Dokuwiki install. The exclusions are only active '
|
||||
'if crs_exclusions_dokuwiki=1 is set. See rule 900130 in crs-setup.conf for instructions.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'CPanel exclusion rules', 'rule_file': 'REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf',
|
||||
'desc': 'These exclusions remedy false positives in a default CPanel install. The exclusions are only active '
|
||||
'if crs_exclusions_cpanel=1 is set. See rule 900130 in crs-setup.conf for instructions.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'XenForo exclusion rules', 'rule_file': 'REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf',
|
||||
'desc': 'These exclusions remedy false positives in a default XenForo install. The exclusions are only active '
|
||||
'if crs_exclusions_xenforo=1 is set. See rule 900130 in crs-setup.conf for instructions.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Common exceptions', 'rule_file': 'REQUEST-905-COMMON-EXCEPTIONS.conf',
|
||||
'desc': 'This file is used as an exception mechanism to remove common false positives that may be encountered.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'IP reputation', 'rule_file': 'REQUEST-910-IP-REPUTATION.conf',
|
||||
'desc': 'IP reputation rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Method enforcement', 'rule_file': 'REQUEST-911-METHOD-ENFORCEMENT.conf',
|
||||
'desc': 'Method enforcement rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'DDOS protection', 'rule_file': 'REQUEST-912-DOS-PROTECTION.conf',
|
||||
'desc': 'Anti-Automation rules to detect Denial of Service attacks.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Protocol enforcement', 'rule_file': 'REQUEST-920-PROTOCOL-ENFORCEMENT.conf',
|
||||
'desc': 'Some protocol violations are common in application layer attacks. Validating HTTP requests eliminates '
|
||||
'a large number of application layer attacks. The purpose of this rules file is to enforce HTTP RFC '
|
||||
'requirements that state how the client is supposed to interact with the server.',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Protocol attack', 'rule_file': 'REQUEST-921-PROTOCOL-ATTACK.conf',
|
||||
'desc': 'Protocol attack rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack LFI', 'rule_file': 'REQUEST-930-APPLICATION-ATTACK-LFI.conf',
|
||||
'desc': 'Application attack LFI rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack RCE', 'rule_file': 'REQUEST-932-APPLICATION-ATTACK-RCE.conf',
|
||||
'desc': 'Application attack RCE rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack PHP', 'rule_file': 'REQUEST-933-APPLICATION-ATTACK-PHP.conf',
|
||||
'desc': 'Application attack PHP rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack NodeJS', 'rule_file': 'REQUEST-934-APPLICATION-ATTACK-NODEJS.conf',
|
||||
'desc': 'Application attack NodeJS rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack SQLI', 'rule_file': 'REQUEST-942-APPLICATION-ATTACK-SQLI.conf',
|
||||
'desc': 'Application attack SQLI rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack session-fixation', 'rule_file': 'REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf',
|
||||
'desc': 'Application attack session-fixation rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack JAVA', 'rule_file': 'REQUEST-944-APPLICATION-ATTACK-JAVA.conf',
|
||||
'desc': 'Application attack JAVA rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Application attack blocking evaluation', 'rule_file': 'REQUEST-949-BLOCKING-EVALUATION.conf',
|
||||
'desc': 'Application attack blocking evaluation rule.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Data leakages', 'rule_file': 'RESPONSE-950-DATA-LEAKAGES.conf',
|
||||
'desc': 'The paranoia level skip rules 950020, 950021 and 950022 have odd numbers not in sync with other paranoia '
|
||||
'level skip rules in other. files. This is done to avoid rule id collisions with CRSv2. This is also true '
|
||||
'for rule 950130.', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Data leakages SQL', 'rule_file': 'RESPONSE-951-DATA-LEAKAGES-SQL.conf',
|
||||
'desc': 'Data leakages SQL rule', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Data leakages JAVA', 'rule_file': 'RESPONSE-952-DATA-LEAKAGES-JAVA.conf',
|
||||
'desc': 'Data leakages JAVA rule', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Data leakages PHP', 'rule_file': 'RESPONSE-953-DATA-LEAKAGES-PHP.conf',
|
||||
'desc': 'Data leakages PHP rule', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Data leakages IIS', 'rule_file': 'RESPONSE-954-DATA-LEAKAGES-IIS.conf',
|
||||
'desc': 'Data leakages IIS rule', 'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Blocking evaluation', 'rule_file': 'RESPONSE-959-BLOCKING-EVALUATION.conf',
|
||||
'desc': 'You should set the score to the proper threshold you would prefer. If kept at "@gt 0" it will work '
|
||||
'similarly to previous Mod CRS rules and will create an event in the error_log file if there are any '
|
||||
'rules that match. If you would like to lessen the number of events generated in the error_log file, '
|
||||
'you should increase the anomaly score threshold to something like "@gt 20". This would only generate '
|
||||
'an event in the error_log file if there are multiple lower severity rule matches or if any 1 higher '
|
||||
'severity item matches. You should also set the desired disruptive action (deny, redirect, etc...).',
|
||||
'service': 'nginx'},
|
||||
{'serv': serv, 'rule_name': 'Correlation', 'rule_file': 'RESPONSE-980-CORRELATION.conf',
|
||||
'desc': 'This file is used in post processing after the response has been sent to the client (in the logging phase). '
|
||||
'Its purpose is to provide inbound+outbound correlation of events to provide a more intelligent designation '
|
||||
'as to the outcome or result of the transaction - meaning, was this a successful attack?',
|
||||
'service': 'nginx'},
|
||||
]
|
||||
try:
|
||||
WafRules.insert_many(data_source).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def select_waf_rules(serv, service):
|
||||
query = WafRules.select(WafRules.id, WafRules.rule_name, WafRules.en, WafRules.desc).where(
|
||||
(WafRules.serv == serv)
|
||||
& (WafRules.service == service)
|
||||
)
|
||||
try:
|
||||
query_res = query.execute()
|
||||
except Exception as e:
|
||||
|
@ -1425,6 +1541,22 @@ def update_enable_waf_rules(rule_id, serv, en):
|
|||
out_error(e)
|
||||
|
||||
|
||||
def insert_new_waf_rule(rule_name: str, rule_file: str, rule_description: str, service: str, serv: str) -> int:
|
||||
try:
|
||||
last_id = WafRules.insert(
|
||||
serv=serv,
|
||||
rule_name=rule_name,
|
||||
rule_file=rule_file,
|
||||
desc=rule_description,
|
||||
service=service
|
||||
).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
else:
|
||||
return last_id
|
||||
|
||||
|
||||
|
||||
def delete_waf_server(server_id):
|
||||
query = Waf.delete().where(Waf.server_id == server_id)
|
||||
try:
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
{% do waf_modes.append("On") %}
|
||||
{% do waf_modes.append("Off") %}
|
||||
{% do waf_modes.append("DetectionOnly") %}
|
||||
{% if waf_service == 'haproxy' %}
|
||||
{% set service_name = 'waf' %}
|
||||
{% else %}
|
||||
{% set service_name = 'waf_nginx' %}
|
||||
{% endif %}
|
||||
{% for service in service_status %}
|
||||
<td class="padding10 first-collumn-wi">
|
||||
{% if service.5|int() >= 1 %}
|
||||
|
@ -17,18 +22,25 @@
|
|||
<span class="serverNone server-status" title="WAF is not installed"></span> <span title="WAF is not installed">{{ service.0 }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{{service.3}}
|
||||
{% if service.3 == "On" or service.3 == "Off" or service.3 == "DetectionOnly" %}
|
||||
<td>
|
||||
{% if role <= 2 %}
|
||||
<a id="{{ service.1 }}" class="start-waf" title="Start WAF service">
|
||||
<span class="service-start" onclick="confirmAjaxAction('start', 'waf', '{{service.1}}')"></span>
|
||||
<span class="service-start" onclick="confirmAjaxAction('start', '{{service_name}}', '{{service.1}}')"></span>
|
||||
</a>
|
||||
<a id="{{ service.1 }}" class="stop-waf" title="Stop WAF service">
|
||||
<span class="service-stop" onclick="confirmAjaxAction('stop', 'waf', '{{service.1}}')"></span>
|
||||
<span class="service-stop" onclick="confirmAjaxAction('stop', '{{service_name}}', '{{service.1}}')"></span>
|
||||
</a>
|
||||
{% if waf_service == 'haproxy' %}
|
||||
<a id="{{ service.1 }}" class="restart-waf" title="Restart WAF service">
|
||||
<span class="service-reload" onclick="confirmAjaxAction('restart', 'waf', '{{service.1}}')"></span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a id="{{ service.1 }}" class="reload-waf" title="Reload WAF service">
|
||||
<span class="service-reload" onclick="confirmAjaxAction('reload', 'nginx', '{{service.1}}')"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
@ -46,6 +58,7 @@
|
|||
{{ service.3 }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if waf_service == 'haproxy' %}
|
||||
<td style="padding-top: 2px;" class="ajaxwafstatus">
|
||||
{% if service.4|int() == 1 %}
|
||||
<label for="metrics{{ service.0 }}"></label><input type="checkbox" id="metrics{{ service.0 }}" checked />
|
||||
|
@ -53,13 +66,18 @@
|
|||
<label for="metrics{{ service.0 }}"></label><input type="checkbox" id="metrics{{ service.0 }}" />
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{% if role <= 2 %}
|
||||
<a href="/app/waf.py?manage_rules=1&serv={{service.1}}" class="ui-button ui-widget ui-corner-all">Open</a>
|
||||
<a href="/app/waf.py?service={{waf_service}}&manage_rules=1&serv={{service.1}}" class="ui-button ui-widget ui-corner-all">Open</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if waf_service == 'haproxy' %}
|
||||
<a href="/app/logs.py?serv={{ service.1 }}&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00&waf=1" class="ui-button ui-widget ui-corner-all" title="View log">View</a>
|
||||
{% elif waf_service == 'nginx' %}
|
||||
<a href="/app/logs.py?service={{waf_service}}&serv={{ service.1 }}&rows=10&grep=ModSecurity&hour=00&minut=00&hour1=24&minut1=00&file=error.log&waf=0" class="ui-button ui-widget ui-corner-all" title="View log">View</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td></td>
|
||||
{% else %}
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
{% if role <= 3 %}
|
||||
<li><a href="/app/versions.py?service=nginx" title="Working with versions NGINX configs" class="version head-submenu">Versions</a></li>
|
||||
<li><a href="/app/add.py?service=nginx#ssl" title="Add proxy: Upload SSL certificates - Roxy-WI" class="cert head-submenu" id="add3">SSL</a></li>
|
||||
<li><a href="/app/waf.py?service=nginx" title="Web application firewall" class="waf-menu head-submenu">WAF</a> </li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -276,7 +277,7 @@
|
|||
<a href="https://github.com/hap-wi/roxy-wi/issues" class="footer-link" target="_blank" title="Community help">Help</a>
|
||||
<a href="https://sd.roxy-wi.org" class="footer-link" target="_blank" title="Service Desk">SD</a>
|
||||
<a href="https://roxy-wi.org/contacts" class="footer-link" target="_blank">Contacts</a>
|
||||
<a href="https://roxy-wi.org/cabinet.py" class="footer-link" target="_blank" title="Private cabinet">Cabinet</a>
|
||||
<a href="https://roxy-wi.org/cabinet" class="footer-link" target="_blank" title="Private cabinet">Cabinet</a>
|
||||
<a href="https://roxy-wi.org/legal" class="footer-link" target="_blank" title="Legal Note">Legal</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -25,14 +25,29 @@
|
|||
</td>
|
||||
<td style="padding-top: 5px;padding-bottom: 10px;">{{r.desc}}</td>
|
||||
<td style="padding: 0 10px 0 10px;">
|
||||
<a href="waf.py?waf_rule_id={{r.id}}&serv={{serv}}" class="ui-button ui-widget ui-corner-all" title="View this rule versions">View</a>
|
||||
<a href="waf.py?service={{service}}&waf_rule_id={{r.id}}&serv={{serv}}" class="ui-button ui-widget ui-corner-all" title="View this rule versions">View/Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><span class="add-button" title="Add a new WAF rule" onclick="addNewConfig()" style="margin-right: 20px;">+ Add</span></p><br><br>
|
||||
<div id="add-new-config" style="display: none">
|
||||
<table class="overview">
|
||||
{% include 'include/tr_validate_tips.html' %}
|
||||
<tr>
|
||||
<td class="padding20">Rule name:<span class="need-field">*</span></td>
|
||||
<td>{{ input('new_rule_name', type='text', placeholder='New protected rule', title='New protected rule') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">Rule description:<span class="need-field">*</span></td>
|
||||
<td>{{ input('new_rule_description', type='text', placeholder='This rule protects again attacks', title='This rule protects again attacks') }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% elif waf_rule_file %}
|
||||
<center>
|
||||
<link rel="stylesheet" href="/inc/codemirror/codemirror.css">
|
||||
<script src="/inc/configshow.js"></script>
|
||||
<script src="/inc/codemirror/codemirror.js"></script>
|
||||
<script src="/inc/codemirror/modsec.js"></script>
|
||||
<h4>Config {{waf_rule_file}} from {{ serv }}</h4>
|
||||
|
@ -41,13 +56,22 @@
|
|||
<input type="hidden" value="{{ serv }}" name="serv">
|
||||
<input type="hidden" value="{{ cfg }}.old" name="oldconfig">
|
||||
<input type="hidden" value="{{ token }}" name="token">
|
||||
<input type="hidden" value="{{ service }}" name="service">
|
||||
<input type="hidden" value="waf_{{ service }}" name="service">
|
||||
<input type="hidden" value="{{ config_file_name }}" name="config_file_name">
|
||||
<div style="margin-left: 20%;width: 60%;">
|
||||
<textarea name="config" id="config_text_area" class="config" rows="35" cols="100">{{ config }}</textarea>
|
||||
</div>
|
||||
<p>
|
||||
<center>
|
||||
<a href="waf.py?manage_rules=1&serv={{serv}}" class="ui-button ui-widget ui-corner-all" title="Return to rules management">Back</a>
|
||||
{% if role <= 3 %}
|
||||
<button type="submit" value="save" name="save" class="btn btn-default" title="Save config without reloading the service">Save</button>
|
||||
{% if service == 'haproxy' %}
|
||||
<button type="submit" value="" name="" class="btn btn-default">Save and restart</button>
|
||||
{% elif service == 'nginx' %}
|
||||
<button type="submit" value="" name="reload" class="btn btn-default">Save and reload</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</center>
|
||||
</p>
|
||||
</form>
|
||||
|
@ -59,7 +83,7 @@
|
|||
</style>
|
||||
<script>
|
||||
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("config_text_area"),
|
||||
{mode: "modsec", lineNumbers: true, autocapitalize: true, autocorrect: true, spellcheck: true, readOnly: true});
|
||||
{mode: "modsec", lineNumbers: true, autocapitalize: true, autocorrect: true, spellcheck: true});
|
||||
myCodeMirror.refresh();
|
||||
</script>
|
||||
{% else %}
|
||||
|
@ -93,7 +117,9 @@
|
|||
<td class="padding10 first-collumn">Server</td>
|
||||
<td class="padding10">Actions</td>
|
||||
<td class="padding10">WAF mode</td>
|
||||
{% if service == 'haproxy' %}
|
||||
<td>Metrics</td>
|
||||
{% endif %}
|
||||
<td>Manage rules</td>
|
||||
<td>Log</td>
|
||||
<td>
|
||||
|
@ -106,11 +132,12 @@
|
|||
<tr class="{{ loop.cycle('odd', 'even') }}" id="{{s[2]}}"></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% if service == 'haproxy' %}
|
||||
<link href="/inc/chart.min.css" rel="stylesheet">
|
||||
<script src="/inc/overview.js"></script>
|
||||
<script src="/inc/metrics.js"></script>
|
||||
<script src="/inc/chart.min.js"></script>
|
||||
<div id="table_metrics"></div>
|
||||
<div style="padding-left: 25px;float: left;margin-top: 3px;">
|
||||
<b>Time range:</b>
|
||||
<select title="Choose time range" id="time-range">
|
||||
|
@ -129,28 +156,31 @@
|
|||
<canvas id="waf_{{s.server.ip}}" role="img"></canvas>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div id="dialog-confirm" style="display: none;">
|
||||
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Are you sure?</p>
|
||||
</div>
|
||||
{% for s in servers %}
|
||||
{{s.ip}}
|
||||
{% endfor %}
|
||||
{{s.ip}}
|
||||
{% endfor %}
|
||||
<script>
|
||||
{%- if service == 'haproxy' %}
|
||||
function showWafMetrics() {
|
||||
{% for s in servers %}
|
||||
{%- for s in servers %}
|
||||
getWafChartData('{{s.server.ip}}');
|
||||
{% endfor %}
|
||||
{%- endfor %}
|
||||
}
|
||||
showWafMetrics();
|
||||
{%- endif %}
|
||||
showOverviewWaf(ip, hostnamea);
|
||||
$( function() {
|
||||
$("#time-range").on('selectmenuchange', function () {
|
||||
removeData()
|
||||
let metrics = new Promise(
|
||||
(resolve, reject) => {
|
||||
{% for s in servers %}
|
||||
{%- for s in servers %}
|
||||
getWafChartData('{{s.server.ip}}')
|
||||
{% endfor %}
|
||||
{%- endfor %}
|
||||
});
|
||||
metrics.then();
|
||||
});
|
||||
|
|
54
app/waf.py
54
app/waf.py
|
@ -1,4 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
|
||||
import funct
|
||||
import sql
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
@ -8,11 +11,13 @@ template = env.get_template('waf.html')
|
|||
form = funct.form
|
||||
manage_rules = form.getvalue('manage_rules')
|
||||
waf_rule_id = form.getvalue('waf_rule_id')
|
||||
service = form.getvalue('service')
|
||||
serv = form.getvalue('serv')
|
||||
config_file_name = ''
|
||||
waf_rule_file = ''
|
||||
servers_waf = ''
|
||||
autorefresh = 0
|
||||
config_read = ''
|
||||
serv = ''
|
||||
rules = ''
|
||||
cfg = ''
|
||||
|
||||
|
@ -21,7 +26,7 @@ funct.check_login(service=1)
|
|||
funct.page_for_admin(level=2)
|
||||
|
||||
try:
|
||||
user, user_id, role, token, servers, user_services = funct.get_users_params()
|
||||
user, user_id, role, token, servers, user_services = funct.get_users_params(haproxy=1)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
@ -29,16 +34,22 @@ if manage_rules == '1':
|
|||
serv = funct.is_ip_or_dns(form.getvalue('serv'))
|
||||
funct.check_is_server_in_group(serv)
|
||||
title = "Manage rules - Web application firewall"
|
||||
rules = sql.select_waf_rules(serv)
|
||||
elif waf_rule_id:
|
||||
rules = sql.select_waf_rules(serv, service)
|
||||
elif waf_rule_id and form.getvalue('config') is None:
|
||||
serv = funct.is_ip_or_dns(form.getvalue('serv'))
|
||||
service = form.getvalue('service')
|
||||
funct.check_is_server_in_group(serv)
|
||||
title = 'Edit a WAF rule'
|
||||
waf_rule_file = sql.select_waf_rule_by_id(waf_rule_id)
|
||||
configs_dir = sql.get_setting('tmp_config_path')
|
||||
cfg = configs_dir + serv + "-" + funct.get_data('config') + "-" + waf_rule_file
|
||||
error = funct.get_config(serv, cfg, waf=1, waf_rule_file=waf_rule_file)
|
||||
error = funct.get_config(serv, cfg, waf=service, waf_rule_file=waf_rule_file)
|
||||
if service == 'haproxy':
|
||||
config_path = sql.get_setting('haproxy_dir')
|
||||
elif service == 'nginx':
|
||||
config_path = sql.get_setting('nginx_dir')
|
||||
|
||||
config_file_name = funct.return_nice_path(config_path) + 'waf/rules/' + waf_rule_file
|
||||
try:
|
||||
conf = open(cfg, "r")
|
||||
config_read = conf.read()
|
||||
|
@ -50,9 +61,40 @@ else:
|
|||
servers_waf = sql.select_waf_servers_metrics(user_id.value)
|
||||
autorefresh = 1
|
||||
|
||||
if serv is not None and form.getvalue('config') is not None:
|
||||
funct.check_is_server_in_group(serv)
|
||||
|
||||
configs_dir = sql.get_setting('tmp_config_path')
|
||||
cfg = configs_dir + serv + "-" + funct.get_data('config')
|
||||
config_file_name = form.getvalue('config_file_name')
|
||||
config = form.getvalue('config')
|
||||
oldcfg = form.getvalue('oldconfig')
|
||||
save = form.getvalue('save')
|
||||
|
||||
try:
|
||||
with open(cfg, "a") as conf:
|
||||
conf.write(config)
|
||||
except IOError:
|
||||
print("error: Cannot read imported config file")
|
||||
|
||||
stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save=save, waf=1, oldcfg=oldcfg, config_file_name=config_file_name)
|
||||
|
||||
funct.diff_config(oldcfg, cfg)
|
||||
|
||||
try:
|
||||
os.system("/bin/rm -f " + configs_dir + "*.old")
|
||||
except Exception as e:
|
||||
print('error: ' + str(e))
|
||||
|
||||
if stderr:
|
||||
print(stderr)
|
||||
|
||||
sys.exit()
|
||||
|
||||
rendered_template = template.render(
|
||||
h2=1, title=title, autorefresh=autorefresh, role=role, user=user, serv=serv, servers=servers_waf,
|
||||
servers_all=servers, manage_rules=manage_rules, rules=rules, user_services=user_services,
|
||||
waf_rule_file=waf_rule_file, waf_rule_id=waf_rule_id, config=config_read, cfg=cfg, token=token
|
||||
waf_rule_file=waf_rule_file, waf_rule_id=waf_rule_id, config=config_read, cfg=cfg, token=token,
|
||||
config_file_name=config_file_name, service=service
|
||||
)
|
||||
print(rendered_template)
|
||||
|
|
|
@ -170,6 +170,8 @@ function ajaxActionNginxServers(action, id) {
|
|||
toastr.error(data);
|
||||
} else if (cur_url[0] == "hapservers.py") {
|
||||
location.reload()
|
||||
} else if (cur_url[0] == "waf.py") {
|
||||
setTimeout(showOverviewWaf(ip, hostnamea), 2000)
|
||||
} else {
|
||||
setTimeout(showOverview(ip, hostnamea), 2000)
|
||||
}
|
||||
|
@ -237,7 +239,6 @@ function ajaxActionApacheServers(action, id) {
|
|||
} );
|
||||
}
|
||||
function ajaxActionWafServers(action, id) {
|
||||
var bad_ans = 'Bad config, check please';
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
|
@ -260,6 +261,29 @@ function ajaxActionWafServers(action, id) {
|
|||
}
|
||||
} );
|
||||
}
|
||||
function ajaxActionWafNginxServers(action, id) {
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
action_waf_nginx: action,
|
||||
serv: id,
|
||||
token: $('#token').val()
|
||||
},
|
||||
success: function( data ) {
|
||||
data = data.replace(/\s+/g,' ');
|
||||
if (data.indexOf('error:') != '-1') {
|
||||
toastr.error(data);
|
||||
} else if( data == 'Bad config, check please ' ) {
|
||||
toastr.error(data);
|
||||
} else {
|
||||
setTimeout(showOverviewWaf(ip, hostnamea), 2000)
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
alert(w.data_error);
|
||||
}
|
||||
} );
|
||||
}
|
||||
$( function() {
|
||||
try {
|
||||
if ((cur_url[0] == 'hapservers.py' && cur_url[1].split('&')[1].split('=')[0] == 'serv') || cur_url[0] == 'overview.py') {
|
||||
|
@ -375,6 +399,8 @@ function confirmAjaxAction(action, service, id) {
|
|||
ajaxActionKeepalivedServers(action, id)
|
||||
} else if (service == "apache") {
|
||||
ajaxActionApacheServers(action, id)
|
||||
} else if (service == "waf_nginx") {
|
||||
ajaxActionWafNginxServers(action, id)
|
||||
}
|
||||
},
|
||||
Cancel: function() {
|
||||
|
|
|
@ -80,6 +80,10 @@ $( function() {
|
|||
show_current_page($(this))
|
||||
} else if(cur_url[0] == 'add.py' && cur_url[1].split('&')[0] == 'service=apache#ssl' && link2 == 'add.py?service=apache#ssl'){
|
||||
show_current_page($(this))
|
||||
} else if(cur_url[0] == 'waf.py' && cur_url[1].split('&')[0] == 'service=haproxy' && link2 == 'waf.py?service=haproxy'){
|
||||
show_current_page($(this))
|
||||
} else if(cur_url[0] == 'waf.py' && cur_url[1].split('&')[0] == 'service=nginx' && link2 == 'waf.py?service=nginx'){
|
||||
show_current_page($(this))
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -318,9 +322,14 @@ function openVersions() {
|
|||
function showLog() {
|
||||
var waf = findGetParameter('waf');
|
||||
var file = $('#log_files').val();
|
||||
if (file === null) {
|
||||
toastr.warning('Select a log file first')
|
||||
return false;
|
||||
if ((file === undefined || file === null) && waf != '1') {
|
||||
var file_from_get = findGetParameter('file');
|
||||
if (file_from_get === undefined || file_from_get === null) {
|
||||
toastr.warning('Select a log file first')
|
||||
return false;
|
||||
} else {
|
||||
file = file_from_get;
|
||||
}
|
||||
}
|
||||
var rows = $('#rows').val()
|
||||
var grep = $('#grep').val()
|
||||
|
|
|
@ -1176,7 +1176,7 @@ function addTelegram(dialog_id) {
|
|||
function addSlack(dialog_id) {
|
||||
var valid = true;
|
||||
toastr.clear();
|
||||
allFields = $( [] ).add( $('#slack-token-add') ).add( $('#slack-chanel-add') )
|
||||
allFields = $( [] ).add( $('#slack-token-add') ).add( $('#slack-chanel-add') );
|
||||
allFields.removeClass( "ui-state-error" );
|
||||
valid = valid && checkLength( $('#slack-token-add'), "token", 1 );
|
||||
valid = valid && checkLength( $('#slack-chanel-add'), "channel name", 1 );
|
||||
|
|
81
inc/waf.js
81
inc/waf.js
|
@ -1,7 +1,10 @@
|
|||
var awesome = "/inc/fontawesome.min.js"
|
||||
function showOverviewWaf(serv, hostnamea) {
|
||||
$.getScript('/inc/chart.min.js');
|
||||
showWafMetrics();
|
||||
var service = findGetParameter('service');
|
||||
if (service == 'haproxy') {
|
||||
$.getScript('/inc/chart.min.js');
|
||||
showWafMetrics();
|
||||
}
|
||||
var i;
|
||||
for (i = 0; i < serv.length; i++) {
|
||||
showOverviewWafCallBack(serv[i], hostnamea[i])
|
||||
|
@ -10,11 +13,13 @@ function showOverviewWaf(serv, hostnamea) {
|
|||
$.getScript('/inc/waf.js');
|
||||
}
|
||||
function showOverviewWafCallBack(serv, hostnamea) {
|
||||
var service = findGetParameter('service');
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
act: "overviewwaf",
|
||||
serv: serv,
|
||||
service: service,
|
||||
token: $('#token').val()
|
||||
},
|
||||
beforeSend: function() {
|
||||
|
@ -56,10 +61,12 @@ function metrics_waf(name) {
|
|||
function installWaf(ip1) {
|
||||
$("#ajax").html('')
|
||||
$("#ajax").html(wait_mess);
|
||||
var service = findGetParameter('service');
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
installwaf: ip1,
|
||||
service: service,
|
||||
token: $('#token').val()
|
||||
},
|
||||
type: "POST",
|
||||
|
@ -72,7 +79,7 @@ function installWaf(ip1) {
|
|||
toastr.info(data);
|
||||
} else if (data.indexOf('success') != '-1' ){
|
||||
toastr.clear();
|
||||
toastr.success('WAF service has installed');
|
||||
toastr.success('WAF service has been installed');
|
||||
showOverviewWaf(ip, hostnamea)
|
||||
}
|
||||
}
|
||||
|
@ -80,13 +87,14 @@ function installWaf(ip1) {
|
|||
}
|
||||
function changeWafMode(id) {
|
||||
var waf_mode = $('#'+id+' option:selected').val();
|
||||
console.log('1')
|
||||
var server_hostname = id.split('_')[0];
|
||||
var service = findGetParameter('service');
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
change_waf_mode: waf_mode,
|
||||
server_hostname: server_hostname,
|
||||
service: service,
|
||||
token: $('#token').val()
|
||||
},
|
||||
type: "POST",
|
||||
|
@ -106,7 +114,6 @@ $( function() {
|
|||
});
|
||||
});
|
||||
function waf_rules_en(id) {
|
||||
console.log('1')
|
||||
var enable = 0;
|
||||
if ($('#rule_id-'+id).is(':checked')) {
|
||||
enable = '1';
|
||||
|
@ -134,3 +141,67 @@ function waf_rules_en(id) {
|
|||
}
|
||||
} );
|
||||
}
|
||||
function addNewConfig() {
|
||||
$( "#add-new-config" ).dialog({
|
||||
autoOpen: true,
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: 600,
|
||||
modal: true,
|
||||
title: "Create a new rule",
|
||||
show: {
|
||||
effect: "fade",
|
||||
duration: 200
|
||||
},
|
||||
hide: {
|
||||
effect: "fade",
|
||||
duration: 200
|
||||
},
|
||||
buttons: {
|
||||
"Create": function() {
|
||||
var valid = true;
|
||||
allFields = $( [] ).add( $('#new_rule_name') ).add( $('#new_rule_description') )
|
||||
allFields.removeClass( "ui-state-error" );
|
||||
valid = valid && checkLength( $('#new_rule_name'), "New rule name", 1 );
|
||||
valid = valid && checkLength( $('#new_rule_description'), "New rule description", 1 );
|
||||
if(valid) {
|
||||
let new_rule_name = $('#new_rule_name').val();
|
||||
let new_rule_description = $('#new_rule_description').val();
|
||||
let new_rule_file = new_rule_name.replaceAll(' ','_');
|
||||
var service = findGetParameter('service');
|
||||
var serv = findGetParameter('serv');
|
||||
service = escapeHtml(service);
|
||||
new_rule_name = escapeHtml(new_rule_name);
|
||||
new_rule_description = escapeHtml(new_rule_description);
|
||||
new_rule_file = escapeHtml(new_rule_file);
|
||||
serv = escapeHtml(serv);
|
||||
$.ajax({
|
||||
url: "options.py",
|
||||
data: {
|
||||
new_waf_rule: new_rule_name,
|
||||
new_rule_description: new_rule_description,
|
||||
new_rule_file: new_rule_file,
|
||||
service: service,
|
||||
serv: serv,
|
||||
token: $('#token').val()
|
||||
},
|
||||
type: "POST",
|
||||
success: function (data) {
|
||||
if (data.indexOf('error:') != '-1') {
|
||||
toastr.error(data);
|
||||
} else {
|
||||
var getId = new RegExp('[0-9]+');
|
||||
var id = data.match(getId) + '';
|
||||
window.location.replace('waf.py?service=' + service + '&waf_rule_id=' + id + '&serv=' + serv);
|
||||
}
|
||||
}
|
||||
});
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
Cancel: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue