Commit 57402268 authored by Alain Takoudjou's avatar Alain Takoudjou

Add patrowl software release

parent 80792020
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[instance]
filename = instance.cfg.in
md5sum = 6b6eadb804d0d15c116d865d02938322
[template-patrowl]
filename = instance-patrowl.cfg.jinja2.in
md5sum = 9a955d621b255cc1c71f7ad7008b7d6e
[template-patrowl-wrapper]
filename = patrowl-wapper.sh.in
md5sum = b58da4365f8b12afb492523c5310cc49
[template-create_default_admin.py.in]
filename = create_default_admin.py.in
md5sum = 9b7bb45c5c934884054eedc0f7d801ef
[template-nginx.conf.in]
filename = nginx.conf.in
md5sum = 4046c3f1e9c7e9d17e1ba245177daa58
from django.contrib.auth import get_user_model
User = get_user_model()
if not User.objects.filter(username='{{ admin_username }}').exists():
User.objects.create_superuser('{{ admin_username }}', '{{ admin_email }}, '{{ admin_passwd }}')
{% set local_ipv4 = (ipv4 | list)[0] -%}
{% set local_ipv6 = (ipv6 | list)[0] -%}
[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
bin = ${buildout:directory}/bin
srv = ${buildout:directory}/srv
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
scripts = ${:etc}/run
services = ${:etc}/service
plugins = ${:etc}/plugin
ssl = ${:etc}/ssl
www = ${:srv}/www
tmp = ${:srv}/tmp
rabbitmq = ${:srv}/rabbitmq
mqlog = ${:log}/rabbitmq
mqlib = ${:var}/lib/rabbitmq
nginx = ${:srv}/nginx
[service-rabbitmq]
recipe = slapos.cookbook:wrapper
command-line =
{{ parameter_dict['rabbitmq-location'] }}/sbin/rabbitmq-server
wrapper-path = ${directory:services}/rabbitmq
environment =
RABBITMQ_CONFIG_FILES=${directory:rabbitmq}/conf.d
RABBITMQ_CONFIG_FILE=${directory:rabbitmq}/rabbitmq.conf
RABBITMQ_SCRIPTS_DIR={{ parameter_dict['rabbitmq-location'] }}/sbin
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=-rabbit log_levels [{connection,error}]
RABBITMQ_ADVANCED_CONFIG_FILE=${directory:rabbitmq}/advanced.config
RABBITMQ_CONF_ENV_FILE=${directory:rabbitmq}/rabbitmq-env.conf
RABBITMQ_NODE_IP_ADDRESS={{ local_ipv4 }}
RABBITMQ_NODE_PORT=${:port}
ERL_EPMD_ADDRESS={{ local_ipv4 }}
ERL_EPMD_PORT=4369
RABBITMQ_NODENAME={{ partition_id }}@localhost
RABBITMQ_LOG_BASE=${directory:mqlog}
RABBITMQ_MNESIA_BASE=${directory:mqlib}/mnesia
RABBITMQ_PLUGINS_DIR=${directory:mqlib}/plugins
PATH={{ parameter_dict['erlang-location'] }}/bin:/usr/local/bin:/usr/bin:/bin
port = 5672
[promise-rabbitmq]
<= monitor-promise-base
promise = check_socket_listening
name = rabbitmq-port-listening.py
config-host = {{ local_ipv4 }}
config-port = ${service-rabbitmq:port}
[service-postgresql]
recipe = slapos.cookbook:postgres
bin = {{ parameter_dict['postgresql-location'] }}/bin
services= ${directory:services}
dbname = patrowl_db
superuser = patrowl-psql
password=
pgdata-directory = ${directory:srv}/postgresql
# empty addresses - listen only on unix socket
ipv4 =
ipv6 =
port =
[promise-postgresql]
<= monitor-promise-base
promise = check_command_execute
name = promise-postgresql.py
config-command =
{{ parameter_dict['postgresql-location'] }}/bin/psql \
-h ${service-postgresql:pgdata-directory} \
-U ${service-postgresql:superuser} \
-d ${service-postgresql:dbname} \
-c '\q'
[gunicorn-wrapper]
recipe = slapos.cookbook:wrapper
command-line =
{{ parameter_dict['gunicorn-bin'] }} -b {{ local_ipv4 }}:${:port} app.wsgi:application
--timeout 300 --log-level error
wrapper-path = ${directory:bin}/gunicorn
port = 8003
depends =
${create-admin.py:recipe}
[promise-gunicorn]
<= monitor-promise-base
promise = check_socket_listening
name = gunicorn-port-listening.py
config-host = {{ local_ipv4 }}
config-port = ${gunicorn-wrapper:port}
[patrowl-env.sh]
recipe = slapos.recipe.template
inline =
PATH={{ parameter_dict['postgresql-location'] }}/bin:${directory:bin}:$PATH
export POSTGRES_HOST=${service-postgresql:pgdata-directory}
export POSTGRES_PORT=5432
export POSTGRES_DBNAME=${service-postgresql:dbname}
export POSTGRES_USER=${service-postgresql:superuser}
export POSTGRES_PASSWORD=
export POSTGRES_CONN_MAX_AGE=0
export RABBITMQ_HOST={{ local_ipv4 }}
export RABBITMQ_PORT=${service-rabbitmq:port}
export RABBITMQ_HOSTNAME='{{ local_ipv4 }}:${service-rabbitmq:port}'
export RABBIT_ENV_USER='guest'
#export RABBIT_ENV_PASS='guest'
export BROKER_URL=
export PE_INSTALL_PATH=
export PATROWL_SU_USERNAME="admin"
export PATROWL_SU_EMAIL="admin@dev.patrowl.io"
export PATROWL_SU_PASSWORD="Bonjour1!"
export PATROWL_REFRESH_ENGINE=7000
export SECRET_KEY="*** omg this is the secret !***"
export SECURE_SSL_REDIRECT=true
export USE_X_FORWARDED_HOST=true
export DEBUG=True
#export INFO,WARNING,ERROR,DEBUG
export LOGGING_LEVEL=DEBUG
export PATROWL_PROXY_HTTP=
export PATROWL_PROXY_HTTPS=
export PATROWL_TZ='Europe/Paris'
export EMAIL_USE_TLS=true
export EMAIL_USE_SSL=
export EMAIL_HOST=smtp.gmail.com
export EMAIL_HOST_USER=test@gmail.com
export EMAIL_HOST_PASSWORD=test
export EMAIL_PORT=587
export SCAN_TIMEOUT=600
export HTTP_REQUEST_MAX_TIMEOUT=600
export SCAN_JOB_DEFAULT_MAX_TIMEOUT=600
export SCAN_JOB_DEFAULT_TIMEOUT=7200
export SCAN_JOB_DEFAULT_SPLIT_ASSETS=100
export PATROWL_ASSETS_MAX=100000000
export PATROWL_ASSETS_MARGIN=10
export PATROWL_ASSETGROUPS_MAX=100000000
export PATROWL_USERS_MAX=5
export PATROWL_SCAN_DEFINITIONS_MAX=5
export PATROWL_FINDINGS_MAX=-1
export PATROWL_ENGINES_MAX=5
export PATROWL_ENGINE_POLICIES_MAX=100
export PATROWL_ENGINES_MANAGE_ENABLED=true
export ALERTS_AUTO_NEW_ENABLED=true
export ALERTS_AUTO_MISSING_ENABLED=true
export ASSET_DETECTION_RULES_FILENAME="app/assets_detection_rules.py"
export ASSET_AUTOTAG_CPE=true
output = ${directory:etc}/.env.sh
[configure-service]
recipe = plone.recipe.command
command =
ln -sf {{ python_bin }} ${directory:bin}/python
FOLDER=${:patrowl-directory}
[ ! -d "$FOLDER" ] && cp -ax {{ parameter_dict['patrowl-location'] }} $FOLDER
cd $FOLDER
cp app/settings.py.sample app/settings.py
cp app/assets_detection_rules.py.sample app/assets_detection_rules.py
patrowl-directory = ${directory:srv}/patrowl
update-command = ${:command}
stop-on-error = true
[create-admin.py]
recipe = slapos.recipe.template:jinja2
url = {{ parameter_dict['template-create-admin'] }}
context =
key admin_email instance-parameters:admin-email
key admin_passwd admin-password:passwd
key admin_username admin-password:username
output = ${configure-service:patrowl-directory}/var/bin/create_default_admin.py
[patrowl-parameters]
patrowl-directory = ${configure-service:patrowl-directory}
patrowl-env = ${patrowl-env.sh:output}
gunicorn-wrapper = ${gunicorn-wrapper:wrapper-path}
[service-patrowl]
recipe = slapos.recipe.template:jinja2
url = {{ parameter_dict['patrowl-wrapper'] }}
context =
section parameter_dict patrowl-parameters
mode = 750
output = ${directory:services}/patrowl
depends =
${promise-gunicorn:recipe}
${configure-service:recipe}
[admin-password]
recipe = slapos.cookbook:generate.password
storage-path = ${directory:etc}/.passwd
username = admin
[nginx-parameters]
nginx-ip = {{ local_ipv6 }}
nginx-port = 8083
access-log = ${directory:log}/nginx.patrowlmanager-access.log
error-log = ${directory:log}/nginx.patrowlmanager-error.log
gunicorn-url = http://{{ local_ipv4 }}:${gunicorn-wrapper:port}
patrowl-directory = ${patrowl-parameters:patrowl-directory}
nginx-mime-types = {{ parameter_dict['nginx-mime-types'] }}
key-file = ${nginx-certificate:key-file}
cert-file = ${nginx-certificate:cert-file}
path-pid = ${directory:run}/nginx.pid
nb-workers = 4
[nginx-conf]
recipe = slapos.recipe.template:jinja2
url = {{ parameter_dict['nginx-conf'] }}
context =
section parameter_dict nginx-parameters
output = ${directory:etc}/nginx.conf
# self-signed certificate for https
[nginx-certificate]
recipe = plone.recipe.command
stop-on-error = true
cert-file = ${directory:ssl}/nginx_backend.crt
key-file = ${directory:ssl}/nginx_backend.key
command =
test -e ${:key-file} || \
{{ openssl_bin }} req -newkey rsa -batch -new -x509 -days 3650 -nodes \
-keyout ${:key-file} -out ${:cert-file}
update-command = ${:command}
[service-nginx]
recipe = slapos.cookbook:wrapper
command-line =
{{ parameter_dict['nginx-bin'] }} -p ${directory:nginx} -c ${nginx-conf:output}
wrapper-path = ${directory:services}/nginx
url = https://[${nginx-parameters:nginx-ip}]:${nginx-parameters:nginx-port}
[promise-nginx]
<= monitor-promise-base
promise = check_command_execute
name = promise_nginx_site.py
promise = check_url_available
config-http-code = 200
config-url = ${service-nginx:url}
[patrowl-frontend]
<= slap-connection
recipe = slapos.cookbook:requestoptional
name = Patrowl nginx Frontend
# XXX We have hardcoded SR URL here.
software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
slave = true
config-url = ${service-nginx:url}
config-https-only = true
return = domain secure_access
[patrowl-frontend-promise]
<= monitor-promise-base
promise = check_url_available
name = check_patrowl_frontend.py
config-url = ${patrowl-frontend:connection-secure_access}
[publish-connection-information]
<= monitor-publish
recipe = slapos.cookbook:publish
backend-url = ${service-nginx:url}
url =${patrowl-frontend-promise:config-url}
admin-username = ${admin-password:username}
admin-password = ${admin-password:passwd}
[instance-parameters]
admin-email = admin@dev.patrowl.io
[buildout]
extends = {{ template_monitor }}
parts =
publish-connection-information
promise-postgresql
service-rabbitmq
promise-rabbitmq
service-patrowl
service-nginx
promise-nginx
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[buildout]
parts = switch-softwaretype
# std stuff for slapos instance
eggs-directory = {{ buildout_egg_directory }}
develop-eggs-directory = {{ buildout_develop_directory }}
offline = true
[switch-softwaretype]
recipe = slapos.cookbook:switch-softwaretype
default = dynamic-template-patrowl:output
RootSoftwareInstance = ${:default}
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
output = ${buildout:directory}/${:filename}
extensions = jinja2.ext.do
extra-context =
context =
key develop_eggs_directory buildout:develop-eggs-directory
key buildout_directory buildout:directory
key eggs_directory buildout:eggs-directory
key ipv4 slap-configuration:ipv4
key ipv6 slap-configuration:ipv6
key global_ipv4_prefix network-information:global-ipv4-network
key slapparameter_dict slap-configuration:configuration
key computer_id slap-configuration:computer
key partition_id slap-configuration:partition
raw openssl_bin {{ openssl_location }}/bin/openssl
raw python_bin {{ bin_directory }}/{{ python_with_eggs }}
raw template_monitor {{ template_monitor_cfg }}
raw logrotate_cfg {{ logrotate_cfg }}
${:extra-context}
[dynamic-template-patrowl-parameters]
erlang-location = {{ erlang_location }}
rabbitmq-location = {{ rabbitmq_location }}
postgresql-location = {{ postgresql_location }}
gunicorn-bin = {{ bin_directory }}/gunicorn
celery-bin = {{ bin_directory }}/celery
patrowl-wrapper = {{ template_patrowl_wrapper }}
patrowl-location = {{ patrowl_location }}
template-create-admin = {{ template_create_admin }}
nginx-conf = {{ template_nginx_conf }}
nginx-bin = {{ nginx_bin }}
nginx-mime-types = {{ nginx_mime_types }}
[dynamic-template-patrowl]
<= jinja2-template-base
url = {{ template_patrowl }}
filename = instance-patrowl.cfg
extra-context =
section parameter_dict dynamic-template-patrowl-parameters
worker_processes {{ parameter_dict['nb-workers'] }};
pid {{ parameter_dict['path-pid'] }};
error_log {{ parameter_dict['access-log' ] }};
daemon off;
events {
worker_connections 1024;
accept_mutex off;
}
http {
include {{ parameter_dict['nginx-mime-types'] }};
default_type application/octet-stream;
types_hash_bucket_size 64;
access_log {{ parameter_dict['access-log' ] }} combined;
server {
listen [{{ parameter_dict['nginx-ip' ] }}]:{{ parameter_dict['nginx-port' ] }} ssl http2;
autoindex off;
server_name _;
ssl_certificate {{ parameter_dict['cert-file'] }};
ssl_certificate_key {{ parameter_dict['key-file'] }};
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# Protects against Clickjacking attacks.
add_header X-Frame-Options "SAMEORIGIN";
# Protects against Clickjacking attacks.
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
# Protects against XSS injections.
add_header X-XSS-Protection "1; mode=block";
# Protects against MIME-type confusion attack.
add_header X-Content-Type-Options "nosniff";
# CSP modern XSS directive-based defence, used since 2014.
add_header Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *;";
# Prevents from leaking referrer data over insecure connections.
add_header Referrer-Policy 'strict-origin';
# Disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
location / {
proxy_pass {{ parameter_dict['gunicorn-url'] }};
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header Proxy "";
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
expires off;
# Custom headers
proxy_connect_timeout 75s;
proxy_read_timeout 300s;
proxy_redirect off;
proxy_buffering off;
proxy_buffer_size "4k";
}
location /static {
alias {{ parameter_dict['patrowl-directory'] }}/staticfiles;
}
# location /media {
# alias /opt/patrowl-manager/media;
# }
}
}
#!/bin/bash
set -e
. {{ parameter_dict['patrowl-env'] }}
cd {{ parameter_dict['patrowl-directory'] }}
export PYTHONPATH={{ parameter_dict['patrowl-directory'] }}:$PYTHONPATH
echo "[+] Test for DB availability"
psql -h $POSTGRES_HOST -U $POSTGRES_USER -d $POSTGRES_DBNAME -c '\q'
echo "[+] Wait for RabbitMQ availability"
while !</dev/tcp/$RABBITMQ_HOST/$RABBITMQ_PORT; do sleep 1; done
echo "[+] PatrowlManager version"
cat VERSION
# Collect static files
echo "[+] Collect static files"
python manage.py collectstatic --noinput
# Check for first install
if [ ! -f status.created ]; then
echo "[+] Update DB schema (if already created)"
var/bin/update_db_migrations.sh
# Apply database migrations
echo "[+] Make database migrations"
echo " - scans"
python manage.py makemigrations scans
echo " - findings"
python manage.py makemigrations findings
echo " - events"
python manage.py makemigrations events
echo " - ... and all the rest"
python manage.py makemigrations
# Apply database migrations
echo "[+] Apply database migrations"
python manage.py migrate
# Create the default admin user
echo "[+] Create the default admin user (if needeed)"
python manage.py shell < var/bin/create_default_admin.py
echo "[+] Create default team if needed"
python manage.py shell < var/bin/create_default_team.py
# Populate the db with default data
echo "[+] Populate the db with default data"
python manage.py loaddata var/data/assets.AssetCategory.json
python manage.py loaddata var/data/engines.Engine.json
python manage.py loaddata var/data/engines.EnginePolicyScope.json
python manage.py loaddata var/data/engines.EnginePolicy.json
echo "[+] Configure the engines nmap, sslscan and owl_dns"
echo -e "\r\
from engines.models import Engine, EngineInstance\r\
try:\r\
EngineInstance(engine=Engine.objects.filter(name=\"NMAP\").first(), name=\"nmap-local-001\", api_url=\"http://engine-nmap:5001/engines/nmap/\").save()\r\
EngineInstance(engine=Engine.objects.filter(name=\"SSLSCAN\").first(), name=\"sslscan-local-001\", api_url=\"http://engine-sslscan:5014/engines/sslscan/\").save()\r\
EngineInstance(engine=Engine.objects.filter(name=\"OWL_DNS\").first(), name=\"owl_dns-local-001\", api_url=\"http://engine-owl_dns:5006/engines/owl_dns/\").save()\r\
except Exception:\r\
pass" | python manage.py shell
touch status.created
fi
# Configure engines and turn-on auto-refresh engine status
# if [ -f set_engines.py ]; then
# python manage.py shell < set_engines.py
# fi
# Start Gunicorn WSGI server
echo "[+] Starting server"
exec {{ parameter_dict['gunicorn-wrapper'] }}
[buildout]
extends =
../../component/postgresql/buildout.cfg
../../component/psycopg2/buildout.cfg
../../component/erlang/buildout.cfg
../../component/openssl/buildout.cfg
../../component/nginx/buildout.cfg
../../stack/monitor/buildout.cfg
buildout.hash.cfg
show-picked-versions = true
allow-picked-versions = true
parts =
slapos-cookbook
postgresql
eggs
instance
[rabbitmq]
recipe= slapos.recipe.build:download-unpacked
url = https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.12.5/rabbitmq-server-generic-unix-3.12.5.tar.xz
md5sum = 6ba62866f5238504d93deed57b4bf7ed
[psycopg2-binary]
<= psycopg2
egg = psycopg2-binary
[eggs]
recipe = zc.recipe.egg
interpreter = python_eggs
eggs =
celery
gunicorn
Django
django-celery-beat
django-cursor-pagination
django-datetime-widget
django-debug-toolbar
django-extensions
django-rest-swagger
django-timezone-field
django-filter
django-cors-headers
djangorestframework-simplejwt
django-health-check
psutil
django-organizations
django-annoying
${django-dbconn-retry-setup:egg}
${django-reset-migrations-setup:egg}
django-celery-results
djangorestframework-datatables
meld3
more-itertools
netaddr
openapi-codec
${psycopg2-binary:egg}
python-crontab
python-dateutil
python-magic
python-memcached
${thehive4py-setup:egg}
tornado
tzlocal
Werkzeug
zipp
cpe
scripts =
gunicorn
celery
[gitclone]
recipe = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git
[patrowl]
<= gitclone
repository = https://github.com/Patrowl/PatrowlManager.git
git-executable = ${git:location}/bin/git
[django-dbconn-retry]
<= gitclone
repository = https://github.com/jdelic/django-dbconn-retry.git
[django-reset-migrations]
<= gitclone
repository = https://github.com/valdergallo/django-reset-migrations.git
[thehive4py]
<= gitclone
repository = https://github.com/TheHive-Project/Thehive4py.git
revision = 1.8.1
[django-dbconn-retry-setup]
recipe = zc.recipe.egg:develop
egg = django-dbconn-retry
setup = ${django-dbconn-retry:location}
[django-reset-migrations-setup]
recipe = zc.recipe.egg:develop
egg = django-reset-migrations
setup = ${django-reset-migrations:location}
[thehive4py-setup]
recipe = zc.recipe.egg:develop
egg = thehive4py
setup = ${thehive4py:location}
[download-template]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:filename}
[instance]
recipe = slapos.recipe.template:jinja2
output = ${buildout:directory}/instance.cfg
url = ${:_profile_base_location_}/${:filename}
context =
key bin_directory buildout:bin-directory
key buildout_egg_directory buildout:eggs-directory
key buildout_develop_directory buildout:develop-eggs-directory
key buildout_directory buildout:directory
key template_monitor_cfg monitor2-template:output
key logrotate_cfg template-logrotate-base:output
key erlang_location erlang:location
key openssl_location openssl:location
key patrowl_location patrowl:location
key postgresql_location postgresql:location
key nginx_bin nginx-output:nginx
key nginx_mime_types nginx-output:mime
key python_with_eggs eggs:interpreter
key rabbitmq_location rabbitmq:location
key template_create_admin template-create_default_admin.py.in:target
key template_patrowl template-patrowl:target
key template_patrowl_wrapper template-patrowl-wrapper:target
key template_nginx_conf template-nginx.conf.in:target
[template-patrowl]
<= download-template
output = ${buildout:directory}/instance-patrowl.cfg.jinja2
[template-patrowl-wrapper]
<= download-template
output = ${buildout:directory}/patrowl-wapper.sh.in
[template-create_default_admin.py.in]
<= download-template
output = ${buildout:directory}/create_default_admin.py.in
[template-nginx.conf.in]
<= download-template
output = ${buildout:directory}/nginx.conf.in
[versions]
amqp = 2.5.2
Babel = 2.9.1
backports-abc = 0.5
billiard = 3.6.1.0
celery = 4.4.0
certifi = 2017.4.17
chardet = 3.0.4
coreapi = 2.3.3
coreschema = 0.0.4
Django = 2.2.26
#django-celery-beat = 1.1.1
django-celery-beat = 2.0.0
django-celery-results = 2.0.1
django-cursor-pagination = 0.1.4
django-datetime-widget = 0.9.3
django-debug-toolbar = 3.2.2
django-extensions = 2.1.9
django-rest-swagger = 2.2.0
django-timezone-field = 4.0
djangorestframework = 3.13.1
djangorestframework-datatables = 0.7.0
flower = 0.9.2
future = 0.16.0
futures = 3.1.1
gunicorn = 20.0.4
idna = 2.5
importlib-metadata = 0.23
itypes = 1.1.0
Jinja2 = 2.11.3
jsonfield = 2.0.2
kombu = 4.6.7
libmagic = 1.0
MarkupSafe = 1.1.0
meld3 = 1.0.2
more-itertools = 7.2.0
netaddr = 0.7.19
openapi-codec = 1.3.2
#psycopg2-binary = 2.8.6
psycopg2-binary = 2.8.6
python-crontab = 2.3.6
python-dateutil = 2.8.0
python-magic = 0.4.15
#python-magic-bin = 0.4.14
python-memcached = 1.59
pytz = 2019.2
requests = 2.25.1
simplejson = 3.16.0
singledispatch = 3.4.0.3
six = 1.10.0
sqlparse = 0.4.2
thehive4py = 1.8.1
#thehive4py = 1.5.1
PyJWT = 2.8.0
tornado = 5.1
tzlocal = 1.5.1
uritemplate = 3.0.0
urllib3 = 1.26.5
vine = 1.3.0
Werkzeug = 2.0.1
zipp = 0.6.0
django-filter = 2.4.0
django-cors-headers = 3.2.0
djangorestframework-simplejwt = 4.4.0
django-health-check = 3.12.1
psutil = 5.7.0
django-organizations = 1.1.2
django-annoying = 0.10.6
#django-reset-migrations
#django-dbconn-retry
cpe = 1.2.1
django-dbconn-retry = 0.1.7
django-reset-migrations = 0.4.0
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment