refactor(center): local-only guild register endpoint without shared secret
This commit is contained in:
@@ -20,7 +20,6 @@ function validateEnv(): void {
|
||||
requireEnv('DB_USER');
|
||||
requireEnv('DB_PASSWORD');
|
||||
requireEnv('DB_NAME');
|
||||
requireEnv('CENTER_SHARED_SECRET');
|
||||
requireEnv('JWT_ACCESS_SECRET');
|
||||
requireEnv('JWT_REFRESH_SECRET');
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
Patch,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
@@ -22,12 +23,6 @@ import { GuildNode } from '../entities/guild-node.entity';
|
||||
import { AuditService } from '../audit/audit.service';
|
||||
import { RegisterNodeDto } from './dto.register-node.dto';
|
||||
import { UpdateNodeStatusDto } from './dto.update-node-status.dto';
|
||||
import {
|
||||
buildCanonical,
|
||||
safeEqualHex,
|
||||
signCanonical,
|
||||
verifyRequestTime,
|
||||
} from '../common/hmac';
|
||||
import { FABRIC_PROTOCOL_VERSION, normalizeVersion } from '../common/version';
|
||||
|
||||
@Controller('nodes')
|
||||
@@ -40,12 +35,19 @@ export class NodesController {
|
||||
|
||||
@Post('register')
|
||||
async register(
|
||||
@Req() req: { ip?: string; socket?: { remoteAddress?: string } },
|
||||
@Body() body: RegisterNodeDto,
|
||||
@Headers('x-fabric-signature') signature?: string,
|
||||
@Headers('x-fabric-timestamp') timestamp?: string,
|
||||
@Headers('x-fabric-nonce') nonce?: string,
|
||||
@Headers('x-fabric-version') fabricVersion?: string,
|
||||
) {
|
||||
const remoteAddress = (req.ip ?? req.socket?.remoteAddress ?? '').toLowerCase();
|
||||
const isLoopback =
|
||||
remoteAddress === '127.0.0.1' ||
|
||||
remoteAddress === '::1' ||
|
||||
remoteAddress === '::ffff:127.0.0.1';
|
||||
if (!isLoopback) {
|
||||
throw new ForbiddenException('register endpoint only allows localhost caller');
|
||||
}
|
||||
|
||||
const requestedVersion = normalizeVersion(fabricVersion);
|
||||
if (requestedVersion !== FABRIC_PROTOCOL_VERSION) {
|
||||
throw new HttpException(
|
||||
@@ -61,23 +63,6 @@ export class NodesController {
|
||||
);
|
||||
}
|
||||
|
||||
const secret = process.env.CENTER_SHARED_SECRET as string;
|
||||
if (!signature || !timestamp || !nonce || !verifyRequestTime(timestamp)) {
|
||||
throw new ForbiddenException('invalid hmac headers');
|
||||
}
|
||||
|
||||
const canonical = buildCanonical({
|
||||
method: 'POST',
|
||||
path: '/api/nodes/register',
|
||||
timestamp,
|
||||
nonce,
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const expected = signCanonical(secret, canonical);
|
||||
if (!safeEqualHex(signature, expected)) {
|
||||
throw new ForbiddenException('invalid shared secret');
|
||||
}
|
||||
|
||||
const existedByNodeId = await this.nodeRepo.findOne({
|
||||
where: { nodeId: body.nodeId },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user