mirror of
https://github.com/ail-project/ail-framework.git
synced 2024-11-23 14:37:17 +00:00
Merge pull request #359 from CIRCL/user_management
User/role management
This commit is contained in:
commit
1c7b66e5de
44 changed files with 2022 additions and 160 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,6 +20,8 @@ indexdir/
|
||||||
logs/
|
logs/
|
||||||
old/
|
old/
|
||||||
|
|
||||||
|
DEFAULT_PASSWORD
|
||||||
|
|
||||||
# Webstuff
|
# Webstuff
|
||||||
var/www/static/
|
var/www/static/
|
||||||
!var/www/static/css/dygraph_gallery.css
|
!var/www/static/css/dygraph_gallery.css
|
||||||
|
|
34
OVERVIEW.md
34
OVERVIEW.md
|
@ -30,6 +30,14 @@ Redis and ARDB overview
|
||||||
|
|
||||||
# Database Map:
|
# Database Map:
|
||||||
|
|
||||||
|
### Redis cache
|
||||||
|
|
||||||
|
##### Brute force protection:
|
||||||
|
| Set Key | Value |
|
||||||
|
| ------ | ------ |
|
||||||
|
| failed_login_ip:**ip** | **nb login failed** | TTL
|
||||||
|
| failed_login_user_id:**user_id** | **nb login failed** | TTL
|
||||||
|
|
||||||
## DB0 - Core:
|
## DB0 - Core:
|
||||||
|
|
||||||
##### Update keys:
|
##### Update keys:
|
||||||
|
@ -42,8 +50,6 @@ Redis and ARDB overview
|
||||||
| | **background update name** |
|
| | **background update name** |
|
||||||
| | **...** |
|
| | **...** |
|
||||||
| | |
|
| | |
|
||||||
| ail:update_date_v1.5 | **update date** |
|
|
||||||
| | |
|
|
||||||
| ail:update_error | **update message error** |
|
| ail:update_error | **update message error** |
|
||||||
| | |
|
| | |
|
||||||
| ail:update_in_progress | **update version in progress** |
|
| ail:update_in_progress | **update version in progress** |
|
||||||
|
@ -52,6 +58,30 @@ Redis and ARDB overview
|
||||||
| ail:current_background_script | **name of the background script currently executed** |
|
| ail:current_background_script | **name of the background script currently executed** |
|
||||||
| ail:current_background_script_stat | **progress in % of the background script** |
|
| ail:current_background_script_stat | **progress in % of the background script** |
|
||||||
|
|
||||||
|
| Hset Key | Field | Value |
|
||||||
|
| ------ | ------ | ------ |
|
||||||
|
| ail:update_date | **update tag** | **update date** |
|
||||||
|
|
||||||
|
##### User Management:
|
||||||
|
| Hset Key | Field | Value |
|
||||||
|
| ------ | ------ | ------ |
|
||||||
|
| user:all | **user id** | **password hash** |
|
||||||
|
| | | |
|
||||||
|
| user:tokens | **token** | **user id** |
|
||||||
|
| | | |
|
||||||
|
| user_metadata:**user id** | token | **token** |
|
||||||
|
| | change_passwd | **boolean** |
|
||||||
|
| | role | **role** |
|
||||||
|
|
||||||
|
| Set Key | Value |
|
||||||
|
| ------ | ------ |
|
||||||
|
| user_role:**role** | **user id** |
|
||||||
|
|
||||||
|
|
||||||
|
| Zrank Key | Field | Value |
|
||||||
|
| ------ | ------ | ------ |
|
||||||
|
| ail:all_role | **role** | **int, role priority (1=admin)** |
|
||||||
|
|
||||||
## DB2 - TermFreq:
|
## DB2 - TermFreq:
|
||||||
|
|
||||||
##### Set:
|
##### Set:
|
||||||
|
|
26
README.md
26
README.md
|
@ -78,14 +78,13 @@ Type these command lines for a fully automated installation and start AIL framew
|
||||||
git clone https://github.com/CIRCL/AIL-framework.git
|
git clone https://github.com/CIRCL/AIL-framework.git
|
||||||
cd AIL-framework
|
cd AIL-framework
|
||||||
./installing_deps.sh
|
./installing_deps.sh
|
||||||
|
|
||||||
cd ~/AIL-framework/
|
cd ~/AIL-framework/
|
||||||
. ./AILENV/bin/activate
|
|
||||||
cd bin/
|
cd bin/
|
||||||
./LAUNCH.sh
|
./LAUNCH.sh -l
|
||||||
```
|
```
|
||||||
|
|
||||||
The default [installing_deps.sh](./installing_deps.sh) is for Debian and Ubuntu based distributions. For Arch
|
The default [installing_deps.sh](./installing_deps.sh) is for Debian and Ubuntu based distributions.
|
||||||
linux based distributions, you can replace it with [installing_deps_archlinux.sh](./installing_deps_archlinux.sh).
|
|
||||||
|
|
||||||
There is also a [Travis file](.travis.yml) used for automating the installation that can be used to build and install AIL on other systems.
|
There is also a [Travis file](.travis.yml) used for automating the installation that can be used to build and install AIL on other systems.
|
||||||
|
|
||||||
|
@ -143,23 +142,12 @@ Install using Ansible
|
||||||
|
|
||||||
Please check the [Ansible readme](ansible/README.md).
|
Please check the [Ansible readme](ansible/README.md).
|
||||||
|
|
||||||
Starting AIL web interface
|
Starting AIL
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
To start the web interface, you first need to fetch the required JavaScript/CSS files:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd $AILENV
|
cd bin/
|
||||||
cd var/www/
|
./LAUNCH -l
|
||||||
bash update_thirdparty.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
and then you can start the web interface python script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd $AILENV
|
|
||||||
cd var/www/
|
|
||||||
./Flask_server.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Eventually you can browse the status of the AIL framework website at the following URL:
|
Eventually you can browse the status of the AIL framework website at the following URL:
|
||||||
|
@ -168,6 +156,8 @@ Eventually you can browse the status of the AIL framework website at the followi
|
||||||
http://localhost:7000/
|
http://localhost:7000/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The default credentials for the web interface are located in ``DEFAULT_PASSWORD``. This file is removed when you change your password.
|
||||||
|
|
||||||
Training
|
Training
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
14
bin/helper/gen_cert/README.md
Normal file
14
bin/helper/gen_cert/README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
These scripts are useful to generate the server's self-signed certificate.
|
||||||
|
## Root Certification Authority ##
|
||||||
|
`gen_root.sh`
|
||||||
|
This will create a rootCA.crt to verify the server's cert.
|
||||||
|
## Server certificate ##
|
||||||
|
### Configuration Files ###
|
||||||
|
Look into these files if you plan to verify the certificate:
|
||||||
|
* san.cnf holds basic information about the certificate.
|
||||||
|
* ext.3 holds in particular the 'subjectAltNames** option that is for the verification to succeed.
|
||||||
|
|
||||||
|
### Generation ###
|
||||||
|
`gen_root.sh`
|
5
bin/helper/gen_cert/ext3.cnf
Normal file
5
bin/helper/gen_cert/ext3.cnf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[alt_names]
|
||||||
|
IP.1 = 127.0.0.1
|
9
bin/helper/gen_cert/gen_cert.sh
Executable file
9
bin/helper/gen_cert/gen_cert.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Create Server key
|
||||||
|
openssl genrsa -out server.key 4096
|
||||||
|
# Create the Server Signing Request - non interactive, config in san.cnf
|
||||||
|
openssl req -sha256 -new -key server.key -out server.csr -config san.cnf
|
||||||
|
# Create the server certificate by rootCA, with ext3 subjectAltName in ext3.cnf
|
||||||
|
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256 -extfile ext3.cnf
|
||||||
|
# Concat in pem
|
||||||
|
cat server.crt server.key > server.pem
|
5
bin/helper/gen_cert/gen_root.sh
Executable file
5
bin/helper/gen_cert/gen_root.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Create Root key
|
||||||
|
openssl genrsa -out rootCA.key 4096
|
||||||
|
# Create and Sign the Root CA Certificate
|
||||||
|
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt -config san.cnf
|
11
bin/helper/gen_cert/san.cnf
Normal file
11
bin/helper/gen_cert/san.cnf
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[req]
|
||||||
|
default_bits = 4096
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[dn]
|
||||||
|
C=LU
|
||||||
|
L=Luxembourg
|
||||||
|
O=AIL-Default
|
||||||
|
CN = localhost
|
72
bin/packages/User.py
Executable file
72
bin/packages/User.py
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
|
import redis
|
||||||
|
import bcrypt
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from flask_login import UserMixin
|
||||||
|
|
||||||
|
class User(UserMixin):
|
||||||
|
|
||||||
|
def __init__(self, id):
|
||||||
|
|
||||||
|
configfile = os.path.join(os.environ['AIL_BIN'], 'packages/config.cfg')
|
||||||
|
if not os.path.exists(configfile):
|
||||||
|
raise Exception('Unable to find the configuration file. \
|
||||||
|
Did you set environment variables? \
|
||||||
|
Or activate the virtualenv.')
|
||||||
|
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(configfile)
|
||||||
|
|
||||||
|
self.r_serv_db = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
port=cfg.getint("ARDB_DB", "port"),
|
||||||
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
if self.r_serv_db.hexists('user:all', id):
|
||||||
|
self.id = id
|
||||||
|
else:
|
||||||
|
self.id = "__anonymous__"
|
||||||
|
|
||||||
|
# return True or False
|
||||||
|
#def is_authenticated():
|
||||||
|
|
||||||
|
# return True or False
|
||||||
|
#def is_anonymous():
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(self_class, id):
|
||||||
|
return self_class(id)
|
||||||
|
|
||||||
|
def user_is_anonymous(self):
|
||||||
|
if self.id == "__anonymous__":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_password(self, password):
|
||||||
|
if self.user_is_anonymous():
|
||||||
|
return False
|
||||||
|
|
||||||
|
password = password.encode()
|
||||||
|
hashed_password = self.r_serv_db.hget('user:all', self.id).encode()
|
||||||
|
if bcrypt.checkpw(password, hashed_password):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def request_password_change(self):
|
||||||
|
if self.r_serv_db.hget('user_metadata:{}'.format(self.id), 'change_passwd') == 'True':
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_in_role(self, role):
|
||||||
|
if self.r_serv_db.sismember('user_role:{}'.format(role), self.id):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
|
@ -99,7 +99,17 @@ if [ -z "$VIRTUAL_ENV" ]; then
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pushd var/www/
|
pushd ${AIL_BIN}helper/gen_cert
|
||||||
|
./gen_root.sh
|
||||||
|
wait
|
||||||
|
./gen_cert.sh
|
||||||
|
wait
|
||||||
|
popd
|
||||||
|
|
||||||
|
cp ${AIL_BIN}helper/gen_cert/server.crt ${AIL_FLASK}server.crt
|
||||||
|
cp ${AIL_BIN}helper/gen_cert/server.key ${AIL_FLASK}server.key
|
||||||
|
|
||||||
|
pushd ${AIL_FLASK}
|
||||||
./update_thirdparty.sh
|
./update_thirdparty.sh
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
@ -123,6 +133,26 @@ python3 setup.py install
|
||||||
HOME=$(pwd) python3 -m textblob.download_corpora
|
HOME=$(pwd) python3 -m textblob.download_corpora
|
||||||
python3 -m nltk.downloader vader_lexicon
|
python3 -m nltk.downloader vader_lexicon
|
||||||
python3 -m nltk.downloader punkt
|
python3 -m nltk.downloader punkt
|
||||||
|
popd
|
||||||
|
|
||||||
#Create the file all_module and update the graph in doc
|
#Create the file all_module and update the graph in doc
|
||||||
$AIL_HOME/doc/generate_modules_data_flow_graph.sh
|
$AIL_HOME/doc/generate_modules_data_flow_graph.sh
|
||||||
|
|
||||||
|
#### DB SETUP ####
|
||||||
|
|
||||||
|
# init update version
|
||||||
|
git describe --abbrev=0 --tags | tr -d '\n' > ${AIL_HOME}/update/current_version
|
||||||
|
|
||||||
|
# LAUNCH ARDB
|
||||||
|
bash ${AIL_BIN}LAUNCH.sh -lav &
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# create default user
|
||||||
|
pushd ${AIL_FLASK}
|
||||||
|
python3 create_default_user.py
|
||||||
|
popd
|
||||||
|
|
||||||
|
bash ${AIL_BIN}LAUNCH.sh -k &
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
|
|
||||||
echo "Currently unmaintained, continue at your own risk of not having a working AIL at the end :( Will be merged into main install deps later on."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
sudo pacman -Syu
|
|
||||||
|
|
||||||
sudo pacman -S python2-pip screen gcc unzip freetype2 python2 git --needed
|
|
||||||
sudo yaourt -S snappy --needed
|
|
||||||
sudo pip2 install virtualenv
|
|
||||||
|
|
||||||
#Needed for bloom filters
|
|
||||||
sudo pacman -S openssl python2-numpy --needed
|
|
||||||
|
|
||||||
# DNS deps
|
|
||||||
sudo pacman -S adns --needed
|
|
||||||
|
|
||||||
#Needed for redis-lvlDB
|
|
||||||
sudo pacman -S libev gmp --needed
|
|
||||||
|
|
||||||
#needed for mathplotlib
|
|
||||||
test ! -L /usr/include/ft2build.h && sudo ln -s freetype2/ft2build.h /usr/include/
|
|
||||||
sudo easy_install-2.7 -U distribute
|
|
||||||
|
|
||||||
# REDIS #
|
|
||||||
test ! -d redis/ && git clone https://github.com/antirez/redis.git
|
|
||||||
pushd redis/
|
|
||||||
git checkout 2.8
|
|
||||||
make
|
|
||||||
popd
|
|
||||||
|
|
||||||
# REDIS LEVEL DB #
|
|
||||||
test ! -d redis-leveldb/ && git clone https://github.com/KDr2/redis-leveldb.git
|
|
||||||
pushd redis-leveldb/
|
|
||||||
git submodule init
|
|
||||||
git submodule update
|
|
||||||
make
|
|
||||||
popd
|
|
||||||
|
|
||||||
# Faup
|
|
||||||
test ! -d faup/ && git clone https://github.com/stricaud/faup.git
|
|
||||||
pushd faup/
|
|
||||||
test ! -d build && mkdir build
|
|
||||||
cd build
|
|
||||||
cmake .. && make
|
|
||||||
sudo make install
|
|
||||||
echo '/usr/local/lib' | sudo tee -a /etc/ld.so.conf.d/faup.conf
|
|
||||||
sudo ldconfig
|
|
||||||
popd
|
|
||||||
|
|
||||||
# tlsh
|
|
||||||
test ! -d tlsh && git clone git://github.com/trendmicro/tlsh.git
|
|
||||||
pushd tlsh/
|
|
||||||
./make.sh
|
|
||||||
pushd build/release/
|
|
||||||
sudo make install
|
|
||||||
sudo ldconfig
|
|
||||||
popd
|
|
||||||
popd
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if [ ! -f bin/packages/config.cfg ]; then
|
|
||||||
cp bin/packages/config.cfg.sample bin/packages/config.cfg
|
|
||||||
fi
|
|
||||||
|
|
||||||
pushd var/www/
|
|
||||||
./update_thirdparty.sh
|
|
||||||
popd
|
|
||||||
|
|
||||||
virtualenv AILENV
|
|
||||||
|
|
||||||
echo export AIL_HOME=$(pwd) >> ./AILENV/bin/activate
|
|
||||||
echo export AIL_BIN=$(pwd)/bin/ >> ./AILENV/bin/activate
|
|
||||||
echo export AIL_FLASK=$(pwd)/var/www/ >> ./AILENV/bin/activate
|
|
||||||
echo export AIL_REDIS=$(pwd)/redis/src/ >> ./AILENV/bin/activate
|
|
||||||
echo export AIL_LEVELDB=$(pwd)/redis-leveldb/ >> ./AILENV/bin/activate
|
|
||||||
|
|
||||||
. ./AILENV/bin/activate
|
|
||||||
|
|
||||||
mkdir -p $AIL_HOME/{PASTES,Blooms,dumps}
|
|
||||||
mkdir -p $AIL_HOME/LEVEL_DB_DATA/2017
|
|
||||||
mkdir -p $AIL_HOME/LEVEL_DB_DATA/3017
|
|
||||||
|
|
||||||
pip install -U pip
|
|
||||||
pip install -U -r pip_packages_requirement.txt
|
|
||||||
|
|
||||||
# Pyfaup
|
|
||||||
pushd faup/src/lib/bindings/python/
|
|
||||||
python setup.py install
|
|
||||||
popd
|
|
||||||
|
|
||||||
# Py tlsh
|
|
||||||
pushd tlsh/py_ext
|
|
||||||
python setup.py build
|
|
||||||
python setup.py install
|
|
||||||
|
|
||||||
# Download the necessary NLTK corpora and sentiment vader
|
|
||||||
HOME=$(pwd) python -m textblob.download_corpora
|
|
||||||
python -m nltk.downloader vader_lexicon
|
|
||||||
python -m nltk.downloader punkt
|
|
||||||
|
|
||||||
#Create the file all_module and update the graph in doc
|
|
||||||
$AIL_HOME/doc/generate_modules_data_flow_graph.sh
|
|
|
@ -43,9 +43,12 @@ psutil
|
||||||
phonenumbers
|
phonenumbers
|
||||||
|
|
||||||
ipython
|
ipython
|
||||||
flask
|
|
||||||
texttable
|
texttable
|
||||||
|
|
||||||
|
flask
|
||||||
|
flask-login
|
||||||
|
bcrypt
|
||||||
|
|
||||||
#DomainClassifier
|
#DomainClassifier
|
||||||
DomainClassifier
|
DomainClassifier
|
||||||
#Indexer requirements
|
#Indexer requirements
|
||||||
|
|
41
update/v2.0/Update.py
Executable file
41
update/v2.0/Update.py
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import redis
|
||||||
|
import datetime
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
start_deb = time.time()
|
||||||
|
|
||||||
|
configfile = os.path.join(os.environ['AIL_BIN'], 'packages/config.cfg')
|
||||||
|
if not os.path.exists(configfile):
|
||||||
|
raise Exception('Unable to find the configuration file. \
|
||||||
|
Did you set environment variables? \
|
||||||
|
Or activate the virtualenv.')
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(configfile)
|
||||||
|
|
||||||
|
r_serv = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
port=cfg.getint("ARDB_DB", "port"),
|
||||||
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
#Set current ail version
|
||||||
|
r_serv.set('ail:version', 'v2.0')
|
||||||
|
|
||||||
|
# use new update_date format
|
||||||
|
date_tag_to_replace = ['v1.5', 'v1.7']
|
||||||
|
for tag in date_tag_to_replace:
|
||||||
|
if r_serv.exists('ail:update_date_{}'.format(tag)):
|
||||||
|
date_tag = r_serv.get('ail:update_date_{}'.format(tag))
|
||||||
|
r_serv.hset('ail:update_date', tag, date_tag)
|
||||||
|
r_serv.delete('ail:update_date_{}'.format(tag))
|
||||||
|
|
||||||
|
#Set current ail version
|
||||||
|
r_serv.hset('ail:update_date', 'v2.0', datetime.datetime.now().strftime("%Y%m%d"))
|
75
update/v2.0/Update.sh
Executable file
75
update/v2.0/Update.sh
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
[ -z "$AIL_HOME" ] && echo "Needs the env var AIL_HOME. Run the script from the virtual environment." && exit 1;
|
||||||
|
[ -z "$AIL_REDIS" ] && echo "Needs the env var AIL_REDIS. Run the script from the virtual environment." && exit 1;
|
||||||
|
[ -z "$AIL_ARDB" ] && echo "Needs the env var AIL_ARDB. Run the script from the virtual environment." && exit 1;
|
||||||
|
[ -z "$AIL_BIN" ] && echo "Needs the env var AIL_ARDB. Run the script from the virtual environment." && exit 1;
|
||||||
|
[ -z "$AIL_FLASK" ] && echo "Needs the env var AIL_FLASK. Run the script from the virtual environment." && exit 1;
|
||||||
|
|
||||||
|
export PATH=$AIL_HOME:$PATH
|
||||||
|
export PATH=$AIL_REDIS:$PATH
|
||||||
|
export PATH=$AIL_ARDB:$PATH
|
||||||
|
export PATH=$AIL_BIN:$PATH
|
||||||
|
export PATH=$AIL_FLASK:$PATH
|
||||||
|
|
||||||
|
GREEN="\\033[1;32m"
|
||||||
|
DEFAULT="\\033[0;39m"
|
||||||
|
|
||||||
|
echo -e $GREEN"Shutting down AIL ..."$DEFAULT
|
||||||
|
bash ${AIL_BIN}/LAUNCH.sh -k
|
||||||
|
wait
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Create Self-Signed Certificate"$DEFAULT
|
||||||
|
echo ""
|
||||||
|
pushd ${AIL_BIN}/helper/gen_cert
|
||||||
|
bash gen_root.sh
|
||||||
|
wait
|
||||||
|
bash gen_cert.sh
|
||||||
|
wait
|
||||||
|
popd
|
||||||
|
|
||||||
|
cp ${AIL_BIN}/helper/gen_cert/server.crt ${AIL_FLASK}/server.crt
|
||||||
|
cp ${AIL_BIN}/helper/gen_cert/server.key ${AIL_FLASK}/server.key
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Update requirement"$DEFAULT
|
||||||
|
echo ""
|
||||||
|
pip3 install flask-login
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
pip3 install bcrypt
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
bash ${AIL_BIN}/LAUNCH.sh -lav &
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Updating AIL VERSION ..."$DEFAULT
|
||||||
|
echo ""
|
||||||
|
python ${AIL_HOME}/update/v2.0/Update.py
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Update thirdparty ..."$DEFAULT
|
||||||
|
bash ${AIL_BIN}/LAUNCH.sh -t
|
||||||
|
wait
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Create Default User"$DEFAULT
|
||||||
|
echo ""
|
||||||
|
python3 ${AIL_FLASK}create_default_user.py
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e $GREEN"Shutting down ARDB ..."$DEFAULT
|
||||||
|
bash ${AIL_BIN}/LAUNCH.sh -k
|
||||||
|
wait
|
||||||
|
|
||||||
|
exit 0
|
|
@ -1,28 +1,42 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*-coding:UTF-8 -*
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
import redis
|
import os
|
||||||
import configparser
|
import re
|
||||||
import json
|
import sys
|
||||||
import datetime
|
import ssl
|
||||||
import time
|
import time
|
||||||
import calendar
|
|
||||||
from flask import Flask, render_template, jsonify, request, Request
|
import redis
|
||||||
|
import random
|
||||||
|
import logging
|
||||||
|
import logging.handlers
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from flask import Flask, render_template, jsonify, request, Request, session, redirect, url_for
|
||||||
|
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
|
||||||
|
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
|
||||||
from os.path import join
|
from os.path import join
|
||||||
import sys
|
|
||||||
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
||||||
sys.path.append('./modules/')
|
sys.path.append('./modules/')
|
||||||
import Paste
|
import Paste
|
||||||
from Date import Date
|
from Date import Date
|
||||||
|
|
||||||
|
from User import User
|
||||||
|
|
||||||
from pytaxonomies import Taxonomies
|
from pytaxonomies import Taxonomies
|
||||||
|
|
||||||
# Import config
|
# Import config
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
# Import Role_Manager
|
||||||
|
from Role_Manager import create_user_db, check_password_strength, check_user_role_integrity
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
|
||||||
# CONFIG #
|
# CONFIG #
|
||||||
cfg = Flask_config.cfg
|
cfg = Flask_config.cfg
|
||||||
baseUrl = cfg.get("Flask", "baseurl")
|
baseUrl = cfg.get("Flask", "baseurl")
|
||||||
|
@ -30,10 +44,63 @@ baseUrl = baseUrl.replace('/', '')
|
||||||
if baseUrl != '':
|
if baseUrl != '':
|
||||||
baseUrl = '/'+baseUrl
|
baseUrl = '/'+baseUrl
|
||||||
|
|
||||||
|
# ========= REDIS =========#
|
||||||
|
r_serv_db = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
port=cfg.getint("ARDB_DB", "port"),
|
||||||
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
r_serv_tags = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_Tags", "host"),
|
||||||
|
port=cfg.getint("ARDB_Tags", "port"),
|
||||||
|
db=cfg.getint("ARDB_Tags", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
r_cache = redis.StrictRedis(
|
||||||
|
host=cfg.get("Redis_Cache", "host"),
|
||||||
|
port=cfg.getint("Redis_Cache", "port"),
|
||||||
|
db=cfg.getint("Redis_Cache", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
# logs
|
||||||
|
log_dir = os.path.join(os.environ['AIL_HOME'], 'logs')
|
||||||
|
if not os.path.isdir(log_dir):
|
||||||
|
os.makedirs(logs_dir)
|
||||||
|
|
||||||
|
log_filename = os.path.join(log_dir, 'flask_server.logs')
|
||||||
|
logger = logging.getLogger()
|
||||||
|
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
|
||||||
|
handler_log = logging.handlers.TimedRotatingFileHandler(log_filename, when="midnight", interval=1)
|
||||||
|
handler_log.suffix = '%Y-%m-%d.log'
|
||||||
|
handler_log.setFormatter(formatter)
|
||||||
|
handler_log.setLevel(30)
|
||||||
|
logger.addHandler(handler_log)
|
||||||
|
logger.setLevel(30)
|
||||||
|
|
||||||
|
# ========= =========#
|
||||||
|
|
||||||
|
# ========= TLS =========#
|
||||||
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
||||||
|
ssl_context.load_cert_chain(certfile='server.crt', keyfile='server.key')
|
||||||
|
#print(ssl_context.get_ciphers())
|
||||||
|
# ========= =========#
|
||||||
|
|
||||||
Flask_config.app = Flask(__name__, static_url_path=baseUrl+'/static/')
|
Flask_config.app = Flask(__name__, static_url_path=baseUrl+'/static/')
|
||||||
app = Flask_config.app
|
app = Flask_config.app
|
||||||
app.config['MAX_CONTENT_LENGTH'] = 900 * 1024 * 1024
|
app.config['MAX_CONTENT_LENGTH'] = 900 * 1024 * 1024
|
||||||
|
|
||||||
|
# ========= session ========
|
||||||
|
app.secret_key = str(random.getrandbits(256))
|
||||||
|
login_manager = LoginManager()
|
||||||
|
login_manager.login_view = 'login'
|
||||||
|
login_manager.init_app(app)
|
||||||
|
|
||||||
|
# ========= LOGIN MANAGER ========
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(user_id):
|
||||||
|
return User.get(user_id)
|
||||||
|
|
||||||
# ========= HEADER GENERATION ========
|
# ========= HEADER GENERATION ========
|
||||||
|
|
||||||
# Get headers items that should be ignored (not displayed)
|
# Get headers items that should be ignored (not displayed)
|
||||||
|
@ -95,7 +162,6 @@ modified_header = modified_header.replace('<!--insert here-->', '\n'.join(to_add
|
||||||
with open('templates/header.html', 'w') as f:
|
with open('templates/header.html', 'w') as f:
|
||||||
f.write(modified_header)
|
f.write(modified_header)
|
||||||
|
|
||||||
|
|
||||||
# ========= JINJA2 FUNCTIONS ========
|
# ========= JINJA2 FUNCTIONS ========
|
||||||
def list_len(s):
|
def list_len(s):
|
||||||
return len(s)
|
return len(s)
|
||||||
|
@ -113,18 +179,123 @@ def add_header(response):
|
||||||
response.headers['Cache-Control'] = 'public, max-age=0'
|
response.headers['Cache-Control'] = 'public, max-age=0'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
# @app.route('/test', methods=['GET'])
|
||||||
|
# def test():
|
||||||
|
# for rule in app.url_map.iter_rules():
|
||||||
|
# print(rule)
|
||||||
|
# return 'o'
|
||||||
|
|
||||||
# ========== ROUTES ============
|
# ========== ROUTES ============
|
||||||
|
@app.route('/login', methods=['POST', 'GET'])
|
||||||
|
def login():
|
||||||
|
|
||||||
|
current_ip = request.remote_addr
|
||||||
|
login_failed_ip = r_cache.get('failed_login_ip:{}'.format(current_ip))
|
||||||
|
|
||||||
|
# brute force by ip
|
||||||
|
if login_failed_ip:
|
||||||
|
login_failed_ip = int(login_failed_ip)
|
||||||
|
if login_failed_ip >= 5:
|
||||||
|
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_ip:{}'.format(current_ip)))
|
||||||
|
return render_template("login.html", error=error)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
username = request.form.get('username')
|
||||||
|
password = request.form.get('password')
|
||||||
|
#next_page = request.form.get('next_page')
|
||||||
|
|
||||||
|
if username is not None:
|
||||||
|
user = User.get(username)
|
||||||
|
login_failed_user_id = r_cache.get('failed_login_user_id:{}'.format(username))
|
||||||
|
# brute force by user_id
|
||||||
|
if login_failed_user_id:
|
||||||
|
login_failed_user_id = int(login_failed_user_id)
|
||||||
|
if login_failed_user_id >= 5:
|
||||||
|
error = 'Max Connection Attempts reached, Please wait {}s'.format(r_cache.ttl('failed_login_user_id:{}'.format(username)))
|
||||||
|
return render_template("login.html", error=error)
|
||||||
|
|
||||||
|
if user and user.check_password(password):
|
||||||
|
if not check_user_role_integrity(user.get_id()):
|
||||||
|
error = 'Incorrect User ACL, Please contact your administrator'
|
||||||
|
return render_template("login.html", error=error)
|
||||||
|
login_user(user) ## TODO: use remember me ?
|
||||||
|
if user.request_password_change():
|
||||||
|
return redirect(url_for('change_password'))
|
||||||
|
else:
|
||||||
|
return redirect(url_for('dashboard.index'))
|
||||||
|
# login failed
|
||||||
|
else:
|
||||||
|
# set brute force protection
|
||||||
|
logger.warning("Login failed, ip={}, username={}".format(current_ip, username))
|
||||||
|
r_cache.incr('failed_login_ip:{}'.format(current_ip))
|
||||||
|
r_cache.expire('failed_login_ip:{}'.format(current_ip), 300)
|
||||||
|
r_cache.incr('failed_login_user_id:{}'.format(username))
|
||||||
|
r_cache.expire('failed_login_user_id:{}'.format(username), 300)
|
||||||
|
#
|
||||||
|
|
||||||
|
error = 'Password Incorrect'
|
||||||
|
return render_template("login.html", error=error)
|
||||||
|
|
||||||
|
return 'please provide a valid username'
|
||||||
|
|
||||||
|
else:
|
||||||
|
#next_page = request.args.get('next')
|
||||||
|
error = request.args.get('error')
|
||||||
|
return render_template("login.html" , error=error)
|
||||||
|
|
||||||
|
@app.route('/change_password', methods=['POST', 'GET'])
|
||||||
|
@login_required
|
||||||
|
def change_password():
|
||||||
|
password1 = request.form.get('password1')
|
||||||
|
password2 = request.form.get('password2')
|
||||||
|
error = request.args.get('error')
|
||||||
|
|
||||||
|
if error:
|
||||||
|
return render_template("change_password.html", error=error)
|
||||||
|
|
||||||
|
if current_user.is_authenticated and password1!=None:
|
||||||
|
if password1==password2:
|
||||||
|
if check_password_strength(password1):
|
||||||
|
user_id = current_user.get_id()
|
||||||
|
create_user_db(user_id , password1, update=True)
|
||||||
|
return redirect(url_for('dashboard.index'))
|
||||||
|
else:
|
||||||
|
error = 'Incorrect password'
|
||||||
|
return render_template("change_password.html", error=error)
|
||||||
|
else:
|
||||||
|
error = "Passwords don't match"
|
||||||
|
return render_template("change_password.html", error=error)
|
||||||
|
else:
|
||||||
|
error = 'Please choose a new password'
|
||||||
|
return render_template("change_password.html", error=error)
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
@login_required
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
|
# role error template
|
||||||
|
@app.route('/role', methods=['POST', 'GET'])
|
||||||
|
@login_required
|
||||||
|
def role():
|
||||||
|
return render_template("error/403.html"), 403
|
||||||
|
|
||||||
@app.route('/searchbox/')
|
@app.route('/searchbox/')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def searchbox():
|
def searchbox():
|
||||||
return render_template("searchbox.html")
|
return render_template("searchbox.html")
|
||||||
|
|
||||||
|
# ========== ERROR HANDLER ============
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
@login_required
|
||||||
|
def page_not_found(e):
|
||||||
|
# avoid endpoint enumeration
|
||||||
|
return render_template('error/404.html'), 404
|
||||||
|
|
||||||
# ========== INITIAL taxonomies ============
|
# ========== INITIAL taxonomies ============
|
||||||
r_serv_tags = redis.StrictRedis(
|
|
||||||
host=cfg.get("ARDB_Tags", "host"),
|
|
||||||
port=cfg.getint("ARDB_Tags", "port"),
|
|
||||||
db=cfg.getint("ARDB_Tags", "db"),
|
|
||||||
decode_responses=True)
|
|
||||||
# add default ail taxonomies
|
# add default ail taxonomies
|
||||||
r_serv_tags.sadd('active_taxonomies', 'infoleak')
|
r_serv_tags.sadd('active_taxonomies', 'infoleak')
|
||||||
r_serv_tags.sadd('active_taxonomies', 'gdpr')
|
r_serv_tags.sadd('active_taxonomies', 'gdpr')
|
||||||
|
@ -139,11 +310,6 @@ for tag in taxonomies.get('fpf').machinetags():
|
||||||
r_serv_tags.sadd('active_tag_fpf', tag)
|
r_serv_tags.sadd('active_tag_fpf', tag)
|
||||||
|
|
||||||
# ========== INITIAL tags auto export ============
|
# ========== INITIAL tags auto export ============
|
||||||
r_serv_db = redis.StrictRedis(
|
|
||||||
host=cfg.get("ARDB_DB", "host"),
|
|
||||||
port=cfg.getint("ARDB_DB", "port"),
|
|
||||||
db=cfg.getint("ARDB_DB", "db"),
|
|
||||||
decode_responses=True)
|
|
||||||
infoleak_tags = taxonomies.get('infoleak').machinetags()
|
infoleak_tags = taxonomies.get('infoleak').machinetags()
|
||||||
infoleak_automatic_tags = []
|
infoleak_automatic_tags = []
|
||||||
for tag in taxonomies.get('infoleak').machinetags():
|
for tag in taxonomies.get('infoleak').machinetags():
|
||||||
|
@ -154,4 +320,4 @@ r_serv_db.sadd('list_export_tags', 'infoleak:submission="manual"')
|
||||||
# ============ MAIN ============
|
# ============ MAIN ============
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host='0.0.0.0', port=7000, threaded=True)
|
app.run(host='0.0.0.0', port=7000, threaded=True, ssl_context=ssl_context)
|
||||||
|
|
53
var/www/create_default_user.py
Executable file
53
var/www/create_default_user.py
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import redis
|
||||||
|
import secrets
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.environ['AIL_FLASK'], 'modules'))
|
||||||
|
|
||||||
|
from Role_Manager import create_user_db, edit_user_db, get_default_admin_token
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
configfile = os.path.join(os.environ['AIL_BIN'], 'packages/config.cfg')
|
||||||
|
if not os.path.exists(configfile):
|
||||||
|
raise Exception('Unable to find the configuration file. \
|
||||||
|
Did you set environment variables? \
|
||||||
|
Or activate the virtualenv.')
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(configfile)
|
||||||
|
|
||||||
|
r_serv = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
port=cfg.getint("ARDB_DB", "port"),
|
||||||
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# create role_list
|
||||||
|
if not r_serv.exists('ail:all_role'):
|
||||||
|
r_serv.zadd('ail:all_role', 1, 'admin')
|
||||||
|
r_serv.zadd('ail:all_role', 2, 'analyst')
|
||||||
|
|
||||||
|
username = 'admin@admin.test'
|
||||||
|
password = secrets.token_urlsafe()
|
||||||
|
if r_serv.exists('user_metadata:admin@admin.test'):
|
||||||
|
edit_user_db(username, password=password, role='admin')
|
||||||
|
else:
|
||||||
|
create_user_db(username, password, role='admin', default=True)
|
||||||
|
token = get_default_admin_token()
|
||||||
|
|
||||||
|
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
||||||
|
to_write_str = '# Password Generated by default\n# This file is deleted after the first login\n#\nemail=admin@admin.test\npassword='
|
||||||
|
to_write_str = to_write_str + password + '\nAPI_Key=' + token
|
||||||
|
with open(default_passwd_file, 'w') as f:
|
||||||
|
f.write(to_write_str)
|
||||||
|
|
||||||
|
print('new user created: {}'.format(username))
|
||||||
|
print('password: {}'.format(password))
|
|
@ -7,6 +7,7 @@
|
||||||
import configparser
|
import configparser
|
||||||
import redis
|
import redis
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# FLASK #
|
# FLASK #
|
||||||
|
@ -175,6 +176,9 @@ max_dashboard_logs = int(cfg.get("Flask", "max_dashboard_logs"))
|
||||||
|
|
||||||
crawler_enabled = cfg.getboolean("Crawler", "activate_crawler")
|
crawler_enabled = cfg.getboolean("Crawler", "activate_crawler")
|
||||||
|
|
||||||
|
email_regex = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}'
|
||||||
|
email_regex = re.compile(email_regex)
|
||||||
|
|
||||||
# VT
|
# VT
|
||||||
try:
|
try:
|
||||||
from virusTotalKEYS import vt_key
|
from virusTotalKEYS import vt_key
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
import redis
|
import redis
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, url_for, redirect
|
from flask import Flask, render_template, jsonify, request, Blueprint, url_for, redirect
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -273,6 +276,8 @@ def hive_create_case(hive_tlp, threat_level, hive_description, hive_case_title,
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/", methods=['GET'])
|
@PasteSubmit.route("/PasteSubmit/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def PasteSubmit_page():
|
def PasteSubmit_page():
|
||||||
#active taxonomies
|
#active taxonomies
|
||||||
active_taxonomies = r_serv_tags.smembers('active_taxonomies')
|
active_taxonomies = r_serv_tags.smembers('active_taxonomies')
|
||||||
|
@ -285,6 +290,8 @@ def PasteSubmit_page():
|
||||||
active_galaxies = active_galaxies)
|
active_galaxies = active_galaxies)
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/submit", methods=['POST'])
|
@PasteSubmit.route("/PasteSubmit/submit", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def submit():
|
def submit():
|
||||||
|
|
||||||
#paste_name = request.form['paste_name']
|
#paste_name = request.form['paste_name']
|
||||||
|
@ -394,6 +401,8 @@ def submit():
|
||||||
return PasteSubmit_page()
|
return PasteSubmit_page()
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/submit_status", methods=['GET'])
|
@PasteSubmit.route("/PasteSubmit/submit_status", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def submit_status():
|
def submit_status():
|
||||||
UUID = request.args.get('UUID')
|
UUID = request.args.get('UUID')
|
||||||
|
|
||||||
|
@ -460,6 +469,8 @@ def submit_status():
|
||||||
|
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/create_misp_event", methods=['POST'])
|
@PasteSubmit.route("/PasteSubmit/create_misp_event", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def create_misp_event():
|
def create_misp_event():
|
||||||
|
|
||||||
distribution = int(request.form['misp_data[Event][distribution]'])
|
distribution = int(request.form['misp_data[Event][distribution]'])
|
||||||
|
@ -482,6 +493,8 @@ def create_misp_event():
|
||||||
return 'error0'
|
return 'error0'
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/create_hive_case", methods=['POST'])
|
@PasteSubmit.route("/PasteSubmit/create_hive_case", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def create_hive_case():
|
def create_hive_case():
|
||||||
|
|
||||||
hive_tlp = int(request.form['hive_tlp'])
|
hive_tlp = int(request.form['hive_tlp'])
|
||||||
|
@ -504,6 +517,8 @@ def create_hive_case():
|
||||||
return 'error'
|
return 'error'
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/edit_tag_export")
|
@PasteSubmit.route("/PasteSubmit/edit_tag_export")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def edit_tag_export():
|
def edit_tag_export():
|
||||||
misp_auto_events = r_serv_db.get('misp:auto-events')
|
misp_auto_events = r_serv_db.get('misp:auto-events')
|
||||||
hive_auto_alerts = r_serv_db.get('hive:auto-alerts')
|
hive_auto_alerts = r_serv_db.get('hive:auto-alerts')
|
||||||
|
@ -568,6 +583,8 @@ def edit_tag_export():
|
||||||
flag_hive=flag_hive)
|
flag_hive=flag_hive)
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/tag_export_edited", methods=['POST'])
|
@PasteSubmit.route("/PasteSubmit/tag_export_edited", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def tag_export_edited():
|
def tag_export_edited():
|
||||||
tag_enabled_misp = request.form.getlist('tag_enabled_misp')
|
tag_enabled_misp = request.form.getlist('tag_enabled_misp')
|
||||||
tag_enabled_hive = request.form.getlist('tag_enabled_hive')
|
tag_enabled_hive = request.form.getlist('tag_enabled_hive')
|
||||||
|
@ -592,26 +609,36 @@ def tag_export_edited():
|
||||||
return redirect(url_for('PasteSubmit.edit_tag_export'))
|
return redirect(url_for('PasteSubmit.edit_tag_export'))
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/enable_misp_auto_event")
|
@PasteSubmit.route("/PasteSubmit/enable_misp_auto_event")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def enable_misp_auto_event():
|
def enable_misp_auto_event():
|
||||||
r_serv_db.set('misp:auto-events', 1)
|
r_serv_db.set('misp:auto-events', 1)
|
||||||
return edit_tag_export()
|
return edit_tag_export()
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/disable_misp_auto_event")
|
@PasteSubmit.route("/PasteSubmit/disable_misp_auto_event")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def disable_misp_auto_event():
|
def disable_misp_auto_event():
|
||||||
r_serv_db.set('misp:auto-events', 0)
|
r_serv_db.set('misp:auto-events', 0)
|
||||||
return edit_tag_export()
|
return edit_tag_export()
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/enable_hive_auto_alert")
|
@PasteSubmit.route("/PasteSubmit/enable_hive_auto_alert")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def enable_hive_auto_alert():
|
def enable_hive_auto_alert():
|
||||||
r_serv_db.set('hive:auto-alerts', 1)
|
r_serv_db.set('hive:auto-alerts', 1)
|
||||||
return edit_tag_export()
|
return edit_tag_export()
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/disable_hive_auto_alert")
|
@PasteSubmit.route("/PasteSubmit/disable_hive_auto_alert")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def disable_hive_auto_alert():
|
def disable_hive_auto_alert():
|
||||||
r_serv_db.set('hive:auto-alerts', 0)
|
r_serv_db.set('hive:auto-alerts', 0)
|
||||||
return edit_tag_export()
|
return edit_tag_export()
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/add_push_tag")
|
@PasteSubmit.route("/PasteSubmit/add_push_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def add_push_tag():
|
def add_push_tag():
|
||||||
tag = request.args.get('tag')
|
tag = request.args.get('tag')
|
||||||
if tag is not None:
|
if tag is not None:
|
||||||
|
@ -629,6 +656,8 @@ def add_push_tag():
|
||||||
return 'None args', 400
|
return 'None args', 400
|
||||||
|
|
||||||
@PasteSubmit.route("/PasteSubmit/delete_push_tag")
|
@PasteSubmit.route("/PasteSubmit/delete_push_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def delete_push_tag():
|
def delete_push_tag():
|
||||||
tag = request.args.get('tag')
|
tag = request.args.get('tag')
|
||||||
|
|
||||||
|
|
184
var/www/modules/Role_Manager.py
Normal file
184
var/www/modules/Role_Manager.py
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import redis
|
||||||
|
import bcrypt
|
||||||
|
import secrets
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
|
||||||
|
|
||||||
|
from flask import request, current_app
|
||||||
|
|
||||||
|
login_manager = LoginManager()
|
||||||
|
login_manager.login_view = 'role'
|
||||||
|
|
||||||
|
# CONFIG #
|
||||||
|
configfile = os.path.join(os.environ['AIL_BIN'], 'packages/config.cfg')
|
||||||
|
if not os.path.exists(configfile):
|
||||||
|
raise Exception('Unable to find the configuration file. \
|
||||||
|
Did you set environment variables? \
|
||||||
|
Or activate the virtualenv.')
|
||||||
|
|
||||||
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(configfile)
|
||||||
|
|
||||||
|
r_serv_db = redis.StrictRedis(
|
||||||
|
host=cfg.get("ARDB_DB", "host"),
|
||||||
|
port=cfg.getint("ARDB_DB", "port"),
|
||||||
|
db=cfg.getint("ARDB_DB", "db"),
|
||||||
|
decode_responses=True)
|
||||||
|
|
||||||
|
default_passwd_file = os.path.join(os.environ['AIL_HOME'], 'DEFAULT_PASSWORD')
|
||||||
|
|
||||||
|
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,100}$'
|
||||||
|
regex_password = re.compile(regex_password)
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
############### CHECK ROLE ACCESS ##################
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
def login_admin(func):
|
||||||
|
@wraps(func)
|
||||||
|
def decorated_view(*args, **kwargs):
|
||||||
|
if not current_user.is_authenticated:
|
||||||
|
return login_manager.unauthorized()
|
||||||
|
elif (not current_user.is_in_role('admin')):
|
||||||
|
return login_manager.unauthorized()
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return decorated_view
|
||||||
|
|
||||||
|
def login_analyst(func):
|
||||||
|
@wraps(func)
|
||||||
|
def decorated_view(*args, **kwargs):
|
||||||
|
if not current_user.is_authenticated:
|
||||||
|
return login_manager.unauthorized()
|
||||||
|
elif (not current_user.is_in_role('analyst')):
|
||||||
|
return login_manager.unauthorized()
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return decorated_view
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
###############################################################
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
def generate_new_token(user_id):
|
||||||
|
# create user token
|
||||||
|
current_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
|
||||||
|
r_serv_db.hdel('user:tokens', current_token)
|
||||||
|
token = secrets.token_urlsafe(41)
|
||||||
|
r_serv_db.hset('user:tokens', token, user_id)
|
||||||
|
r_serv_db.hset('user_metadata:{}'.format(user_id), 'token', token)
|
||||||
|
|
||||||
|
def get_default_admin_token():
|
||||||
|
if r_serv_db.exists('user_metadata:admin@admin.test'):
|
||||||
|
return r_serv_db.hget('user_metadata:admin@admin.test', 'token')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def create_user_db(username_id , password, default=False, role=None, update=False):
|
||||||
|
password = password.encode()
|
||||||
|
password_hash = hashing_password(password)
|
||||||
|
|
||||||
|
# create user token
|
||||||
|
generate_new_token(username_id)
|
||||||
|
|
||||||
|
if update:
|
||||||
|
r_serv_db.hdel('user_metadata:{}'.format(username_id), 'change_passwd')
|
||||||
|
# remove default user password file
|
||||||
|
if username_id=='admin@admin.test':
|
||||||
|
os.remove(default_passwd_file)
|
||||||
|
else:
|
||||||
|
if default:
|
||||||
|
r_serv_db.hset('user_metadata:{}'.format(username_id), 'change_passwd', True)
|
||||||
|
if role:
|
||||||
|
if role in get_all_role():
|
||||||
|
for role_to_add in get_all_user_role(role):
|
||||||
|
r_serv_db.sadd('user_role:{}'.format(role_to_add), username_id)
|
||||||
|
r_serv_db.hset('user_metadata:{}'.format(username_id), 'role', role)
|
||||||
|
|
||||||
|
r_serv_db.hset('user:all', username_id, password_hash)
|
||||||
|
|
||||||
|
def edit_user_db(user_id, role, password=None):
|
||||||
|
if password:
|
||||||
|
password_hash = hashing_password(password.encode())
|
||||||
|
r_serv_db.hset('user:all', user_id, password_hash)
|
||||||
|
|
||||||
|
current_role = r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
|
||||||
|
if role != current_role:
|
||||||
|
request_level = get_role_level(role)
|
||||||
|
current_role = get_role_level(current_role)
|
||||||
|
|
||||||
|
if current_role < request_level:
|
||||||
|
role_to_remove = get_user_role_by_range(current_role -1, request_level - 2)
|
||||||
|
for role_id in role_to_remove:
|
||||||
|
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
||||||
|
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
||||||
|
else:
|
||||||
|
role_to_add = get_user_role_by_range(request_level -1, current_role)
|
||||||
|
for role_id in role_to_add:
|
||||||
|
r_serv_db.sadd('user_role:{}'.format(role_id), user_id)
|
||||||
|
r_serv_db.hset('user_metadata:{}'.format(user_id), 'role', role)
|
||||||
|
|
||||||
|
def delete_user_db(user_id):
|
||||||
|
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
|
||||||
|
role_to_remove =get_all_role()
|
||||||
|
for role_id in role_to_remove:
|
||||||
|
r_serv_db.srem('user_role:{}'.format(role_id), user_id)
|
||||||
|
user_token = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
|
||||||
|
r_serv_db.hdel('user:tokens', user_token)
|
||||||
|
r_serv_db.delete('user_metadata:{}'.format(user_id))
|
||||||
|
r_serv_db.hdel('user:all', user_id)
|
||||||
|
|
||||||
|
def hashing_password(bytes_password):
|
||||||
|
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
||||||
|
return hashed
|
||||||
|
|
||||||
|
def check_password_strength(password):
|
||||||
|
result = regex_password.match(password)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_all_role():
|
||||||
|
return r_serv_db.zrange('ail:all_role', 0, -1)
|
||||||
|
|
||||||
|
def get_role_level(role):
|
||||||
|
return int(r_serv_db.zscore('ail:all_role', role))
|
||||||
|
|
||||||
|
def get_all_user_role(user_role):
|
||||||
|
current_role_val = get_role_level(user_role)
|
||||||
|
return r_serv_db.zrange('ail:all_role', current_role_val -1, -1)
|
||||||
|
|
||||||
|
def get_all_user_upper_role(user_role):
|
||||||
|
current_role_val = get_role_level(user_role)
|
||||||
|
# remove one rank
|
||||||
|
if current_role_val > 1:
|
||||||
|
return r_serv_db.zrange('ail:all_role', 0, current_role_val -2)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_user_role_by_range(inf, sup):
|
||||||
|
return r_serv_db.zrange('ail:all_role', inf, sup)
|
||||||
|
|
||||||
|
def get_user_role(user_id):
|
||||||
|
return r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
|
||||||
|
|
||||||
|
def check_user_role_integrity(user_id):
|
||||||
|
user_role = get_user_role(user_id)
|
||||||
|
all_user_role = get_all_user_role(user_role)
|
||||||
|
res = True
|
||||||
|
for role in all_user_role:
|
||||||
|
if not r_serv_db.sismember('user_role:{}'.format(role), user_id):
|
||||||
|
res = False
|
||||||
|
upper_role = get_all_user_upper_role(user_role)
|
||||||
|
for role in upper_role:
|
||||||
|
if r_serv_db.sismember('user_role:{}'.format(role), user_id):
|
||||||
|
res = False
|
||||||
|
return res
|
|
@ -7,6 +7,9 @@
|
||||||
import redis
|
import redis
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -218,6 +221,8 @@ def update_tag_last_seen(tag, tag_first_seen, tag_last_seen):
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@Tags.route("/tags/", methods=['GET'])
|
@Tags.route("/tags/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def Tags_page():
|
def Tags_page():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -351,6 +356,8 @@ def Tags_page():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/get_all_tags")
|
@Tags.route("/Tags/get_all_tags")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_all_tags():
|
def get_all_tags():
|
||||||
|
|
||||||
all_tags = r_serv_tags.smembers('list_tags')
|
all_tags = r_serv_tags.smembers('list_tags')
|
||||||
|
@ -373,6 +380,8 @@ def get_all_tags():
|
||||||
return jsonify(list_tags)
|
return jsonify(list_tags)
|
||||||
|
|
||||||
@Tags.route("/Tags/get_all_tags_taxonomies")
|
@Tags.route("/Tags/get_all_tags_taxonomies")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_all_tags_taxonomies():
|
def get_all_tags_taxonomies():
|
||||||
|
|
||||||
taxonomies = Taxonomies()
|
taxonomies = Taxonomies()
|
||||||
|
@ -390,6 +399,8 @@ def get_all_tags_taxonomies():
|
||||||
return jsonify(list_tags)
|
return jsonify(list_tags)
|
||||||
|
|
||||||
@Tags.route("/Tags/get_all_tags_galaxies")
|
@Tags.route("/Tags/get_all_tags_galaxies")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_all_tags_galaxy():
|
def get_all_tags_galaxy():
|
||||||
|
|
||||||
active_galaxies = r_serv_tags.smembers('active_galaxies')
|
active_galaxies = r_serv_tags.smembers('active_galaxies')
|
||||||
|
@ -403,6 +414,8 @@ def get_all_tags_galaxy():
|
||||||
return jsonify(list_tags)
|
return jsonify(list_tags)
|
||||||
|
|
||||||
@Tags.route("/Tags/get_tags_taxonomie")
|
@Tags.route("/Tags/get_tags_taxonomie")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_tags_taxonomie():
|
def get_tags_taxonomie():
|
||||||
|
|
||||||
taxonomie = request.args.get('taxonomie')
|
taxonomie = request.args.get('taxonomie')
|
||||||
|
@ -429,6 +442,8 @@ def get_tags_taxonomie():
|
||||||
return 'INCORRECT INPUT'
|
return 'INCORRECT INPUT'
|
||||||
|
|
||||||
@Tags.route("/Tags/get_tags_galaxy")
|
@Tags.route("/Tags/get_tags_galaxy")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_tags_galaxy():
|
def get_tags_galaxy():
|
||||||
|
|
||||||
galaxy = request.args.get('galaxy')
|
galaxy = request.args.get('galaxy')
|
||||||
|
@ -449,6 +464,8 @@ def get_tags_galaxy():
|
||||||
return 'this galaxy is disable'
|
return 'this galaxy is disable'
|
||||||
|
|
||||||
@Tags.route("/Tags/remove_tag")
|
@Tags.route("/Tags/remove_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def remove_tag():
|
def remove_tag():
|
||||||
|
|
||||||
#TODO verify input
|
#TODO verify input
|
||||||
|
@ -460,6 +477,8 @@ def remove_tag():
|
||||||
return redirect(url_for('showsavedpastes.showsavedpaste', paste=path))
|
return redirect(url_for('showsavedpastes.showsavedpaste', paste=path))
|
||||||
|
|
||||||
@Tags.route("/Tags/confirm_tag")
|
@Tags.route("/Tags/confirm_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def confirm_tag():
|
def confirm_tag():
|
||||||
|
|
||||||
#TODO verify input
|
#TODO verify input
|
||||||
|
@ -478,6 +497,8 @@ def confirm_tag():
|
||||||
return 'incompatible tag'
|
return 'incompatible tag'
|
||||||
|
|
||||||
@Tags.route("/Tags/tag_validation")
|
@Tags.route("/Tags/tag_validation")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def tag_validation():
|
def tag_validation():
|
||||||
|
|
||||||
path = request.args.get('paste')
|
path = request.args.get('paste')
|
||||||
|
@ -498,6 +519,8 @@ def tag_validation():
|
||||||
return 'input error'
|
return 'input error'
|
||||||
|
|
||||||
@Tags.route("/Tags/addTags")
|
@Tags.route("/Tags/addTags")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def addTags():
|
def addTags():
|
||||||
|
|
||||||
tags = request.args.get('tags')
|
tags = request.args.get('tags')
|
||||||
|
@ -547,6 +570,8 @@ def addTags():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/taxonomies")
|
@Tags.route("/Tags/taxonomies")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def taxonomies():
|
def taxonomies():
|
||||||
|
|
||||||
active_taxonomies = r_serv_tags.smembers('active_taxonomies')
|
active_taxonomies = r_serv_tags.smembers('active_taxonomies')
|
||||||
|
@ -583,6 +608,8 @@ def taxonomies():
|
||||||
n_tags=n_tags)
|
n_tags=n_tags)
|
||||||
|
|
||||||
@Tags.route("/Tags/edit_taxonomie")
|
@Tags.route("/Tags/edit_taxonomie")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def edit_taxonomie():
|
def edit_taxonomie():
|
||||||
|
|
||||||
taxonomies = Taxonomies()
|
taxonomies = Taxonomies()
|
||||||
|
@ -631,6 +658,8 @@ def edit_taxonomie():
|
||||||
return 'INVALID TAXONOMIE'
|
return 'INVALID TAXONOMIE'
|
||||||
|
|
||||||
@Tags.route("/Tags/disable_taxonomie")
|
@Tags.route("/Tags/disable_taxonomie")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def disable_taxonomie():
|
def disable_taxonomie():
|
||||||
|
|
||||||
taxonomies = Taxonomies()
|
taxonomies = Taxonomies()
|
||||||
|
@ -651,6 +680,8 @@ def disable_taxonomie():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/active_taxonomie")
|
@Tags.route("/Tags/active_taxonomie")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def active_taxonomie():
|
def active_taxonomie():
|
||||||
|
|
||||||
taxonomies = Taxonomies()
|
taxonomies = Taxonomies()
|
||||||
|
@ -670,6 +701,8 @@ def active_taxonomie():
|
||||||
return "INCORRECT INPUT"
|
return "INCORRECT INPUT"
|
||||||
|
|
||||||
@Tags.route("/Tags/edit_taxonomie_tag")
|
@Tags.route("/Tags/edit_taxonomie_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def edit_taxonomie_tag():
|
def edit_taxonomie_tag():
|
||||||
|
|
||||||
taxonomies = Taxonomies()
|
taxonomies = Taxonomies()
|
||||||
|
@ -712,6 +745,8 @@ def edit_taxonomie_tag():
|
||||||
return "INCORRECT INPUT"
|
return "INCORRECT INPUT"
|
||||||
|
|
||||||
@Tags.route("/Tags/galaxies")
|
@Tags.route("/Tags/galaxies")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def galaxies():
|
def galaxies():
|
||||||
|
|
||||||
active_galaxies = r_serv_tags.smembers('active_galaxies')
|
active_galaxies = r_serv_tags.smembers('active_galaxies')
|
||||||
|
@ -758,6 +793,8 @@ def galaxies():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/edit_galaxy")
|
@Tags.route("/Tags/edit_galaxy")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def edit_galaxy():
|
def edit_galaxy():
|
||||||
|
|
||||||
id = request.args.get('galaxy')
|
id = request.args.get('galaxy')
|
||||||
|
@ -825,6 +862,8 @@ def edit_galaxy():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/active_galaxy")
|
@Tags.route("/Tags/active_galaxy")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def active_galaxy():
|
def active_galaxy():
|
||||||
|
|
||||||
id = request.args.get('galaxy')
|
id = request.args.get('galaxy')
|
||||||
|
@ -869,6 +908,8 @@ def active_galaxy():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/disable_galaxy")
|
@Tags.route("/Tags/disable_galaxy")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def disable_galaxy():
|
def disable_galaxy():
|
||||||
|
|
||||||
id = request.args.get('galaxy')
|
id = request.args.get('galaxy')
|
||||||
|
@ -889,6 +930,8 @@ def disable_galaxy():
|
||||||
|
|
||||||
|
|
||||||
@Tags.route("/Tags/edit_galaxy_tag")
|
@Tags.route("/Tags/edit_galaxy_tag")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def edit_galaxy_tag():
|
def edit_galaxy_tag():
|
||||||
|
|
||||||
arg1 = request.args.getlist('tag_enabled')
|
arg1 = request.args.getlist('tag_enabled')
|
||||||
|
@ -961,6 +1004,8 @@ def edit_galaxy_tag():
|
||||||
return "INCORRECT INPUT"
|
return "INCORRECT INPUT"
|
||||||
|
|
||||||
@Tags.route("/Tags/tag_galaxy_info")
|
@Tags.route("/Tags/tag_galaxy_info")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def tag_galaxy_info():
|
def tag_galaxy_info():
|
||||||
|
|
||||||
galaxy = request.args.get('galaxy')
|
galaxy = request.args.get('galaxy')
|
||||||
|
|
|
@ -14,6 +14,9 @@ from Date import Date
|
||||||
|
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, url_for
|
from flask import Flask, render_template, jsonify, request, Blueprint, url_for
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
@ -109,10 +112,14 @@ def datetime_from_utc_to_local(utc_str):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@dashboard.route("/_logs")
|
@dashboard.route("/_logs")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def logs():
|
def logs():
|
||||||
return flask.Response(event_stream(), mimetype="text/event-stream")
|
return flask.Response(event_stream(), mimetype="text/event-stream")
|
||||||
|
|
||||||
@dashboard.route("/_get_last_logs_json")
|
@dashboard.route("/_get_last_logs_json")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_last_logs_json():
|
def get_last_logs_json():
|
||||||
date = datetime.datetime.now().strftime("%Y%m%d")
|
date = datetime.datetime.now().strftime("%Y%m%d")
|
||||||
|
|
||||||
|
@ -154,11 +161,15 @@ def get_last_logs_json():
|
||||||
|
|
||||||
|
|
||||||
@dashboard.route("/_stuff", methods=['GET'])
|
@dashboard.route("/_stuff", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def stuff():
|
def stuff():
|
||||||
return jsonify(row1=get_queues(r_serv))
|
return jsonify(row1=get_queues(r_serv))
|
||||||
|
|
||||||
|
|
||||||
@dashboard.route("/")
|
@dashboard.route("/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def index():
|
def index():
|
||||||
default_minute = cfg.get("Flask", "minute_processed_paste")
|
default_minute = cfg.get("Flask", "minute_processed_paste")
|
||||||
threshold_stucked_module = cfg.getint("Module_ModuleInformation", "threshold_stucked_module")
|
threshold_stucked_module = cfg.getint("Module_ModuleInformation", "threshold_stucked_module")
|
||||||
|
|
|
@ -17,6 +17,8 @@ from hashlib import sha256
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, send_file
|
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, send_file
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
@ -474,6 +476,8 @@ def correlation_graph_node_json(correlation_type, type_id, key_id):
|
||||||
|
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
@hashDecoded.route("/hashDecoded/all_hash_search", methods=['POST'])
|
@hashDecoded.route("/hashDecoded/all_hash_search", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def all_hash_search():
|
def all_hash_search():
|
||||||
date_from = request.form.get('date_from')
|
date_from = request.form.get('date_from')
|
||||||
date_to = request.form.get('date_to')
|
date_to = request.form.get('date_to')
|
||||||
|
@ -483,6 +487,8 @@ def all_hash_search():
|
||||||
return redirect(url_for('hashDecoded.hashDecoded_page', date_from=date_from, date_to=date_to, type=type, encoding=encoding, show_decoded_files=show_decoded_files))
|
return redirect(url_for('hashDecoded.hashDecoded_page', date_from=date_from, date_to=date_to, type=type, encoding=encoding, show_decoded_files=show_decoded_files))
|
||||||
|
|
||||||
@hashDecoded.route("/hashDecoded/", methods=['GET'])
|
@hashDecoded.route("/hashDecoded/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hashDecoded_page():
|
def hashDecoded_page():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -600,6 +606,8 @@ def hashDecoded_page():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_by_type')
|
@hashDecoded.route('/hashDecoded/hash_by_type')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_by_type():
|
def hash_by_type():
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
type = 'text/plain'
|
type = 'text/plain'
|
||||||
|
@ -607,12 +615,16 @@ def hash_by_type():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_hash')
|
@hashDecoded.route('/hashDecoded/hash_hash')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_hash():
|
def hash_hash():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
return render_template('hash_hash.html')
|
return render_template('hash_hash.html')
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/showHash')
|
@hashDecoded.route('/hashDecoded/showHash')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showHash():
|
def showHash():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
#hash = 'e02055d3efaad5d656345f6a8b1b6be4fe8cb5ea'
|
#hash = 'e02055d3efaad5d656345f6a8b1b6be4fe8cb5ea'
|
||||||
|
@ -666,6 +678,8 @@ def showHash():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/downloadHash')
|
@hashDecoded.route('/hashDecoded/downloadHash')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def downloadHash():
|
def downloadHash():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
# sanitize hash
|
# sanitize hash
|
||||||
|
@ -702,6 +716,8 @@ def downloadHash():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_by_type_json')
|
@hashDecoded.route('/hashDecoded/hash_by_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_by_type_json():
|
def hash_by_type_json():
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
|
|
||||||
|
@ -735,6 +751,8 @@ def hash_by_type_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/decoder_type_json')
|
@hashDecoded.route('/hashDecoded/decoder_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def decoder_type_json():
|
def decoder_type_json():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -790,6 +808,8 @@ def decoder_type_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/top5_type_json')
|
@hashDecoded.route('/hashDecoded/top5_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def top5_type_json():
|
def top5_type_json():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -848,6 +868,8 @@ def top5_type_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/daily_type_json')
|
@hashDecoded.route('/hashDecoded/daily_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def daily_type_json():
|
def daily_type_json():
|
||||||
date = request.args.get('date')
|
date = request.args.get('date')
|
||||||
|
|
||||||
|
@ -867,6 +889,8 @@ def daily_type_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/range_type_json')
|
@hashDecoded.route('/hashDecoded/range_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def range_type_json():
|
def range_type_json():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -923,6 +947,8 @@ def range_type_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_graph_line_json')
|
@hashDecoded.route('/hashDecoded/hash_graph_line_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_graph_line_json():
|
def hash_graph_line_json():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
|
@ -952,6 +978,8 @@ def hash_graph_line_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_graph_node_json')
|
@hashDecoded.route('/hashDecoded/hash_graph_node_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_graph_node_json():
|
def hash_graph_node_json():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
|
|
||||||
|
@ -1019,6 +1047,8 @@ def hash_graph_node_json():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/hash_types')
|
@hashDecoded.route('/hashDecoded/hash_types')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def hash_types():
|
def hash_types():
|
||||||
date_from = 20180701
|
date_from = 20180701
|
||||||
date_to = 20180706
|
date_to = 20180706
|
||||||
|
@ -1026,6 +1056,8 @@ def hash_types():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/send_file_to_vt_js')
|
@hashDecoded.route('/hashDecoded/send_file_to_vt_js')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def send_file_to_vt_js():
|
def send_file_to_vt_js():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
|
|
||||||
|
@ -1049,6 +1081,8 @@ def send_file_to_vt_js():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/hashDecoded/update_vt_result')
|
@hashDecoded.route('/hashDecoded/update_vt_result')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def update_vt_result():
|
def update_vt_result():
|
||||||
hash = request.args.get('hash')
|
hash = request.args.get('hash')
|
||||||
|
|
||||||
|
@ -1085,6 +1119,8 @@ def update_vt_result():
|
||||||
############################ PGPDump ############################
|
############################ PGPDump ############################
|
||||||
|
|
||||||
@hashDecoded.route('/decoded/pgp_by_type_json') ## TODO: REFRACTOR
|
@hashDecoded.route('/decoded/pgp_by_type_json') ## TODO: REFRACTOR
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def pgp_by_type_json():
|
def pgp_by_type_json():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
|
@ -1129,6 +1165,8 @@ def pgp_by_type_json():
|
||||||
|
|
||||||
############################ Correlation ############################
|
############################ Correlation ############################
|
||||||
@hashDecoded.route("/correlation/pgpdump", methods=['GET'])
|
@hashDecoded.route("/correlation/pgpdump", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def pgpdump_page():
|
def pgpdump_page():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -1139,6 +1177,8 @@ def pgpdump_page():
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@hashDecoded.route("/correlation/cryptocurrency", methods=['GET'])
|
@hashDecoded.route("/correlation/cryptocurrency", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def cryptocurrency_page():
|
def cryptocurrency_page():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -1149,6 +1189,8 @@ def cryptocurrency_page():
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@hashDecoded.route("/correlation/all_pgpdump_search", methods=['POST'])
|
@hashDecoded.route("/correlation/all_pgpdump_search", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def all_pgpdump_search():
|
def all_pgpdump_search():
|
||||||
date_from = request.form.get('date_from')
|
date_from = request.form.get('date_from')
|
||||||
date_to = request.form.get('date_to')
|
date_to = request.form.get('date_to')
|
||||||
|
@ -1157,6 +1199,8 @@ def all_pgpdump_search():
|
||||||
return redirect(url_for('hashDecoded.pgpdump_page', date_from=date_from, date_to=date_to, type_id=type_id, show_decoded_files=show_decoded_files))
|
return redirect(url_for('hashDecoded.pgpdump_page', date_from=date_from, date_to=date_to, type_id=type_id, show_decoded_files=show_decoded_files))
|
||||||
|
|
||||||
@hashDecoded.route("/correlation/all_cryptocurrency_search", methods=['POST'])
|
@hashDecoded.route("/correlation/all_cryptocurrency_search", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def all_cryptocurrency_search():
|
def all_cryptocurrency_search():
|
||||||
date_from = request.form.get('date_from')
|
date_from = request.form.get('date_from')
|
||||||
date_to = request.form.get('date_to')
|
date_to = request.form.get('date_to')
|
||||||
|
@ -1165,6 +1209,8 @@ def all_cryptocurrency_search():
|
||||||
return redirect(url_for('hashDecoded.cryptocurrency_page', date_from=date_from, date_to=date_to, type_id=type_id, show_decoded_files=show_decoded_files))
|
return redirect(url_for('hashDecoded.cryptocurrency_page', date_from=date_from, date_to=date_to, type_id=type_id, show_decoded_files=show_decoded_files))
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/show_pgpdump')
|
@hashDecoded.route('/correlation/show_pgpdump')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def show_pgpdump():
|
def show_pgpdump():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
|
@ -1172,36 +1218,48 @@ def show_pgpdump():
|
||||||
|
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/show_cryptocurrency')
|
@hashDecoded.route('/correlation/show_cryptocurrency')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def show_cryptocurrency():
|
def show_cryptocurrency():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
return show_correlation('cryptocurrency', type_id, key_id)
|
return show_correlation('cryptocurrency', type_id, key_id)
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/cryptocurrency_range_type_json')
|
@hashDecoded.route('/correlation/cryptocurrency_range_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def cryptocurrency_range_type_json():
|
def cryptocurrency_range_type_json():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
return correlation_type_range_type_json('cryptocurrency', date_from, date_to)
|
return correlation_type_range_type_json('cryptocurrency', date_from, date_to)
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/pgpdump_range_type_json')
|
@hashDecoded.route('/correlation/pgpdump_range_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def pgpdump_range_type_json():
|
def pgpdump_range_type_json():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
return correlation_type_range_type_json('pgpdump', date_from, date_to)
|
return correlation_type_range_type_json('pgpdump', date_from, date_to)
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/pgpdump_graph_node_json')
|
@hashDecoded.route('/correlation/pgpdump_graph_node_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def pgpdump_graph_node_json():
|
def pgpdump_graph_node_json():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
return correlation_graph_node_json('pgpdump', type_id, key_id)
|
return correlation_graph_node_json('pgpdump', type_id, key_id)
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/cryptocurrency_graph_node_json')
|
@hashDecoded.route('/correlation/cryptocurrency_graph_node_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def cryptocurrency_graph_node_json():
|
def cryptocurrency_graph_node_json():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
return correlation_graph_node_json('cryptocurrency', type_id, key_id)
|
return correlation_graph_node_json('cryptocurrency', type_id, key_id)
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/pgpdump_graph_line_json')
|
@hashDecoded.route('/correlation/pgpdump_graph_line_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def pgpdump_graph_line_json():
|
def pgpdump_graph_line_json():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
|
@ -1234,6 +1292,8 @@ def correlation_graph_line_json(correlation_type, type_id, key_id, date_from, da
|
||||||
return jsonify()
|
return jsonify()
|
||||||
|
|
||||||
@hashDecoded.route('/correlation/cryptocurrency_graph_line_json')
|
@hashDecoded.route('/correlation/cryptocurrency_graph_line_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def cryptocurrency_graph_line_json():
|
def cryptocurrency_graph_line_json():
|
||||||
type_id = request.args.get('type_id')
|
type_id = request.args.get('type_id')
|
||||||
key_id = request.args.get('key_id')
|
key_id = request.args.get('key_id')
|
||||||
|
|
|
@ -13,6 +13,9 @@ import json
|
||||||
from pyfaup.faup import Faup
|
from pyfaup.faup import Faup
|
||||||
from flask import Flask, render_template, jsonify, request, send_file, Blueprint, redirect, url_for
|
from flask import Flask, render_template, jsonify, request, send_file, Blueprint, redirect, url_for
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
from Date import Date
|
from Date import Date
|
||||||
from HiddenServices import HiddenServices
|
from HiddenServices import HiddenServices
|
||||||
|
|
||||||
|
@ -239,6 +242,8 @@ def delete_auto_crawler(url):
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/", methods=['GET'])
|
@hiddenServices.route("/crawlers/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def dashboard():
|
def dashboard():
|
||||||
crawler_metadata_onion = get_crawler_splash_status('onion')
|
crawler_metadata_onion = get_crawler_splash_status('onion')
|
||||||
crawler_metadata_regular = get_crawler_splash_status('regular')
|
crawler_metadata_regular = get_crawler_splash_status('regular')
|
||||||
|
@ -253,15 +258,15 @@ def dashboard():
|
||||||
crawler_metadata_regular=crawler_metadata_regular,
|
crawler_metadata_regular=crawler_metadata_regular,
|
||||||
statDomains_onion=statDomains_onion, statDomains_regular=statDomains_regular)
|
statDomains_onion=statDomains_onion, statDomains_regular=statDomains_regular)
|
||||||
|
|
||||||
@hiddenServices.route("/hiddenServices/2", methods=['GET'])
|
|
||||||
def hiddenServices_page_test():
|
|
||||||
return render_template("Crawler_index.html")
|
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/manual", methods=['GET'])
|
@hiddenServices.route("/crawlers/manual", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def manual():
|
def manual():
|
||||||
return render_template("Crawler_Splash_manual.html", crawler_enabled=crawler_enabled)
|
return render_template("Crawler_Splash_manual.html", crawler_enabled=crawler_enabled)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/crawler_splash_onion", methods=['GET'])
|
@hiddenServices.route("/crawlers/crawler_splash_onion", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def crawler_splash_onion():
|
def crawler_splash_onion():
|
||||||
type = 'onion'
|
type = 'onion'
|
||||||
last_onions = get_last_domains_crawled(type)
|
last_onions = get_last_domains_crawled(type)
|
||||||
|
@ -279,6 +284,8 @@ def crawler_splash_onion():
|
||||||
crawler_metadata=crawler_metadata, date_from=date_string, date_to=date_string)
|
crawler_metadata=crawler_metadata, date_from=date_string, date_to=date_string)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/Crawler_Splash_last_by_type", methods=['GET'])
|
@hiddenServices.route("/crawlers/Crawler_Splash_last_by_type", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def Crawler_Splash_last_by_type():
|
def Crawler_Splash_last_by_type():
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
# verify user input
|
# verify user input
|
||||||
|
@ -302,6 +309,8 @@ def Crawler_Splash_last_by_type():
|
||||||
crawler_metadata=crawler_metadata, date_from=date_string, date_to=date_string)
|
crawler_metadata=crawler_metadata, date_from=date_string, date_to=date_string)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/blacklisted_domains", methods=['GET'])
|
@hiddenServices.route("/crawlers/blacklisted_domains", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def blacklisted_domains():
|
def blacklisted_domains():
|
||||||
blacklist_domain = request.args.get('blacklist_domain')
|
blacklist_domain = request.args.get('blacklist_domain')
|
||||||
unblacklist_domain = request.args.get('unblacklist_domain')
|
unblacklist_domain = request.args.get('unblacklist_domain')
|
||||||
|
@ -336,6 +345,8 @@ def blacklisted_domains():
|
||||||
return 'Incorrect Type'
|
return 'Incorrect Type'
|
||||||
|
|
||||||
@hiddenServices.route("/crawler/blacklist_domain", methods=['GET'])
|
@hiddenServices.route("/crawler/blacklist_domain", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def blacklist_domain():
|
def blacklist_domain():
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
|
@ -357,6 +368,8 @@ def blacklist_domain():
|
||||||
return 'Incorrect type'
|
return 'Incorrect type'
|
||||||
|
|
||||||
@hiddenServices.route("/crawler/unblacklist_domain", methods=['GET'])
|
@hiddenServices.route("/crawler/unblacklist_domain", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def unblacklist_domain():
|
def unblacklist_domain():
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
|
@ -378,6 +391,8 @@ def unblacklist_domain():
|
||||||
return 'Incorrect type'
|
return 'Incorrect type'
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/create_spider_splash", methods=['POST'])
|
@hiddenServices.route("/crawlers/create_spider_splash", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def create_spider_splash():
|
def create_spider_splash():
|
||||||
url = request.form.get('url_to_crawl')
|
url = request.form.get('url_to_crawl')
|
||||||
automatic = request.form.get('crawler_type')
|
automatic = request.form.get('crawler_type')
|
||||||
|
@ -464,6 +479,8 @@ def create_spider_splash():
|
||||||
return redirect(url_for('hiddenServices.manual'))
|
return redirect(url_for('hiddenServices.manual'))
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/auto_crawler", methods=['GET'])
|
@hiddenServices.route("/crawlers/auto_crawler", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def auto_crawler():
|
def auto_crawler():
|
||||||
nb_element_to_display = 100
|
nb_element_to_display = 100
|
||||||
try:
|
try:
|
||||||
|
@ -516,6 +533,8 @@ def auto_crawler():
|
||||||
auto_crawler_domain_regular_metadata=auto_crawler_domain_regular_metadata)
|
auto_crawler_domain_regular_metadata=auto_crawler_domain_regular_metadata)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/remove_auto_crawler", methods=['GET'])
|
@hiddenServices.route("/crawlers/remove_auto_crawler", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def remove_auto_crawler():
|
def remove_auto_crawler():
|
||||||
url = request.args.get('url')
|
url = request.args.get('url')
|
||||||
page = request.args.get('page')
|
page = request.args.get('page')
|
||||||
|
@ -525,6 +544,8 @@ def remove_auto_crawler():
|
||||||
return redirect(url_for('hiddenServices.auto_crawler', page=page))
|
return redirect(url_for('hiddenServices.auto_crawler', page=page))
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/crawler_dashboard_json", methods=['GET'])
|
@hiddenServices.route("/crawlers/crawler_dashboard_json", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def crawler_dashboard_json():
|
def crawler_dashboard_json():
|
||||||
|
|
||||||
crawler_metadata_onion = get_crawler_splash_status('onion')
|
crawler_metadata_onion = get_crawler_splash_status('onion')
|
||||||
|
@ -541,6 +562,8 @@ def crawler_dashboard_json():
|
||||||
|
|
||||||
# # TODO: refractor
|
# # TODO: refractor
|
||||||
@hiddenServices.route("/hiddenServices/last_crawled_domains_with_stats_json", methods=['GET'])
|
@hiddenServices.route("/hiddenServices/last_crawled_domains_with_stats_json", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def last_crawled_domains_with_stats_json():
|
def last_crawled_domains_with_stats_json():
|
||||||
last_onions = r_serv_onion.lrange('last_onion', 0 ,-1)
|
last_onions = r_serv_onion.lrange('last_onion', 0 ,-1)
|
||||||
list_onion = []
|
list_onion = []
|
||||||
|
@ -590,6 +613,8 @@ def last_crawled_domains_with_stats_json():
|
||||||
return jsonify({'last_onions': list_onion, 'statDomains': statDomains, 'crawler_metadata':crawler_metadata})
|
return jsonify({'last_onions': list_onion, 'statDomains': statDomains, 'crawler_metadata':crawler_metadata})
|
||||||
|
|
||||||
@hiddenServices.route("/hiddenServices/get_onions_by_daterange", methods=['POST'])
|
@hiddenServices.route("/hiddenServices/get_onions_by_daterange", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_onions_by_daterange():
|
def get_onions_by_daterange():
|
||||||
date_from = request.form.get('date_from')
|
date_from = request.form.get('date_from')
|
||||||
date_to = request.form.get('date_to')
|
date_to = request.form.get('date_to')
|
||||||
|
@ -601,6 +626,8 @@ def get_onions_by_daterange():
|
||||||
return redirect(url_for('hiddenServices.show_domains_by_daterange', date_from=date_from, date_to=date_to, service_type=service_type, domains_up=domains_up, domains_down=domains_down, domains_tags=domains_tags))
|
return redirect(url_for('hiddenServices.show_domains_by_daterange', date_from=date_from, date_to=date_to, service_type=service_type, domains_up=domains_up, domains_down=domains_down, domains_tags=domains_tags))
|
||||||
|
|
||||||
@hiddenServices.route("/hiddenServices/show_domains_by_daterange", methods=['GET'])
|
@hiddenServices.route("/hiddenServices/show_domains_by_daterange", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def show_domains_by_daterange():
|
def show_domains_by_daterange():
|
||||||
date_from = request.args.get('date_from')
|
date_from = request.args.get('date_from')
|
||||||
date_to = request.args.get('date_to')
|
date_to = request.args.get('date_to')
|
||||||
|
@ -705,6 +732,8 @@ def show_domains_by_daterange():
|
||||||
domains_tags=domains_tags, type=service_type, bootstrap_label=bootstrap_label)
|
domains_tags=domains_tags, type=service_type, bootstrap_label=bootstrap_label)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/show_domain", methods=['GET'])
|
@hiddenServices.route("/crawlers/show_domain", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def show_domain():
|
def show_domain():
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
epoch = request.args.get('epoch')
|
epoch = request.args.get('epoch')
|
||||||
|
@ -788,6 +817,8 @@ def show_domain():
|
||||||
domain_tags=domain_tags, screenshot=screenshot)
|
domain_tags=domain_tags, screenshot=screenshot)
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/download_domain", methods=['GET'])
|
@hiddenServices.route("/crawlers/download_domain", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def download_domain():
|
def download_domain():
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
epoch = request.args.get('epoch')
|
epoch = request.args.get('epoch')
|
||||||
|
@ -839,6 +870,8 @@ def download_domain():
|
||||||
|
|
||||||
|
|
||||||
@hiddenServices.route("/hiddenServices/onion_son", methods=['GET'])
|
@hiddenServices.route("/hiddenServices/onion_son", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def onion_son():
|
def onion_son():
|
||||||
onion_domain = request.args.get('onion_domain')
|
onion_domain = request.args.get('onion_domain')
|
||||||
|
|
||||||
|
@ -849,6 +882,8 @@ def onion_son():
|
||||||
|
|
||||||
# ============= JSON ==============
|
# ============= JSON ==============
|
||||||
@hiddenServices.route("/hiddenServices/domain_crawled_7days_json", methods=['GET'])
|
@hiddenServices.route("/hiddenServices/domain_crawled_7days_json", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def domain_crawled_7days_json():
|
def domain_crawled_7days_json():
|
||||||
type = 'onion'
|
type = 'onion'
|
||||||
## TODO: # FIXME: 404 error
|
## TODO: # FIXME: 404 error
|
||||||
|
@ -867,6 +902,8 @@ def domain_crawled_7days_json():
|
||||||
return jsonify(json_domain_stats)
|
return jsonify(json_domain_stats)
|
||||||
|
|
||||||
@hiddenServices.route('/hiddenServices/domain_crawled_by_type_json')
|
@hiddenServices.route('/hiddenServices/domain_crawled_by_type_json')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def domain_crawled_by_type_json():
|
def domain_crawled_by_type_json():
|
||||||
current_date = request.args.get('date')
|
current_date = request.args.get('date')
|
||||||
type = request.args.get('type')
|
type = request.args.get('type')
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
import redis
|
import redis
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
from flask import Flask, render_template, jsonify, request, Blueprint
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
@ -22,6 +25,8 @@ def one():
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@rawSkeleton.route("/rawSkeleton/", methods=['GET'])
|
@rawSkeleton.route("/rawSkeleton/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def skeleton_page():
|
def skeleton_page():
|
||||||
return render_template("rawSkeleton.html")
|
return render_template("rawSkeleton.html")
|
||||||
|
|
||||||
|
|
109
var/www/modules/restApi/Flask_restApi.py
Normal file
109
var/www/modules/restApi/Flask_restApi.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
'''
|
||||||
|
Flask functions and routes for the rest api
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import redis
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
# ============ VARIABLES ============
|
||||||
|
import Flask_config
|
||||||
|
|
||||||
|
app = Flask_config.app
|
||||||
|
cfg = Flask_config.cfg
|
||||||
|
baseUrl = Flask_config.baseUrl
|
||||||
|
r_cache = Flask_config.r_cache
|
||||||
|
r_serv_db = Flask_config.r_serv_db
|
||||||
|
r_serv_onion = Flask_config.r_serv_onion
|
||||||
|
r_serv_metadata = Flask_config.r_serv_metadata
|
||||||
|
|
||||||
|
restApi = Blueprint('restApi', __name__, template_folder='templates')
|
||||||
|
|
||||||
|
# ============ AUTH FUNCTIONS ============
|
||||||
|
|
||||||
|
def check_token_format(strg, search=re.compile(r'[^a-zA-Z0-9_-]').search):
|
||||||
|
return not bool(search(strg))
|
||||||
|
|
||||||
|
def verify_token(token):
|
||||||
|
if len(token) != 55:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not check_token_format(token):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if r_serv_db.hexists('user:tokens', token):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# ============ DECORATOR ============
|
||||||
|
|
||||||
|
def token_required(funct):
|
||||||
|
@wraps(funct)
|
||||||
|
def api_token(*args, **kwargs):
|
||||||
|
data = authErrors()
|
||||||
|
if data:
|
||||||
|
return Response(json.dumps(data[0], indent=2, sort_keys=True), mimetype='application/json'), data[1]
|
||||||
|
else:
|
||||||
|
return funct(*args, **kwargs)
|
||||||
|
return api_token
|
||||||
|
|
||||||
|
def get_auth_from_header():
|
||||||
|
token = request.headers.get('Authorization').replace(' ', '') # remove space
|
||||||
|
return token
|
||||||
|
|
||||||
|
def authErrors():
|
||||||
|
# Check auth
|
||||||
|
if not request.headers.get('Authorization'):
|
||||||
|
return ({'status': 'error', 'reason': 'Authentication needed'}, 401)
|
||||||
|
token = get_auth_from_header()
|
||||||
|
data = None
|
||||||
|
# verify token format
|
||||||
|
|
||||||
|
try:
|
||||||
|
authenticated = False
|
||||||
|
if verify_token(token):
|
||||||
|
authenticated = True
|
||||||
|
|
||||||
|
if not authenticated:
|
||||||
|
data = ({'status': 'error', 'reason': 'Authentication failed'}, 401)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
data = ({'status': 'error', 'reason': 'Malformed Authentication String'}, 400)
|
||||||
|
if data:
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ============ FUNCTIONS ============
|
||||||
|
|
||||||
|
def one():
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
|
# @restApi.route("/api", methods=['GET'])
|
||||||
|
# @login_required
|
||||||
|
# def api():
|
||||||
|
# return 'api doc'
|
||||||
|
|
||||||
|
@restApi.route("api/items", methods=['POST'])
|
||||||
|
@token_required
|
||||||
|
def items():
|
||||||
|
item = request.args.get('id')
|
||||||
|
|
||||||
|
return Response(json.dumps({'test': 2}), mimetype='application/json')
|
||||||
|
|
||||||
|
# ========= REGISTRATION =========
|
||||||
|
app.register_blueprint(restApi, url_prefix=baseUrl)
|
35
var/www/modules/restApi/templates/api_default.html
Normal file
35
var/www/modules/restApi/templates/api_default.html
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>AIL-Framework</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png')}}">
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{% include 'crawler/menu_sidebar.html' %}
|
||||||
|
|
||||||
|
<div class="col-12 col-lg-10" id="core_content">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
|
@ -11,6 +11,9 @@ import datetime
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
from flask import Flask, render_template, jsonify, request, Blueprint
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import Paste
|
import Paste
|
||||||
from whoosh import index
|
from whoosh import index
|
||||||
from whoosh.fields import Schema, TEXT, ID
|
from whoosh.fields import Schema, TEXT, ID
|
||||||
|
@ -93,6 +96,8 @@ def to_iso_date(timestamp):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@searches.route("/search", methods=['POST'])
|
@searches.route("/search", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def search():
|
def search():
|
||||||
query = request.form['query']
|
query = request.form['query']
|
||||||
q = []
|
q = []
|
||||||
|
@ -180,6 +185,8 @@ def search():
|
||||||
|
|
||||||
|
|
||||||
@searches.route("/get_more_search_result", methods=['POST'])
|
@searches.route("/get_more_search_result", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_more_search_result():
|
def get_more_search_result():
|
||||||
query = request.form['query']
|
query = request.form['query']
|
||||||
q = []
|
q = []
|
||||||
|
|
|
@ -11,6 +11,9 @@ from Date import Date
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
from flask import Flask, render_template, jsonify, request, Blueprint
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import Paste
|
import Paste
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
|
@ -39,11 +42,15 @@ def get_date_range(num_day):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@sentiments.route("/sentiment_analysis_trending/")
|
@sentiments.route("/sentiment_analysis_trending/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def sentiment_analysis_trending():
|
def sentiment_analysis_trending():
|
||||||
return render_template("sentiment_analysis_trending.html")
|
return render_template("sentiment_analysis_trending.html")
|
||||||
|
|
||||||
|
|
||||||
@sentiments.route("/sentiment_analysis_getplotdata/", methods=['GET'])
|
@sentiments.route("/sentiment_analysis_getplotdata/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def sentiment_analysis_getplotdata():
|
def sentiment_analysis_getplotdata():
|
||||||
# Get the top providers based on number of pastes
|
# Get the top providers based on number of pastes
|
||||||
oneHour = 60*60
|
oneHour = 60*60
|
||||||
|
@ -94,12 +101,16 @@ def sentiment_analysis_getplotdata():
|
||||||
|
|
||||||
|
|
||||||
@sentiments.route("/sentiment_analysis_plot_tool/")
|
@sentiments.route("/sentiment_analysis_plot_tool/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def sentiment_analysis_plot_tool():
|
def sentiment_analysis_plot_tool():
|
||||||
return render_template("sentiment_analysis_plot_tool.html")
|
return render_template("sentiment_analysis_plot_tool.html")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@sentiments.route("/sentiment_analysis_plot_tool_getdata/", methods=['GET'])
|
@sentiments.route("/sentiment_analysis_plot_tool_getdata/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def sentiment_analysis_plot_tool_getdata():
|
def sentiment_analysis_plot_tool_getdata():
|
||||||
getProviders = request.args.get('getProviders')
|
getProviders = request.args.get('getProviders')
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,13 @@
|
||||||
Flask functions and routes for the settings modules page
|
Flask functions and routes for the settings modules page
|
||||||
'''
|
'''
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from Role_Manager import create_user_db, edit_user_db, delete_user_db, check_password_strength, generate_new_token
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import secrets
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import git_status
|
import git_status
|
||||||
|
@ -22,6 +27,7 @@ max_preview_char = Flask_config.max_preview_char
|
||||||
max_preview_modal = Flask_config.max_preview_modal
|
max_preview_modal = Flask_config.max_preview_modal
|
||||||
REPO_ORIGIN = Flask_config.REPO_ORIGIN
|
REPO_ORIGIN = Flask_config.REPO_ORIGIN
|
||||||
dict_update_description = Flask_config.dict_update_description
|
dict_update_description = Flask_config.dict_update_description
|
||||||
|
email_regex = Flask_config.email_regex
|
||||||
|
|
||||||
settings = Blueprint('settings', __name__, template_folder='templates')
|
settings = Blueprint('settings', __name__, template_folder='templates')
|
||||||
|
|
||||||
|
@ -31,8 +37,12 @@ settings = Blueprint('settings', __name__, template_folder='templates')
|
||||||
def one():
|
def one():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
#def get_v1.5_update_tags_backgroud_status():
|
def check_email(email):
|
||||||
# return '38%'
|
result = email_regex.match(email)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def get_git_metadata():
|
def get_git_metadata():
|
||||||
dict_git = {}
|
dict_git = {}
|
||||||
|
@ -71,20 +81,161 @@ def get_update_metadata():
|
||||||
dict_update['current_background_script_stat'] = r_serv_db.get('ail:current_background_script_stat')
|
dict_update['current_background_script_stat'] = r_serv_db.get('ail:current_background_script_stat')
|
||||||
|
|
||||||
return dict_update
|
return dict_update
|
||||||
|
|
||||||
|
def get_user_metadata(user_id):
|
||||||
|
user_metadata = {}
|
||||||
|
user_metadata['email'] = user_id
|
||||||
|
user_metadata['role'] = r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
|
||||||
|
user_metadata['api_key'] = r_serv_db.hget('user_metadata:{}'.format(user_id), 'token')
|
||||||
|
return user_metadata
|
||||||
|
|
||||||
|
def get_users_metadata(list_users):
|
||||||
|
users = []
|
||||||
|
for user in list_users:
|
||||||
|
users.append(get_user_metadata(user))
|
||||||
|
return users
|
||||||
|
|
||||||
|
def get_all_users():
|
||||||
|
return r_serv_db.hkeys('user:all')
|
||||||
|
|
||||||
|
def get_all_roles():
|
||||||
|
return r_serv_db.zrange('ail:all_role', 0, -1)
|
||||||
|
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@settings.route("/settings/", methods=['GET'])
|
@settings.route("/settings/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def settings_page():
|
def settings_page():
|
||||||
git_metadata = get_git_metadata()
|
git_metadata = get_git_metadata()
|
||||||
current_version = r_serv_db.get('ail:version')
|
current_version = r_serv_db.get('ail:version')
|
||||||
update_metadata = get_update_metadata()
|
update_metadata = get_update_metadata()
|
||||||
|
|
||||||
|
admin_level = current_user.is_in_role('admin')
|
||||||
|
|
||||||
return render_template("settings_index.html", git_metadata=git_metadata,
|
return render_template("settings_index.html", git_metadata=git_metadata,
|
||||||
|
admin_level=admin_level,
|
||||||
current_version=current_version)
|
current_version=current_version)
|
||||||
|
|
||||||
|
@settings.route("/settings/edit_profile", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
|
def edit_profile():
|
||||||
|
user_metadata = get_user_metadata(current_user.get_id())
|
||||||
|
admin_level = current_user.is_in_role('admin')
|
||||||
|
return render_template("edit_profile.html", user_metadata=user_metadata,
|
||||||
|
admin_level=admin_level)
|
||||||
|
|
||||||
|
@settings.route("/settings/new_token", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
|
def new_token():
|
||||||
|
generate_new_token(current_user.get_id())
|
||||||
|
return redirect(url_for('settings.edit_profile'))
|
||||||
|
|
||||||
|
@settings.route("/settings/new_token_user", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def new_token_user():
|
||||||
|
user_id = request.args.get('user_id')
|
||||||
|
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
|
||||||
|
generate_new_token(user_id)
|
||||||
|
return redirect(url_for('settings.users_list'))
|
||||||
|
|
||||||
|
@settings.route("/settings/create_user", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def create_user():
|
||||||
|
user_id = request.args.get('user_id')
|
||||||
|
error = request.args.get('error')
|
||||||
|
error_mail = request.args.get('error_mail')
|
||||||
|
role = None
|
||||||
|
if r_serv_db.exists('user_metadata:{}'.format(user_id)):
|
||||||
|
role = r_serv_db.hget('user_metadata:{}'.format(user_id), 'role')
|
||||||
|
else:
|
||||||
|
user_id = None
|
||||||
|
all_roles = get_all_roles()
|
||||||
|
return render_template("create_user.html", all_roles=all_roles, user_id=user_id, user_role=role,
|
||||||
|
error=error, error_mail=error_mail,
|
||||||
|
admin_level=True)
|
||||||
|
|
||||||
|
@settings.route("/settings/create_user_post", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def create_user_post():
|
||||||
|
email = request.form.get('username')
|
||||||
|
role = request.form.get('user_role')
|
||||||
|
password1 = request.form.get('password1')
|
||||||
|
password2 = request.form.get('password2')
|
||||||
|
|
||||||
|
all_roles = get_all_roles()
|
||||||
|
|
||||||
|
if email and len(email)< 300 and check_email(email) and role:
|
||||||
|
if role in all_roles:
|
||||||
|
# password set
|
||||||
|
if password1 and password2:
|
||||||
|
if password1==password2:
|
||||||
|
if check_password_strength(password1):
|
||||||
|
password = password1
|
||||||
|
else:
|
||||||
|
return render_template("create_user.html", all_roles=all_roles, error="Incorrect Password", admin_level=True)
|
||||||
|
else:
|
||||||
|
return render_template("create_user.html", all_roles=all_roles, error="Passwords don't match", admin_level=True)
|
||||||
|
# generate password
|
||||||
|
else:
|
||||||
|
password = secrets.token_urlsafe()
|
||||||
|
|
||||||
|
if current_user.is_in_role('admin'):
|
||||||
|
# edit user
|
||||||
|
if r_serv_db.exists('user_metadata:{}'.format(email)):
|
||||||
|
if password1 and password2:
|
||||||
|
edit_user_db(email, password=password, role=role)
|
||||||
|
return redirect(url_for('settings.users_list', new_user=email, new_user_password=password, new_user_edited=True))
|
||||||
|
else:
|
||||||
|
edit_user_db(email, role=role)
|
||||||
|
return redirect(url_for('settings.users_list', new_user=email, new_user_password='Password not changed', new_user_edited=True))
|
||||||
|
# create user
|
||||||
|
else:
|
||||||
|
create_user_db(email, password, default=True, role=role)
|
||||||
|
return redirect(url_for('settings.users_list', new_user=email, new_user_password=password, new_user_edited=False))
|
||||||
|
|
||||||
|
else:
|
||||||
|
return render_template("create_user.html", all_roles=all_roles, admin_level=True)
|
||||||
|
else:
|
||||||
|
return render_template("create_user.html", all_roles=all_roles, error_mail=True, admin_level=True)
|
||||||
|
|
||||||
|
@settings.route("/settings/users_list", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def users_list():
|
||||||
|
all_users = get_users_metadata(get_all_users())
|
||||||
|
new_user = request.args.get('new_user')
|
||||||
|
new_user_dict = {}
|
||||||
|
if new_user:
|
||||||
|
new_user_dict['email'] = new_user
|
||||||
|
new_user_dict['edited'] = request.args.get('new_user_edited')
|
||||||
|
new_user_dict['password'] = request.args.get('new_user_password')
|
||||||
|
return render_template("users_list.html", all_users=all_users, new_user=new_user_dict, admin_level=True)
|
||||||
|
|
||||||
|
@settings.route("/settings/edit_user", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def edit_user():
|
||||||
|
user_id = request.args.get('user_id')
|
||||||
|
return redirect(url_for('settings.create_user', user_id=user_id))
|
||||||
|
|
||||||
|
@settings.route("/settings/delete_user", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_admin
|
||||||
|
def delete_user():
|
||||||
|
user_id = request.args.get('user_id')
|
||||||
|
delete_user_db(user_id)
|
||||||
|
return redirect(url_for('settings.users_list'))
|
||||||
|
|
||||||
|
|
||||||
@settings.route("/settings/get_background_update_stats_json", methods=['GET'])
|
@settings.route("/settings/get_background_update_stats_json", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def get_background_update_stats_json():
|
def get_background_update_stats_json():
|
||||||
# handle :end, error
|
# handle :end, error
|
||||||
update_stats = {}
|
update_stats = {}
|
||||||
|
|
153
var/www/modules/settings/templates/create_user.html
Normal file
153
var/www/modules/settings/templates/create_user.html
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Server Management - AIL</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{% include 'settings/menu_sidebar.html' %}
|
||||||
|
|
||||||
|
<div class="col-12 col-lg-10" id="core_content">
|
||||||
|
|
||||||
|
<form class="form-signin" action="{{ url_for('settings.create_user_post')}}" autocomplete="off" method="post">
|
||||||
|
|
||||||
|
<h1 class="h3 mt-1 mb-3 text-center text-secondary">Create User</h1>
|
||||||
|
<label for="inputEmail" class="sr-only">Email address</label>
|
||||||
|
<input type="email" id="inputEmail" name="username" class="form-control {% if error_mail %}is-invalid{% endif %}" placeholder="Email address" autocomplete="off" required {% if user_id %}value="{{user_id}}"{% else %}{% endif %}>
|
||||||
|
{% if error_mail %}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please provide a valid email address
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<label class="mt-3" for="role_selector">User Role</label>
|
||||||
|
<select class="custom-select" id="role_selector" name="user_role">
|
||||||
|
{% for role in all_roles %}
|
||||||
|
{% if role == user_role %}
|
||||||
|
<option value="{{role}}" selected>{{role}}</option>
|
||||||
|
{% else %}
|
||||||
|
<option value="{{role}}">{{role}}</option>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div class="custom-control custom-switch mt-4 mb-3">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="set_manual_password" value="" onclick="toggle_password_fields();">
|
||||||
|
<label class="custom-control-label" for="set_manual_password">Set Password</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="password-section">
|
||||||
|
<h1 class="h3 mb-3 text-center text-secondary">Create Password</h1>
|
||||||
|
<label for="inputPassword1" class="sr-only">Password</label>
|
||||||
|
<input type="password" id="inputPassword1" name="password1" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Password" autocomplete="new-password">
|
||||||
|
<label for="inputPassword2" class="sr-only">Confirm Password</label>
|
||||||
|
<input type="password" id="inputPassword2" name="password2" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Confirm Password" value="" autocomplete="new-password">
|
||||||
|
{% if error %}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{error}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit">Submit</button>
|
||||||
|
|
||||||
|
<div id="password-section-info">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h5 class="h3 mb-3 text-center text-secondary">Password Requirements</h5>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Minimal length
|
||||||
|
<span class="badge badge-primary badge-pill">10</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Upper characters: A-Z
|
||||||
|
<span class="badge badge-primary badge-pill">1</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Lower characters: a-z
|
||||||
|
<span class="badge badge-primary badge-pill">1</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Digits: 0-9
|
||||||
|
<span class="badge badge-primary badge-pill">2</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Maximum length
|
||||||
|
<span class="badge badge-primary badge-pill">100</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#password-section").hide();
|
||||||
|
$("#password-section-info").hide();
|
||||||
|
$("#nav_create_user").addClass("active");
|
||||||
|
$("#nav_user_management").removeClass("text-muted");
|
||||||
|
|
||||||
|
{% if error %}
|
||||||
|
toggle_password_fields();
|
||||||
|
{% endif %}
|
||||||
|
} );
|
||||||
|
|
||||||
|
function toggle_sidebar(){
|
||||||
|
if($('#nav_menu').is(':visible')){
|
||||||
|
$('#nav_menu').hide();
|
||||||
|
$('#side_menu').removeClass('border-right')
|
||||||
|
$('#side_menu').removeClass('col-lg-2')
|
||||||
|
$('#core_content').removeClass('col-lg-10')
|
||||||
|
}else{
|
||||||
|
$('#nav_menu').show();
|
||||||
|
$('#side_menu').addClass('border-right')
|
||||||
|
$('#side_menu').addClass('col-lg-2')
|
||||||
|
$('#core_content').addClass('col-lg-10')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle_password_fields() {
|
||||||
|
var password_div = $("#password-section");
|
||||||
|
if(password_div.is(":visible")){
|
||||||
|
$("#password-section").hide();
|
||||||
|
$("#password-section-info").hide();
|
||||||
|
$("#inputPassword1").prop('required',false);
|
||||||
|
$("#inputPassword2").prop('required',false);
|
||||||
|
} else {
|
||||||
|
$("#password-section").show();
|
||||||
|
$("#password-section-info").show();
|
||||||
|
$("#inputPassword1").prop('required',true);
|
||||||
|
$("#inputPassword2").prop('required',true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
96
var/www/modules/settings/templates/edit_profile.html
Normal file
96
var/www/modules/settings/templates/edit_profile.html
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Server Management - AIL</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{% include 'settings/menu_sidebar.html' %}
|
||||||
|
|
||||||
|
<div class="col-12 col-lg-10" id="core_content">
|
||||||
|
|
||||||
|
<div class="card mb-3 mt-1">
|
||||||
|
<div class="card-header text-white bg-dark pb-1">
|
||||||
|
<h5 class="card-title">My Profile :</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="card text-center border-secondary">
|
||||||
|
<div class="card-body px-1 py-0">
|
||||||
|
<table class="table table-sm">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Email</td>
|
||||||
|
<td>{{user_metadata['email']}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Role</td>
|
||||||
|
<td>{{user_metadata['role']}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>API Key</td>
|
||||||
|
<td>
|
||||||
|
{{user_metadata['api_key']}}
|
||||||
|
<a class="ml-3" href="{{url_for('settings.new_token')}}"><i class="fa fa-random"></i></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#nav_edit_profile").addClass("active");
|
||||||
|
$("#nav_my_profile").removeClass("text-muted");
|
||||||
|
} );
|
||||||
|
|
||||||
|
function toggle_sidebar(){
|
||||||
|
if($('#nav_menu').is(':visible')){
|
||||||
|
$('#nav_menu').hide();
|
||||||
|
$('#side_menu').removeClass('border-right')
|
||||||
|
$('#side_menu').removeClass('col-lg-2')
|
||||||
|
$('#core_content').removeClass('col-lg-10')
|
||||||
|
}else{
|
||||||
|
$('#nav_menu').show();
|
||||||
|
$('#side_menu').addClass('border-right')
|
||||||
|
$('#side_menu').addClass('col-lg-2')
|
||||||
|
$('#core_content').addClass('col-lg-10')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
|
@ -142,7 +142,8 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#page-options").addClass("active");
|
$("#nav_server_status").addClass("active");
|
||||||
|
$("#nav_server").removeClass("text-muted");
|
||||||
} );
|
} );
|
||||||
|
|
||||||
function toggle_sidebar(){
|
function toggle_sidebar(){
|
||||||
|
@ -191,6 +192,7 @@ update_progress();
|
||||||
var progress_interval = setInterval(function(){
|
var progress_interval = setInterval(function(){
|
||||||
update_progress()
|
update_progress()
|
||||||
}, 4000);
|
}, 4000);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
122
var/www/modules/settings/templates/users_list.html
Normal file
122
var/www/modules/settings/templates/users_list.html
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Server Management - AIL</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.edit_icon:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
color: #17a2b8;
|
||||||
|
}
|
||||||
|
.trash_icon:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
color: #c82333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{% include 'settings/menu_sidebar.html' %}
|
||||||
|
|
||||||
|
<div class="col-12 col-lg-10" id="core_content">
|
||||||
|
|
||||||
|
{% if new_user %}
|
||||||
|
<div class="text-center my-3 ">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
{% if new_user['edited']=='True' %}
|
||||||
|
<h5 class="card-title">User Edited</h5>
|
||||||
|
{% else %}
|
||||||
|
<h5 class="card-title">User Created</h5>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>User: {{new_user['email']}}</p>
|
||||||
|
<p>Password: {{new_user['password']}}</p>
|
||||||
|
<a href="{{url_for('settings.users_list')}}" class="btn btn-primary"><i class="fas fa-eye-slash"></i> Hide</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="table-responsive mt-1 table-hover table-borderless table-striped">
|
||||||
|
<table class="table">
|
||||||
|
<thead class="thead-dark">
|
||||||
|
<tr>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Role</th>
|
||||||
|
<th>Api Key</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody_last_crawled">
|
||||||
|
{% for user in all_users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{user['email']}}</td>
|
||||||
|
<td>{{user['role']}}</td>
|
||||||
|
<td>
|
||||||
|
{{user['api_key']}}
|
||||||
|
<a class="ml-3" href="{{url_for('settings.new_token_user')}}?user_id={{user['email']}}"><i class="fa fa-random"></i></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('settings.edit_user')}}?user_id={{user['email']}}">
|
||||||
|
<i class="fas fa-pencil-alt edit_icon"></i>
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('settings.delete_user')}}?user_id={{user['email']}}" class="ml-4">
|
||||||
|
<i class="fas fa-trash-alt trash_icon"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#nav_users_list").addClass("active");
|
||||||
|
$("#nav_user_management").removeClass("text-muted");
|
||||||
|
} );
|
||||||
|
|
||||||
|
function toggle_sidebar(){
|
||||||
|
if($('#nav_menu').is(':visible')){
|
||||||
|
$('#nav_menu').hide();
|
||||||
|
$('#side_menu').removeClass('border-right')
|
||||||
|
$('#side_menu').removeClass('col-lg-2')
|
||||||
|
$('#core_content').removeClass('col-lg-10')
|
||||||
|
}else{
|
||||||
|
$('#nav_menu').show();
|
||||||
|
$('#side_menu').addClass('border-right')
|
||||||
|
$('#side_menu').addClass('col-lg-2')
|
||||||
|
$('#core_content').addClass('col-lg-10')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
|
@ -9,6 +9,10 @@ import json
|
||||||
import os
|
import os
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, make_response, Response, send_from_directory, redirect, url_for
|
from flask import Flask, render_template, jsonify, request, Blueprint, make_response, Response, send_from_directory, redirect, url_for
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import difflib
|
import difflib
|
||||||
import ssdeep
|
import ssdeep
|
||||||
|
|
||||||
|
@ -380,16 +384,22 @@ def show_item_min(requested_path , content_range=0):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@showsavedpastes.route("/showsavedpaste/") #completely shows the paste in a new tab
|
@showsavedpastes.route("/showsavedpaste/") #completely shows the paste in a new tab
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showsavedpaste():
|
def showsavedpaste():
|
||||||
requested_path = request.args.get('paste', '')
|
requested_path = request.args.get('paste', '')
|
||||||
return showpaste(0, requested_path)
|
return showpaste(0, requested_path)
|
||||||
|
|
||||||
@showsavedpastes.route("/showsaveditem_min/") #completely shows the paste in a new tab
|
@showsavedpastes.route("/showsaveditem_min/") #completely shows the paste in a new tab
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showsaveditem_min():
|
def showsaveditem_min():
|
||||||
requested_path = request.args.get('paste', '')
|
requested_path = request.args.get('paste', '')
|
||||||
return show_item_min(requested_path)
|
return show_item_min(requested_path)
|
||||||
|
|
||||||
@showsavedpastes.route("/showsavedrawpaste/") #shows raw
|
@showsavedpastes.route("/showsavedrawpaste/") #shows raw
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showsavedrawpaste():
|
def showsavedrawpaste():
|
||||||
requested_path = request.args.get('paste', '')
|
requested_path = request.args.get('paste', '')
|
||||||
paste = Paste.Paste(requested_path)
|
paste = Paste.Paste(requested_path)
|
||||||
|
@ -397,6 +407,8 @@ def showsavedrawpaste():
|
||||||
return Response(content, mimetype='text/plain')
|
return Response(content, mimetype='text/plain')
|
||||||
|
|
||||||
@showsavedpastes.route("/showpreviewpaste/")
|
@showsavedpastes.route("/showpreviewpaste/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showpreviewpaste():
|
def showpreviewpaste():
|
||||||
num = request.args.get('num', '')
|
num = request.args.get('num', '')
|
||||||
requested_path = request.args.get('paste', '')
|
requested_path = request.args.get('paste', '')
|
||||||
|
@ -404,6 +416,8 @@ def showpreviewpaste():
|
||||||
|
|
||||||
|
|
||||||
@showsavedpastes.route("/getmoredata/")
|
@showsavedpastes.route("/getmoredata/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def getmoredata():
|
def getmoredata():
|
||||||
requested_path = request.args.get('paste', '')
|
requested_path = request.args.get('paste', '')
|
||||||
paste = Paste.Paste(requested_path)
|
paste = Paste.Paste(requested_path)
|
||||||
|
@ -412,6 +426,8 @@ def getmoredata():
|
||||||
return to_return
|
return to_return
|
||||||
|
|
||||||
@showsavedpastes.route("/showDiff/")
|
@showsavedpastes.route("/showDiff/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def showDiff():
|
def showDiff():
|
||||||
s1 = request.args.get('s1', '')
|
s1 = request.args.get('s1', '')
|
||||||
s2 = request.args.get('s2', '')
|
s2 = request.args.get('s2', '')
|
||||||
|
@ -428,10 +444,14 @@ def showDiff():
|
||||||
return the_html
|
return the_html
|
||||||
|
|
||||||
@showsavedpastes.route('/screenshot/<path:filename>')
|
@showsavedpastes.route('/screenshot/<path:filename>')
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def screenshot(filename):
|
def screenshot(filename):
|
||||||
return send_from_directory(SCREENSHOT_FOLDER, filename+'.png', as_attachment=True)
|
return send_from_directory(SCREENSHOT_FOLDER, filename+'.png', as_attachment=True)
|
||||||
|
|
||||||
@showsavedpastes.route('/send_file_to_vt/', methods=['POST'])
|
@showsavedpastes.route('/send_file_to_vt/', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def send_file_to_vt():
|
def send_file_to_vt():
|
||||||
b64_path = request.form['b64_path']
|
b64_path = request.form['b64_path']
|
||||||
paste = request.form['paste']
|
paste = request.form['paste']
|
||||||
|
|
|
@ -11,6 +11,10 @@ import datetime
|
||||||
import calendar
|
import calendar
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint, url_for, redirect
|
from flask import Flask, render_template, jsonify, request, Blueprint, url_for, redirect
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import Paste
|
import Paste
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
@ -143,6 +147,8 @@ def save_tag_to_auto_push(list_tag):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@terms.route("/terms_management/")
|
@terms.route("/terms_management/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_management():
|
def terms_management():
|
||||||
per_paste = request.args.get('per_paste')
|
per_paste = request.args.get('per_paste')
|
||||||
if per_paste == "1" or per_paste is None:
|
if per_paste == "1" or per_paste is None:
|
||||||
|
@ -261,6 +267,8 @@ def terms_management():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_management_query_paste/")
|
@terms.route("/terms_management_query_paste/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_management_query_paste():
|
def terms_management_query_paste():
|
||||||
term = request.args.get('term')
|
term = request.args.get('term')
|
||||||
paste_info = []
|
paste_info = []
|
||||||
|
@ -293,6 +301,8 @@ def terms_management_query_paste():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_management_query/")
|
@terms.route("/terms_management_query/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_management_query():
|
def terms_management_query():
|
||||||
TrackedTermsDate_Name = "TrackedTermDate"
|
TrackedTermsDate_Name = "TrackedTermDate"
|
||||||
BlackListTermsDate_Name = "BlackListTermDate"
|
BlackListTermsDate_Name = "BlackListTermDate"
|
||||||
|
@ -315,6 +325,8 @@ def terms_management_query():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_management_action/", methods=['GET'])
|
@terms.route("/terms_management_action/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_management_action():
|
def terms_management_action():
|
||||||
today = datetime.datetime.now()
|
today = datetime.datetime.now()
|
||||||
today = today.replace(microsecond=0)
|
today = today.replace(microsecond=0)
|
||||||
|
@ -440,6 +452,8 @@ def terms_management_action():
|
||||||
return jsonify(to_return)
|
return jsonify(to_return)
|
||||||
|
|
||||||
@terms.route("/terms_management/delete_terms_tags", methods=['POST'])
|
@terms.route("/terms_management/delete_terms_tags", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def delete_terms_tags():
|
def delete_terms_tags():
|
||||||
term = request.form.get('term')
|
term = request.form.get('term')
|
||||||
tags_to_delete = request.form.getlist('tags_to_delete')
|
tags_to_delete = request.form.getlist('tags_to_delete')
|
||||||
|
@ -452,6 +466,8 @@ def delete_terms_tags():
|
||||||
return 'None args', 400
|
return 'None args', 400
|
||||||
|
|
||||||
@terms.route("/terms_management/delete_terms_email", methods=['GET'])
|
@terms.route("/terms_management/delete_terms_email", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def delete_terms_email():
|
def delete_terms_email():
|
||||||
term = request.args.get('term')
|
term = request.args.get('term')
|
||||||
email = request.args.get('email')
|
email = request.args.get('email')
|
||||||
|
@ -464,6 +480,8 @@ def delete_terms_email():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_plot_tool/")
|
@terms.route("/terms_plot_tool/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_plot_tool():
|
def terms_plot_tool():
|
||||||
term = request.args.get('term')
|
term = request.args.get('term')
|
||||||
if term is not None:
|
if term is not None:
|
||||||
|
@ -473,6 +491,8 @@ def terms_plot_tool():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_plot_tool_data/")
|
@terms.route("/terms_plot_tool_data/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_plot_tool_data():
|
def terms_plot_tool_data():
|
||||||
oneDay = 60*60*24
|
oneDay = 60*60*24
|
||||||
range_start = datetime.datetime.utcfromtimestamp(int(float(request.args.get('range_start')))) if request.args.get('range_start') is not None else 0;
|
range_start = datetime.datetime.utcfromtimestamp(int(float(request.args.get('range_start')))) if request.args.get('range_start') is not None else 0;
|
||||||
|
@ -503,6 +523,8 @@ def terms_plot_tool_data():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_plot_top/")
|
@terms.route("/terms_plot_top/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_plot_top():
|
def terms_plot_top():
|
||||||
per_paste = request.args.get('per_paste')
|
per_paste = request.args.get('per_paste')
|
||||||
per_paste = per_paste if per_paste is not None else 1
|
per_paste = per_paste if per_paste is not None else 1
|
||||||
|
@ -510,6 +532,8 @@ def terms_plot_top():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/terms_plot_top_data/")
|
@terms.route("/terms_plot_top_data/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def terms_plot_top_data():
|
def terms_plot_top_data():
|
||||||
oneDay = 60*60*24
|
oneDay = 60*60*24
|
||||||
today = datetime.datetime.now()
|
today = datetime.datetime.now()
|
||||||
|
@ -556,10 +580,14 @@ def terms_plot_top_data():
|
||||||
|
|
||||||
|
|
||||||
@terms.route("/credentials_tracker/")
|
@terms.route("/credentials_tracker/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def credentials_tracker():
|
def credentials_tracker():
|
||||||
return render_template("credentials_tracker.html")
|
return render_template("credentials_tracker.html")
|
||||||
|
|
||||||
@terms.route("/credentials_management_query_paste/", methods=['GET', 'POST'])
|
@terms.route("/credentials_management_query_paste/", methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def credentials_management_query_paste():
|
def credentials_management_query_paste():
|
||||||
cred = request.args.get('cred')
|
cred = request.args.get('cred')
|
||||||
allPath = request.json['allPath']
|
allPath = request.json['allPath']
|
||||||
|
@ -583,6 +611,8 @@ def credentials_management_query_paste():
|
||||||
return jsonify(paste_info)
|
return jsonify(paste_info)
|
||||||
|
|
||||||
@terms.route("/credentials_management_action/", methods=['GET'])
|
@terms.route("/credentials_management_action/", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def cred_management_action():
|
def cred_management_action():
|
||||||
|
|
||||||
supplied = request.args.get('term')
|
supplied = request.args.get('term')
|
||||||
|
|
|
@ -10,6 +10,9 @@ from Date import Date
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
from flask import Flask, render_template, jsonify, request, Blueprint
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
@ -36,6 +39,8 @@ def get_date_range(num_day):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@trendings.route("/_progressionCharts", methods=['GET'])
|
@trendings.route("/_progressionCharts", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def progressionCharts():
|
def progressionCharts():
|
||||||
attribute_name = request.args.get('attributeName')
|
attribute_name = request.args.get('attributeName')
|
||||||
trending_name = request.args.get('trendingName')
|
trending_name = request.args.get('trendingName')
|
||||||
|
@ -61,18 +66,24 @@ def progressionCharts():
|
||||||
return jsonify(keyw_value)
|
return jsonify(keyw_value)
|
||||||
|
|
||||||
@trendings.route("/wordstrending/")
|
@trendings.route("/wordstrending/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def wordstrending():
|
def wordstrending():
|
||||||
default_display = cfg.get("Flask", "default_display")
|
default_display = cfg.get("Flask", "default_display")
|
||||||
return render_template("Wordstrending.html", default_display = default_display)
|
return render_template("Wordstrending.html", default_display = default_display)
|
||||||
|
|
||||||
|
|
||||||
@trendings.route("/protocolstrending/")
|
@trendings.route("/protocolstrending/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def protocolstrending():
|
def protocolstrending():
|
||||||
default_display = cfg.get("Flask", "default_display")
|
default_display = cfg.get("Flask", "default_display")
|
||||||
return render_template("Protocolstrending.html", default_display = default_display)
|
return render_template("Protocolstrending.html", default_display = default_display)
|
||||||
|
|
||||||
|
|
||||||
@trendings.route("/trending/")
|
@trendings.route("/trending/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def trending():
|
def trending():
|
||||||
default_display = cfg.get("Flask", "default_display")
|
default_display = cfg.get("Flask", "default_display")
|
||||||
return render_template("Trending.html", default_display = default_display)
|
return render_template("Trending.html", default_display = default_display)
|
||||||
|
|
|
@ -10,6 +10,9 @@ from Date import Date
|
||||||
import flask
|
import flask
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
from flask import Flask, render_template, jsonify, request, Blueprint
|
||||||
|
|
||||||
|
from Role_Manager import login_admin, login_analyst
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
@ -49,6 +52,8 @@ def get_date_range(num_day):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@trendingmodules.route("/_moduleCharts", methods=['GET'])
|
@trendingmodules.route("/_moduleCharts", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def modulesCharts():
|
def modulesCharts():
|
||||||
keyword_name = request.args.get('keywordName')
|
keyword_name = request.args.get('keywordName')
|
||||||
module_name = request.args.get('moduleName')
|
module_name = request.args.get('moduleName')
|
||||||
|
@ -75,6 +80,8 @@ def modulesCharts():
|
||||||
|
|
||||||
|
|
||||||
@trendingmodules.route("/_providersChart", methods=['GET'])
|
@trendingmodules.route("/_providersChart", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def providersChart():
|
def providersChart():
|
||||||
keyword_name = request.args.get('keywordName')
|
keyword_name = request.args.get('keywordName')
|
||||||
module_name = request.args.get('moduleName')
|
module_name = request.args.get('moduleName')
|
||||||
|
@ -121,6 +128,8 @@ def providersChart():
|
||||||
|
|
||||||
|
|
||||||
@trendingmodules.route("/moduletrending/")
|
@trendingmodules.route("/moduletrending/")
|
||||||
|
@login_required
|
||||||
|
@login_analyst
|
||||||
def moduletrending():
|
def moduletrending():
|
||||||
return render_template("Moduletrending.html")
|
return render_template("Moduletrending.html")
|
||||||
|
|
||||||
|
|
108
var/www/templates/change_password.html
Normal file
108
var/www/templates/change_password.html
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>AIL-Framework</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png')}}">
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 40px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-signin {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 330px;
|
||||||
|
padding: 15px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.form-signin .checkbox {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.form-signin .form-control {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: auto;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.form-signin .form-control:focus {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.form-signin input[type="password"] {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="text-center">
|
||||||
|
|
||||||
|
|
||||||
|
<form class="form-signin" action="{{ url_for('change_password')}}" autocomplete="off" method="post">
|
||||||
|
<img class="mb-4" src="{{ url_for('static', filename='image/AIL-logo.png')}}" width="300">
|
||||||
|
<h1 class="h3 mb-3 text-secondary">Change Password</h1>
|
||||||
|
<label for="inputPassword1" class="sr-only">Password</label>
|
||||||
|
<input type="password" id="inputPassword1" name="password1" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Password" autocomplete="new-password" required autofocus>
|
||||||
|
<label for="inputPassword2" class="sr-only">Confirm Password</label>
|
||||||
|
<input type="password" id="inputPassword2" name="password2" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Confirm Password" value="" autocomplete="new-password" required>
|
||||||
|
{% if error %}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{error}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-lg btn-primary btn-block" type="submit">Submit</button>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h5 class="h3 mb-3 text-secondary">Password Requirements</h5>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Minimal length
|
||||||
|
<span class="badge badge-primary badge-pill">10</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Upper characters: A-Z
|
||||||
|
<span class="badge badge-primary badge-pill">1</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Lower characters: a-z
|
||||||
|
<span class="badge badge-primary badge-pill">1</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Digits: 0-9
|
||||||
|
<span class="badge badge-primary badge-pill">2</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Maximum length
|
||||||
|
<span class="badge badge-primary badge-pill">100</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
50
var/www/templates/error/403.html
Normal file
50
var/www/templates/error/403.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>403 - AIL</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h1 class="text-center">403 Forbidden</h1>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<pre>
|
||||||
|
,d8 ,a8888a, ad888888b,
|
||||||
|
,d888 ,8P"' `"Y8, d8" "88
|
||||||
|
,d8" 88 ,8P Y8, a8P
|
||||||
|
,d8" 88 88 88 aad8"
|
||||||
|
,d8" 88 88 88 ""Y8,
|
||||||
|
8888888888888 `8b d8' "8b
|
||||||
|
88 `8ba, ,ad8' Y8, a88
|
||||||
|
88 "Y8888P" "Y888888P'
|
||||||
|
|
||||||
|
88888888888 88 88 88 88
|
||||||
|
88 88 "" 88 88
|
||||||
|
88 88 88 88
|
||||||
|
88aaaaa ,adPPYba, 8b,dPPYba, 88,dPPYba, 88 ,adPPYb,88 ,adPPYb,88 ,adPPYba, 8b,dPPYba,
|
||||||
|
88""""" a8" "8a 88P' "Y8 88P' "8a 88 a8" `Y88 a8" `Y88 a8P_____88 88P' `"8a
|
||||||
|
88 8b d8 88 88 d8 88 8b 88 8b 88 8PP""""""" 88 88
|
||||||
|
88 "8a, ,a8" 88 88b, ,a8" 88 "8a, ,d88 "8a, ,d88 "8b, ,aa 88 88
|
||||||
|
88 `"YbbdP"' 88 8Y"Ybbd8"' 88 `"8bbdP"Y8 `"8bbdP"Y8 `"Ybbd8"' 88 88
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</html>
|
41
var/www/templates/error/404.html
Normal file
41
var/www/templates/error/404.html
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>404 - AIL</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include 'nav_bar.html' %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h1 class="text-center">404 Not Found</h1>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<pre>
|
||||||
|
,d8 ,a8888a, ,d8
|
||||||
|
,d888 ,8P"' `"Y8, ,d888
|
||||||
|
,d8" 88 ,8P Y8, ,d8" 88
|
||||||
|
,d8" 88 88 88 ,d8" 88
|
||||||
|
,d8" 88 88 88 ,d8" 88
|
||||||
|
8888888888888 `8b d8' 8888888888888
|
||||||
|
88 `8ba, ,ad8' 88
|
||||||
|
88 "Y8888P" 88
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</html>
|
85
var/www/templates/login.html
Normal file
85
var/www/templates/login.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>AIL-Framework</title>
|
||||||
|
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png')}}">
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 40px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-signin {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 330px;
|
||||||
|
padding: 15px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.form-signin .checkbox {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.form-signin .form-control {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: auto;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.form-signin .form-control:focus {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.form-signin input[type="email"] {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
.form-signin input[type="password"] {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="text-center">
|
||||||
|
|
||||||
|
|
||||||
|
<form class="form-signin" action="{{ url_for('login')}}" method="post">
|
||||||
|
<img class="mb-4" src="{{ url_for('static', filename='image/AIL-logo.png')}}" width="300">
|
||||||
|
<h1 class="h3 mb-3 text-secondary">Please sign in</h1>
|
||||||
|
<label for="inputEmail" class="sr-only">Email address</label>
|
||||||
|
<input type="email" id="inputEmail" name="username" class="form-control" placeholder="Email address" required autofocus>
|
||||||
|
<label for="inputPassword" class="sr-only">Password</label>
|
||||||
|
<input type="password" id="inputPassword" name="password" class="form-control {% if error %}is-invalid{% endif %}" placeholder="Password" required>
|
||||||
|
{% if error %}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{error}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
|
@ -33,6 +33,9 @@
|
||||||
<li class="nav-item mr-3">
|
<li class="nav-item mr-3">
|
||||||
<a class="nav-link" id="page-options" href="{{ url_for('settings.settings_page') }}" aria-disabled="true"><i class="fas fa-cog"></i> Server Management</a>
|
<a class="nav-link" id="page-options" href="{{ url_for('settings.settings_page') }}" aria-disabled="true"><i class="fas fa-cog"></i> Server Management</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item mr-3">
|
||||||
|
<a class="nav-link" id="page-options" href="{{ url_for('logout') }}" aria-disabled="true"><i class="fas fa-sign-out-alt"></i> Log Out</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<form class="form-inline my-2 my-lg-0 ml-auto justify-content-center" action="{{ url_for('searches.search') }}" method=POST>
|
<form class="form-inline my-2 my-lg-0 ml-auto justify-content-center" action="{{ url_for('searches.search') }}" method=POST>
|
||||||
|
|
|
@ -1,13 +1,58 @@
|
||||||
<div class="col-12 col-lg-2 p-0 bg-light border-right" id="side_menu">
|
<div class="col-12 col-lg-2 p-0 bg-light border-right" id="side_menu">
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-secondary mt-1 ml-3" onclick="toggle_sidebar()">
|
<button type="button" class="btn btn-outline-secondary mt-1 ml-3" onclick="toggle_sidebar();">
|
||||||
<i class="fas fa-align-left"></i>
|
<i class="fas fa-align-left"></i>
|
||||||
<span>Toggle Sidebar</span>
|
<span>Toggle Sidebar</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-light flex-md-column flex-row align-items-start py-2" id="nav_menu">
|
<nav class="navbar navbar-expand navbar-light bg-light flex-md-column flex-row align-items-start py-2" id="nav_menu">
|
||||||
<h5 class="d-flex text-muted w-100">
|
<h5 class="d-flex text-muted w-100" id="nav_server">
|
||||||
<span>Diagnostic</span>
|
<span>Diagnostic</span>
|
||||||
</h5>
|
</h5>
|
||||||
</nav>
|
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100"> <!--nav-pills-->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url_for('settings.settings_page')}}" id="nav_server_status">
|
||||||
|
<i class="fas fa-tools"></i>
|
||||||
|
<span>Server Status</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h5 class="d-flex text-muted w-100 py-2" id="nav_my_profile">
|
||||||
|
<span>My Profile</span>
|
||||||
|
</h5>
|
||||||
|
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100"> <!--nav-pills-->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url_for('settings.edit_profile')}}" id="nav_edit_profile">
|
||||||
|
<i class="fas fa-user-edit"></i>
|
||||||
|
<span>My Profile</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url_for('change_password')}}" id="nav_dashboard">
|
||||||
|
<i class="fas fa-key"></i>
|
||||||
|
<span>Change Password</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% if admin_level %}
|
||||||
|
<h5 class="d-flex text-muted w-100 py-2" id="nav_user_management">
|
||||||
|
<span>User Management</span>
|
||||||
|
</h5>
|
||||||
|
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100"> <!--nav-pills-->
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url_for('settings.create_user')}}" id="nav_create_user">
|
||||||
|
<i class="fas fa-user-plus"></i>
|
||||||
|
<span>Create User</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{url_for('settings.users_list')}}" id="nav_users_list">
|
||||||
|
<i class="fas fa-users"></i>
|
||||||
|
<span>Users List</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -102,6 +102,7 @@ rm -rf temp
|
||||||
mkdir -p ./static/image
|
mkdir -p ./static/image
|
||||||
pushd static/image
|
pushd static/image
|
||||||
wget -q https://www.circl.lu/assets/images/logos/AIL.png -O AIL.png
|
wget -q https://www.circl.lu/assets/images/logos/AIL.png -O AIL.png
|
||||||
|
wget -q https://www.circl.lu/assets/images/logos/AIL-logo.png -O AIL-logo.png
|
||||||
popd
|
popd
|
||||||
|
|
||||||
if ! [[ -n "$AIL_HOME" ]]
|
if ! [[ -n "$AIL_HOME" ]]
|
||||||
|
|
Loading…
Reference in a new issue