Hey all! So I need to start off by apologising if ...
# ask-community
k
Hey all! So I need to start off by apologising if this is the wrong channel to post this, but I'm having a rather simple issue that doesn't seem to make sense to me. Am I correct in assuming that there is no way to secure the Prefect Server deployment? Seems like this is a huge limitation for the open source solution?
1
f
for now there is no api key or token, but you can easily handle it by yourself
like in a reverse proxy ensure there is a basic auth
k
But if i'm interacting with
prefect-server
via the cli commands, there isn't a way to pass in the required basic auth values. So you wouldn't be able to have routing based authentication (as there is no way to pass in those auth headers)? It would need to be behind a VPN? So that there is no actual auth behind the htts://my-server-name.prefect.com/api ?
f
for prefect cloud (the SaaS product) there is auth, but for on-premise there isn't
1
k
@flapili Thanks so much 🙂
f
if you are on-premise it's pretty easy to add auth on top of prefect server
k
But for on-prem stuff, that would be auth that allows you access to the servers url, not actually an auth mechanism within prefect itself?
f
yes, for now auth mechanism is not yet build-in
1
there are various way to handle that
auth on reverse proxy, ssh tunnel, vpn / private network
k
Yup, 100%!
Thanks again for confirming my suspicions!
f
else, you could create a thin wrapper and bypass the cli
👀 2
give me few minutes I'll try the idea
@Kyle Hoffman
Copy code
# coding: utf-8
from secrets import compare_digest

from fastapi import Depends, FastAPI, status, Security, HTTPException
from fastapi.security.api_key import APIKeyQuery, APIKeyCookie, APIKeyHeader
from fastapi.openapi.utils import get_openapi
from prefect.server.api.server import create_orion_api, create_ui_app


def get_token(
    access_token_query: str | None = Security(APIKeyQuery(name="token", auto_error=False)),
    access_token_header: str | None = Security(APIKeyHeader(name="token", auto_error=False)),
    access_token_cookie: str | None = Security(APIKeyCookie(name="token", auto_error=False)),
):
    if access_token_query is not None:
        return access_token_query

    elif access_token_header is not None:
        return access_token_header

    elif access_token_cookie is not None:
        return access_token_cookie

    else:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="token is missing")


def verify_token(token=Depends(get_token)):
    if compare_digest(token, "secret") is False:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="bad token")


custom_app = FastAPI()
api_app = create_orion_api(dependencies=[Depends(verify_token)])
custom_app.mount("/api", api_app)
custom_app.mount("/", create_ui_app(ephemeral=False))


def openapi():
    partial_schema = get_openapi(title="Prefect API customized", version="0.1.0", routes=api_app.routes)
    new_schema = partial_schema.copy()
    new_schema["paths"] = {}
    for path, value in partial_schema["paths"].items():
        new_schema["paths"][f"/api{path}"] = value

    new_schema["info"]["x-logo"] = {"url": "static/prefect-logo-mark-gradient.png"}
    return new_schema


custom_app.openapi = openapi
a basic setup
🙌 1