mirror of
https://github.com/netinvent/npbackup.git
synced 2025-10-05 19:25:42 +08:00
upgrade_server: Implement basic permission and multi user support
This commit is contained in:
parent
321fafa8af
commit
76f591d943
2 changed files with 80 additions and 16 deletions
|
@ -3,18 +3,23 @@
|
|||
http_server:
|
||||
listen: 0.0.0.0
|
||||
port: 8080
|
||||
username: upgrade_client
|
||||
password: super_secret_password
|
||||
users:
|
||||
- upgrade_client:
|
||||
password: super_secret_password
|
||||
permissions:
|
||||
- audience:
|
||||
- private
|
||||
- public
|
||||
|
||||
upgrades:
|
||||
# Build dir should contain the following structure
|
||||
# /VERSION
|
||||
# VERSION is a file containing a single line with the currently built NPBackup version, example: 2.2.0
|
||||
# /{platform}/{arch}/{binary}
|
||||
# /{platform}/{arch}/{binary}/{audience}
|
||||
# Current platforms are 'windows', 'linux'
|
||||
# Current arches are 'x64', 'x86', 'arm' and 'arm64'
|
||||
# In each folder there should be a npbackup or npbackup.exe binary depending on the platform
|
||||
data_root: /var/www/upgrade_server/dist
|
||||
data_root: /var/npbackup_upgrade_server/dist
|
||||
# We'll store a CSV containing backup clients that upgrade here
|
||||
statistics_file: /var/www/upgrade_server/stats.csv
|
||||
statistics_file: /var/npbackup_upgrade_server/stats.csv
|
||||
|
||||
|
|
|
@ -60,17 +60,20 @@ security = HTTPBasic()
|
|||
|
||||
|
||||
def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
|
||||
current_username_bytes = credentials.username.encode("utf8")
|
||||
correct_username_bytes = config_dict["http_server"]["username"].encode("utf-8")
|
||||
is_correct_username = secrets.compare_digest(
|
||||
current_username_bytes, correct_username_bytes
|
||||
)
|
||||
current_password_bytes = credentials.password.encode("utf8")
|
||||
correct_password_bytes = config_dict["http_server"]["password"].encode("utf-8")
|
||||
is_correct_password = secrets.compare_digest(
|
||||
current_password_bytes, correct_password_bytes
|
||||
)
|
||||
if not (is_correct_username and is_correct_password):
|
||||
authenticated_user = None
|
||||
|
||||
|
||||
for user in config_dict["http_server"]["users"]:
|
||||
try:
|
||||
if secrets.compare_digsest(credentials.username.encode("utf-8"), user.encode("utf-8")):
|
||||
if secrets.compare_digest(credentials.password.encode("utf-8"), config_dict["http_server"]["users"]["user"]["password"].encode("utf-8")):
|
||||
authenticated_user = user
|
||||
break
|
||||
except Exception as exc:
|
||||
logger.info(f"Failed to check user: {exc}")
|
||||
|
||||
|
||||
if authenticated_user is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
|
@ -79,6 +82,17 @@ def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
|
|||
return credentials.username
|
||||
|
||||
|
||||
def get_user_permissions(username: str):
|
||||
"""
|
||||
Returns a list of permissions
|
||||
"""
|
||||
try:
|
||||
return config_dict["http_server"]["users"][username]["permissions"]
|
||||
except Exception as exc:
|
||||
logger.error(f"Failed to get user permissions: {exc}")
|
||||
return []
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def api_root(auth=Depends(get_current_username)):
|
||||
if crud.is_enabled():
|
||||
|
@ -139,9 +153,18 @@ async def current_version(
|
|||
client_ip = x_forwarded_for
|
||||
else:
|
||||
client_ip = request.client.host
|
||||
|
||||
try:
|
||||
has_permission = True if audience.value in get_user_permissions(auth)["audience"] else False
|
||||
except Exception as exc:
|
||||
logger.error(f"Failed to get user permissions: {exc}")
|
||||
has_permission = False
|
||||
|
||||
data = {
|
||||
"action": "check_version",
|
||||
"ip": client_ip,
|
||||
"user": auth,
|
||||
"has_permission": has_permission,
|
||||
"auto_upgrade_host_identity": auto_upgrade_host_identity,
|
||||
"installed_version": installed_version,
|
||||
"group": group,
|
||||
|
@ -156,6 +179,12 @@ async def current_version(
|
|||
except KeyError:
|
||||
logger.error("No statistics file set.")
|
||||
|
||||
if not has_permission:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="User does not have permission to access this resource",
|
||||
)
|
||||
|
||||
if not crud.is_enabled():
|
||||
return CurrentVersion(version="0.00")
|
||||
|
||||
|
@ -222,9 +251,18 @@ async def upgrades(
|
|||
client_ip = x_forwarded_for
|
||||
else:
|
||||
client_ip = request.client.host
|
||||
|
||||
try:
|
||||
has_permission = True if audience.value in get_user_permissions(auth)["audience"] else False
|
||||
except Exception as exc:
|
||||
logger.error(f"Failed to get user permissions: {exc}")
|
||||
has_permission = False
|
||||
|
||||
data = {
|
||||
"action": "get_file_info",
|
||||
"ip": client_ip,
|
||||
"user": auth,
|
||||
"has_permission": has_permission,
|
||||
"auto_upgrade_host_identity": auto_upgrade_host_identity,
|
||||
"installed_version": installed_version,
|
||||
"group": group,
|
||||
|
@ -239,6 +277,12 @@ async def upgrades(
|
|||
except KeyError:
|
||||
logger.error("No statistics file set.")
|
||||
|
||||
if not has_permission:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="User does not have permission to access this resource",
|
||||
)
|
||||
|
||||
if not crud.is_enabled():
|
||||
raise HTTPException(
|
||||
status_code=503, detail="Service is currently disabled for maintenance"
|
||||
|
@ -307,9 +351,18 @@ async def download(
|
|||
client_ip = x_forwarded_for
|
||||
else:
|
||||
client_ip = request.client.host
|
||||
|
||||
try:
|
||||
has_permission = True if audience.value in get_user_permissions(auth)["audience"] else False
|
||||
except Exception as exc:
|
||||
logger.error(f"Failed to get user permissions: {exc}")
|
||||
has_permission = False
|
||||
|
||||
data = {
|
||||
"action": "download_upgrade",
|
||||
"ip": client_ip,
|
||||
"user": auth,
|
||||
"has_permission": has_permission,
|
||||
"auto_upgrade_host_identity": auto_upgrade_host_identity,
|
||||
"installed_version": installed_version,
|
||||
"group": group,
|
||||
|
@ -324,6 +377,12 @@ async def download(
|
|||
except KeyError:
|
||||
logger.error("No statistics file set.")
|
||||
|
||||
if not has_permission:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="User does not have permission to access this resource",
|
||||
)
|
||||
|
||||
if not crud.is_enabled():
|
||||
raise HTTPException(
|
||||
status_code=503, detail="Service is currently disabled for maintenance"
|
||||
|
|
Loading…
Add table
Reference in a new issue