From c53611925b30723fdb219862e75649300d566832 Mon Sep 17 00:00:00 2001 From: Daniel Pimenta <105205108+daniel-pimenta-DME@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:46:45 +0000 Subject: [PATCH] Release (#32) * Fix develop dockerfile * Change keycloak urls * Fix develop workflow tag * Fix production workflow * Change log message * Change config * Add health check * Fix health check * Add ready health endpoint * Fix issue * Change workflow filenames * Eoepca 910 um keycloak develop an identity api based on keycloak api (#17) * feat: policies endpoints added, not completely * feat: working on update policies * feat: all remaining added, still policy update not working, create and update scope based permission not working * feat: last resource permissions endpoints added and working * fix: changed pyyaml version from 5.4.1 to 5.3.1 * feat: endpoints changed * Update README * Update config * Update config * Update config * Api testing (#18) * feat: added client_id as param to enpoints and other fixes * added changes for permissions endpoints * Update ci * Update ci * Release v1.0.0 * Fix ci * Fix requirements * Fix ci * Upgrade flask version * Update requirements * feat: added error handling (#23) * feat: added validator of register and protect resource enpoint to test * feat: register and protect resources endpoint working * feat: added delete resources, policies and permissions * Update ci * Update ci * Fix ci * Add options method to endpoints * feat: added endpoint to create client, add resources and protect them if provided * Revert "Add options method to endpoints" This reverts commit 9d8c034a088b92e325f2cfa0b23cc6e754948767. * fea: commit fixes * feat: more fixes, some endpoint were dounbled * fix: last fix * Update ci * fix: policies fix, response now return client id and resources created * feat: create client default to confidential and authorization enabled * Convert to FastAPI * Convert to FastAPI * changes to models * Remove file * Add error handling, pydantic models, files restructuring * Fix issues * Handle keycloak error message * added fildes to models and descriptions * Add authenticated field * Clean and reformat * Point to keycloak client 1.0.0 * Change logging * Fix readme * Clean * Change logging * Clean * merge to develop * added default resource to response list * Create default resource * Fix policies issue * Improvements * Change keycloak client to v1.0.0 * Clarify readme * Add log file * Fix gitignore * Fix dockerfile * Change logging * Change settings to pydantic * Clean and reformat --------- Co-authored-by: flaviorosadme <82375986+flaviorosadme@users.noreply.github.com> Co-authored-by: flaviorosadme --- .dockerignore | 3 +- .env | 6 ++++ .gitignore | 2 -- Dockerfile | 3 +- app/configuration.py | 28 +++++++++++++++---- app/keycloak_client.py | 16 +++++------ app/log.py | 63 +++++++++++------------------------------- app/main.py | 10 +++---- config.ini | 11 -------- requirements.txt | 1 + 10 files changed, 60 insertions(+), 83 deletions(-) create mode 100644 .env delete mode 100644 config.ini diff --git a/.dockerignore b/.dockerignore index 6729cbd..8f3080b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ * !app !requirements.* -!config.ini -!um-identity-api.log \ No newline at end of file +!.env \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 0000000..bcc4ac8 --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +LOG_LEVEL=INFO +AUTH_SERVER_URL=http://localhost +ADMIN_USERNAME=admin +ADMIN_PASSWORD=admin +REALM=master +VERSION=v1.0.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 14488f4..d06caa4 100644 --- a/.gitignore +++ b/.gitignore @@ -53,8 +53,6 @@ cover/ # PyBuilder target/ -# Environments -.env .venv env/ diff --git a/Dockerfile b/Dockerfile index 7865790..1d57ac7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,6 @@ FROM python:3.12 WORKDIR /code COPY ./requirements.txt /code/requirements.txt RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -COPY ./config.ini /code/config.ini COPY ./app /code/app -COPY ./um-identity-api.log /code/um-identity-api.log +COPY .env /code CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "8080"] \ No newline at end of file diff --git a/app/configuration.py b/app/configuration.py index 1beff0e..852d297 100644 --- a/app/configuration.py +++ b/app/configuration.py @@ -1,8 +1,24 @@ -import os -from typing import Mapping +from functools import lru_cache -from identityutils.configuration import load_configuration +from pydantic_settings import BaseSettings, SettingsConfigDict -config: Mapping[str, str] = ( - load_configuration(os.path.join(os.path.dirname(__file__), "../config.ini")) -) \ No newline at end of file + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_file=".env") + + # Keycloak + auth_server_url: str = "http://localhost" + admin_username: str = "admin" + admin_password: str = "admin" + realm: str = "master" + + # Swagger + version: str = "v1.0.0" + + # Logging + log_level: str = "INFO" + + +@lru_cache +def get_settings(): + return Settings() \ No newline at end of file diff --git a/app/keycloak_client.py b/app/keycloak_client.py index 05585ee..21695c0 100644 --- a/app/keycloak_client.py +++ b/app/keycloak_client.py @@ -3,19 +3,19 @@ from retry.api import retry_call from urllib3.exceptions import NewConnectionError -from app.configuration import config +from app.configuration import get_settings from app.log import logger +settings = get_settings() + def __create_keycloak_client(): - auth_server_url = config.get("Keycloak", "auth_server_url") - realm = config.get("Keycloak", "realm") - logger.info("Starting Keycloak client for: " + auth_server_url + "/realms/" + realm) + logger.info("Starting Keycloak client for: " + settings.auth_server_url + "/realms/" + settings.realm) return KeycloakClient( - server_url=auth_server_url, - realm=realm, - username=config.get("Keycloak", "admin_username"), - password=config.get("Keycloak", "admin_password") + server_url=settings.auth_server_url, + realm=settings.realm, + username=settings.admin_username, + password=settings.admin_password, ) diff --git a/app/log.py b/app/log.py index 7844491..5d70869 100644 --- a/app/log.py +++ b/app/log.py @@ -1,61 +1,30 @@ import logging - from logging.config import dictConfig -from pydantic import BaseModel - -from app.configuration import config - - - -class LogConfig(BaseModel): - """Logging configuration to be set for the server""" - LOGGER_NAME: str = "mycoolapp" - LOG_FORMAT: str = "%(levelprefix)s | %(asctime)s | %(message)s" - level = config.get("App", "logging_level") - if not level: - level = 'INFO' - LOG_LEVEL: str = level.upper() +from app.configuration import get_settings - # Logging config - version = 1 - disable_existing_loggers = False - formatters = { +settings = get_settings() +logging_config = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { "default": { "()": "uvicorn.logging.DefaultFormatter", - "fmt": LOG_FORMAT, + "fmt": "%(levelprefix)s | %(asctime)s | %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", + }, - } - handlers = { + }, + "handlers": { "default": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stderr", }, - } - loggers = { - LOGGER_NAME: {"handlers": ["default"], "level": LOG_LEVEL}, - } - -def get_logging_level(): - level = config.get("App", "logging_level") - if not level: - level = 'info' - level = level.lower() - if level == 'critical' or level == 'critical': - return logging.CRITICAL - if level == 'error': - return logging.ERROR - if level == 'warning' or level == 'warn': - return logging.WARNING - if level == 'info': - return logging.INFO - if level == 'debug': - return logging.DEBUG - if level == 'notset': - return logging.NOTSET - - -dictConfig(LogConfig().model_dump()) + }, + "loggers": { + "um-identity-api": {"handlers": ["default"], "level": settings.log_level.upper()}, + }, +} +dictConfig(logging_config) logger = logging.getLogger("um-identity-api") \ No newline at end of file diff --git a/app/main.py b/app/main.py index 84d8ff4..ebf3610 100644 --- a/app/main.py +++ b/app/main.py @@ -5,15 +5,15 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse -from app.configuration import config +from app.configuration import get_settings from app.error_handling import exception_handler from app.routers import clients, health, policies, resources, clients_permissions, clients_resources, clients_policies - +settings = get_settings() app = FastAPI( - title=config.get("Swagger", "swagger_title"), - description=config.get("Swagger", "swagger_description"), - version=config.get("Swagger", "swagger_version"), + title="Identity API Documentation", + description="API endpoints", + version=settings.version, ) app.add_middleware( CORSMiddleware, diff --git a/config.ini b/config.ini deleted file mode 100644 index 09469c7..0000000 --- a/config.ini +++ /dev/null @@ -1,11 +0,0 @@ -[App] -logging_level = info -[Keycloak] -auth_server_url = http://localhost -admin_username = admin -admin_password = admin -realm = master -[Swagger] -swagger_title = Identity API Documentation -swagger_description = API endpoints -swagger_version = v1.0.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c5373c4..30322d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ configparser==6.0.0 retry==0.9.2 urllib3==2.0.7 pydantic==2.5.0 +pydantic-settings==2.1.0 identityutils @ git+https://github.com/eoepca/um-identity-service@v1.0.0 \ No newline at end of file