homebridge-config-ui-x
Version:
A web based management, configuration and control platform for Homebridge.
126 lines • 5.73 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var SslCertGeneratorService_1;
import { Buffer } from 'node:buffer';
import { existsSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join, resolve } from 'node:path';
import process from 'node:process';
import { Injectable } from '@nestjs/common';
import { ensureDir } from 'fs-extra/esm';
import forge from 'node-forge';
import { Logger } from '../logger/logger.service.js';
import { RE_IPV4, RE_IPV6 } from '../regex.constants.js';
let SslCertGeneratorService = SslCertGeneratorService_1 = class SslCertGeneratorService {
logger = new Logger(SslCertGeneratorService_1.name);
certDir;
privateKeyPath;
certificatePath;
constructor() {
const storagePath = process.env.UIX_STORAGE_PATH || resolve(homedir(), '.homebridge');
this.certDir = join(storagePath, 'ssl-certs');
this.privateKeyPath = join(this.certDir, 'private-key.pem');
this.certificatePath = join(this.certDir, 'certificate.pem');
}
async generateOrLoadCertificate(hostnames = ['localhost']) {
if (existsSync(this.privateKeyPath) && existsSync(this.certificatePath)) {
try {
const privateKey = await readFile(this.privateKeyPath);
const certificate = await readFile(this.certificatePath);
this.logger.log('Loaded existing self-signed certificate');
return { privateKey, certificate };
}
catch (error) {
this.logger.warn('Failed to load existing certificate, generating new one:', error.message);
}
}
return this.generateCertificate(hostnames);
}
async generateCertificate(hostnames) {
this.logger.log('Generating self-signed certificate...');
try {
await ensureDir(this.certDir);
const keys = forge.pki.rsa.generateKeyPair(2048);
const cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date('2050-01-01T00:00:00Z');
const attrs = [
{ name: 'commonName', value: hostnames[0] || 'localhost' },
{ name: 'countryName', value: 'US' },
{ shortName: 'ST', value: 'State' },
{ name: 'localityName', value: 'City' },
{ name: 'organizationName', value: 'Homebridge' },
{ shortName: 'OU', value: 'Homebridge UI' },
];
cert.setSubject(attrs);
cert.setIssuer(attrs);
const extensions = [
{
name: 'basicConstraints',
cA: true,
},
{
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true,
},
{
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
},
{
name: 'subjectAltName',
altNames: hostnames.map((hostname) => {
if (RE_IPV4.test(hostname) || RE_IPV6.test(hostname)) {
return {
type: 7,
ip: hostname,
};
}
else {
return {
type: 2,
value: hostname,
};
}
}),
},
];
cert.setExtensions(extensions);
cert.sign(keys.privateKey, forge.md.sha256.create());
const privateKeyPem = forge.pki.privateKeyToPem(keys.privateKey);
const certificatePem = forge.pki.certificateToPem(cert);
await writeFile(this.privateKeyPath, privateKeyPem, 'utf8');
await writeFile(this.certificatePath, certificatePem, 'utf8');
this.logger.log(`Self-signed certificate generated successfully for: ${hostnames.join(', ')}`);
return {
privateKey: Buffer.from(privateKeyPem),
certificate: Buffer.from(certificatePem),
};
}
catch (error) {
this.logger.error('Failed to generate self-signed certificate:', error);
throw error;
}
}
};
SslCertGeneratorService = SslCertGeneratorService_1 = __decorate([
Injectable(),
__metadata("design:paramtypes", [])
], SslCertGeneratorService);
export { SslCertGeneratorService };
//# sourceMappingURL=ssl-cert-generator.service.js.map