Skip to content
This repository was archived by the owner on Jul 16, 2019. It is now read-only.

Added Docker support #9

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ language: python
python:
- "2.7"
sudo: false

services:
- docker

install: pip install -r requirements.txt

script:
- docker build .
- flake8 --ignore F401 securitybot/
- PYTHONPATH=$(pwd) py.test -v tests/
16 changes: 16 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM python:2.7

COPY . /securitybot

ENV PYTHONPATH $PYTHONPATH:/securitybot

RUN apt-get update
RUN apt-get install -y mysql-client
RUN pip install -r /securitybot/requirements.txt
RUN useradd -N -s '/bin/false' -e '' securitybot

USER securitybot

WORKDIR /securitybot

ENTRYPOINT ["/securitybot/docker_entrypoint.sh"]
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,46 @@ If the following were all generated successfully, Securitybot should be up and r
To test it, message the bot user it's assigned to and say `hi`.
To test the process of dealing with an alert, message `test` to test the bot.

#### Environment variable
To prevent having to modify the scripts, you can set the following environment variables to configure the bot:

|Variable|Setting|
|--------|-------|
|SLACK_API_TOKEN|Slack API Token|
|REPORTING_CHANNEL|Slack Channel ID|
|DUO_INTEGRATION_KEY|Duo Integration Key|
|DUO_SECRET_KEY|Duo Secret Key|
|DUO_ENDPOINT|Duo Endpoint|
|DB_HOST|MySQL Hostname|
|DB_USER|MySQL Username|
|DB_PASS|MySQL Password|
|DB_NAME|MySQL Database name|

#### Docker

Dockerfile is included to generate a Docker Image to run the bot. Entrypoint script will wait for database startup and initialize database if it does not already exist. Entrypoint takes one of two arguments:

* bot: Starts the main bot
* frontend: starts the frontend and API server

Run configuration will be based on the environment variables above.

Example:

Bot:
```
docker build --tag securitybot
docker run -e DB_NAME=securitybot -e DB_USER=root -e DB_HOST=127.0.0.1 -e DB_PASS=password -e SLACK_API_TOKEN=<your api token> -e REPORTING_CHANNEL=security-notifications -e DUO_INTEGRATION_KEY=<your integration key> -e DUO_SECRET_KEY=<your secret key> -e DUO_ENDPOINT=<your endpoint> securitybot bot
```

Frontend:
```
docker build --tag securitybot
docker run -p 8888:8888 -e DB_NAME=securitybot -e DB_USER=root -e DB_HOST=127.0.0.1 -e DB_PASS=password securitybot frontend
```

A docker-compose file is provided for ease of use. docker-compose up will start database, bot and frontend. Frontend and API server will be available on port 8888. Database content will be stored in persistent volume `mysql-securitybot`. Slack-related, Duo related and database password environment variables must be set for docker-compose stack to run properly.

## Architecture
Securitybot was designed to be as modular as possible.
This means that it's possible to easily swap out chat systems, 2FA providers, and alerting data sources.
Expand Down
37 changes: 37 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: '3'
services:
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=${DB_PASS}
volumes:
- mysql-securitybot:/var/lib/mysql
ports:
- "3306"
bot:
build: .
image: securitybot
command: bot
environment:
- SLACK_API_TOKEN=${SLACK_API_TOKEN}
- REPORTING_CHANNEL=${REPORTING_CHANNEL}
- DUO_INTEGRATION_KEY=${DUO_INTEGRATION_KEY}
- DUO_SECRET_KEY=${DUO_SECRET_KEY}
- DUO_ENDPOINT=${DUO_ENDPOINT}
- DB_HOST=db
- DB_USER=root
- DB_PASS=${DB_PASS}
- DB_NAME=securitybot
frontend:
build: .
image: securitybot
command: frontend
ports:
- "8888:8888"
environment:
- DB_HOST=db
- DB_USER=root
- DB_PASS=${DB_PASS}
- DB_NAME=securitybot
volumes:
mysql-securitybot:
29 changes: 29 additions & 0 deletions docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
set -e


end=$((SECONDS + 120))

# Wait max of 2 minutes for database to come up
until mysql --user $DB_USER --password=$DB_PASS --host=$DB_HOST -e"quit" || [ $SECONDS -ge $end ]; do echo "Waiting for DB"; sleep 2; done;

# Check if database is initialized
if ! mysql --user $DB_USER --password=$DB_PASS --host=$DB_HOST -e"use $DB_NAME"; then
echo "Creating database"
mysql --user $DB_USER --password=$DB_PASS --host=$DB_HOST -e"create database $DB_NAME"
echo "Populating database"
python /securitybot/util/db_up.py
fi


if [ "$1" = 'bot' ]; then
echo "Starting bot"
shift
exec python /securitybot/main.py "$@"
elif [ "$1" = 'frontend' ]; then
echo "Starting frontend"
shift
exec python /securitybot/frontend/securitybot_frontend.py "$@"
fi

exec "$@"
12 changes: 7 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
from securitybot.tasker.sql_tasker import SQLTasker
from securitybot.auth.duo import DuoAuth
from securitybot.sql import init_sql
from os import getenv

import duo_client

CONFIG = {}
SLACK_KEY = 'slack_api_token'
DUO_INTEGRATION = 'duo_integration_key'
DUO_SECRET = 'duo_secret_key'
DUO_ENDPOINT = 'duo_endpoint'
REPORTING_CHANNEL = 'some_slack_channel_id'
SLACK_KEY = getenv('SLACK_API_TOKEN', 'slack_api_token')
DUO_INTEGRATION = getenv('DUO_INTEGRATION_KEY', 'duo_integration_key')
DUO_SECRET = getenv('DUO_SECRET_KEY', 'duo_secret_key')
DUO_ENDPOINT = getenv('DUO_ENDPOINT', 'duo_endpoint')
REPORTING_CHANNEL = getenv('REPORTING_CHANNEL', 'some_slack_channel_id')
ICON_URL = 'https://dl.dropboxusercontent.com/s/t01pwfrqzbz3gzu/securitybot.png'

def init():
Expand Down
9 changes: 8 additions & 1 deletion securitybot/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
import MySQLdb
import logging

from os import getenv
from typing import Any, Sequence

DB_HOST = getenv('DB_HOST', 'localhost')
DB_USER = getenv('DB_USER', 'root')
DB_PASS = getenv('DB_PASS', '')
DB_NAME = getenv('DB_NAME', 'securitybot')


class SQLEngine(object):
# Whether the singleton has been instantiated
_host = None # type: str
Expand Down Expand Up @@ -90,4 +97,4 @@ class SQLEngineException(Exception):
def init_sql():
# type: () -> None
'''Initializes SQL.'''
SQLEngine('localhost', 'root', '', 'securitybot')
SQLEngine(DB_HOST, DB_USER, DB_PASS, DB_NAME)
10 changes: 6 additions & 4 deletions util/db_up.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#!/usr/bin/env python
import MySQLdb
import sys
from os import getenv

# DB CONFIG GOES HERE
host = 'localhost'
user = 'root'
passwd= ''
host = getenv('DB_HOST', 'localhost')
user = getenv('DB_USER', 'root')
passwd=getenv('DB_PASS', '')
dbname=getenv('DB_NAME', 'securitybot')

db = MySQLdb.connect(host=host,
user=user,
passwd=passwd,
db='securitybot')
db=dbname)

cur = db.cursor()

Expand Down