From 79c2cdfcb157a0b1046bf6e45afb8266ad74b9f9 Mon Sep 17 00:00:00 2001 From: Vallari Date: Wed, 16 Aug 2023 20:31:14 +0530 Subject: [PATCH 1/7] Login callback: redirect to pulpito with session cookies Signed-off-by: Vallari --- src/routes/login.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/routes/login.py b/src/routes/login.py index ef1dcf3..80833c9 100644 --- a/src/routes/login.py +++ b/src/routes/login.py @@ -1,7 +1,7 @@ import logging import os from fastapi import APIRouter, HTTPException, Request -from starlette.responses import RedirectResponse +from fastapi.responses import RedirectResponse from dotenv import load_dotenv import httpx @@ -12,6 +12,7 @@ GH_AUTHORIZATION_BASE_URL = os.getenv("GH_AUTHORIZATION_BASE_URL") GH_TOKEN_URL = os.getenv("GH_TOKEN_URL") GH_FETCH_MEMBERSHIP_URL = os.getenv("GH_FETCH_MEMBERSHIP_URL") +PULPITO_URL = os.getenv("PULPITO_URL") log = logging.getLogger(__name__) router = APIRouter( @@ -82,4 +83,7 @@ async def handle_callback(code: str, request: Request): "access_token": token, } request.session["user"] = data - return RedirectResponse(url="/") + cookie = "; ".join([f'{str(key)}={str(value)}' for key, value in {"username": data["username"]}]) + response = RedirectResponse(PULPITO_URL) + response.set_cookie(key="GH_USER", value=cookie) + return response From c22ea9e918078a67c8b9e415751d67eaca731a57 Mon Sep 17 00:00:00 2001 From: Vallari Date: Wed, 16 Aug 2023 20:31:36 +0530 Subject: [PATCH 2/7] main: change 'allow_origins' from * to URLs To send cross site requests from pulpito-ng with `withCredentials`, the server cannot have `*` as allowed origins. Signed-off-by: Vallari --- src/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index b4f4313..b04fba8 100644 --- a/src/main.py +++ b/src/main.py @@ -10,6 +10,8 @@ DEPLOYMENT = os.getenv("DEPLOYMENT") SESSION_SECRET_KEY = os.getenv("SESSION_SECRET_KEY") +PULPITO_URL = os.getenv("PULPITO_URL") +PADDLES_URL = os.getenv("PADDLES_URL") log = logging.getLogger(__name__) app = FastAPI() @@ -26,7 +28,7 @@ def read_root(request: Request): if DEPLOYMENT == "development": app.add_middleware( CORSMiddleware, - allow_origins=["*"], + allow_origins=[PULPITO_URL, PADDLES_URL], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], From 50ff7d0c61b215beb4c29b7e63fbc5a8f17683c7 Mon Sep 17 00:00:00 2001 From: Vallari Date: Wed, 16 Aug 2023 21:11:40 +0530 Subject: [PATCH 3/7] fix cookie_data.items() error Signed-off-by: Vallari --- src/routes/login.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/login.py b/src/routes/login.py index 80833c9..7b1f924 100644 --- a/src/routes/login.py +++ b/src/routes/login.py @@ -83,7 +83,10 @@ async def handle_callback(code: str, request: Request): "access_token": token, } request.session["user"] = data - cookie = "; ".join([f'{str(key)}={str(value)}' for key, value in {"username": data["username"]}]) + cookie_data = {"username": data["username"]} + cookie = "; ".join( + [f"{str(key)}={str(value)}" for key, value in cookie_data.items()] + ) response = RedirectResponse(PULPITO_URL) response.set_cookie(key="GH_USER", value=cookie) return response From b1e4ea7cec5078b24613e0fd6b1e9558886abdfb Mon Sep 17 00:00:00 2001 From: Vallari Date: Thu, 17 Aug 2023 13:13:50 +0530 Subject: [PATCH 4/7] add .env.dev Signed-off-by: Vallari --- .env.dev | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .env.dev diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..84a3ae6 --- /dev/null +++ b/.env.dev @@ -0,0 +1,13 @@ +DEPLOYMENT=development +PADDLES_URL=http://localhost:8080 +PULPITO_URL=http://localhost:8081 + +# Github Related Stuff +GH_CLIENT_ID= +GH_CLIENT_SECRET= +GH_AUTHORIZATION_BASE_URL='https://github.com/login/oauth/authorize' +GH_TOKEN_URL='https://github.com/login/oauth/access_token' +GH_FETCH_MEMBERSHIP_URL='https://api.github.com/user/memberships/orgs/ceph' + +#Session Related Stuff +SESSION_SECRET_KEY= \ No newline at end of file From 2deffd6488e6504d3ee9eeda458f4ca89c6106bd Mon Sep 17 00:00:00 2001 From: Vallari Date: Thu, 17 Aug 2023 18:01:55 +0530 Subject: [PATCH 5/7] add avatar_url in /login response and redirect /logout to pulpito-ng Signed-off-by: Vallari --- src/routes/login.py | 5 ++++- src/routes/logout.py | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/routes/login.py b/src/routes/login.py index 7b1f924..e803c7a 100644 --- a/src/routes/login.py +++ b/src/routes/login.py @@ -83,7 +83,10 @@ async def handle_callback(code: str, request: Request): "access_token": token, } request.session["user"] = data - cookie_data = {"username": data["username"]} + cookie_data = { + "username": data["username"], + "avatar_url": response_org_dic.get("user", {}).get("avatar_url"), + } cookie = "; ".join( [f"{str(key)}={str(value)}" for key, value in cookie_data.items()] ) diff --git a/src/routes/logout.py b/src/routes/logout.py index d8927b2..bba1cc8 100644 --- a/src/routes/logout.py +++ b/src/routes/logout.py @@ -1,7 +1,10 @@ -import logging +import logging, os from fastapi import APIRouter, HTTPException, Request +from fastapi.responses import RedirectResponse +PULPITO_URL = os.getenv("PULPITO_URL") log = logging.getLogger(__name__) + router = APIRouter( prefix="/logout", tags=["logout"], @@ -17,7 +20,7 @@ def logout(request: Request): user = request.session.get("user") if user: request.session.pop("user", None) - return {"logout": "success"} + return RedirectResponse(PULPITO_URL) log.warning("No session found, probably already logged out.") raise HTTPException( status_code=204, detail="No session found, probably already logged out." From 315dbc72f8fba6f052d187c55d70dfe6815ed04d Mon Sep 17 00:00:00 2001 From: Vallari Agrawal Date: Mon, 21 Aug 2023 16:00:12 +0530 Subject: [PATCH 6/7] login: add error handling for missing env variable Signed-off-by: Vallari Agrawal --- src/routes/login.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/routes/login.py b/src/routes/login.py index e803c7a..c4916a2 100644 --- a/src/routes/login.py +++ b/src/routes/login.py @@ -28,6 +28,8 @@ async def github_login(): GET route for /login, (If first time) will redirect to github login page where you should authorize the app to gain access. """ + if not GH_AUTHORIZATION_BASE_URL or not GH_CLIENT_ID: + return HTTPException(status_code=500, detail="Environment secrets are missing.") scope = "read:org" return RedirectResponse( f"{GH_AUTHORIZATION_BASE_URL}?client_id={GH_CLIENT_ID}&scope={scope}", From aa0461547bde017f5b8d4a1d3e97347b9f06adbd Mon Sep 17 00:00:00 2001 From: Vallari Agrawal Date: Mon, 21 Aug 2023 16:01:01 +0530 Subject: [PATCH 7/7] README: add instructions to configure github oauth And add random value of SESSION_SECRET_KEY in .env.dev Signed-off-by: Vallari Agrawal --- .env.dev | 4 +++- README.md | 13 +++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.env.dev b/.env.dev index 84a3ae6..8aa1f0f 100644 --- a/.env.dev +++ b/.env.dev @@ -10,4 +10,6 @@ GH_TOKEN_URL='https://github.com/login/oauth/access_token' GH_FETCH_MEMBERSHIP_URL='https://api.github.com/user/memberships/orgs/ceph' #Session Related Stuff -SESSION_SECRET_KEY= \ No newline at end of file +## SESSION_SECRET_KEY is used to encrypt session data +## and it's prod value should be kept secret. +SESSION_SECRET_KEY=my-secret-key \ No newline at end of file diff --git a/README.md b/README.md index 6de2513..13e864b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,16 @@ A REST API to execute [teuthology commands](https://docs.ceph.com/projects/teuth #### Option 1: (teuthology docker setup) 1. Clone [teuthology](https://github.com/ceph/teuthology) and [teuthology-api](https://github.com/VallariAg/teuthology-api). -2. Add the following to [teuthology's docker-compose](https://github.com/ceph/teuthology/blob/main/docs/docker-compose/docker-compose.yml) services. +2. Rename `.env.dev` file to `.env`. +3. Configure secrets: + + 3.1. Create a Github OAuth Application by following [these](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) instructions. Set "Homepage URL" as `http://localhost:8082/` and "Authorization callback URL" as `http://localhost:8082/login/callback/`. + + 3.2. Ensure [ceph](https://github.com/ceph) belongs in your public list of organizations[[ref](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-membership-in-organizations/about-organization-membership)]. By default your membership is set private, change that to public by following [these](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-membership-in-organizations/publicizing-or-hiding-organization-membership) steps. + + 3.3. Save `CLIENT_ID` and `CLIENT_SECRET` from your Github OAuth App to your local `.env` file as `GH_CLIENT_ID` and `GH_CLIENT_SECRET`. + +4. Add the following to [teuthology's docker-compose](https://github.com/ceph/teuthology/blob/main/docs/docker-compose/docker-compose.yml) services. ``` teuthology_api: build: @@ -21,7 +30,7 @@ A REST API to execute [teuthology commands](https://docs.ceph.com/projects/teuth - teuthology - paddles ``` -3. Follow teuthology development setup instructions from [here](https://github.com/ceph/teuthology/tree/main/docs/docker-compose). +5. Follow teuthology development setup instructions from [here](https://github.com/ceph/teuthology/tree/main/docs/docker-compose). ## Documentation