Skip to content

Commit

Permalink
adding hashing functions and users db functions as prep work for allo…
Browse files Browse the repository at this point in the history
…wing multiusers
  • Loading branch information
Naor Livne committed Mar 7, 2019
1 parent 5f10f63 commit 3060c0d
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ can help

* Fork the latest branch of the component you want to contribute to
* Make sure you have a [GitHub account](https://github.com/signup/free)
* Use virtualenv to install all requirements from the requirements.txt file, this may require having GCC compiler depending on your environment setup due to gevent requiring compilation on some OS.
* Use virtualenv to install all requirements from the requirements.txt file, this may require having GCC compiler & libffi-dev depending on your environment setup due to gevent & bcrypt requiring compilation on some OS.
* Fix the issue you want \ add a feature
* Make sure the unittests pass, you will need to have a running mongo to test them against, the following script will allow you to easily start one: test/travis_ci_scripts/travis_ci_build_script.sh
* Create a pull request
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ COPY . /www
RUN chmod +x /www/manager.py

# install required packages - requires build-base due to gevent GCC complier requirements
RUN apk add --no-cache build-base
RUN apk add --no-cache build-base libffi-dev
RUN pip install -r /www/requirements.txt

# adding the gunicorn config
Expand Down
53 changes: 52 additions & 1 deletion functions/db/mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ def __init__(self, mongo_connection_string, schema_name="nebula", max_pool_size=
self.collection_apps = self.db["nebula_apps"]
self.collection_device_groups = self.db["nebula_device_groups"]
self.collection_reports = self.db["nebula_reports"]
self.collection_users = self.db["nebula_users"]
except Exception as e:
print("error connection to mongodb")
print(e, file=sys.stderr)
os._exit(2)

# create indexes
def mongo_create_indexes(self, app_index_name, device_groups_index_name):
def mongo_create_indexes(self, app_index_name, device_groups_index_name, users_index_name):
try:
self.collection_apps.create_index([(app_index_name, ASCENDING)], background=True,
name=app_index_name + "_index", unique=True, sparse=True)
self.collection_device_groups.create_index([(device_groups_index_name, ASCENDING)], background=True,
name=device_groups_index_name + "_index", unique=True,
sparse=True)
self.collection_users.create_index([(users_index_name, ASCENDING)], background=True,
name=users_index_name + "_index", unique=True, sparse=True)
except Exception as e:
print("error creating mongodb indexes")
print(e, file=sys.stderr)
Expand Down Expand Up @@ -254,3 +257,51 @@ def mango_list_paginated_filtered_reports(self, page_size=10, last_id=None, filt

# Return data and last_id
return data, last_id

# list all users
def mongo_list_users(self):
users_list = []
for user in self.collection_users.find({"user_name": {"$exists": "true"}}, {'_id': False}):
users_list.append(user["user_name"])
return users_list

# check if user exists
def mongo_check_user_exists(self, user_name):
result, ignored = self.mongo_get_user(user_name)
return result

# get user info - the password and\or token are returned hashed for security reasons
def mongo_get_user(self, user_name):
result = self.collection_users.find_one({"user_name": user_name}, {'_id': False})
if result is None:
user_exists = False
else:
user_exists = True
return user_exists, result

# delete a user
def mongo_delete_user(self, user_name):
result = self.collection_users.delete_one({"user_name": user_name})
return result

# create a user - make sure to hash the password & token before using this function as it does not hash anything on
# it's own
def mongo_add_user(self, user_name, password, token):
user_doc = {
"user_name": user_name,
"hashed_password": password,
"hashed_token": token
}
insert_id = self.collection_users.insert_one(user_doc).inserted_id
ignored_device_group_existence_status, result = self.mongo_get_user(user_name)
return result

# update a user - make sure to hash the password & token before using this function as it does not hash anything on
# it's own
def mongo_update_user(self, user_name, update_fields_dict):
result = self.collection_users.find_one_and_update({'user_name': user_name},
{'$inc': {'app_id': 1},
'$set': update_fields_dict},
return_document=ReturnDocument.AFTER)
return result

13 changes: 13 additions & 0 deletions functions/hashing/hashing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import bcrypt


def hash_secret(value_to_hash):
hashed_secret = bcrypt.hashpw(value_to_hash.encode('utf-8'), bcrypt.gensalt())
return hashed_secret


def check_secret_matches(value_to_check, hashed_value):
if bcrypt.checkpw(value_to_check.encode('utf-8'), hashed_value):
return True
else:
return False
3 changes: 2 additions & 1 deletion manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask import json, Flask, request, g
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth
from functions.db.mongo import *
from functions.hashing.hashing import *
from bson.json_util import dumps
from cachetools import cached, TTLCache
from retrying import retry
Expand Down Expand Up @@ -114,7 +115,7 @@ def get_param_filter(param_name, full_request, filter_param="eq", request_type=s
print("opened MongoDB connection")

# ensure mongo is indexed properly
mongo_connection.mongo_create_indexes("app_name", "device_group")
mongo_connection.mongo_create_indexes("app_name", "device_group", "users")

# get current list of apps at startup
nebula_apps = mongo_connection.mongo_list_apps()
Expand Down
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
backports.ssl-match-hostname==3.5.0.1
bcrypt==3.1.6
cachetools==3.1.0
certifi==2018.11.29
cffi==1.12.2
chardet==3.0.4
Click==7.0
colorama==0.4.1
Expand All @@ -17,6 +19,7 @@ ipaddress==1.0.22
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.0
pycparser==2.19
pymongo==3.7.2
requests==2.21.0
retrying==1.3.3
Expand Down
17 changes: 17 additions & 0 deletions test/test_nebula_python_manager_functions_hashing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from unittest import TestCase
from functions.hashing.hashing import *


class MongoTests(TestCase):

def test_hashing_matches(self):
# check hashing compare right password works
test_hash = hash_secret("test")
secret_matches = check_secret_matches("test", test_hash)
self.assertTrue(secret_matches)

def test_hashing_does_not_matches(self):
# check hashing compare right password works
test_hash = hash_secret("test")
secret_matches = check_secret_matches("a_wrong_value", test_hash)
self.assertFalse(secret_matches)

0 comments on commit 3060c0d

Please sign in to comment.