Skip to content

Commit

Permalink
Set up travis. Add unittest TestAppBase, which sets up the app and ad…
Browse files Browse the repository at this point in the history
…ds the admin user for further tests.
  • Loading branch information
VertexC committed Jun 26, 2019
1 parent 8484ca1 commit be0a982
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 4 deletions.
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Config file for automatic testing at travis-ci.org
sudo: true # http://docs.travis-ci.com/user/migrating-from-legacy/
language: python
python:
- 2.7
install:
- sudo ./travis_install.sh
- sudo ./tests/installTestDb.sh
script:
- nose2 -v
1 change: 1 addition & 0 deletions install/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ DATABASE_URI = '${config_db_uri}'
COLLECTOR_UDP_PORT = ${config_collector_udp}
COLLECTOR_SSL_PORT = ${config_collector_ssl}
NETWORK_INTERFACE = ${network_interface}
TESTING = False
" > "${dir}/../config.py"
echo "* Making necessary scripts executable (if they aren't already)"
chmod +x "${dir}/../bin/pipotd" "${dir}/../bin/create_image.sh" "${dir}/../../client/bin/chroot.sh" >> "$install_log" 2>&1
Expand Down
4 changes: 3 additions & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ def install_secret_keys(application, secret_session='secret_key',
if do_exit:
sys.exit(1)

install_secret_keys(app)

if not app.config['TESTING']:
install_secret_keys(app)


# Expose submenu method for jinja templates
Expand Down
49 changes: 49 additions & 0 deletions tests/installTestDb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
date=`date +%Y-%m-%d`
install_log="${dir}/TestDbSetUp_${date}_log.txt"
read -e -p "Password of the 'root' user of MySQL: " -i "" db_root_password
# Verify password
while ! mysql -u root --password="${db_root_password}" -e ";" ; do
read -e -p "Invalid password, please retry: " -i "" db_root_password
done
db_user="pipot"
db_name="pipotTest"
mysql -u root --password="${db_root_password}" -e "CREATE DATABASE IF NOT EXISTS ${db_name};" >> "$install_log" 2>&1
# Check if DB exists
db_exists=`mysql -u root --password="${db_root_password}" -se"USE ${db_name};" 2>&1`
if [ ! "${db_exists}" == "" ]; then
echo "Failed to create the database! Please check the installation log!"
exit -1
fi
# Check if user exists
db_user_exists=`mysql -u root --password="${db_root_password}" -sse "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '${db_user}')"`
db_user_password=""
if [ ${db_user_exists} = 0 ]; then
rand_pass=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)
read -e -p "Password for ${db_user} (will be created): " -i "${rand_pass}" db_user_password
# Attempt to create the user
mysql -u root --password="$db_root_password" -e "CREATE USER '${db_user}'@'localhost' IDENTIFIED BY '${db_user_password}';" >> "$install_log" 2>&1
db_user_exists=`mysql -u root --password="$db_root_password" -sse "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '$db_user')"`
if [ ${db_user_exists} = 0 ]; then
echo "Failed to create the user! Please check the installation log!"
exit -1
fi
else
read -e -p "Password for ${db_user}: " db_user_password
# Check if we have access
while ! mysql -u "${db_user}" --password="${db_user_password}" -e ";" ; do
read -e -p "Invalid password, please retry: " -i "" db_user_password
done
fi
# Grant user access to database
mysql -u root --password="${db_root_password}" -e "GRANT ALL ON ${db_name}.* TO '${db_user}'@'localhost';" >> "$install_log" 2>&1
# Check if user has access
db_access=`mysql -u "${db_user}" --password="${db_user_password}" -se"USE ${db_name};" 2>&1`
if [ ! "${db_access}" == "" ]; then
echo "Failed to grant user access to database! Please check the installation log!"
exit -1
fi

echo "# Auto-generated configuration by installTestDb.sh
DATABASE_URI = 'mysql+pymysql://${db_user}:${db_user_password}@localhost:3306/${db_name}'
" > "${dir}/tests/config.py"
110 changes: 110 additions & 0 deletions tests/testAppBase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import os
import sys
import mock
import unittest
from mock import patch


from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy.orm import scoped_session, sessionmaker

# Need to append server root path to ensure we can import the necessary files.
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import tests.config
from collections import namedtuple
from flask import g, current_app
from database import create_session, Base
from mod_auth.models import User, Role, Page, PageAccess
from mod_config.models import Service, Notification, Actions, Conditions, Rule
from mod_honeypot.models import Profile, PiModels, PiPotReport, ProfileService, \
CollectorTypes, Deployment


def generate_keys(tempdir):
secret_csrf_path = os.path.join(tempdir, "secret_csrf")
secret_key_path = os.path.join(tempdir, "secret_key")
if not os.path.exists(secret_csrf_path):
secret_csrf_cmd = "head -c 24 /dev/urandom > {path}".format(path=secret_csrf_path)
os.system(secret_csrf_cmd)
if not os.path.exists(secret_key_path):
secret_key_cmd = "head -c 24 /dev/urandom > {path}".format(path=secret_key_path)
os.system(secret_key_cmd)

