Files
blackbird/ca/inc/Conf.hpp
T
qing 407ce3c366 feat(ca): 认证独立化 CA 模块 v1.0.0 + gateway v0.9.0 纯转发瘦身
拓扑:waf:443 → ca:8443(认证+前置转发)→ gateway:8445(仅 loopback 纯转发),
WAF upstream 不变,core/dnfs2/前端零改动。

ca v1.0.0(新模块):
- 认证资产逐字搬迁自 gateway v0.8.0(9 条认证路由、Token 双轨吊销、
  PBKDF2、限流、WS 代理鉴权、wrapperHttp、优雅关闭)
- handleForward 前置转发层:固定上游 gateway:8445;无 Target-Url 公开直转,
  有则本地验签后注入 X-Auth-User/X-Auth-Admin/Authorization(strip-then-set)
- is_special_header 新增剥离 x-auth-user/x-auth-admin;上游不可达统一 502
- confs/configs/ca.ini 新增([Upstream] gateway + UPSTREAM_GATEWAY env)

gateway v0.9.0(2470→约 560 行):
- 删除全部认证代码,退居 127.0.0.1:8445
- 启动 loopback 强制自检(非 loopback 拒绝启动)
- X-Auth-User 存在性不变量:显式 Target-Url 无该头一律 401
- gateway.ini 精简至 [Server]/[Proxy]/[Downstream db]

验收:黑盒 34 断言对 8443 原样全绿(32 passed/2 skipped,与基线一致);
探针实测伪造 X-Auth-User 经 CA 被剥离(echo 实证)、直连 8445 无头 401、
白名单外 403、gateway 宕机 CA 502。core/init.txt 加入 ca/_run.sh。
2026-08-09 12:15:35 +00:00

78 lines
2.3 KiB
C++

#pragma once
#include <iostream>
#include <exception>
#include <string>
#include <sstream>
#include <cstdlib>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
namespace property_tree = boost::property_tree;
using ptree = property_tree::ptree;
namespace qing {
class ConfIni {
public:
/// 默认构造(空配置,后续通过赋值覆盖,仅供 confs 加载流程内部使用)
ConfIni() = default;
/// 从文件路径解析 ini(保留用于开发/调试模式)
ConfIni(const std::string &filename) {
if (filename.empty()) return; // 空文件名不报错,后续会通过赋值覆盖
try {
std::cout << "[conf] 从文件加载配置: " << filename << std::endl;
property_tree::ini_parser::read_ini(filename, pt);
}
catch (const boost::property_tree::ini_parser_error& e) {
std::cerr << "[conf] INI 解析错误: " << e.what() << std::endl;
throw IniConfigureFileParseException("INI parsing error!");
}
}
/// 从 ini 文本字符串解析(用于从 confs 拉取后解析)
static ConfIni fromString(const std::string &ini_text) {
ConfIni c;
try {
std::istringstream iss(ini_text);
property_tree::ini_parser::read_ini(iss, c.pt);
}
catch (const boost::property_tree::ini_parser_error& e) {
std::cerr << "[conf] INI 文本解析错误: " << e.what() << std::endl;
throw IniConfigureFileParseException("INI parsing error!");
}
return c;
}
template <typename T>
T get(const std::string &path, const T &_defaut) {
return pt.get<T>(path, _defaut);
}
/// 读取环境变量,不存在则返回默认值
static std::string env(const char *name, const std::string &default_val = "") {
const char *v = std::getenv(name);
return v ? std::string(v) : default_val;
}
static int env_int(const char *name, int default_val) {
const char *v = std::getenv(name);
if (!v || !*v) return default_val;
try { return std::stoi(v); }
catch (...) { return default_val; }
}
class IniConfigureFileParseException: public std::exception {
public:
explicit IniConfigureFileParseException(const std::string &msg)
: message(msg) {}
const char* what() const noexcept override {
return message.c_str();
}
private:
std::string message;
};
private:
ptree pt;
};
}