修复 BgFilter 内部 Token 单段校验
统一校验 BgFilter 内部 Token 并限制启动角色 部署与 provision 预检拒绝内部空白和多行 Token 补充定向测试、运维门禁与架构文档
This commit is contained in:
@@ -61,6 +61,8 @@ function main() {
|
||||
assertDeployRejectsInlineBgFilterInternalToken();
|
||||
assertDeployRejectsEmptyBgFilterInternalToken();
|
||||
assertDeployRejectsWhitespaceBgFilterInternalToken();
|
||||
assertDeployRejectsInternalWhitespaceBgFilterInternalToken();
|
||||
assertDeployRejectsMultilineBgFilterInternalToken();
|
||||
assertReadinessFailureKeepsMaintenanceAfterCurrentSwitch();
|
||||
assertMissingReleaseManifestFails();
|
||||
assertReleaseManifestMissingApiArtifactFails();
|
||||
@@ -933,7 +935,7 @@ function assertDeployRejectsWhitespaceBgFilterInternalToken() {
|
||||
}
|
||||
assertIncludes(
|
||||
result.stderr,
|
||||
'BgFilter 内部 Token 文件必须至少包含一个非空白字符',
|
||||
'BgFilter 内部 Token 文件必须为不含空白字符的单段值',
|
||||
'纯空白 Token 文件预检必须给出明确错误。',
|
||||
);
|
||||
assertBgFilterPreflightFailedBeforeSwitch(
|
||||
@@ -942,6 +944,44 @@ function assertDeployRejectsWhitespaceBgFilterInternalToken() {
|
||||
);
|
||||
}
|
||||
|
||||
function assertDeployRejectsInternalWhitespaceBgFilterInternalToken() {
|
||||
const fixture = prepareFixture('internal-whitespace-bgfilter-internal-token');
|
||||
writeFileSync(fixture.bgfilterTokenFile, 'fixture bgfilter-token\n', 'utf8');
|
||||
const result = runDeploy(fixture);
|
||||
|
||||
if (result.status === 0) {
|
||||
failures.push('BgFilter 内部 Token 含内部空格时部署必须失败。');
|
||||
}
|
||||
assertIncludes(
|
||||
result.stderr,
|
||||
'BgFilter 内部 Token 文件必须为不含空白字符的单段值',
|
||||
'含内部空格的 Token 文件预检必须给出明确错误。',
|
||||
);
|
||||
assertBgFilterPreflightFailedBeforeSwitch(
|
||||
fixture,
|
||||
'BgFilter 含内部空格 Token 文件预检失败',
|
||||
);
|
||||
}
|
||||
|
||||
function assertDeployRejectsMultilineBgFilterInternalToken() {
|
||||
const fixture = prepareFixture('multiline-bgfilter-internal-token');
|
||||
writeFileSync(fixture.bgfilterTokenFile, 'fixture-token\nsecond-token\n', 'utf8');
|
||||
const result = runDeploy(fixture);
|
||||
|
||||
if (result.status === 0) {
|
||||
failures.push('BgFilter 内部 Token 包含多个非空行时部署必须失败。');
|
||||
}
|
||||
assertIncludes(
|
||||
result.stderr,
|
||||
'BgFilter 内部 Token 文件必须为不含空白字符的单段值',
|
||||
'多行 Token 文件预检必须给出明确错误。',
|
||||
);
|
||||
assertBgFilterPreflightFailedBeforeSwitch(
|
||||
fixture,
|
||||
'BgFilter 多行 Token 文件预检失败',
|
||||
);
|
||||
}
|
||||
|
||||
function assertDeployRejectsInlineBgFilterInternalToken() {
|
||||
const cases = [
|
||||
['api-env', 'apiEnvFile'],
|
||||
|
||||
@@ -1681,9 +1681,9 @@ const checks = [
|
||||
},
|
||||
{
|
||||
file: 'scripts/jenkins-server-provision.sh',
|
||||
includes: 'BgFilter 内部 Token 文件不得为空或只包含空白字符',
|
||||
includes: 'BgFilter 内部 Token 文件必须为不含空白字符的单段值',
|
||||
reason:
|
||||
'Server-Provision 必须拒绝仅含空白字符的 BgFilter 内部 Token 文件。',
|
||||
'Server-Provision 必须拒绝纯空白、含内部空白或包含多个非空行的 BgFilter 内部 Token 文件。',
|
||||
},
|
||||
{
|
||||
file: 'scripts/jenkins-server-provision.sh',
|
||||
|
||||
@@ -654,6 +654,22 @@ validate_no_bgfilter_internal_token_plaintext() {
|
||||
done
|
||||
}
|
||||
|
||||
bgfilter_internal_token_file_is_single_segment() {
|
||||
local token_file="$1"
|
||||
|
||||
run_privileged awk '
|
||||
/[^[:space:]]/ {
|
||||
non_empty_lines += 1
|
||||
if ($0 !~ /^[[:space:]]*[^[:space:]]+[[:space:]]*$/) {
|
||||
invalid = 1
|
||||
}
|
||||
}
|
||||
END {
|
||||
exit !(non_empty_lines == 1 && invalid == 0)
|
||||
}
|
||||
' "${token_file}"
|
||||
}
|
||||
|
||||
validate_bgfilter_internal_token_file() {
|
||||
local api_env_file="$1"
|
||||
local token_file token_metadata
|
||||
@@ -667,8 +683,8 @@ validate_bgfilter_internal_token_file() {
|
||||
echo "[production-api-deploy] BgFilter 内部 Token 必须是非空普通文件且不能是符号链接: ${token_file}" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! run_privileged grep -q '[^[:space:]]' -- "${token_file}"; then
|
||||
echo "[production-api-deploy] BgFilter 内部 Token 文件必须至少包含一个非空白字符: ${token_file}" >&2
|
||||
if ! bgfilter_internal_token_file_is_single_segment "${token_file}"; then
|
||||
echo "[production-api-deploy] BgFilter 内部 Token 文件必须为不含空白字符的单段值: ${token_file}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -809,6 +809,22 @@ ensure_bgfilter_worker_runtime_env_defaults() {
|
||||
ensure_env_value "${BGFILTER_WORKER_ENV_FILE}" "GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS" "300"
|
||||
}
|
||||
|
||||
bgfilter_internal_token_file_is_single_segment() {
|
||||
local token_file="$1"
|
||||
|
||||
awk '
|
||||
/[^[:space:]]/ {
|
||||
non_empty_lines += 1
|
||||
if ($0 !~ /^[[:space:]]*[^[:space:]]+[[:space:]]*$/) {
|
||||
invalid = 1
|
||||
}
|
||||
}
|
||||
END {
|
||||
exit !(non_empty_lines == 1 && invalid == 0)
|
||||
}
|
||||
' "${token_file}"
|
||||
}
|
||||
|
||||
ensure_bgfilter_internal_token_file() {
|
||||
local token_file="/etc/genarrative/secrets/bgfilter-worker.token"
|
||||
local token_dir="/etc/genarrative/secrets"
|
||||
@@ -840,9 +856,9 @@ ensure_bgfilter_internal_token_file() {
|
||||
echo "[server-provision] 生成 BgFilter 内部 Token 失败。" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -q '[^[:space:]]' -- "${temporary_file}"; then
|
||||
if ! bgfilter_internal_token_file_is_single_segment "${temporary_file}"; then
|
||||
rm -f "${temporary_file}"
|
||||
echo "[server-provision] 生成的 BgFilter 内部 Token 不得为空或只包含空白字符。" >&2
|
||||
echo "[server-provision] 生成的 BgFilter 内部 Token 必须为不含空白字符的单段值。" >&2
|
||||
exit 1
|
||||
fi
|
||||
chown root:genarrative "${temporary_file}"
|
||||
@@ -850,8 +866,8 @@ ensure_bgfilter_internal_token_file() {
|
||||
mv -T "${temporary_file}" "${token_file}"
|
||||
echo "[server-provision] 已生成 BgFilter 内部 Token 文件: ${token_file}"
|
||||
else
|
||||
if ! grep -q '[^[:space:]]' -- "${token_file}"; then
|
||||
echo "[server-provision] BgFilter 内部 Token 文件不得为空或只包含空白字符: ${token_file}" >&2
|
||||
if ! bgfilter_internal_token_file_is_single_segment "${token_file}"; then
|
||||
echo "[server-provision] BgFilter 内部 Token 文件必须为不含空白字符的单段值: ${token_file}" >&2
|
||||
exit 1
|
||||
fi
|
||||
chown root:genarrative "${token_file}"
|
||||
|
||||
Reference in New Issue
Block a user