summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristofer Hallin <kristofer@sunet.se>2022-01-17 14:01:08 +0100
committerKristofer Hallin <kristofer@sunet.se>2022-01-17 14:01:08 +0100
commitbb5029d512a58021718061aca439383c8b11e575 (patch)
tree74354b6bf55a9159695eea695653ef03009e5ad4
parent571997129ba5275cc5e148a8ac1c0f64d895a9ef (diff)
parent0b55f7ff7cdd3b78bd9992063208476c1c080a02 (diff)
* Merge branch 'main' into feature.callhome
* New API endpoints * Updated requirements
-rw-r--r--README.md6
-rw-r--r--auth-server-poc/requirements.txt34
-rw-r--r--auth-server-poc/src/app.py39
-rwxr-xr-xauth-server-poc/src/authn.py (renamed from src/authn.py)61
-rw-r--r--auth-server-poc/src/userdb.yaml23
-rw-r--r--demo/wsgi_demo_users.yaml15
-rwxr-xr-xdo-as17
-rw-r--r--env-vars.sh6
-rwxr-xr-xquickstart.sh12
-rw-r--r--requirements.txt7
-rwxr-xr-xsrc/db/db.py9
-rw-r--r--src/db/scanner.py30
-rwxr-xr-xsrc/main.py1
-rw-r--r--src/routers/collector.py67
-rw-r--r--src/routers/scanner.py6
15 files changed, 223 insertions, 110 deletions
diff --git a/README.md b/README.md
index 1e4ecbb..40fdb1f 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,8 @@ We can also limit the number of results and skip N results forward with the para
curl -s -H "Authorization: Bearer $JWT" 'http://localhost:80/sc/v0/get?limit=5&skip=2' | json_pp -json_opt utf8,pretty
+There is also a convenience script `do-as` which simplifies performing actions as a particular user.
+
## Development
There are two docker-compose files used for development:
@@ -88,9 +90,7 @@ There are two docker-compose files used for development:
- `docker/docker-compose-dev.yaml` for the collector, and
- `auth-server-poc/docker-compose.yml` for the JWT server.
-To apply changes, build with `docker-compose build -f docker/docker-compose-dev.yaml` or `docker-compose -f auth-server-poc/docker-compose.yml` (depending on what has changed) and then restart the containers with `./quickstart.sh`.
-
-If you want to save build time you can also pass a service name to `docker-compose build`, i.e. `docker-compose build -f docker/docker-compose-dev.yaml collector`.
+To apply changes, `source env-vars.sh` and do e.g. `docker-compose -f docker/docker-compose-dev.yaml up -d --build collector`.
## JWT mechanics (work in progress)
diff --git a/auth-server-poc/requirements.txt b/auth-server-poc/requirements.txt
index 9927acb..fc8fc53 100644
--- a/auth-server-poc/requirements.txt
+++ b/auth-server-poc/requirements.txt
@@ -248,3 +248,37 @@ zipp==3.6.0 \
# via
# -r requirements.txt
# importlib-metadata
+pyyaml==6.0 \
+ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \
+ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \
+ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \
+ --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \
+ --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \
+ --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \
+ --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \
+ --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \
+ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \
+ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \
+ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \
+ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \
+ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \
+ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \
+ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \
+ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \
+ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \
+ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \
+ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \
+ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \
+ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \
+ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \
+ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \
+ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \
+ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \
+ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \
+ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \
+ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \
+ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \
+ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \
+ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \
+ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \
+ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5
diff --git a/auth-server-poc/src/app.py b/auth-server-poc/src/app.py
index 443eded..c7ba0d1 100644
--- a/auth-server-poc/src/app.py
+++ b/auth-server-poc/src/app.py
@@ -3,40 +3,51 @@ from flask_restful import Api, Resource
from flask_jwt_extended import create_access_token, JWTManager
from flask_cors import CORS
+import authn
+
app = Flask(__name__)
cors = CORS(
app,
resources={r"/api/*": {"origins": "*"}},
expose_headers=["Content-Type", "Authorization", "X-Total-Count"],
)
-api = Api(app, prefix='/api/v1.0')
+api = Api(app, prefix="/api/v1.0")
jwt = JWTManager(app)
-PEM_PRIVATE = '/opt/auth-server-poc/cert/private.pem'
-PEM_PUBLIC = '/opt/auth-server-poc/cert/public.pem'
+PEM_PRIVATE = "/opt/auth-server-poc/cert/private.pem"
+PEM_PUBLIC = "/opt/auth-server-poc/cert/public.pem"
-app.config['JWT_PRIVATE_KEY'] = open(PEM_PRIVATE).read()
-app.config['JWT_PUBLIC_KEY'] = open(PEM_PUBLIC).read()
-app.config['JWT_ALGORITHM'] = 'ES256'
-app.config['JWT_IDENTITY_CLAIM'] = 'sub'
-app.config['JWT_ACCESS_TOKEN_EXPIRES'] = False
+app.config["JWT_PRIVATE_KEY"] = open(PEM_PRIVATE).read()
+app.config["JWT_PUBLIC_KEY"] = open(PEM_PUBLIC).read()
+app.config["JWT_ALGORITHM"] = "ES256"
+app.config["JWT_IDENTITY_CLAIM"] = "sub"
+app.config["JWT_ACCESS_TOKEN_EXPIRES"] = False
class AuthApi(Resource):
def post(self):
- additional_claims = {"type": "access", "domains": ["sunet.se"]}
+
+ identity = request.environ.get("REMOTE_USER")
+ db = authn.UserDB("userdb.yaml")
+ additional_claims = {
+ "type": "access",
+ "read": db.read_perms(identity),
+ "write": db.write_perms(identity),
+ }
+
access_token = create_access_token(
- identity=request.environ.get('REMOTE_USER'),
+ identity=identity,
additional_claims=additional_claims,
)
- return {'access_token': access_token}, 200
+
+ return {"access_token": access_token}, 200
-@app.route('/')
+@app.route("/")
def index():
return "<p>Username: {}</p><p>Auth type: {}</p>".format(
- request.environ.get('REMOTE_USER'), request.environ.get('AUTH_TYPE')
+ request.environ.get("REMOTE_USER"), request.environ.get("AUTH_TYPE")
)
-api.add_resource(AuthApi, '/auth')
+api.add_resource(AuthApi, "/auth")
diff --git a/src/authn.py b/auth-server-poc/src/authn.py
index e90118a..8b32cdc 100755
--- a/src/authn.py
+++ b/auth-server-poc/src/authn.py
@@ -12,26 +12,24 @@ class Authz:
return "{}: {}".format(self._org, self._perms)
def read_p(self):
- return 'r' in self._perms
+ return "r" in self._perms
def write_p(self):
- return 'w' in self._perms
+ return "w" in self._perms
class User:
- def __init__(self, username, pw, authz):
+ def __init__(self, username, authz):
self._username = username
- self._password = pw
self._authz = {}
for org, perms in authz.items():
self._authz[org] = Authz(org, perms)
def dump(self):
- return ["{}/{}: {}".format(self._username, self._password, auth.dump())
- for auth in self._authz.values()]
-
- def authn_p(self, pw):
- return pw == self._password
+ return [
+ "{}: {}".format(self._username, auth.dump())
+ for auth in self._authz.values()
+ ]
def orgnames(self):
return [x for x in self._authz.keys()]
@@ -55,58 +53,45 @@ class UserDB:
def __init__(self, yamlfile):
self._users = {}
for u, d in yaml.safe_load(open(yamlfile)).items():
- self._users[u] = User(u, d['pw'], d['authz'])
+ self._users[u] = User(u, d["authz"])
def dump(self):
return [u.dump() for u in self._users.values()]
- def user_authn_p(self, username, password):
- user = self._users.get(username)
- if not user:
- return False
- return user.authn_p(password)
-
def orgs_for_user(self, username):
return self._users.get(username).orgnames()
- def read_perms(self, username, password):
+ def read_perms(self, username):
user = self._users.get(username)
if not user:
return None
- if not user.authn_p(password):
- return None
return user.read_perms()
- def write_perms(self, username, password):
+ def write_perms(self, username):
user = self._users.get(username)
if not user:
return None
- if not user.authn_p(password):
- return None
return user.write_perms()
def self_test():
- db = UserDB('userdb.yaml')
+ db = UserDB("userdb.yaml")
print(db.dump())
- orgs = db.orgs_for_user('user3')
- assert('sunet.se' in orgs)
- assert('su.se' in orgs)
- assert(len(orgs) == 2)
-
- assert(db.user_authn_p('user3', 'pw3') == True)
- assert(db.user_authn_p('user3', 'wrongpw') == False)
+ orgs = db.orgs_for_user("user3")
+ assert "sunet.se" in orgs
+ assert "su.se" in orgs
+ assert len(orgs) == 2
- rp = db.read_perms('user3', 'pw3')
- assert(len(rp) == 2)
- assert('sunet.se' in rp)
- assert('su.se' in rp)
+ rp = db.read_perms("user3", "pw3")
+ assert len(rp) == 2
+ assert "sunet.se" in rp
+ assert "su.se" in rp
- wp = db.write_perms('user3', 'pw3')
- assert(len(wp) == 1)
- assert('sunet.se' in wp)
+ wp = db.write_perms("user3", "pw3")
+ assert len(wp) == 1
+ assert "sunet.se" in wp
-if __name__ == '__main__':
+if __name__ == "__main__":
self_test()
diff --git a/auth-server-poc/src/userdb.yaml b/auth-server-poc/src/userdb.yaml
new file mode 100644
index 0000000..c55773b
--- /dev/null
+++ b/auth-server-poc/src/userdb.yaml
@@ -0,0 +1,23 @@
+user1:
+ authz:
+ sunet.se: r
+ su.se: r
+ kth.se: r
+
+user2:
+ authz:
+ sunet.se: w
+ su.se: w
+ kth.se: w
+
+user3:
+ authz:
+ sunet.se: rw
+ su.se: rw
+ kth.se: rw
+
+user4:
+ authz:
+ sunet.se: rw
+ su.se: r
+ kth.se: w
diff --git a/demo/wsgi_demo_users.yaml b/demo/wsgi_demo_users.yaml
deleted file mode 100644
index 49c4795..0000000
--- a/demo/wsgi_demo_users.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-user1:
- pw: pw1
- authz:
- sunet.se: r
-
-user2:
- pw: pw2
- authz:
- su.se: r
-
-user3:
- pw: pw3
- authz:
- sunet.se: rw
- su.se: r
diff --git a/do-as b/do-as
new file mode 100755
index 0000000..8d5cdaa
--- /dev/null
+++ b/do-as
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+# Usage:
+# ./do-as <username> <last part of URL> [<any additional curl args>]
+# Example:
+# ./do-as user1 get
+# ./do-as user3 delete/1642091653617 -X DELETE
+
+set -e
+
+USER=$1
+CMD=$2
+shift
+shift
+
+JWT=$(curl http://localhost:8000/api/v1.0/auth -X POST -p -u "$USER:pwd" | jq -r .access_token)
+curl -s -H "Authorization: Bearer $JWT" http://localhost:80/sc/v0/$CMD "$@"
diff --git a/env-vars.sh b/env-vars.sh
new file mode 100644
index 0000000..8361a2f
--- /dev/null
+++ b/env-vars.sh
@@ -0,0 +1,6 @@
+export COUCHDB_USER=test
+export COUCHDB_PASSWORD=test
+export COUCHDB_NAME=test
+export COUCHDB_HOSTNAME=couchdb
+export DOCKER_JWT_PUBKEY_PATH=/tmp/soc_collector/
+export DOCKER_JWT_HTPASSWD_PATH=/tmp/soc_collector_htpasswd/
diff --git a/quickstart.sh b/quickstart.sh
index d46a791..edf8c43 100755
--- a/quickstart.sh
+++ b/quickstart.sh
@@ -1,11 +1,6 @@
#!/bin/sh
-export COUCHDB_USER=test
-export COUCHDB_PASSWORD=test
-export COUCHDB_NAME=test
-export COUCHDB_HOSTNAME=couchdb
-export DOCKER_JWT_PUBKEY_PATH=/tmp/soc_collector/
-export DOCKER_JWT_HTPASSWD_PATH=/tmp/soc_collector_htpasswd/
+source env-vars.sh
# Create a directory to store the certificates in.
if [ ! -d ${DOCKER_JWT_PUBKEY_PATH} ]; then
@@ -27,7 +22,10 @@ fi
# Generate a default htpasswd file with a user "usr:pwd".
if [ ! -f ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd ]; then
- htpasswd -b -c ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd usr pwd
+ htpasswd -b -c ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user1 pwd
+ htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user2 pwd
+ htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user3 pwd
+ htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user4 pwd
fi
# Launch the containers.
diff --git a/requirements.txt b/requirements.txt
index ce2f921..7922e54 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
anyio==3.3.4
+APScheduler==3.8.1
asgiref==3.4.1
attrs==21.2.0
certifi==2021.10.8
@@ -20,10 +21,16 @@ pydantic==1.8.2
PyJWT==1.7.1
pyparsing==3.0.6
pytest==6.2.5
+pytz==2021.3
+pytz-deprecation-shim==0.1.0.post0
requests==2.26.0
+six==1.16.0
sniffio==1.2.0
+SQLAlchemy==1.4.29
starlette==0.16.0
toml==0.10.2
typing-extensions==3.10.0.2
+tzdata==2021.5
+tzlocal==4.1
urllib3==1.26.7
uvicorn==0.15.0
diff --git a/src/db/db.py b/src/db/db.py
index cbb87ce..3926fda 100755
--- a/src/db/db.py
+++ b/src/db/db.py
@@ -1,12 +1,3 @@
-# A database storing dictionaries, keyed on a timestamp. value = A
-# dict which will be stored as a JSON object encoded in UTF-8. Note
-# that dict keys of type integer or float will become strings while
-# values will keep their type.
-
-# Note that there's a (slim) chance that you'd stomp on the previous
-# value if you're too quick with generating the timestamps, ie
-# invoking time.time() several times quickly enough.
-
import os
import sys
import time
diff --git a/src/db/scanner.py b/src/db/scanner.py
index e9ac8c3..625fd8e 100644
--- a/src/db/scanner.py
+++ b/src/db/scanner.py
@@ -1,7 +1,7 @@
import enum
from datetime import datetime
-from sqlalchemy import (Boolean, Column, DateTime, Integer, Unicode,
+from sqlalchemy import (JSON, Boolean, Column, DateTime, Integer, Unicode,
UniqueConstraint, create_engine)
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
@@ -22,13 +22,12 @@ class Scanner(Base):
id = Column(Integer, autoincrement=True, primary_key=True)
uuid = Column(Unicode(37), nullable=False)
- enabled = Column(Boolean, nullable=False)
+ enabled = Column(Boolean, default=False, nullable=False)
first_seen = Column(DateTime, default=datetime.utcnow, nullable=False)
last_seen = Column(DateTime, default=datetime.utcnow,
onupdate=datetime.utcnow, nullable=False)
- comment = Column(Unicode(255), nullable=True)
- scanners = Column(Unicode(2048), nullable=False)
- targets = Column(Unicode(255), nullable=True)
+ comment = Column(Unicode(255), default="", nullable=True)
+ scanners = Column(JSON, nullable=True)
def as_dict(self):
"""Return JSON serializable dict."""
@@ -47,7 +46,8 @@ class Scanner(Base):
@classmethod
def comment(cls, uuid, comment):
with SqlDB.sql_session() as session:
- scanner: Scanner = session.query(Scanner).filter(Scanner.uuid == uuid).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.uuid == uuid).one_or_none()
if scanner:
scanner.comment = comment
@@ -58,7 +58,8 @@ class Scanner(Base):
@classmethod
def enable(cls, uuid):
with SqlDB.sql_session() as session:
- scanner: Scanner = session.query(Scanner).filter(Scanner.uuid == uuid).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.uuid == uuid).one_or_none()
if scanner:
scanner.enabled = True
@@ -69,7 +70,8 @@ class Scanner(Base):
@classmethod
def disable(cls, uuid):
with SqlDB.sql_session() as session:
- scanner: Scanner = session.query(Scanner).filter(Scanner.uuid == uuid).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.uuid == uuid).one_or_none()
if scanner:
scanner.enabled = False
@@ -84,9 +86,11 @@ class Scanner(Base):
with SqlDB.sql_session() as session:
if scanner_id:
- scanner: Scanner = session.query(Scanner).filter(Scanner.id == scanner_id).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.id == scanner_id).one_or_none()
elif uuid:
- scanner: Scanner = session.query(Scanner).filter(Scanner.uuid == uuid).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.uuid == uuid).one_or_none()
else:
return None
@@ -104,7 +108,7 @@ class Scanner(Base):
scanner = Scanner()
scanner.uuid = uuid
scanner.enabled = False
- scanner.scanners = "None"
+ scanner.scanners = {}
session.add(scanner)
session.flush()
@@ -113,11 +117,11 @@ class Scanner(Base):
except IntegrityError:
return None
-
@classmethod
def is_enabled(cls, uuid):
with SqlDB.sql_session() as session:
- scanner: Scanner = session.query(Scanner).filter(Scanner.uuid == uuid).one_or_none()
+ scanner: Scanner = session.query(Scanner).filter(
+ Scanner.uuid == uuid).one_or_none()
if scanner is None:
return None
diff --git a/src/main.py b/src/main.py
index aa3b133..a65971d 100755
--- a/src/main.py
+++ b/src/main.py
@@ -24,6 +24,7 @@ app.add_middleware(
expose_headers=["X-Total-Count"],
)
+
@app.middleware("http")
async def mock_x_total_count_header(request: Request, call_next):
response = await call_next(request)
diff --git a/src/routers/collector.py b/src/routers/collector.py
index 3cda23a..7d91609 100644
--- a/src/routers/collector.py
+++ b/src/routers/collector.py
@@ -48,18 +48,22 @@ def get_data(key=None, limit=25, skip=0, ip=None,
@router.get('/get')
async def get(key=None, limit=25, skip=0, ip=None, port=None,
asn=None, Authorize: AuthJWT = Depends()):
+
Authorize.jwt_required()
data = []
raw_jwt = Authorize.get_raw_jwt()
- if 'domains' not in raw_jwt:
- return JSONResponse(content={"status": "error",
- "message": "Could not find domains" +
- "claim in JWT token"},
- status_code=400)
+ if "read" not in raw_jwt:
+ return JSONResponse(
+ content={
+ "status": "error",
+ "message": "Could not find read claim in JWT token",
+ },
+ status_code=400,
+ )
else:
- domains = raw_jwt['domains']
+ domains = raw_jwt["read"]
for domain in domains:
data.extend(get_data(key, limit, skip, ip, port, asn, domain))
@@ -69,17 +73,39 @@ async def get(key=None, limit=25, skip=0, ip=None, port=None,
@router.get('/get/{key}')
async def get_key(key=None, Authorize: AuthJWT = Depends()):
+
Authorize.jwt_required()
- # TODO: Use JWT authz and check e.g. domain here
+ raw_jwt = Authorize.get_raw_jwt()
+
+ if "read" not in raw_jwt:
+ return JSONResponse(
+ content={
+ "status": "error",
+ "message": "Could not find read claim in JWT token",
+ },
+ status_code=400,
+ )
+ else:
+ allowed_domains = raw_jwt["read"]
data = get_data(key)
+ if data["domain"] not in allowed_domains:
+ return JSONResponse(
+ content={
+ "status": "error",
+ "message": "User not authorized to view this object",
+ },
+ status_code=400,
+ )
+
return JSONResponse(content={"status": "success", "docs": data})
@router.post('/add')
async def add(data: Request, Authorize: AuthJWT = Depends()):
+
Authorize.jwt_required()
json_data = await data.json()
@@ -91,11 +117,36 @@ async def add(data: Request, Authorize: AuthJWT = Depends()):
@router.delete('/delete/{key}')
async def delete(key, Authorize: AuthJWT = Depends()):
+
Authorize.jwt_required()
+ raw_jwt = Authorize.get_raw_jwt()
+
+ if "write" not in raw_jwt:
+ return JSONResponse(
+ content={
+ "status": "error",
+ "message": "Could not find write claim in JWT token",
+ },
+ status_code=400,
+ )
+ else:
+ allowed_domains = raw_jwt["write"]
+
+ data = get_data(key)
+
+ if data["domain"] not in allowed_domains:
+ return JSONResponse(
+ content={
+ "status": "error",
+ "message": "User not authorized to delete this object",
+ },
+ status_code=400,
+ )
+
if db.delete(key) is None:
return JSONResponse(content={"status": "error",
"message": "Document not found"},
status_code=400)
- return JSONResponse(content={"status": "success", "docs": {}})
+ return JSONResponse(content={"status": "success", "docs": data})
diff --git a/src/routers/scanner.py b/src/routers/scanner.py
index 9bb0f98..645cd74 100644
--- a/src/routers/scanner.py
+++ b/src/routers/scanner.py
@@ -84,9 +84,9 @@ async def callhome(uuid, data: Request, Authorize: AuthJWT = Depends()):
else:
if Scanner.add(uuid):
- return JSONResponse(content={"status": "success",
- "message": "Scanner added."},
- status_code=200)
+ return JSONResponse(content={"status": "error",
+ "message": "Scanner added but disabled."},
+ status_code=400)
else:
return JSONResponse(content={"status": "error",
"message": "Failed to add scanner."},