HANDIN COMMIT

This commit is contained in:
2024-07-01 00:08:04 +02:00
parent 854fba049d
commit e62914e738
36 changed files with 195 additions and 883 deletions

View File

@@ -1,36 +0,0 @@
__pycache__
.venv
iottb.egg-info
.idea
*.log
logs/
*.pyc
.obsidian
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
.private/
*.pcap

View File

@@ -0,0 +1,110 @@
Usage: iottb [OPTIONS] COMMAND [ARGS]...
Options:
-v, --verbosity Set verbosity [default: 0; 0<=x<=3]
-d, --debug Enable debug mode
--dry-run [default: True]
--cfg-file PATH Path to iottb config file [default:
/home/seb/.config/iottb/iottb.cfg]
--help Show this message and exit.
Commands:
add-device Add a device to a database
init-db
rm-cfg Removes the cfg file from the filesystem.
rm-dbs Removes ALL(!) databases from the filesystem if...
set-key-in-table-to Edit config or metadata files.
show-all Show everything: configuration, databases, and...
show-cfg Show the current configuration context
sniff Sniff packets with tcpdump
Usage: iottb init-db [OPTIONS]
Options:
-d, --dest PATH Location to put (new) iottb database
-n, --name TEXT Name of new database. [default: iottb.db]
--update-default / --no-update-default
If new db should be set as the new default
[default: update-default]
--help Show this message and exit.
Usage: iottb add-device [OPTIONS]
Add a device to a database
Options:
--dev, --device-name TEXT The name of the device to be added. If this
string contains spaces or other special
characters normalization is
performed to derive a canonical name [required]
--db, --database DIRECTORY Database in which to add this device. If not
specified use default from config. [env var:
IOTTB_DB]
--guided Add device interactively [env var:
IOTTB_GUIDED_ADD]
--help Show this message and exit.
Usage: iottb sniff [OPTIONS] [TCPDUMP-ARGS] [DEVICE]
Sniff packets with tcpdump
Options:
Testbed sources:
--db, --database TEXT Database of device. Only needed if not current
default. [env var: IOTTB_DB]
--app TEXT Companion app being used during capture
Runtime behaviour:
--unsafe Disable checks for otherwise required options.
[env var: IOTTB_UNSAFE]
--guided [env var: IOTTB_GUIDED]
--pre TEXT Script to be executed before main command is
started.
--post TEXT Script to be executed upon completion of main
command.
Tcpdump options:
-i, --interface TEXT Network interface to capture on.If not specified
tcpdump tries to find and appropriate one. [env
var: IOTTB_CAPTURE_INTERFACE]
-a, --address TEXT IP or MAC address to filter packets by. [env var:
IOTTB_CAPTURE_ADDRESS]
-I, --monitor-mode Put interface into monitor mode.
--ff TEXT tcpdump filter as string or file path. [env var:
IOTTB_CAPTURE_FILTER]
-#, --print-pacno Print packet number at beginning of line. True by
default. [default: True]
-e, --print-ll Print link layer headers. True by default.
-c, --count INTEGER Number of packets to capture. [default: 1000]
--help Show this message and exit.
Utility Commands mostly for development
Usage: iottb rm-cfg [OPTIONS]
Removes the cfg file from the filesystem.
This is mostly a utility during development. Once non-standard database
locations are implemented, deleting this would lead to iottb not being able
to find them anymore.
Options:
--yes Confirm the action without prompting.
--help Show this message and exit.
Usage: iottb rm-dbs [OPTIONS]
Removes ALL(!) databases from the filesystem if they're empty.
Development utility currently unfit for use.
Options:
--yes Confirm the action without prompting.
--help Show this message and exit.
Usage: iottb show-cfg [OPTIONS]
Show the current configuration context
Options:
--cfg-file PATH Path to the config file [default:
/home/seb/.config/iottb/iottb.cfg]
-pp Pretty Print
--help Show this message and exit.
Usage: iottb show-all [OPTIONS]
Show everything: configuration, databases, and device metadata
Options:
--help Show this message and exit.

View File

