Database Models & Connector

This commit is contained in:
Evan Reichard 2021-03-17 22:19:03 -04:00
parent 7d0749e562
commit 8ff4aaebbe
6 changed files with 129 additions and 2 deletions

View File

@ -1,9 +1,42 @@
# Overseer
## Description
Overseer is a port scanning web interface. All current and historical results are stored in a database.
## Building
## Developing
### Server
Ideally from a virtualenv:
```
python setup.py develop
```
### Client
At this point, you have to build the client to appropriately populate the static resources for
the Flask server to serve up.
## Building
Overseer consists of a server and client component.
### Server:
Ideally from a virtualenv:
```
python setup.py install
```
### Client:
You must run these commands from the `./src/overseer_client/` directory:
```
yarn build
```
## Running
Ideally from a virtual env:
```
overseer run
```
# Notes
In a production environment, it would be ideal to setup something like nginx to properly forward
the `/api/*` routes to the Flask server, and all other endpoints to the static client resources.

View File

@ -16,6 +16,7 @@ setup(
},
install_requires = [
"Flask",
"flask_socketio"
"flask_socketio",
"sqlalchemy",
],
)

View File

@ -0,0 +1,54 @@
import models
from datetime import datetime
from os import path
from sqlalchemy import create_engine, or_, insert, Table, Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import declarative_base, Session
class DatabaseConnector:
def __init__(self, data_path):
self.engine = create_engine("sqlite+pysqlite:///%s" % path.join(data_path, "overseer.sqlite"), echo=True, future=True)
models.Base.metadata.create_all(self.engine)
def create_scan_result(self, ip_address, scan_results, hostname=None):
session = Session(bind=self.engine)
# Does an existing target exist?
scan_target = session.query(models.ScanTarget).filter(or_(
models.ScanTarget.ip==ip_address,
models.ScanTarget.hostname==hostname,
)).first()
# Nope, create one
if not scan_target:
scan_target = models.ScanTarget(ip=ip_address, hostname=hostname)
session.add(scan_target)
session.commit()
# Create scan history
scan_history = models.ScanHistory(target=scan_target.id, results=",".join(map(str, scan_results)), datetime=datetime.now())
session.add(scan_history)
session.commit()
session.close()
def create_target(self, ip_address, hostname):
stmt = insert(models.ScanTarget).values(ip=ip_address, hostname=hostname)
compiled = stmt.compile()
self.__execute_statement(stmt)
return stmt
def __execute_statement(self, stmt):
with self.engine.connect() as conn:
result = conn.execute(stmt)
conn.commit()
return result
# FOR TESTING PURPOSES
def main():
db = DatabaseConnector("/Users/evanreichard/Development/git/overseer/src/overseer")
db.create_scan_result(1234577, [5,6,7,8], "test222.com")
if __name__ == "__main__":
main()

37
src/overseer/models.py Normal file
View File

@ -0,0 +1,37 @@
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class ScanTarget(Base):
__tablename__ = "scan_target"
# Unique ID
id = Column(Integer, primary_key=True, unique=True)
# Integer representation of an IP Address. Can use SQL queries to filter subnets.
ip = Column(Integer, index=True, unique=True)
# Corresponding hostname.
hostname = Column(String, index=True, unique=True)
def __repr__(self):
return f"ScanTarget(id={self.id!r}, ip={self.ip!r}, hostname={self.hostname!r})"
class ScanHistory(Base):
__tablename__ = "scan_history"
# Unique ID
id = Column(Integer, primary_key=True, unique=True)
# Scan Target Reference
target = Column(Integer, ForeignKey("scan_target.id"))
# Results
results = Column(String)
# DateTime
datetime = Column(DateTime())
def __repr__(self):
return f"ScanHistory(id={self.id!r}, target={self.target!r}, results={self.results!r}, datetime={self.datetime!r})"

0
src/overseer/scanner.py Normal file
View File

View File

@ -11,6 +11,8 @@ yarn serve
```
### Compiles and minifies for production
This will automatically populate the overseer server with the appropriate resources in `templates` and `static`
```
yarn build
```