Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: quick query lookup #214

Merged
merged 1 commit into from
Apr 13, 2024
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
3 changes: 2 additions & 1 deletion backend/api/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from fastapi import APIRouter

from backend.api.endpoints import fingerprint
from backend.api.endpoints import counters, fingerprint

api_router = APIRouter()
api_router.include_router(
fingerprint.router, prefix="/fingerprint", tags=["fingerprint"]
)
api_router.include_router(counters.router, prefix="/counters", tags=["counters"])
41 changes: 41 additions & 0 deletions backend/api/endpoints/counters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status

from backend import schemas, services, settings

router = APIRouter()


def get_shodan():
if settings.SHODAN_API_KEY is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Shodan is not configured correctly",
)

return services.Shodan(settings.SHODAN_API_KEY)


def get_censys():
if settings.CENSYS_APP_ID is None or settings.CENSYS_SECRET is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Censys is not configured correctly",
)

return services.Censys(settings.CENSYS_APP_ID, settings.CENSYS_SECRET)


Shodan = Annotated[services.Shodan, Depends(get_shodan)]
Censys = Annotated[services.Censys, Depends(get_censys)]


@router.get("/shodan")
async def shodan(query: str, *, shodan: Shodan) -> schemas.Count:
return schemas.Count(count=await shodan.call(query))


@router.get("/censys")
async def censys(query: str, *, censys: Censys):
return schemas.Count(count=await censys.call(query))
Empty file removed backend/core/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from fastapi.staticfiles import StaticFiles
from loguru import logger

from backend import settings
from backend.api.api import api_router
from backend.core import settings


def create_app():
Expand Down
6 changes: 6 additions & 0 deletions backend/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from pydantic import BaseModel

from .certificate import Certificate # noqa: F401
from .dns import DNS # noqa: F401
from .favicon import Favicon # noqa: F401
Expand All @@ -7,3 +9,7 @@
from .tls import TLS # noqa: F401
from .tracker import Tracker # noqa: F401
from .whois import Whois # noqa: F401


class Count(BaseModel):
count: int
1 change: 1 addition & 0 deletions backend/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .certificate import Certificate # noqa: F401
from .counters import Censys, Shodan # noqa: F401
from .dns import DNS # noqa: F401
from .favicon import Favicon # noqa: F401
from .fingerprint import Fingerprint # noqa: F401
Expand Down
37 changes: 37 additions & 0 deletions backend/services/counters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import httpx
from starlette.datastructures import Secret


class Shodan:
def __init__(self, api_key: Secret):
self.api_key = api_key

async def call(self, query: str):
async with httpx.AsyncClient(base_url="https://api.shodan.io") as client:
res = await client.get(
"/shodan/host/search", params={"key": str(self.api_key), "query": query}
)
res.raise_for_status()

return res.json()["total"]


class Censys:
def __init__(
self,
app_id: Secret,
secret: Secret,
):
self.app_id = app_id
self.secret = secret

async def call(self, query: str):
auth = httpx.BasicAuth(username=str(self.app_id), password=str(self.secret))

async with httpx.AsyncClient(
base_url="https://search.censys.io", auth=auth
) as client:
res = await client.get("/api/v2/hosts/search", params={"q": query})
res.raise_for_status()

return res.json()["result"]["total"]
11 changes: 7 additions & 4 deletions backend/core/settings.py → backend/settings.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import sys

from starlette.config import Config
from starlette.datastructures import Secret

try:
config = Config(".env")
except Exception:
config = Config()
config = Config(".env")

PROJECT_NAME: str = config("PROJECT_NAME", default="shimon")

Expand All @@ -15,3 +13,8 @@
LOG_FILE = config("LOG_FILE", default=sys.stderr)
LOG_LEVEL: str = config("LOG_LEVEL", cast=str, default="DEBUG")
LOG_BACKTRACE: bool = config("LOG_BACKTRACE", cast=bool, default=True)


SHODAN_API_KEY: Secret | None = config("SHODAN_API_KEY", cast=Secret, default=None)
CENSYS_APP_ID: Secret | None = config("CENSYS_APP_ID", cast=Secret, default=None)
CENSYS_SECRET: Secret | None = config("CENSYS_SECRET", cast=Secret, default=None)
Loading