cancan-microstack 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cancan_microstack/__init__.py +14 -0
- cancan_microstack/__version__.py +10 -0
- cancan_microstack/assets/__init__.py +6 -0
- cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
- cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
- cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
- cancan_microstack/assets/builds/caddy/README.md +343 -0
- cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
- cancan_microstack/assets/builds/caddy/start.sh +78 -0
- cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
- cancan_microstack/assets/builds/service/Dockerfile +59 -0
- cancan_microstack/assets/builds/service/README.md +13 -0
- cancan_microstack/assets/ddl/create_db.sql +22 -0
- cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
- cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
- cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
- cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
- cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
- cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
- cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
- cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
- cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
- cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
- cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
- cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
- cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
- cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
- cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
- cancan_microstack/assets/ddl/trigger.sql +21 -0
- cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
- cancan_microstack/assets/scripts/README.md +195 -0
- cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
- cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
- cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
- cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
- cancan_microstack/assets/scripts/docker/restart.sh +35 -0
- cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
- cancan_microstack/assets/scripts/docker/start.sh +78 -0
- cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
- cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
- cancan_microstack/assets/scripts/docker/stop.sh +67 -0
- cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
- cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
- cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
- cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
- cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
- cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
- cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
- cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
- cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
- cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
- cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
- cancan_microstack/assets/scripts/podman/stop.sh +73 -0
- cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
- cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
- cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
- cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
- cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
- cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
- cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
- cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
- cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
- cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
- cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
- cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
- cancan_microstack/assets/service/Dockerfile +65 -0
- cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
- cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
- cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
- cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
- cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
- cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
- cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
- cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
- cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
- cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
- cancan_microstack/assets/www/adminops/index.html +16 -0
- cancan_microstack/assets/www/adminops/vite.svg +1 -0
- cancan_microstack/cli/__init__.py +14 -0
- cancan_microstack/cli/__main__.py +9 -0
- cancan_microstack/cli/main.py +552 -0
- cancan_microstack/cmd/__init__.py +54 -0
- cancan_microstack/cmd/cancan/__init__.py +12 -0
- cancan_microstack/cmd/cancan/run.py +395 -0
- cancan_microstack/cmd/controllersrv/__init__.py +0 -0
- cancan_microstack/cmd/controllersrv/run.py +131 -0
- cancan_microstack/cmd/infrasrv/__init__.py +5 -0
- cancan_microstack/cmd/infrasrv/run.py +100 -0
- cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
- cancan_microstack/cmd/opsbffsrv/run.py +96 -0
- cancan_microstack/core/__init__.py +5 -0
- cancan_microstack/core/assets.py +123 -0
- cancan_microstack/core/compose_builder.py +102 -0
- cancan_microstack/core/doctor.py +152 -0
- cancan_microstack/core/microstack.py +71 -0
- cancan_microstack/core/runner.py +56 -0
- cancan_microstack/core/stack_manager.py +186 -0
- cancan_microstack/public/__init__.py +7 -0
- cancan_microstack/public/api/__init__.py +1 -0
- cancan_microstack/public/api/controllersrv_client.py +277 -0
- cancan_microstack/public/api/infrasrv_client.py +404 -0
- cancan_microstack/public/const/__init__.py +1 -0
- cancan_microstack/public/const/action_consts.py +18 -0
- cancan_microstack/public/const/app_consts.py +42 -0
- cancan_microstack/public/const/caddy_consts.py +22 -0
- cancan_microstack/public/const/controllersrv_consts.py +163 -0
- cancan_microstack/public/const/docker_consts.py +15 -0
- cancan_microstack/public/const/error.py +56 -0
- cancan_microstack/public/const/health_consts.py +52 -0
- cancan_microstack/public/const/hook_enums.py +56 -0
- cancan_microstack/public/const/logging_enums.py +13 -0
- cancan_microstack/public/const/metrics_enums.py +36 -0
- cancan_microstack/public/const/monitor_enums.py +26 -0
- cancan_microstack/public/const/operation_consts.py +53 -0
- cancan_microstack/public/const/opsbffsrv_error.py +92 -0
- cancan_microstack/public/const/overrides_consts.py +13 -0
- cancan_microstack/public/const/redis.py +17 -0
- cancan_microstack/public/const/service_consts.py +15 -0
- cancan_microstack/public/const/workflow_consts.py +65 -0
- cancan_microstack/public/error.py +41 -0
- cancan_microstack/public/logging/__init__.py +0 -0
- cancan_microstack/public/logging/initializer.py +109 -0
- cancan_microstack/public/logging/mq_handler.py +279 -0
- cancan_microstack/public/schemas/__init__.py +1 -0
- cancan_microstack/public/schemas/caddy/__init__.py +381 -0
- cancan_microstack/public/schemas/caddy/analysis.py +90 -0
- cancan_microstack/public/schemas/caddy/route.py +18 -0
- cancan_microstack/public/schemas/common.py +79 -0
- cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
- cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
- cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
- cancan_microstack/public/schemas/controllersrv/const.py +24 -0
- cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
- cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
- cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
- cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
- cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
- cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
- cancan_microstack/public/schemas/hook_metrics.py +124 -0
- cancan_microstack/public/schemas/hooks.py +39 -0
- cancan_microstack/public/schemas/infra/__init__.py +0 -0
- cancan_microstack/public/schemas/infra/cleanup.py +25 -0
- cancan_microstack/public/schemas/infra/container.py +74 -0
- cancan_microstack/public/schemas/infra/enums.py +135 -0
- cancan_microstack/public/schemas/infra/health_check.py +42 -0
- cancan_microstack/public/schemas/infra/hook_log.py +42 -0
- cancan_microstack/public/schemas/infra/operation.py +90 -0
- cancan_microstack/public/schemas/infra/overview.py +25 -0
- cancan_microstack/public/schemas/infra/push.py +33 -0
- cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
- cancan_microstack/public/schemas/infra/service_config.py +10 -0
- cancan_microstack/public/schemas/infra/service_info.py +69 -0
- cancan_microstack/public/schemas/infra/service_instance.py +93 -0
- cancan_microstack/public/schemas/infra/service_management.py +152 -0
- cancan_microstack/public/schemas/infra/service_operation.py +79 -0
- cancan_microstack/public/schemas/infra/service_registry.py +158 -0
- cancan_microstack/public/schemas/infra/status_types.py +19 -0
- cancan_microstack/public/schemas/infra/workflow.py +566 -0
- cancan_microstack/public/schemas/logging/__init__.py +1 -0
- cancan_microstack/public/schemas/logging/log_event.py +121 -0
- cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
- cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
- cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
- cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
- cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
- cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
- cancan_microstack/public/schemas/service_operation.py +24 -0
- cancan_microstack/public/schemas/service_registry.py +40 -0
- cancan_microstack/public/types/__init__.py +7 -0
- cancan_microstack/public/web/__init__.py +0 -0
- cancan_microstack/public/web/config_value.py +105 -0
- cancan_microstack/public/web/server.py +385 -0
- cancan_microstack/py.typed +0 -0
- cancan_microstack/runtime/__init__.py +0 -0
- cancan_microstack/runtime/compose_cmd.py +228 -0
- cancan_microstack/runtime/host_daemon.py +318 -0
- cancan_microstack/runtime/overrides.py +103 -0
- cancan_microstack/runtime/resources.py +25 -0
- cancan_microstack/runtime/workspace.py +94 -0
- cancan_microstack/services/__init__.py +0 -0
- cancan_microstack/services/controllersrv/__init__.py +8 -0
- cancan_microstack/services/controllersrv/application/__init__.py +0 -0
- cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
- cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
- cancan_microstack/services/controllersrv/conf/config.py +76 -0
- cancan_microstack/services/controllersrv/conf/settings.py +54 -0
- cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
- cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
- cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
- cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
- cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
- cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
- cancan_microstack/services/controllersrv/router.py +132 -0
- cancan_microstack/services/infrasrv/__init__.py +4 -0
- cancan_microstack/services/infrasrv/application/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
- cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
- cancan_microstack/services/infrasrv/application/service_config.py +22 -0
- cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
- cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
- cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
- cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
- cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
- cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
- cancan_microstack/services/infrasrv/conf/config.py +98 -0
- cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
- cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
- cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
- cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
- cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
- cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
- cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
- cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
- cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
- cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
- cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
- cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
- cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
- cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
- cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
- cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
- cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
- cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
- cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
- cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
- cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
- cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
- cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
- cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
- cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
- cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
- cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
- cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
- cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
- cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
- cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
- cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
- cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
- cancan_microstack/services/infrasrv/router.py +341 -0
- cancan_microstack/services/opsbffsrv/__init__.py +4 -0
- cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
- cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
- cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
- cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
- cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
- cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
- cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
- cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
- cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
- cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
- cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
- cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
- cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
- cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
- cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
- cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
- cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
- cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
- cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
- cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
- cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
- cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
- cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
- cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
- cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
- cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
- cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
- cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
- cancan_microstack/services/opsbffsrv/router.py +901 -0
- cancan_microstack/utils/__init__.py +1 -0
- cancan_microstack/utils/container_env.py +218 -0
- cancan_microstack-0.0.1.dist-info/METADATA +155 -0
- cancan_microstack-0.0.1.dist-info/RECORD +440 -0
- cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
- cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
- cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
- cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from linglong_web import LinglongConfigBase
|
|
7
|
+
|
|
8
|
+
from cancan_microstack.runtime.resources import resolve_workspace_or_asset
|
|
9
|
+
from cancan_microstack.runtime.workspace import configure_workspace, ensure_server_log_dir
|
|
10
|
+
|
|
11
|
+
_WORKSPACE_ROOT = str(configure_workspace())
|
|
12
|
+
ensure_server_log_dir()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _build_basic_auth(username: str, password: str) -> str:
|
|
16
|
+
"""构建 Basic Auth 头 / Build HTTP Basic Authorization header."""
|
|
17
|
+
|
|
18
|
+
token = base64.b64encode(f"{username}:{password}".encode("latin1")).decode("ascii")
|
|
19
|
+
return f"Basic {token}"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _resolve_compose_file(project_root: str) -> str | None:
|
|
23
|
+
"""Resolve docker-compose file path, preferring env overrides."""
|
|
24
|
+
env_override = os.getenv("DBADMIN_COMPOSE_FILE")
|
|
25
|
+
if env_override:
|
|
26
|
+
return env_override
|
|
27
|
+
|
|
28
|
+
candidates = (
|
|
29
|
+
os.path.join(project_root, "docker-compose.yml"),
|
|
30
|
+
os.path.join(project_root, "docker-compose.infra.yml"),
|
|
31
|
+
)
|
|
32
|
+
for candidate in candidates:
|
|
33
|
+
if os.path.exists(candidate):
|
|
34
|
+
return candidate
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class _BaseConfig(LinglongConfigBase):
|
|
39
|
+
"""基础配置"""
|
|
40
|
+
DEBUG = False
|
|
41
|
+
|
|
42
|
+
# 项目根目录(动态获取)
|
|
43
|
+
_PROJECT_ROOT = _WORKSPACE_ROOT
|
|
44
|
+
|
|
45
|
+
# 基础设施服务地址 / Infrastructure service URL
|
|
46
|
+
INFRASRV_HOST = os.getenv("INFRASRV_HOST", "http://infrasrv.service:8080")
|
|
47
|
+
CONTROLLERSRV_HOST = os.getenv("CONTROLLERSRV_HOST", "http://host.containers.internal:22100")
|
|
48
|
+
|
|
49
|
+
# opsbffsrv 不参与服务注册 / Opsbffsrv does not participate in service registry
|
|
50
|
+
SKIP_SERVICE_REGISTRY = True
|
|
51
|
+
|
|
52
|
+
# DDL 自管理配置
|
|
53
|
+
ENABLE_DDL_AUTO_INIT = True # 启动时自动创建 ops 表
|
|
54
|
+
# DDL 脚本路径使用项目根目录
|
|
55
|
+
# - In Pod: /app/ddl/ops (Dockerfile COPY)
|
|
56
|
+
# - Out Pod: {project_root}/ddl/ops
|
|
57
|
+
DDL_SCRIPT_PATH = str(resolve_workspace_or_asset("ddl/ops", "ddl/ops"))
|
|
58
|
+
|
|
59
|
+
# 服务注册信息展示的陈旧实例剔除阈值(秒)
|
|
60
|
+
# Stale instance threshold (seconds) for registry/overview views
|
|
61
|
+
SERVICE_INSTANCE_STALE_SECONDS = 180
|
|
62
|
+
|
|
63
|
+
# 数据库配置(Docker 网络地址)
|
|
64
|
+
PGSQL_DB = "ops"
|
|
65
|
+
|
|
66
|
+
# PostgreSQL 连接池配置(强制限制连接数,避免连接无限上涨)
|
|
67
|
+
# PostgreSQL pool settings (hard cap connections to avoid exhaustion)
|
|
68
|
+
PGSQL_POOL_SIZE = 1
|
|
69
|
+
PGSQL_MAX_OVERFLOW = 0
|
|
70
|
+
PGSQL_DATABASES = {
|
|
71
|
+
"infra": {
|
|
72
|
+
"database": "infra",
|
|
73
|
+
},
|
|
74
|
+
"biz": {
|
|
75
|
+
"database": "biz",
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# 管理 UI 代理凭据 / Admin proxy credentials for proxied UIs
|
|
80
|
+
# 管理 UI 代理上游地址 / Upstream base URLs for proxied UIs
|
|
81
|
+
MONGO_EXPRESS_BASE_URL = os.getenv("MONGO_EXPRESS_BASE_URL", "http://mongo-express.internal:8081")
|
|
82
|
+
RABBITMQ_MGMT_BASE_URL = os.getenv("RABBITMQ_MGMT_BASE_URL", "http://rabbitmq.internal:15672")
|
|
83
|
+
PGWEB_BASE_URL = os.getenv("PGWEB_BASE_URL", "http://pgweb.internal:8081")
|
|
84
|
+
REDIS_COMMANDER_BASE_URL = os.getenv("REDIS_COMMANDER_BASE_URL", "http://redis-commander.internal:8081")
|
|
85
|
+
|
|
86
|
+
MONGO_EXPRESS_USERNAME = os.getenv("MONGO_EXPRESS_USERNAME", "admin")
|
|
87
|
+
MONGO_EXPRESS_PASSWORD = os.getenv("MONGO_EXPRESS_PASSWORD", "admin123")
|
|
88
|
+
RABBITMQ_MGMT_USERNAME = os.getenv("RABBITMQ_MGMT_USERNAME", "admin")
|
|
89
|
+
RABBITMQ_MGMT_PASSWORD = os.getenv("RABBITMQ_MGMT_PASSWORD", "admin123")
|
|
90
|
+
|
|
91
|
+
# RabbitMQ Management UI 假登录注入凭据 / Fake login credentials injected for RabbitMQ UI
|
|
92
|
+
DUMMY_USER = os.getenv("RABBITMQ_MGMT_DUMMY_USER", "ops_user")
|
|
93
|
+
DUMMY_PASS = os.getenv("RABBITMQ_MGMT_DUMMY_PASS", "dummy_pass")
|
|
94
|
+
DUMMY_AUTH_TOKEN = os.getenv(
|
|
95
|
+
"RABBITMQ_MGMT_DUMMY_AUTH_TOKEN",
|
|
96
|
+
_build_basic_auth(DUMMY_USER, DUMMY_PASS),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# 日志查询 MongoDB 配置 / Mongo settings for log queries
|
|
100
|
+
# 注意:默认使用 root 用户认证数据库 admin
|
|
101
|
+
# Note: default uses root user with authSource=admin
|
|
102
|
+
MONGODB_URI = os.getenv(
|
|
103
|
+
"MONGODB_URI",
|
|
104
|
+
"mongodb://admin:admin123@mongo.internal:27017/admin?authSource=admin",
|
|
105
|
+
)
|
|
106
|
+
MONGODB_DB = "infra_logging"
|
|
107
|
+
MONGODB_COLLECTION = "service_logs"
|
|
108
|
+
LOG_QUERY_MAX_RANGE_DAYS = 7 # 最大查询时间跨度(天)/ Max time range for log search (days)
|
|
109
|
+
LOG_QUERY_DEFAULT_PAGE_SIZE = 100
|
|
110
|
+
LOG_QUERY_MAX_PAGE_SIZE = 500
|
|
111
|
+
|
|
112
|
+
# 数据库 schema 管理配置(opsbffsrv 在 Docker 内,可以访问 Docker Compose 服务)
|
|
113
|
+
DOCKER_COMPOSE_FILE = _resolve_compose_file(_PROJECT_ROOT)
|
|
114
|
+
DOCKER_COMPOSE_PROJECT_NAME = os.getenv(
|
|
115
|
+
"DBADMIN_COMPOSE_PROJECT",
|
|
116
|
+
os.getenv("CANCAN_STACK_PREFIX", Path(_PROJECT_ROOT).name or "cancan"),
|
|
117
|
+
)
|
|
118
|
+
DBADMIN_TARGET_SERVICE = "postgres.service" # 直接访问 postgres 服务
|
|
119
|
+
DBADMIN_SCRIPT_PATH = "src/tools/dbadmin/manage.py"
|
|
120
|
+
DBADMIN_PYTHON_EXECUTABLE = "python"
|
|
121
|
+
|
|
122
|
+
# 日志配置 - 使用项目根目录
|
|
123
|
+
# - In Pod: /app/server_log_data/{}.log (volume 挂载到宿主机)
|
|
124
|
+
# - Out Pod: {project_root}/server_log_data/{}.log
|
|
125
|
+
LOGGING_ENABLE_FILE_HANDLER = True
|
|
126
|
+
LOGGING_FILE_ADDR_FORMAT = os.path.join(_PROJECT_ROOT, "server_log_data", "{}.log")
|
|
127
|
+
DBADMIN_PYTHONPATH = "/app/src:/app/cmd"
|
|
128
|
+
|
|
129
|
+
# ── 认证配置 / Authentication configuration ──────────────────────────────
|
|
130
|
+
AUTH_TOTP_FERNET_KEY = os.getenv("AUTH_TOTP_FERNET_KEY", "")
|
|
131
|
+
AUTH_SESSION_TTL = int(os.getenv("AUTH_SESSION_TTL", "86400"))
|
|
132
|
+
AUTH_TEMP_TOKEN_TTL = int(os.getenv("AUTH_TEMP_TOKEN_TTL", "300"))
|
|
133
|
+
AUTH_CAPTCHA_TTL = int(os.getenv("AUTH_CAPTCHA_TTL", "60"))
|
|
134
|
+
AUTH_IP_MAX_FAILURES = int(os.getenv("AUTH_IP_MAX_FAILURES", "5"))
|
|
135
|
+
AUTH_IP_LOCKOUT_TTL = int(os.getenv("AUTH_IP_LOCKOUT_TTL", "1800"))
|
|
136
|
+
# TOTP 单 temp_token 允许的最大失败次数(超过则失效 token)
|
|
137
|
+
# Max TOTP attempts allowed per temp_token before the token is invalidated.
|
|
138
|
+
AUTH_TOTP_MAX_FAILURES = int(os.getenv("AUTH_TOTP_MAX_FAILURES", "5"))
|
|
139
|
+
# 生产默认 true(仅 HTTPS 下发 session cookie),可被环境变量覆盖(如本地 http 调试设 false)。
|
|
140
|
+
# Default true in production (session cookie only over HTTPS); override via env (e.g. "false" for local http).
|
|
141
|
+
AUTH_COOKIE_SECURE = os.getenv("AUTH_COOKIE_SECURE", "true")
|
|
142
|
+
AUTH_TOTP_ISSUER = os.getenv("AUTH_TOTP_ISSUER", "OPS Admin")
|
|
143
|
+
AUTH_REDIS_URL = os.getenv("AUTH_REDIS_URL", "redis://redis.service:6379/0")
|
|
144
|
+
|
|
145
|
+
# 代理接口跨域白名单(逗号分隔的 Origin),默认空 = 仅同源。
|
|
146
|
+
# 用于 RabbitMQ 等管理 UI 代理;绝不反射任意 Origin + 带凭证。
|
|
147
|
+
# Allowlist of cross-origin Origins for proxy endpoints (comma-separated).
|
|
148
|
+
# Empty (default) means same-origin only. Never reflect arbitrary Origin with credentials.
|
|
149
|
+
PROXY_CORS_ALLOWED_ORIGINS = os.getenv("PROXY_CORS_ALLOWED_ORIGINS", "")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class _ProductionConfig(_BaseConfig):
|
|
153
|
+
"""生产环境配置"""
|
|
154
|
+
ENV_MODE = "prod"
|
|
155
|
+
DEBUG = False
|
|
156
|
+
LOGGING_LEVEL = logging.INFO
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
service_conf_dict = {
|
|
160
|
+
'prod': _ProductionConfig,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
_logger = logging.getLogger(__name__)
|
|
165
|
+
|
|
166
|
+
# 临时生成的 Fernet key 在开发模式下会写回 LinglongConfig,
|
|
167
|
+
# 这里记录,避免重复生成/重复打印 warning。
|
|
168
|
+
# Holds the dev-mode ephemeral Fernet key so it stays stable within a process.
|
|
169
|
+
_dev_ephemeral_fernet_key: str | None = None
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _is_production_mode() -> bool:
|
|
173
|
+
"""判断是否处于生产模式 / Decide whether we are running in production.
|
|
174
|
+
|
|
175
|
+
生产模式 = ENV_MODE 显式为 prod,或 DEBUG 关闭。
|
|
176
|
+
Production = ENV_MODE explicitly "prod", or DEBUG turned off.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
from linglong_web import LinglongConfig # 延迟导入,避免启动顺序问题
|
|
180
|
+
|
|
181
|
+
env_mode = str(getattr(LinglongConfig, "ENV_MODE", "prod")).strip().lower()
|
|
182
|
+
debug = bool(getattr(LinglongConfig, "DEBUG", False))
|
|
183
|
+
return env_mode == "prod" or not debug
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def validate_auth_config() -> None:
|
|
187
|
+
"""启动期认证配置校验 / Fail-fast validation of auth-critical config.
|
|
188
|
+
|
|
189
|
+
必须在服务启动早期调用(admin 初始化之前)。
|
|
190
|
+
Must be called early during startup (before admin init / serving traffic).
|
|
191
|
+
|
|
192
|
+
规则 / Rules:
|
|
193
|
+
- 生产模式下 AUTH_TOTP_FERNET_KEY 为空 → 直接抛错,拒绝带不可用 TOTP 加密的状态上线。
|
|
194
|
+
- 开发模式下为空 → 临时生成一个进程内 key 并打 warning(不持久化,重启失效)。
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
from cryptography.fernet import Fernet
|
|
198
|
+
|
|
199
|
+
from linglong_web import LinglongConfig
|
|
200
|
+
|
|
201
|
+
global _dev_ephemeral_fernet_key
|
|
202
|
+
|
|
203
|
+
key = getattr(LinglongConfig, "AUTH_TOTP_FERNET_KEY", "")
|
|
204
|
+
if key:
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
if _is_production_mode():
|
|
208
|
+
raise RuntimeError(
|
|
209
|
+
"AUTH_TOTP_FERNET_KEY is empty in production mode. "
|
|
210
|
+
"TOTP secret encryption cannot run safely without it. "
|
|
211
|
+
"Generate a key and set it via the AUTH_TOTP_FERNET_KEY environment variable, e.g.:\n"
|
|
212
|
+
" python -c \"from cryptography.fernet import Fernet; "
|
|
213
|
+
"print(Fernet.generate_key().decode())\""
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# 开发模式:临时生成(进程内稳定,重启会变;不落盘)。
|
|
217
|
+
if _dev_ephemeral_fernet_key is None:
|
|
218
|
+
_dev_ephemeral_fernet_key = Fernet.generate_key().decode()
|
|
219
|
+
LinglongConfig.AUTH_TOTP_FERNET_KEY = _dev_ephemeral_fernet_key
|
|
220
|
+
_logger.warning(
|
|
221
|
+
"AUTH_TOTP_FERNET_KEY is empty; generated an EPHEMERAL key for DEV mode only. "
|
|
222
|
+
"TOTP secrets encrypted with it will NOT survive a restart. "
|
|
223
|
+
"Set AUTH_TOTP_FERNET_KEY explicitly for any persistent/non-dev use."
|
|
224
|
+
)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""admin 用户初始化 / Admin user initialization on startup."""
|
|
2
|
+
from nanoid import generate as nanoid_generate
|
|
3
|
+
|
|
4
|
+
from linglong_web.utils import logger
|
|
5
|
+
|
|
6
|
+
from cancan_microstack.services.opsbffsrv.infrastructure.auth.password_service import hash_password
|
|
7
|
+
from cancan_microstack.services.opsbffsrv.infrastructure.db.operate.admin_user_operate import (
|
|
8
|
+
create_admin_user,
|
|
9
|
+
get_admin_user,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def ensure_admin_user() -> None:
|
|
14
|
+
"""启动时检查并创建 admin 用户 / Ensure admin user exists on startup."""
|
|
15
|
+
existing = await get_admin_user("admin")
|
|
16
|
+
if existing is not None:
|
|
17
|
+
logger.info("Admin user already exists, skip creation")
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
plain_password = nanoid_generate(size=10)
|
|
21
|
+
hashed = hash_password(plain_password)
|
|
22
|
+
await create_admin_user("admin", hashed)
|
|
23
|
+
|
|
24
|
+
# 安全:初始密码绝不写入文件 logger(server_log_data 是宿主挂载,会落盘泄露)。
|
|
25
|
+
# 仅一次性打印到 stdout,由运维即时读取后保存到安全位置。
|
|
26
|
+
# Security: never write the initial password to the file logger
|
|
27
|
+
# (server_log_data is host-mounted and would persist the secret on disk).
|
|
28
|
+
# Print once to stdout only, for the operator to capture immediately.
|
|
29
|
+
print("=" * 60, flush=True)
|
|
30
|
+
print("ADMIN USER CREATED", flush=True)
|
|
31
|
+
print("Username: admin", flush=True)
|
|
32
|
+
print(f"Password: {plain_password}", flush=True)
|
|
33
|
+
print("Please change the password after first login.", flush=True)
|
|
34
|
+
print("This password is shown ONCE and is NOT written to any log file.", flush=True)
|
|
35
|
+
print("=" * 60, flush=True)
|
|
36
|
+
# 仅在文件日志记录"已创建"事实,不含密码。
|
|
37
|
+
# Record only the creation fact in the file log, without the secret.
|
|
38
|
+
logger.info("Admin user created; initial password printed to stdout once (not logged).")
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""认证领域逻辑 / Authentication domain logic."""
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from nanoid import generate as nanoid_generate
|
|
6
|
+
|
|
7
|
+
from linglong_web import LinglongConfig
|
|
8
|
+
|
|
9
|
+
from cancan_microstack.services.opsbffsrv.infrastructure.auth import (
|
|
10
|
+
password_service,
|
|
11
|
+
redis_store,
|
|
12
|
+
)
|
|
13
|
+
from cancan_microstack.services.opsbffsrv.infrastructure.db.operate.admin_user_operate import (
|
|
14
|
+
get_admin_user,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class AuthResult:
|
|
20
|
+
"""认证结果 / Authentication result."""
|
|
21
|
+
success: bool
|
|
22
|
+
user_id: Optional[int] = None
|
|
23
|
+
totp_bound: bool = False
|
|
24
|
+
error_code: Optional[str] = None
|
|
25
|
+
error_msg: Optional[str] = None
|
|
26
|
+
temp_token: Optional[str] = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def check_ip_rate_limit(ip: str) -> bool:
|
|
30
|
+
"""检查 IP 是否被锁定 / Check if IP is locked due to too many failures.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
True if locked, False if allowed.
|
|
34
|
+
"""
|
|
35
|
+
max_failures = int(LinglongConfig.get("AUTH_IP_MAX_FAILURES", 5))
|
|
36
|
+
count = await redis_store.get_ip_fail_count(ip)
|
|
37
|
+
return count >= max_failures
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
async def validate_captcha(captcha_id: str, answer: str) -> bool:
|
|
41
|
+
"""校验图形验证码 / Validate captcha answer (case-insensitive, one-time use)."""
|
|
42
|
+
stored = await redis_store.get_and_delete_captcha(captcha_id)
|
|
43
|
+
if stored is None:
|
|
44
|
+
return False
|
|
45
|
+
return stored.upper() == answer.upper()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def authenticate(username: str, password: str, client_ip: str) -> AuthResult:
|
|
49
|
+
"""验证用户名密码 / Authenticate user with credentials and IP rate limiting."""
|
|
50
|
+
# 1. 检查 IP 限频
|
|
51
|
+
if await check_ip_rate_limit(client_ip):
|
|
52
|
+
return AuthResult(
|
|
53
|
+
success=False,
|
|
54
|
+
error_code="AUTH_IP_LOCKED",
|
|
55
|
+
error_msg="IP locked for 30 minutes due to too many failed attempts",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# 2. 查询用户
|
|
59
|
+
user = await get_admin_user(username)
|
|
60
|
+
if user is None:
|
|
61
|
+
lockout_ttl = int(LinglongConfig.get("AUTH_IP_LOCKOUT_TTL", 1800))
|
|
62
|
+
await redis_store.increment_ip_fail(client_ip, ttl=lockout_ttl)
|
|
63
|
+
return AuthResult(
|
|
64
|
+
success=False,
|
|
65
|
+
error_code="AUTH_CREDENTIALS_INVALID",
|
|
66
|
+
error_msg="Invalid credentials",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# 3. 校验密码
|
|
70
|
+
if not password_service.verify_password(password, user.password_hash):
|
|
71
|
+
lockout_ttl = int(LinglongConfig.get("AUTH_IP_LOCKOUT_TTL", 1800))
|
|
72
|
+
await redis_store.increment_ip_fail(client_ip, ttl=lockout_ttl)
|
|
73
|
+
return AuthResult(
|
|
74
|
+
success=False,
|
|
75
|
+
error_code="AUTH_CREDENTIALS_INVALID",
|
|
76
|
+
error_msg="Invalid credentials",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# 4. 登录成功,重置 IP 计数,生成临时 token
|
|
80
|
+
await redis_store.reset_ip_fail(client_ip)
|
|
81
|
+
temp_token = nanoid_generate(size=32)
|
|
82
|
+
temp_ttl = int(LinglongConfig.get("AUTH_TEMP_TOKEN_TTL", 300))
|
|
83
|
+
await redis_store.save_temp_token(temp_token, user.id, ttl=temp_ttl)
|
|
84
|
+
|
|
85
|
+
return AuthResult(
|
|
86
|
+
success=True,
|
|
87
|
+
user_id=user.id,
|
|
88
|
+
totp_bound=bool(user.totp_bound),
|
|
89
|
+
temp_token=temp_token,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def create_session_token(user_id: int) -> str:
|
|
94
|
+
"""创建 session token / Create session and store in Redis."""
|
|
95
|
+
token = nanoid_generate(size=32)
|
|
96
|
+
session_ttl = int(LinglongConfig.get("AUTH_SESSION_TTL", 86400))
|
|
97
|
+
await redis_store.save_session(token, user_id, ttl=session_ttl)
|
|
98
|
+
return token
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
async def verify_session(token: str) -> Optional[int]:
|
|
102
|
+
"""校验 session token / Verify session token and return user_id or None."""
|
|
103
|
+
return await redis_store.get_session(token)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
async def revoke_session(token: str) -> None:
|
|
107
|
+
"""撤销 session token / Revoke a session token from Redis."""
|
|
108
|
+
await redis_store.delete_session(token)
|
|
File without changes
|