From 2dab5ecc88cb9baa9bf9eb0dd1669da3dd4c8b95 Mon Sep 17 00:00:00 2001 From: Aravinda-HWK Date: Sun, 15 Feb 2026 09:30:46 +0530 Subject: [PATCH 1/3] feat: add Identity Provider Factory and Interface scripts --- scripts/idp/idp-factory.sh | 146 ++++++++++++++++++++++++++++++++ scripts/idp/idp-interface.sh | 157 +++++++++++++++++++++++++++++++++++ 2 files changed, 303 insertions(+) create mode 100644 scripts/idp/idp-factory.sh create mode 100644 scripts/idp/idp-interface.sh diff --git a/scripts/idp/idp-factory.sh b/scripts/idp/idp-factory.sh new file mode 100644 index 0000000..0778453 --- /dev/null +++ b/scripts/idp/idp-factory.sh @@ -0,0 +1,146 @@ +#!/bin/bash + + +# ============================================ +# Identity Provider Factory +# ============================================ +# +# This factory creates and returns the appropriate Identity Provider +# based on the configuration in silver.yaml +# +# Usage: +# source "$(dirname "$0")/../idp/idp-factory.sh" +# create_idp_provider "thunder" +# # Now you can call: thunder_initialize, thunder_wait_for_ready, etc. + + +# Get the directory where this script is located +IDP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROVIDERS_DIR="${IDP_DIR}/providers" + + +# Source the interface +source "${IDP_DIR}/idp-interface.sh" + + +# ============================================ +# Function: Create IdP Provider +# ============================================ +# Creates and initializes the specified Identity Provider +# +# Arguments: +# $1 - Provider name (thunder, keycloak, etc.) +# +# Returns: +# 0 on success, 1 on failure +# +# Exports: +# IDP_PROVIDER - The name of the loaded provider +# IDP_INITIALIZE - Function name for initialize +# IDP_WAIT_FOR_READY - Function name for wait_for_ready +# IDP_CONFIGURE - Function name for configure +# IDP_GET_COMPOSE_FILE - Function name for get_compose_file +# IDP_CLEANUP - Function name for cleanup +# ============================================ +create_idp_provider() { + local provider_name="$1" + + + if [ -z "$provider_name" ]; then + echo -e "${RED}✗ Provider name is required${NC}" >&2 + return 1 + fi + + + # Convert to lowercase + provider_name=$(echo "$provider_name" | tr '[:upper:]' '[:lower:]') + + + echo -e "${CYAN}Loading Identity Provider: ${provider_name}${NC}" + + + # Load the appropriate provider implementation + case "$provider_name" in + thunder) + if [ ! -f "${PROVIDERS_DIR}/thunder-idp.sh" ]; then + echo -e "${RED}✗ Thunder provider not found at ${PROVIDERS_DIR}/thunder-idp.sh${NC}" >&2 + return 1 + fi + source "${PROVIDERS_DIR}/thunder-idp.sh" + ;; + keycloak) + if [ ! -f "${PROVIDERS_DIR}/keycloak-idp.sh" ]; then + echo -e "${RED}✗ Keycloak provider not found at ${PROVIDERS_DIR}/keycloak-idp.sh${NC}" >&2 + return 1 + fi + source "${PROVIDERS_DIR}/keycloak-idp.sh" + ;; + *) + echo -e "${RED}✗ Unknown identity provider: ${provider_name}${NC}" >&2 + echo -e "${YELLOW}Supported providers: thunder, keycloak${NC}" >&2 + return 1 + ;; + esac + + + # Validate that the provider implements all required functions + if ! validate_provider_implementation "$provider_name"; then + echo -e "${RED}✗ Provider '${provider_name}' does not implement the required interface${NC}" >&2 + return 1 + fi + + + # Export provider information + export IDP_PROVIDER="$provider_name" + export IDP_INITIALIZE="${provider_name}_initialize" + export IDP_WAIT_FOR_READY="${provider_name}_wait_for_ready" + export IDP_CONFIGURE="${provider_name}_configure" + export IDP_GET_COMPOSE_FILE="${provider_name}_get_compose_file" + export IDP_CLEANUP="${provider_name}_cleanup" + + + echo -e "${GREEN}✓ Identity Provider '${provider_name}' loaded successfully${NC}" + return 0 +} + + +# ============================================ +# Function: Get Provider from Config +# ============================================ +# Reads the provider name from silver.yaml +# +# Arguments: +# $1 - Path to silver.yaml config file +# +# Returns: +# Provider name (stdout), empty if not found +# ============================================ +get_provider_from_config() { + local config_file="$1" + + + if [ ! -f "$config_file" ]; then + echo -e "${RED}✗ Configuration file not found: ${config_file}${NC}" >&2 + return 1 + fi + + + # Extract provider from YAML (simple grep-based parsing) + # Looking for: identity: + # provider: thunder + local provider=$(grep -A 1 '^identity:' "$config_file" | grep 'provider:' | sed 's/.*provider:\s*//' | xargs) + + + if [ -z "$provider" ]; then + echo -e "${YELLOW}⚠ No identity provider configured in ${config_file}${NC}" >&2 + echo -e "${YELLOW} Defaulting to 'thunder'${NC}" >&2 + echo "thunder" + else + echo "$provider" + fi +} + + +# Export functions +export -f create_idp_provider +export -f get_provider_from_config \ No newline at end of file diff --git a/scripts/idp/idp-interface.sh b/scripts/idp/idp-interface.sh new file mode 100644 index 0000000..5a27045 --- /dev/null +++ b/scripts/idp/idp-interface.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# ============================================ +# Identity Provider Interface Contract +# ============================================ +# +# This file defines the interface that all Identity Provider +# implementations must follow. It serves as a contract for the +# Strategy pattern. +# +# Each IdP provider must implement these functions: +# - _initialize() +# - _wait_for_ready() +# - _configure() +# - _get_compose_file() +# - _cleanup() +# +# Where is the name of the provider (e.g., thunder, keycloak) + +# Colors for output +CYAN="\033[0;36m" +GREEN="\033[0;32m" +YELLOW="\033[1;33m" +RED="\033[0;31m" +NC="\033[0m" # No Color + +# ============================================ +# Interface: initialize +# ============================================ +# Starts the Identity Provider service +# +# Arguments: +# $1 - Mail domain +# +# Returns: +# 0 on success, 1 on failure +# +# Example: +# thunder_initialize "example.com" +# keycloak_initialize "example.com" +# ============================================ + +# ============================================ +# Interface: wait_for_ready +# ============================================ +# Waits for the Identity Provider to be healthy and ready +# +# Arguments: +# $1 - IdP host +# $2 - IdP port +# +# Returns: +# 0 on success, 1 on timeout/failure +# +# Example: +# thunder_wait_for_ready "example.com" "8090" +# keycloak_wait_for_ready "example.com" "8080" +# ============================================ + +# ============================================ +# Interface: configure +# ============================================ +# Configures the Identity Provider with necessary settings +# This includes creating realms, clients, schemas, etc. +# +# Arguments: +# $1 - Mail domain +# +# Returns: +# 0 on success, 1 on failure +# +# Example: +# thunder_configure "example.com" +# keycloak_configure "example.com" +# ============================================ + +# ============================================ +# Interface: get_compose_file +# ============================================ +# Returns the path to the docker-compose file for this provider +# +# Arguments: +# None +# +# Returns: +# Path to docker-compose file (stdout) +# +# Example: +# compose_file=$(thunder_get_compose_file) +# compose_file=$(keycloak_get_compose_file) +# ============================================ + +# ============================================ +# Interface: cleanup +# ============================================ +# Cleans up and stops the Identity Provider service +# +# Arguments: +# None +# +# Returns: +# 0 on success, 1 on failure +# +# Example: +# thunder_cleanup +# keycloak_cleanup +# ============================================ + +# ============================================ +# Helper: Validate Provider Implementation +# ============================================ +# Validates that a provider implements all required functions +# +# Arguments: +# $1 - Provider name (e.g., "thunder", "keycloak") +# +# Returns: +# 0 if valid, 1 if missing functions +# ============================================ +validate_provider_implementation() { + local provider_name="$1" + + if [ -z "$provider_name" ]; then + echo -e "${RED}✗ Provider name is required for validation${NC}" >&2 + return 1 + fi + + local required_functions=( + "${provider_name}_initialize" + "${provider_name}_wait_for_ready" + "${provider_name}_configure" + "${provider_name}_get_compose_file" + "${provider_name}_cleanup" + ) + + local missing_functions=() + + for func in "${required_functions[@]}"; do + if ! declare -f "$func" > /dev/null 2>&1; then + missing_functions+=("$func") + fi + done + + if [ ${#missing_functions[@]} -gt 0 ]; then + echo -e "${RED}✗ Provider '${provider_name}' is missing required functions:${NC}" >&2 + for func in "${missing_functions[@]}"; do + echo -e "${RED} - ${func}${NC}" >&2 + done + return 1 + fi + + echo -e "${GREEN}✓ Provider '${provider_name}' implements all required functions${NC}" + return 0 +} + +# Export validation function +export -f validate_provider_implementation \ No newline at end of file From 53c225a7659604cc35c602cb64da351276665898 Mon Sep 17 00:00:00 2001 From: Aravinda-HWK Date: Sun, 15 Feb 2026 09:50:42 +0530 Subject: [PATCH 2/3] fix: streamline provider loading logic in create_idp_provider function --- scripts/idp/idp-factory.sh | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/scripts/idp/idp-factory.sh b/scripts/idp/idp-factory.sh index 0778453..f1dfc21 100644 --- a/scripts/idp/idp-factory.sh +++ b/scripts/idp/idp-factory.sh @@ -61,19 +61,13 @@ create_idp_provider() { # Load the appropriate provider implementation case "$provider_name" in - thunder) - if [ ! -f "${PROVIDERS_DIR}/thunder-idp.sh" ]; then - echo -e "${RED}✗ Thunder provider not found at ${PROVIDERS_DIR}/thunder-idp.sh${NC}" >&2 + thunder|keycloak) + local provider_script="${PROVIDERS_DIR}/${provider_name}-idp.sh" + if [ ! -f "$provider_script" ]; then + echo -e "${RED}✗ ${provider_name^} provider not found at ${provider_script}${NC}" >&2 return 1 fi - source "${PROVIDERS_DIR}/thunder-idp.sh" - ;; - keycloak) - if [ ! -f "${PROVIDERS_DIR}/keycloak-idp.sh" ]; then - echo -e "${RED}✗ Keycloak provider not found at ${PROVIDERS_DIR}/keycloak-idp.sh${NC}" >&2 - return 1 - fi - source "${PROVIDERS_DIR}/keycloak-idp.sh" + source "$provider_script" ;; *) echo -e "${RED}✗ Unknown identity provider: ${provider_name}${NC}" >&2 From b3617c315d4d32c60245031cd49c438a16f48987 Mon Sep 17 00:00:00 2001 From: Aravinda-HWK Date: Sun, 15 Feb 2026 09:56:20 +0530 Subject: [PATCH 3/3] fix: added end of file empty line --- scripts/idp/idp-factory.sh | 2 +- scripts/idp/idp-interface.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/idp/idp-factory.sh b/scripts/idp/idp-factory.sh index f1dfc21..1689606 100644 --- a/scripts/idp/idp-factory.sh +++ b/scripts/idp/idp-factory.sh @@ -137,4 +137,4 @@ get_provider_from_config() { # Export functions export -f create_idp_provider -export -f get_provider_from_config \ No newline at end of file +export -f get_provider_from_config diff --git a/scripts/idp/idp-interface.sh b/scripts/idp/idp-interface.sh index 5a27045..fabb1c3 100644 --- a/scripts/idp/idp-interface.sh +++ b/scripts/idp/idp-interface.sh @@ -154,4 +154,4 @@ validate_provider_implementation() { } # Export validation function -export -f validate_provider_implementation \ No newline at end of file +export -f validate_provider_implementation