Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ui_catalog.db
site/
addons/
collectors/
.worktrees/

notebooks

Expand Down
4 changes: 2 additions & 2 deletions example-configurations/bloodhound-enterprise/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Quick-start

1. Copy `.dlt-example` to `${HOME}/.dlt`and `docker-compose.yml` to `${HOME}`.
1. Copy `.dlt-example` to `${HOME}/.dlt`. From the repository root, run `cd example-configurations/bloodhound-enterprise` before the Compose commands below so the configured build context can access the root `Dockerfile`.
2. Fill in your credentials in the toml files.
3. Place any required key files (github.pem, okta.json) in `${HOME}/.dlt`.
4. Pull image from SpecterOps Docker Hub: `docker pull specterops/openhound:latest-enterprise`
Expand All @@ -13,4 +13,4 @@ Full configuration reference: https://bloodhound.specterops.io/openhound/enterpr
## WARNING:
All config and secret files referenced below MUST exist before running
`docker compose up`. If they are missing, Docker will create them as directories,
which will cause the collector to fail.
which will cause the collector to fail.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
x-scheduler: &scheduler
image: specterops/openhound:${IMAGE_VERSION:-latest-enterprise}
build:
context: ../..
target: enterprise
Comment thread
coderabbitai[bot] marked this conversation as resolved.
restart: unless-stopped
init: true
volumes:
Expand Down Expand Up @@ -30,6 +33,9 @@ services:
environment:
<<: *env
DESTINATION__BLOODHOUNDENTERPRISE__COLLECTOR_NAME: github
# Docker mounts the GitHub App key at this absolute path. Do not use
# ~/.dlt/github.pem here: the collector does not expand `~`.
SOURCES__SOURCE__GITHUB__CREDENTIALS__KEY_PATH: /app/.dlt/github.pem
secrets:
- source: secrets_github
target: /app/.dlt/secrets.toml
Expand Down
46 changes: 46 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,52 @@ typecheck:
@echo "Running type checks"
uv run mypy src/openhound

# Run one test area, e.g. `just test bhe_job_scheduling`.
test area:
uv run pytest "tests/test_{{area}}.py" -v

# Run every discovered test.
test-all:
uv run pytest

dashboard:
@echo "Starting marimo openhound dashboard"
marimo edit notebooks/explore.py --watch

# Docker commands for the Enterprise example configuration.
# Examples: `just oh`, `just oh up github`, `just oh down github`, `just oh down`
oh action='up' collector='':
#!/usr/bin/env bash
set -euo pipefail

compose=(
docker compose
-f ./example-configurations/bloodhound-enterprise/docker-compose.yml
)

case "{{action}}" in
up)
if [[ -n "{{collector}}" ]]; then
"${compose[@]}" up -d --build --force-recreate "scheduler-{{collector}}"
else
"${compose[@]}" up -d --build --force-recreate
fi
;;
down)
if [[ -n "{{collector}}" ]]; then
"${compose[@]}" down "scheduler-{{collector}}"
else
"${compose[@]}" down
fi
;;
*)
>&2 echo "Usage: just oh [up|down] [github|jamf|okta]"
exit 1
;;
esac

# Follow the most recent logs for one collector, e.g. `just oh-logs github`.
oh-logs collector:
docker compose \
-f ./example-configurations/bloodhound-enterprise/docker-compose.yml \
logs --follow --tail=100 "scheduler-{{collector}}"
31 changes: 23 additions & 8 deletions src/openhound/core/clients/bloodhound.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def request(
path: str,
body: bytes | None = None,
extra_headers: dict[str, str] | None = None,
timeout: tuple[float, float] | None = None,
): ...

def _request(
Expand All @@ -56,6 +57,7 @@ def _request(
headers: dict[str, str],
body: bytes | None = None,
extra_headers: dict[str, str] | None = None,
timeout: tuple[float, float] | None = None,
):

logger.debug(
Expand All @@ -65,14 +67,23 @@ def _request(
if extra_headers:
headers = {**headers, **extra_headers}

response = requests.request(
method=method,
url=f"{self.base_uri}{path}",
headers=headers,
data=body,
)

if response.status_code not in [200, 201, 202]:
if timeout is None:
response = requests.request(
method=method,
url=f"{self.base_uri}{path}",
headers=headers,
data=body,
)
else:
response = requests.request(
method=method,
url=f"{self.base_uri}{path}",
headers=headers,
data=body,
timeout=timeout,
)

if not 200 <= response.status_code < 300:
raise BloodHoundHTTPError(code=response.status_code, reason=response.text)

return response
Expand Down Expand Up @@ -160,6 +171,7 @@ def request(
path: str,
body: bytes | None = None,
extra_headers: dict[str, str] | None = None,
timeout: tuple[float, float] | None = None,
):
# HMAC Part 1
digester = hmac.new(self.token_key.encode(), None, hashlib.sha256)
Expand Down Expand Up @@ -192,6 +204,7 @@ def request(
headers=headers,
body=body,
extra_headers=extra_headers,
timeout=timeout,
)


Expand All @@ -206,6 +219,7 @@ def request(
path: str,
body: bytes | None = None,
extra_headers: dict[str, str] | None = None,
timeout: tuple[float, float] | None = None,
):
headers = {
"User-Agent": self.user_agent,
Expand All @@ -218,4 +232,5 @@ def request(
headers=headers,
body=body,
extra_headers=extra_headers,
timeout=timeout,
)
Loading
Loading