@@ -0,0 +1,38 @@
Usage: iottb [OPTIONS] COMMAND [ARGS]...
Options:
-v, --verbosity Set verbosity [default: 0; 0<=x<=3]
-d, --debug Enable debug mode
--dry-run [default: True]
--cfg-file PATH Path to iottb config file [default:
/home/seb/.config/iottb/iottb.cfg]
--help Show this message and exit.
Commands:
add-device Add a device to a database
init-db
rm-cfg Removes the cfg file from the filesystem.
rm-dbs Removes ALL(!) databases from the filesystem if...
set-key-in-table-to Edit config or metadata files.
show-all Show everything: configuration, databases, and...
show-cfg Show the current configuration context
sniff Sniff packets with tcpdump
Usage: iottb [OPTIONS] COMMAND [ARGS]...
Options:
-v, --verbosity Set verbosity [default: 0; 0<=x<=3]
-d, --debug Enable debug mode
--dry-run [default: True]
--cfg-file PATH Path to iottb config file [default:
/home/seb/.config/iottb/iottb.cfg]
--help Show this message and exit.
Commands:
add-device Add a device to a database
init-db
rm-cfg Removes the cfg file from the filesystem.
rm-dbs Removes ALL(!) databases from the filesystem if...
set-key-in-table-to Edit config or metadata files.
show-all Show everything: configuration, databases, and...
show-cfg Show the current configuration context
sniff Sniff packets with tcpdump

View File

@@ -1,9 +1,9 @@
Main Command: iottb
Testbed [I]
Usage: [OPTIONS] COMMAND [ARGS]...
# Main Command: `iottb`
Usage: `iottb [OPTIONS] COMMAND [ARGS]...`
Options:
-v, --verbosity Set verbosity [0<=x<=3]
-v, --verbosity Set verbosity [0<=x<=3] \n
-d, --debug Enable debug mode
--dry-run
--cfg-file PATH Path to iottb config file

View File

@@ -1,100 +0,0 @@
import click
from pathlib import Path
import logging
from logging.handlers import RotatingFileHandler
import sys
from iottb.models.iottb_config import IottbConfig
from iottb.definitions import DB_NAME
logger = logging.getLogger(__name__)
@click.command()
@click.option('-d', '--dest', type=click.Path(), help='Location to put (new) iottb database')
@click.option('-n', '--name', default=DB_NAME, type=str, help='Name of new database.')
@click.option('--update-default/--no-update-default', default=True, help='If new db should be set as the new default')
@click.pass_context
def init_db(ctx, dest, name, update_default):
logger.info('init-db invoked')
config = ctx.obj['CONFIG']
logger.debug(f'str(config)')
# Use the default path from config if dest is not provided
known_dbs = config.get_known_databases()
logger.debug(f'Known databases: {known_dbs}')
if name in known_dbs:
dest = config.get_database_location(name)
if Path(dest).joinpath(name).is_dir():
click.echo(f'A database {name} already exists.')
logger.debug(f'DB {name} exists in {dest}')
click.echo(f'Exiting...')
exit()
logger.debug(f'DB name {name} registered but does not exist.')
if not dest:
logger.info('No dest set, choosing default destination.')
dest = Path(config.default_db_location).parent
db_path = Path(dest).joinpath(name)
logger.debug(f'Full path for db {str(db_path)}')
# Create the directory if it doesn't exist
db_path.mkdir(parents=True, exist_ok=True)
logger.info(f"mkdir {db_path} successful")
click.echo(f'Created {db_path}')
# Update configuration
config.set_database_location(name, str(dest))
if update_default:
config.set_default_database(name, str(dest))
config.save_config()
logger.info(f"Updated configuration with database {name} at {db_path}")
@click.command()
@click.option('-d', '--dest', type=click.Path(), help='Location to put (new) iottb database')
@click.option('-n', '--name', default=DB_NAME, type=str, help='Name of new database.')
@click.option('--update-default/--no-update-default', default=True, help='If new db should be set as the new default')
@click.pass_context
def init_db_inactive(ctx, dest, name, update_default):
logger.info('init-db invoked')
config = ctx.obj['CONFIG']
logger.debug(f'str(config)')
# Retrieve known databases
known_dbs = config.get_known_databases()
# Determine destination path
if name in known_dbs:
dest = Path(config.get_database_location(name))
if dest.joinpath(name).is_dir():
click.echo(f'A database {name} already exists.')
logger.debug(f'DB {name} exists in {dest}')
click.echo(f'Exiting...')
exit()
logger.debug(f'DB name {name} registered but does not exist.')
elif not dest:
logger.info('No destination set, using default path from config.')
dest = Path(config.default_db_location).parent
# Ensure destination path is absolute
dest = dest.resolve()
# Combine destination path with database name
db_path = dest / name
logger.debug(f'Full path for database: {str(db_path)}')
# Create the directory if it doesn't exist
try:
db_path.mkdir(parents=True, exist_ok=True)
logger.info(f'Directory {db_path} created successfully.')
click.echo(f'Created {db_path}')
except Exception as e:
logger.error(f'Failed to create directory {db_path}: {e}')
click.echo(f'Failed to create directory {db_path}: {e}', err=True)
exit(1)
# Update configuration
config.set_database_location(name, str(db_path))
if update_default:
config.set_default_database(name, str(db_path))
config.save_config()
logger.info(f'Updated configuration with database {name} at {db_path}')
click.echo(f'Updated configuration with database {name} at {db_path}')

