Database Models & Connector
This commit is contained in:
parent
7d0749e562
commit
8ff4aaebbe
35
README.md
35
README.md
@ -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.
|
||||
|
3
setup.py
3
setup.py
@ -16,6 +16,7 @@ setup(
|
||||
},
|
||||
install_requires = [
|
||||
"Flask",
|
||||
"flask_socketio"
|
||||
"flask_socketio",
|
||||
"sqlalchemy",
|
||||
],
|
||||
)
|
||||
|
@ -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
37
src/overseer/models.py
Normal 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
0
src/overseer/scanner.py
Normal 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
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user