mirror of https://github.com/CIRCL/AIL-framework
chg: [user_management] create + check user password
parent
1ab1a55a4f
commit
64ff94ce5f
12
OVERVIEW.md
12
OVERVIEW.md
|
@ -52,6 +52,18 @@ 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** |
|
||||||
|
|
||||||
|
##### User Management:
|
||||||
|
| Key | Field | Value |
|
||||||
|
| ------ | ------ | ------ |
|
||||||
|
| user:all | **user id** | **password hash** |
|
||||||
|
|
||||||
|
| Key | Value |
|
||||||
|
| ------ | ------ |
|
||||||
|
| user:request_password_change | **user id** |
|
||||||
|
| user:admin | **user id** |
|
||||||
|
| | |
|
||||||
|
| user_role:**role** | **user id** |
|
||||||
|
|
||||||
## DB2 - TermFreq:
|
## DB2 - TermFreq:
|
||||||
|
|
||||||
##### Set:
|
##### Set:
|
||||||
|
|
|
@ -1,36 +1,65 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*-coding:UTF-8 -*
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
import os
|
||||||
import redis
|
import redis
|
||||||
|
import bcrypt
|
||||||
|
import configparser
|
||||||
|
|
||||||
from flask_login import UserMixin
|
from flask_login import UserMixin
|
||||||
|
|
||||||
class User(UserMixin):
|
class User(UserMixin):
|
||||||
|
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
self.id = 'abcdef'
|
|
||||||
|
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
|
# return True or False
|
||||||
#def is_authenticated():
|
#def is_authenticated():
|
||||||
|
|
||||||
# return True or False
|
|
||||||
#def is_active():
|
|
||||||
|
|
||||||
# return True or False
|
# return True or False
|
||||||
#def is_anonymous():
|
#def is_anonymous():
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(self_class, id):
|
def get(self_class, id):
|
||||||
print(id)
|
|
||||||
return self_class(id)
|
return self_class(id)
|
||||||
|
|
||||||
def check_password(self, password):
|
def check_password(self, password):
|
||||||
|
password = password.encode()
|
||||||
print(self.id)
|
print(self.id)
|
||||||
if password=='admin':
|
hashed_password = self.r_serv_db.hget('user:all', self.id).encode()
|
||||||
print('password ok')
|
if bcrypt.checkpw(password, hashed_password):
|
||||||
|
print('password correct')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_password(self):
|
def request_password_change(self):
|
||||||
return True
|
if self.r_serv_db.sismember('user:request_password_change', self.id):
|
||||||
|
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
|
||||||
|
|
|
@ -47,6 +47,7 @@ texttable
|
||||||
|
|
||||||
flask
|
flask
|
||||||
flask-login
|
flask-login
|
||||||
|
bcrypt
|
||||||
|
|
||||||
#DomainClassifier
|
#DomainClassifier
|
||||||
DomainClassifier
|
DomainClassifier
|
||||||
|
|
|
@ -11,6 +11,8 @@ import calendar
|
||||||
from flask import Flask, render_template, jsonify, request, Request, session, redirect, url_for
|
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
|
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
|
import os
|
||||||
|
@ -28,6 +30,41 @@ from pytaxonomies import Taxonomies
|
||||||
# Import config
|
# Import config
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
def flask_init():
|
||||||
|
int_user_management()
|
||||||
|
|
||||||
|
def int_user_management():
|
||||||
|
# # TODO: check for admin account
|
||||||
|
# check if an account exists
|
||||||
|
if not r_serv_db.hexists('user:all'):
|
||||||
|
password = 'admin@admin.test'
|
||||||
|
create_user_db('admin', password, default=True)
|
||||||
|
|
||||||
|
def hashing_password(bytes_password):
|
||||||
|
hashed = bcrypt.hashpw(bytes_password, bcrypt.gensalt())
|
||||||
|
return hashed
|
||||||
|
|
||||||
|
def verify_password(id, bytes_password):
|
||||||
|
hashed_password = r_serv_db.hget('user:all', id)
|
||||||
|
if bcrypt.checkpw(password, hashed):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_user_db(username_id , password, default=False):
|
||||||
|
## TODO: validate username
|
||||||
|
## TODO: validate password
|
||||||
|
|
||||||
|
if username_id == '__anonymous__':
|
||||||
|
## TODO: return 500
|
||||||
|
return 'ERROR'
|
||||||
|
|
||||||
|
password = password.encode()
|
||||||
|
password_hash = hashing_password(password)
|
||||||
|
r_serv_db.hset('user:all', username_id, password_hash)
|
||||||
|
if default:
|
||||||
|
r_serv_db.set('user:request_password_change', username_id)
|
||||||
|
|
||||||
# CONFIG #
|
# CONFIG #
|
||||||
cfg = Flask_config.cfg
|
cfg = Flask_config.cfg
|
||||||
baseUrl = cfg.get("Flask", "baseurl")
|
baseUrl = cfg.get("Flask", "baseurl")
|
||||||
|
@ -35,6 +72,20 @@ 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)
|
||||||
|
|
||||||
|
# ========= =========#
|
||||||
|
|
||||||
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
|
||||||
|
@ -152,6 +203,8 @@ def login():
|
||||||
#print(user.is_authenticated)
|
#print(user.is_authenticated)
|
||||||
if user and user.check_password(password):
|
if user and user.check_password(password):
|
||||||
login_user(user) ## TODO: use remember me ?
|
login_user(user) ## TODO: use remember me ?
|
||||||
|
#print(user.request_password_change())
|
||||||
|
print(user.is_active)
|
||||||
return redirect(url_for('dashboard.index'))
|
return redirect(url_for('dashboard.index'))
|
||||||
else:
|
else:
|
||||||
return 'incorrect password'
|
return 'incorrect password'
|
||||||
|
@ -167,7 +220,27 @@ def login():
|
||||||
@login_required
|
@login_required
|
||||||
def logout():
|
def logout():
|
||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for('dashboard.index'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
|
@app.route('/create_user')
|
||||||
|
@login_required
|
||||||
|
def create_user():
|
||||||
|
username = request.form.get('username')
|
||||||
|
password = request.form.get('password')
|
||||||
|
#role = request.form.get('role') ## TODO: create role
|
||||||
|
|
||||||
|
## TODO: validate username
|
||||||
|
## TODO: validate password
|
||||||
|
|
||||||
|
username = 'admin@admin.test'
|
||||||
|
password = 'admin'
|
||||||
|
|
||||||
|
if r_serv_db.hexists('user:all', username):
|
||||||
|
return 'this id is not available'
|
||||||
|
|
||||||
|
create_user_db(username, password)
|
||||||
|
|
||||||
|
return 'True'
|
||||||
|
|
||||||
|
|
||||||
@app.route('/searchbox/')
|
@app.route('/searchbox/')
|
||||||
|
@ -176,11 +249,6 @@ def searchbox():
|
||||||
|
|
||||||
|
|
||||||
# ========== 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')
|
||||||
|
@ -195,11 +263,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():
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*-coding:UTF-8 -*
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
|
||||||
|
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
def login_required(role="ANY"):
|
||||||
|
@wraps(role)
|
||||||
|
def decorated_view(*args, **kwargs):
|
||||||
|
if not current_user.is_authenticated:
|
||||||
|
return current_app.login_manager.unauthorized()
|
||||||
|
elif (not current_user.is_in_role(role)) and (role != "ANY"):
|
||||||
|
return login_manager.unauthorized()
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return decorated_view
|
|
@ -13,6 +13,7 @@ import flask
|
||||||
from Date import Date
|
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 flask_login import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
@ -109,10 +110,12 @@ def datetime_from_utc_to_local(utc_str):
|
||||||
# ============ ROUTES ============
|
# ============ ROUTES ============
|
||||||
|
|
||||||
@dashboard.route("/_logs")
|
@dashboard.route("/_logs")
|
||||||
|
@login_required
|
||||||
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
|
||||||
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 +157,13 @@ def get_last_logs_json():
|
||||||
|
|
||||||
|
|
||||||
@dashboard.route("/_stuff", methods=['GET'])
|
@dashboard.route("/_stuff", methods=['GET'])
|
||||||
|
@login_required
|
||||||
def stuff():
|
def stuff():
|
||||||
return jsonify(row1=get_queues(r_serv))
|
return jsonify(row1=get_queues(r_serv))
|
||||||
|
|
||||||
|
|
||||||
@dashboard.route("/")
|
@dashboard.route("/")
|
||||||
|
@login_required
|
||||||
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 flask_login import login_required
|
||||||
from Date import Date
|
from Date import Date
|
||||||
from HiddenServices import HiddenServices
|
from HiddenServices import HiddenServices
|
||||||
|
|
||||||
|
from Decorator import login_required
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
# ============ VARIABLES ============
|
||||||
import Flask_config
|
import Flask_config
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ list_types=['onion', 'regular']
|
||||||
dic_type_name={'onion':'Onion', 'regular':'Website'}
|
dic_type_name={'onion':'Onion', 'regular':'Website'}
|
||||||
|
|
||||||
# ============ FUNCTIONS ============
|
# ============ FUNCTIONS ============
|
||||||
|
|
||||||
def one():
|
def one():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -233,6 +236,7 @@ def delete_auto_crawler(url):
|
||||||
# ============= ROUTES ==============
|
# ============= ROUTES ==============
|
||||||
|
|
||||||
@hiddenServices.route("/crawlers/", methods=['GET'])
|
@hiddenServices.route("/crawlers/", methods=['GET'])
|
||||||
|
#@login_required(role="ADMIN")
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard():
|
def dashboard():
|
||||||
crawler_metadata_onion = get_crawler_splash_status('onion')
|
crawler_metadata_onion = get_crawler_splash_status('onion')
|
||||||
|
|
Loading…
Reference in New Issue