fix: 收敛NapCat运行态检查脚本边界
This commit is contained in:
parent
bfb10c50cb
commit
2a890d894d
@ -26,7 +26,7 @@ export class QqbotNapcatAccountRuntimeService implements QqbotAccountNapcatRunti
|
||||
/**
|
||||
* Creates the account-list runtime adapter that joins persisted bindings, container status, and optional profile summaries.
|
||||
* @param accountNapcatRepository - Binding repository used to pick the primary NapCat container for each QQBot account.
|
||||
* @param napcatContainerRepository - Container repository used for cached Docker/WebUI status and non-secret metadata.
|
||||
* @param napcatContainerRepository - Container repository used for cached runtime/WebUI status and non-secret metadata.
|
||||
* @param napcatContainerService - Runtime integration service for bounded NapCat/WebUI status probes and auto-login.
|
||||
* @param toolsService - Shared helpers for status text normalization and NapCat offline-message classification.
|
||||
* @param runtimeProfileInspector - Optional profile reader that enriches list rows without changing login state.
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Optional } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { ToolsService } from '@/common';
|
||||
import { NapcatRuntimeProfileInspectionScriptService } from '../../infrastructure/integration/container/napcat-runtime-profile-inspection-script.service';
|
||||
import { NapcatProtocolProfile } from '../../infrastructure/persistence/napcat-protocol-profile.entity';
|
||||
import { NapcatRuntimeProfile } from '../../infrastructure/persistence/napcat-runtime-profile.entity';
|
||||
|
||||
@ -22,11 +23,12 @@ export type NapcatRuntimeProfileSummary = {
|
||||
@Injectable()
|
||||
export class NapcatRuntimeProfileInspectorService {
|
||||
/**
|
||||
* Initializes runtime inspection over the existing SSH-managed container model.
|
||||
* @param runtimeProfileRepository - Runtime profile repository updated with latest Docker and desktop evidence.
|
||||
* Initializes runtime inspection over the existing remote-managed runtime model.
|
||||
* @param runtimeProfileRepository - Runtime profile repository updated with latest container and desktop evidence.
|
||||
* @param protocolProfileRepository - Protocol profile repository updated with config hashes and drift state.
|
||||
* @param configService - Runtime config provider used for SSH target and inspection timeout defaults.
|
||||
* @param configService - Runtime config provider used for inspection timeout defaults.
|
||||
* @param toolsService - Shared helper used to normalize string evidence before redaction.
|
||||
* @param inspectionScriptService - Infrastructure helper that owns remote script construction.
|
||||
*/
|
||||
constructor(
|
||||
@InjectRepository(NapcatRuntimeProfile)
|
||||
@ -35,25 +37,26 @@ export class NapcatRuntimeProfileInspectorService {
|
||||
private readonly protocolProfileRepository: Repository<NapcatProtocolProfile>,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly toolsService: ToolsService,
|
||||
) {}
|
||||
@Optional()
|
||||
private readonly inspectionScriptService?: NapcatRuntimeProfileInspectionScriptService,
|
||||
) {
|
||||
this.inspectionScriptService =
|
||||
inspectionScriptService ||
|
||||
new NapcatRuntimeProfileInspectionScriptService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the remote inspection script for Docker and in-container profile evidence.
|
||||
* @param containerName - Docker container name selected from the persisted NapCat container row.
|
||||
* @returns Shell script that collects runtime evidence without reading secret env values.
|
||||
* Delegates remote profile evidence script creation to the infrastructure helper.
|
||||
* @param containerName - Runtime container name selected from the persisted NapCat container row.
|
||||
* @returns Read-only profile evidence script without secret environment reads.
|
||||
*/
|
||||
buildInspectScript(containerName: string) {
|
||||
return `
|
||||
set -eu
|
||||
NAME=${this.sh(containerName)}
|
||||
docker inspect "$NAME"
|
||||
docker exec "$NAME" sh -lc 'locale -a; locale; date +%Z; fc-match "Noto Sans CJK SC"; test ! -e /.dockerenv; cat /proc/1/cgroup; id; ps -eo user,args | grep -E "qq|NapCat|Xvfb" | grep -v grep || true'
|
||||
`;
|
||||
return this.inspectionScriptService.buildInspectScript(containerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redacts secrets before evidence is stored, logged, or returned to Admin.
|
||||
* @param value - Evidence object or primitive produced by Docker, NapCat, or config writers.
|
||||
* @param value - Evidence object or primitive produced by runtime, NapCat, or config writers.
|
||||
* @returns Evidence with sensitive keys and token query values replaced by placeholders.
|
||||
*/
|
||||
sanitizeEvidence(value: unknown): unknown {
|
||||
@ -140,7 +143,7 @@ docker exec "$NAME" sh -lc 'locale -a; locale; date +%Z; fc-match "Noto Sans CJK
|
||||
|
||||
/**
|
||||
* Reads the bounded runtime profile inspection timeout.
|
||||
* @returns Positive timeout in milliseconds for future SSH inspection calls.
|
||||
* @returns Positive timeout in milliseconds for future remote inspection calls.
|
||||
*/
|
||||
private getInspectionTimeoutMs() {
|
||||
const value = Number(
|
||||
@ -173,13 +176,4 @@ docker exec "$NAME" sh -lc 'locale -a; locale; date +%Z; fc-match "Noto Sans CJK
|
||||
private redactString(value: string) {
|
||||
return value.replace(/token=[^&\s]+/gi, 'token=[REDACTED]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes shell literals used by read-only inspection scripts.
|
||||
* @param value - Container name selected from trusted persistence.
|
||||
* @returns POSIX-safe single-quoted shell literal.
|
||||
*/
|
||||
private sh(value: string) {
|
||||
return `'${`${value}`.replace(/'/g, `'\\''`)}'`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import type { NapcatRuntimeProfileSnapshot } from '../../domain/runtime/napcat-p
|
||||
@Injectable()
|
||||
export class NapcatRuntimeProfileService {
|
||||
/**
|
||||
* Initializes the profile resolver used before Docker script generation.
|
||||
* Initializes the profile resolver used before managed runtime script generation.
|
||||
* @param configService - Nest config provider that supplies image ref, UID/GID, shm size, and profile version.
|
||||
*/
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
@ -13,7 +13,7 @@ export class NapcatRuntimeProfileService {
|
||||
/**
|
||||
* Resolves the runtime profile for an account-owned NapCat container.
|
||||
* @param input - Account, container, data directory, and device identity ids that tie generated profile evidence to persistence.
|
||||
* @returns Runtime profile snapshot used by Docker script generation and later persistence.
|
||||
* @returns Runtime profile snapshot used by managed runtime script generation and later persistence.
|
||||
*/
|
||||
resolveRuntimeProfile(input: {
|
||||
accountId: string;
|
||||
@ -49,7 +49,7 @@ export class NapcatRuntimeProfileService {
|
||||
* Reads a trimmed string config value for profile generation.
|
||||
* @param key - Environment key that controls NapCat runtime profile generation.
|
||||
* @param defaultValue - Value used when the key is absent from runtime config.
|
||||
* @returns Trimmed string value consumed by Docker script generation.
|
||||
* @returns Trimmed string value consumed by managed runtime script generation.
|
||||
*/
|
||||
private getString(key: string, defaultValue: string) {
|
||||
return `${this.configService.get<string>(key) || defaultValue}`.trim();
|
||||
|
||||
@ -41,7 +41,7 @@ export class NapcatSessionBehaviorService {
|
||||
/**
|
||||
* Converts housekeeping failure into an evidence-only action.
|
||||
* @param input - Account and failure summary from a low-side-effect housekeeping call.
|
||||
* @returns Decision that disables behavior extensions without resetting login, retrying password, recreating Docker, or refreshing QR.
|
||||
* @returns Decision that disables behavior extensions without resetting login, retrying password, recreating runtime, or refreshing QR.
|
||||
*/
|
||||
handleHousekeepingFailure(input: {
|
||||
accountId: string;
|
||||
|
||||
@ -28,7 +28,7 @@ export const NAPCAT_REJECTED_VIRTUAL_OUI_PREFIXES = [
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Checks whether a generated MAC starts with a Docker or VM-style prefix.
|
||||
* Checks whether a generated MAC starts with a container or VM-style prefix.
|
||||
* @param macAddress - Stable MAC candidate generated from account/device seed.
|
||||
* @returns True when the prefix belongs to a rejected container or virtualization range.
|
||||
*/
|
||||
|
||||
@ -19,4 +19,5 @@ export * from './application/runtime/napcat-login-event.service';
|
||||
export * from './application/runtime/napcat-runtime-profile-inspector.service';
|
||||
export * from './application/runtime/napcat-session-behavior.service';
|
||||
export * from './infrastructure/persistence';
|
||||
export * from './infrastructure/integration/container/napcat-runtime-profile-inspection-script.service';
|
||||
export * from './infrastructure/integration/container/qqbot-napcat-container.service';
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class NapcatRuntimeProfileInspectionScriptService {
|
||||
/**
|
||||
* Builds the remote inspection script for Docker and in-container profile evidence.
|
||||
* @param containerName - Docker container name selected from the persisted NapCat container row.
|
||||
* @returns Shell script that collects runtime evidence without reading secret environment values.
|
||||
*/
|
||||
buildInspectScript(containerName: string) {
|
||||
return `
|
||||
set -eu
|
||||
NAME=${this.sh(containerName)}
|
||||
docker inspect "$NAME"
|
||||
docker exec "$NAME" sh -lc 'locale -a; locale; date +%Z; fc-match "Noto Sans CJK SC"; test ! -e /.dockerenv; cat /proc/1/cgroup; id; ps -eo user,args | grep -E "qq|NapCat|Xvfb" | grep -v grep || true'
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes shell literals used by read-only inspection scripts.
|
||||
* @param value - Container name selected from trusted persistence.
|
||||
* @returns POSIX-safe single-quoted shell literal.
|
||||
*/
|
||||
private sh(value: string) {
|
||||
return `'${`${value}`.replace(/'/g, `'\\''`)}'`;
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ import { NapcatRuntimeProfileService } from './application/runtime/napcat-runtim
|
||||
import { NapcatSessionBehaviorService } from './application/runtime/napcat-session-behavior.service';
|
||||
import { QqbotNapcatLoginController } from './contract/qqbot-napcat-login.controller';
|
||||
import { QqbotNapcatRuntimeController } from './contract/qqbot-napcat-runtime.controller';
|
||||
import { NapcatRuntimeProfileInspectionScriptService } from './infrastructure/integration/container/napcat-runtime-profile-inspection-script.service';
|
||||
import { QqbotNapcatContainerService } from './infrastructure/integration/container/qqbot-napcat-container.service';
|
||||
import { NapcatDeviceIdentityService } from './infrastructure/integration/device/napcat-device-identity.service';
|
||||
import { NAPCAT_RUNTIME_ENTITIES } from './infrastructure/persistence';
|
||||
@ -32,6 +33,7 @@ export const QQBOT_NAPCAT_PROVIDERS = [
|
||||
NapcatLoginStateStoreService,
|
||||
NapcatLoginEventService,
|
||||
NapcatRuntimeProfileInspectorService,
|
||||
NapcatRuntimeProfileInspectionScriptService,
|
||||
NapcatRuntimeProfileService,
|
||||
NapcatSessionBehaviorService,
|
||||
QqbotNapcatAccountRuntimeService,
|
||||
|
||||
@ -9,6 +9,7 @@ import { JwtAuthGuard } from '../../../../src/modules/admin/identity/auth/jwt-au
|
||||
import { NapcatConfigWriterService } from '../../../../src/modules/qqbot/napcat/application/runtime/napcat-config-writer.service';
|
||||
import { NapcatRuntimeProfileService } from '../../../../src/modules/qqbot/napcat/application/runtime/napcat-runtime-profile.service';
|
||||
import { NapcatRuntimeProfileInspectorService } from '../../../../src/modules/qqbot/napcat/application/runtime/napcat-runtime-profile-inspector.service';
|
||||
import { NapcatRuntimeProfileInspectionScriptService } from '../../../../src/modules/qqbot/napcat/infrastructure/integration/container/napcat-runtime-profile-inspection-script.service';
|
||||
import { QqbotNapcatRuntimeController } from '../../../../src/modules/qqbot/napcat/contract/qqbot-napcat-runtime.controller';
|
||||
import {
|
||||
NapcatLoginEvent,
|
||||
@ -178,12 +179,7 @@ describe('NapCat runtime profile generation', () => {
|
||||
|
||||
describe('NapCat runtime profile inspector', () => {
|
||||
it('builds a bounded SSH inspection script without exposing secrets', () => {
|
||||
const service = new NapcatRuntimeProfileInspectorService(
|
||||
{} as any,
|
||||
{} as any,
|
||||
{} as any,
|
||||
new ToolsService(),
|
||||
) as any;
|
||||
const service = new NapcatRuntimeProfileInspectionScriptService();
|
||||
|
||||
const script = service.buildInspectScript('kt-qqbot-napcat-10001');
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user