feat(09-05): implement convertCert + wire POST /convert (GREEN)

- Add FileResponse interface and FORMAT_MIME map to service
- Implement convertCert: parses any input format (PEM/DER/PFX/P7B) via
  same logic as parseCert; serializes to pem/der/p7b targetFormat
- DER output uses bytesToHex→Buffer.from(hex,'hex') to avoid utf-8
  corruption (Pitfall 1 / T-09-06)
- P7B output: pkcs7.createSignedData + pem.encode (PEM-wrapped PKCS7)
- Wrap all forge ops in try/catch → BadRequestException (T-09-01)
- Controller: add @Body('pemText') + reject when neither file nor pemText
- Fix: re-add NotImplementedException import for mergeCerts stub
- All 23 API cert-manager tests green (including 4 new convertCert)
This commit is contained in:
2026-07-02 07:37:41 +02:00
parent 37db58b816
commit 59694642dd
3 changed files with 153 additions and 8 deletions
@@ -93,7 +93,12 @@ export class CertManagerController {
/**
* POST /modules/cert-manager/convert
* Convert a certificate between PEM, DER, PFX/P12, P7B, CRT/CER formats.
* Convert a certificate between PEM, DER, and P7B formats.
* Accepts a multipart file upload OR a pemText body field.
*
* T-09-03: fileSize limit 5 MB (DoS mitigation)
* T-09-04: global JwtAuthGuard + @UseModule('cert-manager') ModuleGuard
* T-09-02: password is never passed to the logger
*/
@Post('convert')
@UseInterceptors(
@@ -105,10 +110,11 @@ export class CertManagerController {
@UploadedFile() file: any,
@Body('targetFormat') targetFormat: string,
@Body('password') password?: string,
@Body('pemText') pemText?: string,
) {
if (!file) {
throw new BadRequestException('No file provided');
if (!file && !pemText) {
throw new BadRequestException('No file or PEM text provided');
}
return this.certManagerService.convertCert({ file, targetFormat, password });
return this.certManagerService.convertCert({ file, pemText, targetFormat, password });
}
}