View File

View File

@@ -1,18 +1,16 @@
import json
import logging
import os
import shutil
import re
import subprocess
import uuid
from datetime import datetime
from pathlib import Path
from time import time
import click
import subprocess
import json
from pathlib import Path
import logging
import re
from datetime import datetime
from click_option_group import optgroup
from iottb.definitions import APP_NAME, CFG_FILE_PATH
from iottb.models.iottb_config import IottbConfig
from iottb.utils.string_processing import make_canonical_name
# Setup logger
@@ -47,11 +45,13 @@ def validate_sniff(ctx, param, value):
def run_pre(pre):
pass
subprocess.run(pre, shell=True)
logger.debug(f'finnished {pre}')
def run_post(post):
pass
subprocess.run(post, shell=True)
logger.debug(f'finnished {post}')
@click.command('sniff', help='Sniff packets with tcpdump')
@@ -63,9 +63,8 @@ def run_post(post):
@optgroup.option('--unsafe', is_flag=True, default=False, envvar='IOTTB_UNSAFE', is_eager=True,
help='Disable checks for otherwise required options.\n', show_envvar=True)
@optgroup.option('--guided', is_flag=True, default=False, envvar='IOTTB_GUIDED', show_envvar=True)
@optgroup.option('--pre', type=click.Path(exists=True, executable=True), help='Script to be executed before main '
'command'
'is started.')
@optgroup.option('--pre', help='Script to be executed before main command is started.')
@optgroup.option('--post', help='Script to be executed upon completion of main command.')
@optgroup.group('Tcpdump options')
@optgroup.option('-i', '--interface',
help='Network interface to capture on.' +
@@ -74,11 +73,11 @@ def run_post(post):
@optgroup.option('-a', '--address', callback=validate_sniff,
help='IP or MAC address to filter packets by.\n', show_envvar=True,
envvar='IOTTB_CAPTURE_ADDRESS')
@optgroup.option('-I', '--monitor-mode', help='Put interface into monitor mode.', is_flag=True)
@optgroup.option('-I', '--monitor-mode', help='Put interface into monitor mode.\n', is_flag=True)
@optgroup.option('--ff', type=str, envvar='IOTTB_CAPTURE_FILTER', show_envvar=True,
help='tcpdump filter as string or file path.')
@optgroup.option('-#', '--print-pacno', is_flag=True, default=True,
help='Print packet number at beginning of line. True by default.')
help='Print packet number at beginning of line. True by default.\n')
@optgroup.option('-e', '--print-ll', is_flag=True, default=False,
help='Print link layer headers. True by default.')
@optgroup.option('-c', '--count', type=int, help='Number of packets to capture.', default=1000)
@@ -263,7 +262,7 @@ def sniff(ctx, device, interface, print_pacno, ff, count, monitor_mode, print_ll
out.write(tcp_complete.stdout)
err.write(tcp_complete.stderr)
#click.echo(f'Mock sniff execution')
# click.echo(f'Mock sniff execution')
click.echo(f"Capture complete. Saved to {pcap_file}")
except subprocess.CalledProcessError as e:
logger.error(f'Failed to capture packets: {e}')
@@ -285,6 +284,8 @@ def sniff(ctx, device, interface, print_pacno, ff, count, monitor_mode, print_ll
end_time = datetime.now().strftime("%H:%M:%S")
end = time()
delta = end - start
click.echo(f'tcpdump took {delta:.2f} seconds.')
# Step 9: Register metadata
metadata = {
@@ -310,7 +311,9 @@ def sniff(ctx, device, interface, print_pacno, ff, count, monitor_mode, print_ll
'resources': {
'pcap_file': str(pcap_file),
'stdout_log': str(stdout_log_file),
'stderr_log': str(stderr_log_file)
'stderr_log': str(stderr_log_file),
'pre': str(pre),
'post': str(post)
},
'environment': {
'capture_dir': capture_dir,
@@ -337,5 +340,7 @@ def sniff(ctx, device, interface, print_pacno, ff, count, monitor_mode, print_ll
click.echo(f'END SNIFF SUBCOMMAND')
if post:
click.echo(f'Running post command {post}')
click.echo(f'Running post script {post}')
run_post(post)

View File

@@ -65,56 +65,3 @@ def init_db(ctx, dest, name, update_default):
# config.save_config()
@click.command()
@click.option('-d', '--dest', type=click.Path(), help='Location to put (new) iottb database')
@click.option('-n', '--name', default=DB_NAME, type=str, help='Name of new database.')
@click.option('--update-default/--no-update-default', default=True, help='If new db should be set as the new default')
@click.pass_context
def init_db_inactive(ctx, dest, name, update_default):
logger.info('init-db invoked')
config = ctx.obj['CONFIG']
logger.debug(f'str(config)')
# Retrieve known databases
known_dbs = config.get_known_databases()
# Determine destination path
if name in known_dbs:
dest = Path(config.get_database_location(name))
if dest.joinpath(name).is_dir():
click.echo(f'A database {name} already exists.')
logger.debug(f'DB {name} exists in {dest}')
click.echo(f'Exiting...')
exit()
logger.debug(f'DB name {name} registered but does not exist.')
elif not dest:
logger.info('No destination set, using default path from config.')
dest = Path(config.default_db_location).parent
# Ensure destination path is absolute
dest = dest.resolve()
# Combine destination path with database name
db_path = dest / name
logger.debug(f'Full path for database: {str(db_path)}')
# Create the directory if it doesn't exist
try:
db_path.mkdir(parents=True, exist_ok=True)
logger.info(f'Directory {db_path} created successfully.')
click.echo(f'Created {db_path}')
except Exception as e:
logger.error(f'Failed to create directory {db_path}: {e}')
click.echo(f'Failed to create directory {db_path}: {e}', err=True)
exit(1)
# Update configuration
config.set_database_location(name, str(db_path))
if update_default:
config.set_default_database(name, str(db_path))
config.save_config()
logger.info(f'Updated configuration with database {name} at {db_path}')
click.echo(f'Updated configuration with database {name} at {db_path}')

View File

@@ -50,8 +50,23 @@ def write_help_to_file(cli, filename):
f.write("\n\n")
def manual():
comands = [
'init-db',
'add-device',
'sniff'
]
dev_commands = [
'show-all',
'rm-dbs',
'show-cfg',
'show-all'
]
if __name__ == "__main__":
from iottb import DOCS_FOLDER
print('Must be in project root for this to work properly!')
print(f'CWD is {str(Path.cwd())}')
DOCS_FOLDER.mkdir(exist_ok=True)

View File

@@ -8,7 +8,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12"
click = "^8.1"
scapy = "^2.5"
# scapy = "^2.5"
[tool.poetry.scripts]
iottb = "iottb.main:cli"