Source code for credproxy.routes
# SPDX-License-Identifier: MPL-2.0
# Copyright 2025-present John Mille <john@ews-network.net>
from __future__ import annotations
from flask import Blueprint, g, jsonify, request
from credproxy.logger import LOG
from credproxy.metrics import get_metrics
# Create a Blueprint for API routes
api_bp = Blueprint("api", __name__)
@api_bp.route("/health", methods=["GET", "HEAD"])
def health_check():
"""Health check endpoint."""
from flask import current_app
config = current_app.config.get("credproxy_config")
# Only log health checks if enabled in config or if there's an error
if config.server.log_health_checks:
LOG.info(
"Health check accessed", extra={"services_count": len(config.services)}
)
return jsonify({"status": "healthy", "services": len(config.services)})
@api_bp.route("/v1/credentials", methods=["GET"])
def get_credentials():
"""Get AWS credentials for a service."""
from flask import current_app
config = current_app.config.get("credproxy_config")
credentials_handler = current_app.config.get("credentials_handler")
provided_token = request.headers.get("Authorization")
# Use simplified logger for structured logging
if not provided_token:
LOG.warning("Request missing Authorization header")
return jsonify({"error": "Authorization header required"}), 401
try:
LOG.debug(
"Attempting token validation",
extra={
"token_prefix": provided_token[:8] + "...",
"total_services": len(config.services),
"available_services": list(config.services.keys()),
},
)
service_name = config.get_service_name_by_token(provided_token)
if not service_name:
LOG.warning(
"Invalid authorization token",
extra={
"token_prefix": provided_token[:8] + "...",
"total_services": len(config.services),
"available_services": list(config.services.keys()),
},
)
return jsonify({"error": "Invalid authorization token"}), 401
# Set service context in Flask g for logging
service = config.services[service_name]
g.service_name = service_name
g.service_source_file = service.source_file
LOG.info("Providing credentials for service")
credentials = credentials_handler.get_credentials(service_name)
return jsonify(credentials)
except Exception as error:
LOG.error("Error getting credentials")
LOG.exception(error)
return jsonify({"error": "Internal server error"}), 500
[docs]
def register_metrics_route(app, config):
"""Register metrics endpoint if enabled in configuration."""
# Register Flask route when metrics are enabled
# The separate Prometheus server functionality can be added later
if config.metrics.prometheus.enabled:
def metrics():
"""Prometheus metrics endpoint."""
try:
metrics_data = get_metrics()
return metrics_data, 200, {"Content-Type": "text/plain; version=0.0.4"}
except Exception as error:
LOG.error("Failed to generate metrics: %s", error)
return jsonify({"error": "Failed to generate metrics"}), 500
# Register the route directly on the app with static /metrics path
app.add_url_rule(
"/metrics", endpoint="metrics", view_func=metrics, methods=["GET"]
)