return {'secret_csrf_path': secret_csrf_path, 'secret_key_path': secret_key_path}


def load_config(tempdir):
key_paths = generate_keys(tempdir)
with open(key_paths['secret_key_path'], 'rb') as secret_key_file:
secret_key = secret_key_file.read()
with open(key_paths['secret_csrf_path'], 'rb') as secret_csrf_file:
secret_csrf = secret_csrf_file.read()

return {
'TESTING': True,
'WTF_CSRF_ENABLED': False,
'SQLALCHEMY_POOL_SIZE': 1,
'SECRET_KEY': secret_key,
'CSRF_SESSION_KEY': secret_csrf,
'SERVER_IP': '127.0.0.1',
'SERVER_PORT': 443,
'INSTANCE_NAME': 'testInstance',
'APPLICATION_ROOT': '/',
'CSRF_ENABLED': False,
'DATABASE_URI': tests.config.DATABASE_URI,
'COLLECTOR_UDP_PORT': 1234,
'COLLECTOR_SSL_PORT': 1235
}


class TestAppBaseTest(unittest.TestCase):
tempdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp")

def create_app(self):
with patch('config_parser.parse_config', return_value=load_config(self.tempdir)):
from run import app
return app

def create_admin(self):
# test if there is admin existed
db = create_session(self.app.config['DATABASE_URI'], drop_tables=False)
role = Role(name="Admin")
db.add(role)
db.commit()
admin_user = User(role_id=role.id, name="Admin", password="admin", email="admin@sample.com")
db.add(admin_user)
db.commit()
db.remove()
return admin_user

def setUp(self):
if not os.path.exists(self.tempdir):
os.mkdir(self.tempdir)
self.app = self.create_app()

def tearDown(self):
db_engine = create_engine(self.app.config['DATABASE_URI'], convert_unicode=True)
Base.metadata.drop_all(bind=db_engine)

def test_app_is_running(self):
self.assertFalse(current_app is None)

def test_app_is_testing(self):
self.assertTrue(self.app.config['TESTING'])

def admin_is_created(self):
db = create_session(self.app.config['DATABASE_URI'], drop_tables=False)
admin_row = Role.query.filter(Role.is_admin).first()
admin = User.query.filter(User.role_id == admin_row.id).first()
db.remove()
return admin is not None

def test_create_admin(self):
self.create_admin()
self.assertTrue(self.admin_is_created())


if __name__ == '__main__':
unittest.main()
15 changes: 12 additions & 3 deletions tests/TestNestedMenus.py → tests/testNestedMenus.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import unittest
import os
import sys

from mock import patch, call
from server.decorators import get_menu_entries, get_permissible_entries
# Need to append server root path to ensure we can import the necessary files.
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from decorators import get_menu_entries, get_permissible_entries


class TestGetMenuEntries(unittest.TestCase):

@patch('mod_auth.models.User')
@patch('server.decorators.get_permissible_entries')
@patch('decorators.get_permissible_entries')
def test_get_menu_entries_with_simple_entries(self, mock_permissible_entries, mock_user):
"""
Passing a menu entry to get_menu_entries() when all the
Expand Down Expand Up @@ -59,7 +64,7 @@ def side_effect(*args):
mock_permissible_entries.assert_has_calls(calls) # Check that mocked function correctly called

@patch('mod_auth.models.User')
@patch('server.decorators.get_permissible_entries')
@patch('decorators.get_permissible_entries')
def test_get_menu_entries_with_no_permissions(self, mock_permissible_entries, mock_user):
"""
Passing a menu entry to get_menu_entries() when user is not
Expand Down Expand Up @@ -158,3 +163,7 @@ def side_effect(*args):
'entries': [{'title': 'Honeypot services', 'route': 'config.services', 'icon': 'sliders'}],
'icon': 'bell-o'}], 'icon': 'bell-o'}
self.assertDictEqual(entries, correct_entries)


if __name__ == "__main__":
unittest.main()
21 changes: 21 additions & 0 deletions travis_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
echo "-------------------------------"
echo "| Installing dependencies |"
echo "-------------------------------"
echo ""
echo "* Updating package list "
apt-get update
echo "* Installing nginx, python & pip "

apt-get -q -y install dnsutils nginx python python-dev python-pip

if [[ "$OSTYPE" == "linux-gnu" ]]; then
apt-get -q -y install build-essential libffi-dev libssl-dev
fi
if [ ! -f /etc/init.d/mysql* ]; then
echo "* Installing MySQL (root password will be empty!)"
DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
fi
echo "* Update setuptools "
pip install --upgrade setuptools
echo "* Installing pip dependencies"
pip install nose2 mock ipaddress enum34 cryptography idna sqlalchemy twisted pyopenssl flask-sqlalchemy flask passlib pymysql service_identity pycrypto flask-wtf netifaces gunicorn

0 comments on commit be0a982

Please sign in to comment.