From 616efd851d4b83e6344466ff33030d733e98979a Mon Sep 17 00:00:00 2001 From: arnoldknott Date: Fri, 6 Dec 2024 16:27:00 +0100 Subject: [PATCH 1/3] chore: disconnects frontend from redis at shutdown --- frontend_svelte/src/lib/server/cache.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend_svelte/src/lib/server/cache.ts b/frontend_svelte/src/lib/server/cache.ts index 8c5ad9b5..6a4d9f7a 100644 --- a/frontend_svelte/src/lib/server/cache.ts +++ b/frontend_svelte/src/lib/server/cache.ts @@ -78,7 +78,10 @@ class RedisCache { // TBD: stop the client when the server is stopped! public stopClient() { + this.redisClient?.disconnect(); + console.log('👍 🥞 cache - server - stopClient - redisClient disconnected'); this.redisClient?.quit(); + console.log('👍 🥞 cache - server - stopClient - redisClient quit') } public async setSession( @@ -156,6 +159,9 @@ class RedisCache { export const redisCache = new RedisCache(); + +process.on('exit', () => redisCache?.stopClient()); + // OLD CODE: // let redisClient: RedisClientType | null = null; From dccb242aaddf02a1695878782736d92c101b1cd7 Mon Sep 17 00:00:00 2001 From: arnoldknott Date: Fri, 6 Dec 2024 17:21:46 +0100 Subject: [PATCH 2/3] refactor: moves jwks into session database in redis - now all session management is gathered in a single place in redis --- .github/workflows/backendAPI.yml | 3 --- .github/workflows/infrastructure.yml | 2 -- backendAPI/src/.env.example | 1 - backendAPI/src/core/cache.py | 8 ++++---- backendAPI/src/core/config.py | 6 +++--- backendAPI/src/core/security.py | 9 ++++----- backendAPI/src/tests/.env.example | 1 - compose.override.test.yml | 3 --- frontend_svelte/src/.env.example | 1 - frontend_svelte/src/lib/server/cache.ts | 5 ++--- frontend_svelte/src/lib/server/config.ts | 8 ++++++-- infrastructure/.env.example | 1 - infrastructure/containerApps.tf | 4 ++-- infrastructure/variables.tf | 5 ----- scripts/deploy_infrastructure.sh | 4 ---- 15 files changed, 21 insertions(+), 40 deletions(-) diff --git a/.github/workflows/backendAPI.yml b/.github/workflows/backendAPI.yml index 6ebae0bd..b9402396 100644 --- a/.github/workflows/backendAPI.yml +++ b/.github/workflows/backendAPI.yml @@ -36,7 +36,6 @@ jobs: REDIS_ARGS: ${{ secrets.REDIS_ARGS }} REDIS_HOST: ${{ vars.REDIS_HOST }} REDIS_PORT: ${{ vars.REDIS_PORT }} - REDIS_JWKS_DB: ${{ vars.REDIS_JWKS_DB }} REDIS_SESSION_DB: ${{ vars.REDIS_SESSION_DB }} REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }} MONGODB_HOST: ${{ vars.MONGODB_HOST }} @@ -92,8 +91,6 @@ jobs: # echo $REDIS_HOST # echo "=== REDIS_PORT ===" # echo $REDIS_PORT - # echo "=== REDIS_JWKS_DB ===" - # echo $REDIS_JWKS_DB # echo "=== REDIS_SESSION_DB ===" # echo $REDIS_SESSION_DB - uses: actions/checkout@v4 diff --git a/.github/workflows/infrastructure.yml b/.github/workflows/infrastructure.yml index cfd235e2..ddf30f29 100644 --- a/.github/workflows/infrastructure.yml +++ b/.github/workflows/infrastructure.yml @@ -61,7 +61,6 @@ jobs: # Redis settings: REDIS_PORT: ${{ secrets.REDIS_PORT }} REDIS_INSIGHT_PORT: ${{ secrets.REDIS_INSIGHT_PORT }} - REDIS_JWKS_DB: ${{ secrets.REDIS_JWKS_DB }} REDIS_SESSION_DB: ${{ secrets.REDIS_SESSION_DB }} # public ssh key for the VM: SSH_PUBLIC_KEY: ${{ secrets.SSH_PUBLIC_KEY }} @@ -196,7 +195,6 @@ jobs: -var "postgres_port=${POSTGRES_PORT}" \ -var "redis_port=${REDIS_PORT}" \ -var "redis_insight_port=${REDIS_INSIGHT_PORT}" \ - -var "redis_jwks_db=${REDIS_JWKS_DB}" \ -var "redis_session_db=${REDIS_SESSION_DB}" \ -var "public_ssh_key_path=${PUBLIC_SSH_KEY_PATH}" diff --git a/backendAPI/src/.env.example b/backendAPI/src/.env.example index b934dc56..5f08b327 100644 --- a/backendAPI/src/.env.example +++ b/backendAPI/src/.env.example @@ -23,7 +23,6 @@ PGADMIN_DEFAULT_PASSWORD="" REDIS_HOST='' REDIS_PORT='' # sync database numbers with all other services! -REDIS_JWKS_DB='' REDIS_SESSION_DB='' REDIS_PASSWORD="" REDIS_ARGS="--save 500 1 --requirepass <...>" diff --git a/backendAPI/src/core/cache.py b/backendAPI/src/core/cache.py index ac72e230..31316220 100644 --- a/backendAPI/src/core/cache.py +++ b/backendAPI/src/core/cache.py @@ -8,14 +8,14 @@ # print(config.REDIS_HOST) # print("=== config.REDIS_PORT ===") # print(config.REDIS_PORT) -# print("=== config.REDIS_JWKS_DB ===") -# print(config.REDIS_JWKS_DB) +# print("=== config.REDIS_SESSION_DB ===") +# print(config.REDIS_SESSION_DB) -redis_jwks_client = redis.Redis( +redis_session_client = redis.Redis( host=config.REDIS_HOST, port=config.REDIS_PORT, password=config.REDIS_PASSWORD, - db=config.REDIS_JWKS_DB, + db=config.REDIS_SESSION_DB, ) # print("=== cache.py finished ===") diff --git a/backendAPI/src/core/config.py b/backendAPI/src/core/config.py index 66e83303..3b6309a5 100644 --- a/backendAPI/src/core/config.py +++ b/backendAPI/src/core/config.py @@ -112,9 +112,9 @@ def build_postgres_url(cls, url: Optional[str], values: ValidationInfo) -> Any: REDIS_PORT: int = int(os.getenv("REDIS_PORT")) # print("=== REDIS_PORT ===") # print(REDIS_PORT) - # print("=== get_variable('REDIS_REDIS_JWKS_DB') ===") - # print(get_variable("REDIS_JWKS_DB")) - REDIS_JWKS_DB: int = int(get_variable("REDIS_JWKS_DB")) + # print("=== get_variable('REDIS_REDIS_SESSION_DB') ===") + # print(get_variable("REDIS_SESSION_DB")) + REDIS_SESSION_DB: int = int(get_variable("REDIS_SESSION_DB")) REDIS_PASSWORD: str = get_variable("REDIS_PASSWORD") diff --git a/backendAPI/src/core/security.py b/backendAPI/src/core/security.py index 780d6cdf..ea515cc2 100644 --- a/backendAPI/src/core/security.py +++ b/backendAPI/src/core/security.py @@ -1,4 +1,3 @@ -import json import logging from typing import List, Optional @@ -11,7 +10,7 @@ from fastapi import Depends, HTTPException, Request from jwt.algorithms import RSAAlgorithm -from core.cache import redis_jwks_client +from core.cache import redis_session_client from core.config import config from core.types import CurrentUserData, GuardTypes from crud.identity import UserCRUD @@ -54,12 +53,12 @@ async def get_azure_jwks(no_cache: bool = False): if no_cache is False: # print("=== no_cache ===") # print(no_cache) - jwks = redis_jwks_client.json().get("jwks") + jwks = redis_session_client.json().get("jwks:microsoft") # print("=== jwks ===") # print(jwks) if jwks: # print("=== 🔑 JWKS fetched from cache ===") - return json.loads(jwks) + return jwks else: await get_azure_jwks(no_cache=True) else: @@ -78,7 +77,7 @@ async def get_azure_jwks(no_cache: bool = False): ) try: # TBD: for real multi-tenant applications, the cache-key should be tenant specific - redis_jwks_client.json().set("jwks", ".", json.dumps(jwks)) + redis_session_client.json().set("jwks:microsoft", ".", jwks) logger.info("🔑 Setting JWKs in cache") print("=== 🔑 JWKS set in cache ===") return jwks diff --git a/backendAPI/src/tests/.env.example b/backendAPI/src/tests/.env.example index faefe2f8..d81fe5e1 100644 --- a/backendAPI/src/tests/.env.example +++ b/backendAPI/src/tests/.env.example @@ -29,7 +29,6 @@ POSTGRES_PASSWORD="" REDIS_HOST="" REDIS_PORT="" # sync database numbers with all other services! -REDIS_JWKS_DB='' REDIS_SESSION_DB='' REDIS_PASSWORD="" REDIS_ARGS="--save 500 1 --requirepass <...>" diff --git a/compose.override.test.yml b/compose.override.test.yml index eec71ef7..5894d9d1 100644 --- a/compose.override.test.yml +++ b/compose.override.test.yml @@ -24,7 +24,6 @@ services: - POSTGRES_PASSWORD=$POSTGRES_PASSWORD - REDIS_HOST=$REDIS_HOST - REDIS_PORT=$REDIS_PORT - - REDIS_JWKS_DB=$REDIS_JWKS_DB - REDIS_SESSION_DB=$REDIS_SESSION_DB - REDIS_PASSWORD=$REDIS_PASSWORD networks: @@ -52,7 +51,6 @@ services: args: - REDIS_HOST=$REDIS_HOST - REDIS_PORT=$REDIS_PORT - - REDIS_JWKS_DB=$REDIS_JWKS_DB - REDIS_SESSION_DB=$REDIS_SESSION_DB - REDIS_PASSWORD=$REDIS_PASSWORD - APP_REG_CLIENT_ID=$APP_REG_CLIENT_ID @@ -62,7 +60,6 @@ services: environment: - REDIS_HOST=$REDIS_HOST - REDIS_PORT=$REDIS_PORT - - REDIS_JWKS_DB=$REDIS_JWKS_DB - REDIS_SESSION_DB=$REDIS_SESSION_DB - REDIS_PASSWORD=$REDIS_PASSWORD - APP_REG_CLIENT_ID=$APP_REG_CLIENT_ID diff --git a/frontend_svelte/src/.env.example b/frontend_svelte/src/.env.example index 6efe3d25..400a6750 100644 --- a/frontend_svelte/src/.env.example +++ b/frontend_svelte/src/.env.example @@ -18,7 +18,6 @@ API_SCOPE='' REDIS_HOST='' REDIS_PORT='' # sync database numbers with all other services! -REDIS_JWKS_DB='' REDIS_SESSION_DB='' REDIS_PASSWORD="" REDIS_ARGS="--save 500 1 --requirepass <...>" diff --git a/frontend_svelte/src/lib/server/cache.ts b/frontend_svelte/src/lib/server/cache.ts index 6a4d9f7a..eff14d70 100644 --- a/frontend_svelte/src/lib/server/cache.ts +++ b/frontend_svelte/src/lib/server/cache.ts @@ -40,7 +40,7 @@ class RedisCache { } } - // TBD: what about disconnecting? + // TBD: what about disconnecting? private async connectClient() { try { await this.redisClient?.connect(); @@ -81,7 +81,7 @@ class RedisCache { this.redisClient?.disconnect(); console.log('👍 🥞 cache - server - stopClient - redisClient disconnected'); this.redisClient?.quit(); - console.log('👍 🥞 cache - server - stopClient - redisClient quit') + console.log('👍 🥞 cache - server - stopClient - redisClient quit'); } public async setSession( @@ -159,7 +159,6 @@ class RedisCache { export const redisCache = new RedisCache(); - process.on('exit', () => redisCache?.stopClient()); // OLD CODE: diff --git a/frontend_svelte/src/lib/server/config.ts b/frontend_svelte/src/lib/server/config.ts index 8ae87236..6774a6ea 100644 --- a/frontend_svelte/src/lib/server/config.ts +++ b/frontend_svelte/src/lib/server/config.ts @@ -65,8 +65,12 @@ export default class AppConfig { // console.log("📜 app_config - process.env.AZ_CLIENT_ID:"); // console.log(process.env.AZ_CLIENT_ID); if (!process.env.AZ_CLIENT_ID || !process.env.AZ_KEYVAULT_HOST) { - console.error('🥞 app_config - server - connectKeyvault - keyvault connection data missing'); - throw new Error('🥞 app_config - server - connectKeyvault - keyvault connection data missing'); + console.error( + '🥞 app_config - server - connectKeyvault - keyvault connection data missing' + ); + throw new Error( + '🥞 app_config - server - connectKeyvault - keyvault connection data missing' + ); } const credential = new ManagedIdentityCredential(process.env.AZ_CLIENT_ID); const client = new SecretClient(process.env.AZ_KEYVAULT_HOST, credential); diff --git a/infrastructure/.env.example b/infrastructure/.env.example index 94fef4ae..6d8d5ab6 100644 --- a/infrastructure/.env.example +++ b/infrastructure/.env.example @@ -47,7 +47,6 @@ POSTGRES_PORT= # cache settings: REDIS_PORT = REDIS_INSIGHT_PORT = -REDIS_JWKS_DB = REDIS_SESSION_DB = # public ssh key for virtual machine login: diff --git a/infrastructure/containerApps.tf b/infrastructure/containerApps.tf index 41911b83..545371f5 100644 --- a/infrastructure/containerApps.tf +++ b/infrastructure/containerApps.tf @@ -216,8 +216,8 @@ resource "azurerm_container_app" "BackendContainer" { value = var.redis_port } env { - name = "REDIS_JWKS_DB" - value = var.redis_jwks_db + name = "REDIS_SESSION_DB" + value = var.redis_session_db } } volume { diff --git a/infrastructure/variables.tf b/infrastructure/variables.tf index db4d3903..706d8852 100644 --- a/infrastructure/variables.tf +++ b/infrastructure/variables.tf @@ -103,11 +103,6 @@ variable "redis_insight_port" { type = number } -variable "redis_jwks_db" { - description = "Database number for storing JSON Web Keys in Redis cache" - type = number -} - variable "redis_session_db" { description = "Database number for storing session data in Redis cache" type = number diff --git a/scripts/deploy_infrastructure.sh b/scripts/deploy_infrastructure.sh index 99d1406b..632a1514 100755 --- a/scripts/deploy_infrastructure.sh +++ b/scripts/deploy_infrastructure.sh @@ -187,7 +187,6 @@ tofu plan -out=${WORKSPACE}.tfplan \ -var "postgres_port=${POSTGRES_PORT}" \ -var "redis_port=${REDIS_PORT}" \ -var "redis_insight_port=${REDIS_INSIGHT_PORT}" \ - -var "redis_jwks_db=${REDIS_JWKS_DB}" \ -var "redis_session_db=${REDIS_SESSION_DB}" \ -var "public_ssh_key_path=${PUBLIC_SSH_KEY_PATH}"' @@ -214,7 +213,6 @@ tofu plan -out=${WORKSPACE}.tfplan \ # -var "postgres_port=${POSTGRES_PORT}" \ # -var "redis_port=${REDIS_PORT}" \ # -var "redis_insight_port=${REDIS_INSIGHT_PORT}" \ -# -var "redis_jwks_db=${REDIS_JWKS_DB}" \ # -var "redis_session_db=${REDIS_SESSION_DB}" \ # -var "public_ssh_key_path=${PUBLIC_SSH_KEY_PATH}" # -var "owner_user_principal_name=${OWNER_USER_PRINCIPAL_NAME}" \ @@ -300,7 +298,6 @@ exit $tofu_changes_applied # -var "postgres_port=${POSTGRES_PORT}" \ # -var "redis_port=${REDIS_PORT}" \ # -var "redis_insight_port=${REDIS_INSIGHT_PORT}" \ -# -var "redis_jwks_db=${REDIS_JWKS_DB}" \ # -var "redis_session_db=${REDIS_SESSION_DB}" \ # -var "public_ssh_key_path=${PUBLIC_SSH_KEY_PATH}" && # echo "=== tofu - approval before apply ===" && @@ -320,7 +317,6 @@ exit $tofu_changes_applied # -var "postgres_port=${POSTGRES_PORT}" \ # -var "redis_port=${REDIS_PORT}" \ # -var "redis_insight_port=${REDIS_INSIGHT_PORT}" \ - # -var "redis_jwks_db=${REDIS_JWKS_DB}" \ # -var "redis_session_db=${REDIS_SESSION_DB}" \ # -var "public_ssh_key_path=${PUBLIC_SSH_KEY_PATH}" && # tofu_plan_exit_code=$? && From ed98b82dc5df89173a7676e2c423c0803466a830 Mon Sep 17 00:00:00 2001 From: arnoldknott Date: Fri, 6 Dec 2024 17:54:55 +0100 Subject: [PATCH 3/3] refacotr: removes jwks database number from keyvault --- infrastructure/security.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/infrastructure/security.tf b/infrastructure/security.tf index 0814d0c4..81bccb04 100644 --- a/infrastructure/security.tf +++ b/infrastructure/security.tf @@ -307,12 +307,6 @@ resource "azurerm_key_vault_secret" "redisArgs" { key_vault_id = azurerm_key_vault.keyVault.id } -resource "azurerm_key_vault_secret" "redisJwksDb" { - name = "redis-jwks-db" - value = 14 - key_vault_id = azurerm_key_vault.keyVault.id -} - resource "azurerm_key_vault_secret" "redisSessionDb" { name = "redis-session-db" value = 15