Merge branch 'dev' into ui
# Conflicts: # app/main.py
This commit is contained in:
commit
6ef1216db6
27
.DEBIAN/env.default
Normal file
27
.DEBIAN/env.default
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Toggle debug mode
|
||||||
|
#DEBUG=false
|
||||||
|
|
||||||
|
# Where the client can find the DLS server
|
||||||
|
DLS_URL=127.0.0.1
|
||||||
|
DLS_PORT=443
|
||||||
|
|
||||||
|
# CORS configuration
|
||||||
|
## comma separated list without spaces
|
||||||
|
#CORS_ORIGINS="https://$DLS_URL:$DLS_PORT"
|
||||||
|
|
||||||
|
# Lease expiration in days
|
||||||
|
LEASE_EXPIRE_DAYS=90
|
||||||
|
LEASE_RENEWAL_PERIOD=0.2
|
||||||
|
|
||||||
|
# Database location
|
||||||
|
## https://docs.sqlalchemy.org/en/14/core/engines.html
|
||||||
|
DATABASE=sqlite:////etc/fastapi-dls/db.sqlite
|
||||||
|
|
||||||
|
# UUIDs for identifying the instance
|
||||||
|
#SITE_KEY_XID="00000000-0000-0000-0000-000000000000"
|
||||||
|
#INSTANCE_REF="10000000-0000-0000-0000-000000000001"
|
||||||
|
#ALLOTMENT_REF="20000000-0000-0000-0000-000000000001"
|
||||||
|
|
||||||
|
# Site-wide signing keys
|
||||||
|
INSTANCE_KEY_RSA=/etc/fastapi-dls/instance.private.pem
|
||||||
|
INSTANCE_KEY_PUB=/etc/fastapi-dls/instance.public.pem
|
25
.DEBIAN/fastapi-dls.service
Normal file
25
.DEBIAN/fastapi-dls.service
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Service for fastapi-dls
|
||||||
|
Documentation=https://git.collinwebdesigns.de/oscar.krause/fastapi-dls
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=www-data
|
||||||
|
Group=www-data
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
WorkingDirectory=/usr/share/fastapi-dls/app
|
||||||
|
EnvironmentFile=/etc/fastapi-dls/env
|
||||||
|
ExecStart=uvicorn main:app \
|
||||||
|
--env-file /etc/fastapi-dls/env \
|
||||||
|
--host $DLS_URL --port $DLS_PORT \
|
||||||
|
--app-dir /usr/share/fastapi-dls/app \
|
||||||
|
--ssl-keyfile /etc/fastapi-dls/webserver.key \
|
||||||
|
--ssl-certfile /etc/fastapi-dls/webserver.crt \
|
||||||
|
--proxy-headers
|
||||||
|
Restart=always
|
||||||
|
KillSignal=SIGQUIT
|
||||||
|
Type=simple
|
||||||
|
NotifyAccess=all
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -3,89 +3,26 @@
|
|||||||
WORKING_DIR=/usr/share/fastapi-dls
|
WORKING_DIR=/usr/share/fastapi-dls
|
||||||
CONFIG_DIR=/etc/fastapi-dls
|
CONFIG_DIR=/etc/fastapi-dls
|
||||||
|
|
||||||
echo "> Create config directory ..."
|
if [[ ! -f $CONFIG_DIR/instance.private.pem ]]; then
|
||||||
mkdir -p $CONFIG_DIR
|
echo "> Create dls-instance keypair ..."
|
||||||
|
openssl genrsa -out $CONFIG_DIR/instance.private.pem 2048
|
||||||
# normally we would define services in `conffiles` and as separate file, but we like to keep thinks simple.
|
openssl rsa -in $CONFIG_DIR/instance.private.pem -outform PEM -pubout -out $CONFIG_DIR/instance.public.pem
|
||||||
echo "> Install service ..."
|
else
|
||||||
cat <<EOF >/etc/systemd/system/fastapi-dls.service
|
echo "> Create dls-instance keypair skipped! (exists)"
|
||||||
[Unit]
|
|
||||||
Description=Service for fastapi-dls
|
|
||||||
Documentation=https://git.collinwebdesigns.de/oscar.krause/fastapi-dls
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=www-data
|
|
||||||
Group=www-data
|
|
||||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
||||||
WorkingDirectory=$WORKING_DIR/app
|
|
||||||
EnvironmentFile=$CONFIG_DIR/env
|
|
||||||
ExecStart=uvicorn main:app \\
|
|
||||||
--env-file /etc/fastapi-dls/env \\
|
|
||||||
--host \$DLS_URL --port \$DLS_PORT \\
|
|
||||||
--app-dir $WORKING_DIR/app \\
|
|
||||||
--ssl-keyfile /etc/fastapi-dls/webserver.key \\
|
|
||||||
--ssl-certfile /etc/fastapi-dls/webserver.crt \\
|
|
||||||
--proxy-headers
|
|
||||||
Restart=always
|
|
||||||
KillSignal=SIGQUIT
|
|
||||||
Type=simple
|
|
||||||
NotifyAccess=all
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl daemon-reload
|
|
||||||
|
|
||||||
# normally we would define configfiles in `conffiles` and as separate file, but we like to keep thinks simple.
|
|
||||||
if [[ ! -f $CONFIG_DIR/env ]]; then
|
|
||||||
echo "> Writing initial config ..."
|
|
||||||
touch $CONFIG_DIR/env
|
|
||||||
cat <<EOF >$CONFIG_DIR/env
|
|
||||||
# Toggle debug mode
|
|
||||||
#DEBUG=false
|
|
||||||
|
|
||||||
# Where the client can find the DLS server
|
|
||||||
DLS_URL=127.0.0.1
|
|
||||||
DLS_PORT=443
|
|
||||||
|
|
||||||
# CORS configuration
|
|
||||||
## comma separated list without spaces
|
|
||||||
#CORS_ORIGINS="https://$DLS_URL:$DLS_PORT"
|
|
||||||
|
|
||||||
# Lease expiration in days
|
|
||||||
LEASE_EXPIRE_DAYS=90
|
|
||||||
|
|
||||||
# Database location
|
|
||||||
## https://docs.sqlalchemy.org/en/14/core/engines.html
|
|
||||||
DATABASE=sqlite:///$CONFIG_DIR/db.sqlite
|
|
||||||
|
|
||||||
# UUIDs for identifying the instance
|
|
||||||
#SITE_KEY_XID="00000000-0000-0000-0000-000000000000"
|
|
||||||
#INSTANCE_REF="00000000-0000-0000-0000-000000000000"
|
|
||||||
|
|
||||||
# Site-wide signing keys
|
|
||||||
INSTANCE_KEY_RSA=$CONFIG_DIR/instance.private.pem
|
|
||||||
INSTANCE_KEY_PUB=$CONFIG_DIR/instance.public.pem
|
|
||||||
|
|
||||||
EOF
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "> Create dls-instance keypair ..."
|
|
||||||
openssl genrsa -out $CONFIG_DIR/instance.private.pem 2048
|
|
||||||
openssl rsa -in $CONFIG_DIR/instance.private.pem -outform PEM -pubout -out $CONFIG_DIR/instance.public.pem
|
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
read -p "> Do you wish to create self-signed webserver certificate? [Y/n]" yn
|
[[ -f $CONFIG_DIR/webserver.key ]] && default_answer="N" || default_answer="Y"
|
||||||
yn=${yn:-y} # ${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
|
[[ $default_answer == "Y" ]] && V="Y/n" || V="y/N"
|
||||||
|
read -p "> Do you wish to create self-signed webserver certificate? [${V}]" yn
|
||||||
|
yn=${yn:-$default_answer} # ${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
|
||||||
case $yn in
|
case $yn in
|
||||||
[Yy]*)
|
[Yy]*)
|
||||||
|
echo "> Generating keypair ..."
|
||||||
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout $CONFIG_DIR/webserver.key -out $CONFIG_DIR/webserver.crt
|
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout $CONFIG_DIR/webserver.key -out $CONFIG_DIR/webserver.crt
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
[Nn]*) break ;;
|
[Nn]*) echo "> Generating keypair skipped! (exists)"; break ;;
|
||||||
*) echo "Please answer [y] or [n]." ;;
|
*) echo "Please answer [y] or [n]." ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@ -115,7 +52,7 @@ cat <<EOF
|
|||||||
# Service should be up and running. #
|
# Service should be up and running. #
|
||||||
# Webservice is listen to https://localhost #
|
# Webservice is listen to https://localhost #
|
||||||
# #
|
# #
|
||||||
# Configuration is stored in ${CONFIG_DIR}/env #
|
# Configuration is stored in /etc/fastapi-dls/env. #
|
||||||
# #
|
# #
|
||||||
# #
|
# #
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
@ -47,7 +47,10 @@ build:apt:
|
|||||||
- cp README.md version.env build/usr/share/fastapi-dls
|
- cp README.md version.env build/usr/share/fastapi-dls
|
||||||
# create conf file
|
# create conf file
|
||||||
- mkdir -p build/etc/fastapi-dls
|
- mkdir -p build/etc/fastapi-dls
|
||||||
- touch build/etc/fastapi-dls/env
|
- cp .DEBIAN/env.default build/etc/fastapi-dls/env
|
||||||
|
# create service file
|
||||||
|
- mkdir -p build/etc/systemd/system
|
||||||
|
- cp .DEBIAN/fastapi-dls.service build/etc/systemd/system
|
||||||
# cd into "build/"
|
# cd into "build/"
|
||||||
- cd build/
|
- cd build/
|
||||||
script:
|
script:
|
||||||
@ -143,6 +146,7 @@ test:
|
|||||||
--proxy-headers &
|
--proxy-headers &
|
||||||
- FASTAPI_DLS_PID=$!
|
- FASTAPI_DLS_PID=$!
|
||||||
- echo "Started service with pid $FASTAPI_DLS_PID"
|
- echo "Started service with pid $FASTAPI_DLS_PID"
|
||||||
|
- cat /etc/fastapi-dls/env
|
||||||
# testing service
|
# testing service
|
||||||
- if [ "`curl --insecure -s https://127.0.0.1/-/health | jq .status`" != "up" ]; then echo "Success"; else "Error"; fi
|
- if [ "`curl --insecure -s https://127.0.0.1/-/health | jq .status`" != "up" ]; then echo "Success"; else "Error"; fi
|
||||||
# cleanup
|
# cleanup
|
||||||
|
@ -109,7 +109,7 @@ Goto [`docker-compose.yml`](docker-compose.yml) for more advanced example.
|
|||||||
version: '3.9'
|
version: '3.9'
|
||||||
|
|
||||||
x-dls-variables: &dls-variables
|
x-dls-variables: &dls-variables
|
||||||
DLS_URL: localhost # REQUIRED
|
DLS_URL: localhost # REQUIRED, change to your ip or hostname
|
||||||
DLS_PORT: 443
|
DLS_PORT: 443
|
||||||
LEASE_EXPIRE_DAYS: 90
|
LEASE_EXPIRE_DAYS: 90
|
||||||
DATABASE: sqlite:////app/database/db.sqlite
|
DATABASE: sqlite:////app/database/db.sqlite
|
||||||
@ -290,6 +290,7 @@ After first success you have to replace `--issue` with `--renew`.
|
|||||||
| `DEBUG` | `false` | Toggles `fastapi` debug mode |
|
| `DEBUG` | `false` | Toggles `fastapi` debug mode |
|
||||||
| `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable |
|
| `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||||
| `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable |
|
| `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||||
|
| `TOKEN_EXPIRE_DAYS` | `1` | Client auth-token validity (used for authenticate client against api, **not `.tok` file!**) |
|
||||||
| `LEASE_EXPIRE_DAYS` | `90` | Lease time in days |
|
| `LEASE_EXPIRE_DAYS` | `90` | Lease time in days |
|
||||||
| `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
|
| `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
|
||||||
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
||||||
|
82
app/main.py
82
app/main.py
@ -6,16 +6,16 @@ from os.path import join, dirname
|
|||||||
from os import getenv as env
|
from os import getenv as env
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI
|
||||||
from fastapi.requests import Request
|
from fastapi.requests import Request
|
||||||
import json
|
from json import loads as json_loads
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from calendar import timegm
|
from calendar import timegm
|
||||||
from jose import jws, jwk, jwt
|
from jose import jws, jwk, jwt, JWTError
|
||||||
from jose.constants import ALGORITHMS
|
from jose.constants import ALGORITHMS
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
from starlette.responses import StreamingResponse, JSONResponse, Response, RedirectResponse
|
from starlette.responses import StreamingResponse, JSONResponse as JSONr, HTMLResponse as HTMLr, Response, RedirectResponse
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from starlette.staticfiles import StaticFiles
|
from starlette.staticfiles import StaticFiles
|
||||||
@ -47,7 +47,7 @@ INSTANCE_REF = str(env('INSTANCE_REF', '10000000-0000-0000-0000-000000000001'))
|
|||||||
ALLOTMENT_REF = str(env('ALLOTMENT_REF', '20000000-0000-0000-0000-000000000001'))
|
ALLOTMENT_REF = str(env('ALLOTMENT_REF', '20000000-0000-0000-0000-000000000001'))
|
||||||
INSTANCE_KEY_RSA = load_key(str(env('INSTANCE_KEY_RSA', join(dirname(__file__), 'cert/instance.private.pem'))))
|
INSTANCE_KEY_RSA = load_key(str(env('INSTANCE_KEY_RSA', join(dirname(__file__), 'cert/instance.private.pem'))))
|
||||||
INSTANCE_KEY_PUB = load_key(str(env('INSTANCE_KEY_PUB', join(dirname(__file__), 'cert/instance.public.pem'))))
|
INSTANCE_KEY_PUB = load_key(str(env('INSTANCE_KEY_PUB', join(dirname(__file__), 'cert/instance.public.pem'))))
|
||||||
TOKEN_EXPIRE_DELTA = relativedelta(hours=1) # days=1
|
TOKEN_EXPIRE_DELTA = relativedelta(days=int(env('TOKEN_EXPIRE_DAYS', 1)), hours=int(env('TOKEN_EXPIRE_HOURS', 0)))
|
||||||
LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
|
LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
|
||||||
LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
|
LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
|
||||||
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
|
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
|
||||||
@ -85,12 +85,12 @@ async def _index(request: Request):
|
|||||||
|
|
||||||
@app.get('/-/health', summary='* Health')
|
@app.get('/-/health', summary='* Health')
|
||||||
async def _health(request: Request):
|
async def _health(request: Request):
|
||||||
return JSONResponse({'status': 'up'})
|
return JSONr({'status': 'up'})
|
||||||
|
|
||||||
|
|
||||||
@app.get('/-/config', summary='* Config', description='returns environment variables.')
|
@app.get('/-/config', summary='* Config', description='returns environment variables.')
|
||||||
async def _config():
|
async def _config():
|
||||||
return JSONResponse({
|
return JSONr({
|
||||||
'VERSION': str(VERSION),
|
'VERSION': str(VERSION),
|
||||||
'COMMIT': str(COMMIT),
|
'COMMIT': str(COMMIT),
|
||||||
'DEBUG': str(DEBUG),
|
'DEBUG': str(DEBUG),
|
||||||
@ -98,7 +98,7 @@ async def _config():
|
|||||||
'DLS_PORT': str(DLS_PORT),
|
'DLS_PORT': str(DLS_PORT),
|
||||||
'SITE_KEY_XID': str(SITE_KEY_XID),
|
'SITE_KEY_XID': str(SITE_KEY_XID),
|
||||||
'INSTANCE_REF': str(INSTANCE_REF),
|
'INSTANCE_REF': str(INSTANCE_REF),
|
||||||
'ALLOTMENT_REF': [ALLOTMENT_REF],
|
'ALLOTMENT_REF': [str(ALLOTMENT_REF)],
|
||||||
'TOKEN_EXPIRE_DELTA': str(TOKEN_EXPIRE_DELTA),
|
'TOKEN_EXPIRE_DELTA': str(TOKEN_EXPIRE_DELTA),
|
||||||
'LEASE_EXPIRE_DELTA': str(LEASE_EXPIRE_DELTA),
|
'LEASE_EXPIRE_DELTA': str(LEASE_EXPIRE_DELTA),
|
||||||
'LEASE_RENEWAL_PERIOD': str(LEASE_RENEWAL_PERIOD),
|
'LEASE_RENEWAL_PERIOD': str(LEASE_RENEWAL_PERIOD),
|
||||||
@ -146,7 +146,7 @@ async def _origins(request: Request, leases: bool = False):
|
|||||||
x['leases'] = list(map(lambda _: _.serialize(), Lease.find_by_origin_ref(db, origin.origin_ref)))
|
x['leases'] = list(map(lambda _: _.serialize(), Lease.find_by_origin_ref(db, origin.origin_ref)))
|
||||||
response.append(x)
|
response.append(x)
|
||||||
session.close()
|
session.close()
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
@app.delete('/-/origins', summary='* Origins')
|
@app.delete('/-/origins', summary='* Origins')
|
||||||
@ -159,7 +159,7 @@ async def _origins_delete(request: Request):
|
|||||||
async def _origins_delete_origin_ref(request: Request, origin_ref: str):
|
async def _origins_delete_origin_ref(request: Request, origin_ref: str):
|
||||||
if Origin.delete(db, origin_ref) == 1:
|
if Origin.delete(db, origin_ref) == 1:
|
||||||
return Response(status_code=201)
|
return Response(status_code=201)
|
||||||
raise JSONResponse(status_code=404, content={'status': 404, 'detail': 'lease not found'})
|
raise JSONr(status_code=404, content={'status': 404, 'detail': 'lease not found'})
|
||||||
|
|
||||||
|
|
||||||
@app.get('/-/leases', summary='* Leases')
|
@app.get('/-/leases', summary='* Leases')
|
||||||
@ -173,14 +173,14 @@ async def _leases(request: Request, origin: bool = False):
|
|||||||
x['origin'] = session.query(Origin).filter(Origin.origin_ref == lease.origin_ref).first().serialize()
|
x['origin'] = session.query(Origin).filter(Origin.origin_ref == lease.origin_ref).first().serialize()
|
||||||
response.append(x)
|
response.append(x)
|
||||||
session.close()
|
session.close()
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
@app.delete('/-/lease/{lease_ref}', summary='* Lease')
|
@app.delete('/-/lease/{lease_ref}', summary='* Lease')
|
||||||
async def _lease_delete(request: Request, lease_ref: str):
|
async def _lease_delete(request: Request, lease_ref: str):
|
||||||
if Lease.delete(db, lease_ref) == 1:
|
if Lease.delete(db, lease_ref) == 1:
|
||||||
return Response(status_code=201)
|
return Response(status_code=201)
|
||||||
raise HTTPException(status_code=404, detail='lease not found')
|
return JSONr(status_code=404, content={'status': 404, 'detail': 'lease not found'})
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_core_service_instance/service_instance_token_manager.py
|
# venv/lib/python3.9/site-packages/nls_core_service_instance/service_instance_token_manager.py
|
||||||
@ -232,7 +232,7 @@ async def _client_token():
|
|||||||
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py
|
||||||
@app.post('/auth/v1/origin', description='find or create an origin')
|
@app.post('/auth/v1/origin', description='find or create an origin')
|
||||||
async def auth_v1_origin(request: Request):
|
async def auth_v1_origin(request: Request):
|
||||||
j, cur_time = json.loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
j, cur_time = json_loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
||||||
|
|
||||||
origin_ref = j.get('candidate_origin_ref')
|
origin_ref = j.get('candidate_origin_ref')
|
||||||
logging.info(f'> [ origin ]: {origin_ref}: {j}')
|
logging.info(f'> [ origin ]: {origin_ref}: {j}')
|
||||||
@ -256,13 +256,13 @@ async def auth_v1_origin(request: Request):
|
|||||||
"sync_timestamp": cur_time.isoformat()
|
"sync_timestamp": cur_time.isoformat()
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py
|
||||||
@app.post('/auth/v1/origin/update', description='update an origin evidence')
|
@app.post('/auth/v1/origin/update', description='update an origin evidence')
|
||||||
async def auth_v1_origin_update(request: Request):
|
async def auth_v1_origin_update(request: Request):
|
||||||
j, cur_time = json.loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
j, cur_time = json_loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
||||||
|
|
||||||
origin_ref = j.get('origin_ref')
|
origin_ref = j.get('origin_ref')
|
||||||
logging.info(f'> [ update ]: {origin_ref}: {j}')
|
logging.info(f'> [ update ]: {origin_ref}: {j}')
|
||||||
@ -282,14 +282,14 @@ async def auth_v1_origin_update(request: Request):
|
|||||||
"sync_timestamp": cur_time.isoformat()
|
"sync_timestamp": cur_time.isoformat()
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_auth_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_auth_controller.py
|
||||||
# venv/lib/python3.9/site-packages/nls_core_auth/auth.py - CodeResponse
|
# venv/lib/python3.9/site-packages/nls_core_auth/auth.py - CodeResponse
|
||||||
@app.post('/auth/v1/code', description='get an authorization code')
|
@app.post('/auth/v1/code', description='get an authorization code')
|
||||||
async def auth_v1_code(request: Request):
|
async def auth_v1_code(request: Request):
|
||||||
j, cur_time = json.loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
j, cur_time = json_loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
||||||
|
|
||||||
origin_ref = j.get('origin_ref')
|
origin_ref = j.get('origin_ref')
|
||||||
logging.info(f'> [ code ]: {origin_ref}: {j}')
|
logging.info(f'> [ code ]: {origin_ref}: {j}')
|
||||||
@ -314,22 +314,27 @@ async def auth_v1_code(request: Request):
|
|||||||
"prompts": None
|
"prompts": None
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_auth_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_auth_controller.py
|
||||||
# venv/lib/python3.9/site-packages/nls_core_auth/auth.py - TokenResponse
|
# venv/lib/python3.9/site-packages/nls_core_auth/auth.py - TokenResponse
|
||||||
@app.post('/auth/v1/token', description='exchange auth code and verifier for token')
|
@app.post('/auth/v1/token', description='exchange auth code and verifier for token')
|
||||||
async def auth_v1_token(request: Request):
|
async def auth_v1_token(request: Request):
|
||||||
j, cur_time = json.loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
j, cur_time = json_loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
||||||
payload = jwt.decode(token=j.get('auth_code'), key=jwt_decode_key)
|
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(token=j.get('auth_code'), key=jwt_decode_key)
|
||||||
|
except JWTError as e:
|
||||||
|
return JSONr(status_code=400, content={'status': 400, 'title': 'invalid token', 'detail': str(e)})
|
||||||
|
|
||||||
origin_ref = payload.get('origin_ref')
|
origin_ref = payload.get('origin_ref')
|
||||||
logging.info(f'> [ auth ]: {origin_ref}: {j}')
|
logging.info(f'> [ auth ]: {origin_ref}: {j}')
|
||||||
|
|
||||||
# validate the code challenge
|
# validate the code challenge
|
||||||
if payload.get('challenge') != b64enc(sha256(j.get('code_verifier').encode('utf-8')).digest()).rstrip(b'=').decode('utf-8'):
|
challenge = b64enc(sha256(j.get('code_verifier').encode('utf-8')).digest()).rstrip(b'=').decode('utf-8')
|
||||||
raise HTTPException(status_code=401, detail='expected challenge did not match verifier')
|
if payload.get('challenge') != challenge:
|
||||||
|
return JSONr(status_code=401, content={'status': 401, 'detail': 'expected challenge did not match verifier'})
|
||||||
|
|
||||||
access_expires_on = cur_time + TOKEN_EXPIRE_DELTA
|
access_expires_on = cur_time + TOKEN_EXPIRE_DELTA
|
||||||
|
|
||||||
@ -352,13 +357,18 @@ async def auth_v1_token(request: Request):
|
|||||||
"sync_timestamp": cur_time.isoformat(),
|
"sync_timestamp": cur_time.isoformat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
||||||
@app.post('/leasing/v1/lessor', description='request multiple leases (borrow) for current origin')
|
@app.post('/leasing/v1/lessor', description='request multiple leases (borrow) for current origin')
|
||||||
async def leasing_v1_lessor(request: Request):
|
async def leasing_v1_lessor(request: Request):
|
||||||
j, token, cur_time = json.loads((await request.body()).decode('utf-8')), __get_token(request), datetime.utcnow()
|
j, token, cur_time = json_loads((await request.body()).decode('utf-8')), __get_token(request), datetime.utcnow()
|
||||||
|
|
||||||
|
try:
|
||||||
|
token = __get_token(request)
|
||||||
|
except JWTError:
|
||||||
|
return JSONr(status_code=401, content={'status': 401, 'detail': 'token is not valid'})
|
||||||
|
|
||||||
origin_ref = token.get('origin_ref')
|
origin_ref = token.get('origin_ref')
|
||||||
scope_ref_list = j.get('scope_ref_list')
|
scope_ref_list = j.get('scope_ref_list')
|
||||||
@ -367,7 +377,7 @@ async def leasing_v1_lessor(request: Request):
|
|||||||
lease_result_list = []
|
lease_result_list = []
|
||||||
for scope_ref in scope_ref_list:
|
for scope_ref in scope_ref_list:
|
||||||
# if scope_ref not in [ALLOTMENT_REF]:
|
# if scope_ref not in [ALLOTMENT_REF]:
|
||||||
# raise HTTPException(status_code=500, detail=f'no service instances found for scopes: ["{scope_ref}"]')
|
# return JSONr(status_code=500, detail=f'no service instances found for scopes: ["{scope_ref}"]')
|
||||||
|
|
||||||
lease_ref = str(uuid4())
|
lease_ref = str(uuid4())
|
||||||
expires = cur_time + LEASE_EXPIRE_DELTA
|
expires = cur_time + LEASE_EXPIRE_DELTA
|
||||||
@ -394,7 +404,7 @@ async def leasing_v1_lessor(request: Request):
|
|||||||
"prompts": None
|
"prompts": None
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
||||||
@ -414,7 +424,7 @@ async def leasing_v1_lessor_lease(request: Request):
|
|||||||
"prompts": None
|
"prompts": None
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
|
||||||
@ -428,7 +438,7 @@ async def leasing_v1_lease_renew(request: Request, lease_ref: str):
|
|||||||
|
|
||||||
entity = Lease.find_by_origin_ref_and_lease_ref(db, origin_ref, lease_ref)
|
entity = Lease.find_by_origin_ref_and_lease_ref(db, origin_ref, lease_ref)
|
||||||
if entity is None:
|
if entity is None:
|
||||||
raise HTTPException(status_code=404, detail='requested lease not available')
|
return JSONr(status_code=404, content={'status': 404, 'detail': 'requested lease not available'})
|
||||||
|
|
||||||
expires = cur_time + LEASE_EXPIRE_DELTA
|
expires = cur_time + LEASE_EXPIRE_DELTA
|
||||||
response = {
|
response = {
|
||||||
@ -442,7 +452,7 @@ async def leasing_v1_lease_renew(request: Request, lease_ref: str):
|
|||||||
|
|
||||||
Lease.renew(db, entity, expires, cur_time)
|
Lease.renew(db, entity, expires, cur_time)
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
|
||||||
@ -455,12 +465,12 @@ async def leasing_v1_lease_delete(request: Request, lease_ref: str):
|
|||||||
|
|
||||||
entity = Lease.find_by_lease_ref(db, lease_ref)
|
entity = Lease.find_by_lease_ref(db, lease_ref)
|
||||||
if entity.origin_ref != origin_ref:
|
if entity.origin_ref != origin_ref:
|
||||||
raise HTTPException(status_code=403, detail='access or operation forbidden')
|
return JSONr(status_code=403, content={'status': 403, 'detail': 'access or operation forbidden'})
|
||||||
if entity is None:
|
if entity is None:
|
||||||
raise HTTPException(status_code=404, detail='requested lease not available')
|
return JSONr(status_code=404, content={'status': 404, 'detail': 'requested lease not available'})
|
||||||
|
|
||||||
if Lease.delete(db, lease_ref) == 0:
|
if Lease.delete(db, lease_ref) == 0:
|
||||||
raise HTTPException(status_code=404, detail='lease not found')
|
return JSONr(status_code=404, content={'status': 404, 'detail': 'lease not found'})
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
"lease_ref": lease_ref,
|
"lease_ref": lease_ref,
|
||||||
@ -468,7 +478,7 @@ async def leasing_v1_lease_delete(request: Request, lease_ref: str):
|
|||||||
"sync_timestamp": cur_time.isoformat(),
|
"sync_timestamp": cur_time.isoformat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
|
||||||
@ -489,12 +499,12 @@ async def leasing_v1_lessor_lease_remove(request: Request):
|
|||||||
"prompts": None
|
"prompts": None
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
@app.post('/leasing/v1/lessor/shutdown', description='shutdown all leases')
|
@app.post('/leasing/v1/lessor/shutdown', description='shutdown all leases')
|
||||||
async def leasing_v1_lessor_shutdown(request: Request):
|
async def leasing_v1_lessor_shutdown(request: Request):
|
||||||
j, cur_time = json.loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
j, cur_time = json_loads((await request.body()).decode('utf-8')), datetime.utcnow()
|
||||||
|
|
||||||
token = j.get('token')
|
token = j.get('token')
|
||||||
token = jwt.decode(token=token, key=jwt_decode_key, algorithms=ALGORITHMS.RS256, options={'verify_aud': False})
|
token = jwt.decode(token=token, key=jwt_decode_key, algorithms=ALGORITHMS.RS256, options={'verify_aud': False})
|
||||||
@ -511,7 +521,7 @@ async def leasing_v1_lessor_shutdown(request: Request):
|
|||||||
"prompts": None
|
"prompts": None
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSONResponse(response)
|
return JSONr(response)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
version: '3.9'
|
version: '3.9'
|
||||||
|
|
||||||
x-dls-variables: &dls-variables
|
x-dls-variables: &dls-variables
|
||||||
DLS_URL: localhost # REQUIRED
|
DLS_URL: localhost # REQUIRED, change to your ip or hostname
|
||||||
DLS_PORT: 443 # must match nginx listen port
|
DLS_PORT: 443 # must match nginx listen port
|
||||||
LEASE_EXPIRE_DAYS: 90
|
LEASE_EXPIRE_DAYS: 90
|
||||||
DATABASE: sqlite:////app/database/db.sqlite
|
DATABASE: sqlite:////app/database/db.sqlite
|
||||||
|
Loading…
Reference in New Issue
Block a user