templates/webpunk-templates/ssl-manager.js
2025-06-15 00:02:46 +03:00

240 lines
7.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
import fs from 'fs'
import path from 'path'
import { execSync } from 'child_process'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const sslDir = path.join(__dirname, 'ssl')
const keyPath = path.join(sslDir, 'server.key')
const certPath = path.join(sslDir, 'server.crt')
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m'
}
const log = (message, color = 'reset') => {
console.log(`${colors[color]}${message}${colors.reset}`)
}
const checkOpenSSL = () => {
try {
execSync('openssl version', { stdio: 'pipe' })
return true
} catch (error) {
return false
}
}
const installInstructions = () => {
log('\n📋 Инструкции по установке OpenSSL:', 'cyan')
log('Windows: https://slproweb.com/products/Win32OpenSSL.html', 'blue')
log('macOS: brew install openssl', 'blue')
log('Ubuntu/Debian: sudo apt-get install openssl', 'blue')
log('CentOS/RHEL: sudo yum install openssl', 'blue')
}
const createCertificates = (domain = 'localhost', days = 365) => {
if (!fs.existsSync(sslDir)) {
fs.mkdirSync(sslDir, { recursive: true })
log(`📁 Создана папка: ${sslDir}`, 'green')
}
try {
log('🔐 Создание SSL сертификатов...', 'yellow')
// Генерируем приватный ключ
log('📝 Генерация приватного ключа...', 'blue')
execSync(`openssl genrsa -out "${keyPath}" 2048`, { stdio: 'pipe' })
// Конфигурация для сертификата с SAN
const configContent = `
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = RU
ST = Development
L = Local
O = Development Server
OU = IT Department
CN = ${domain}
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${domain}
DNS.2 = *.${domain}
DNS.3 = localhost
DNS.4 = *.localhost
IP.1 = 127.0.0.1
IP.2 = ::1
`
const configPath = path.join(sslDir, 'openssl.conf')
fs.writeFileSync(configPath, configContent.trim())
// Генерируем сертификат
log('📜 Генерация сертификата...', 'blue')
const certCommand = `openssl req -new -x509 -key "${keyPath}" -out "${certPath}" -days ${days} -config "${configPath}" -extensions v3_req`
execSync(certCommand, { stdio: 'pipe' })
// Удаляем временный конфиг
fs.unlinkSync(configPath)
log('\n✅ SSL сертификаты успешно созданы!', 'green')
log(`🔑 Ключ: ${keyPath}`, 'cyan')
log(`📄 Сертификат: ${certPath}`, 'cyan')
log(`🌐 Домен: ${domain}`, 'cyan')
log(`⏰ Действителен: ${days} дней`, 'cyan')
// Показываем информацию о сертификате
showCertInfo()
log('\n⚠ Важно:', 'yellow')
log('• Это сертификаты только для разработки', 'yellow')
log('• Добавьте сертификат в доверенные в браузере для устранения предупреждений', 'yellow')
} catch (error) {
log('\n❌ Ошибка создания SSL сертификатов:', 'red')
log(error.message, 'red')
installInstructions()
}
}
const showCertInfo = () => {
if (!fs.existsSync(certPath)) {
log('❌ Сертификат не найден', 'red')
return
}
try {
log('\n📋 Информация о сертификате:', 'cyan')
const certInfo = execSync(`openssl x509 -in "${certPath}" -text -noout`, { encoding: 'utf8' })
// Извлекаем нужную информацию
const subjectMatch = certInfo.match(/Subject: (.+)/);
const validFromMatch = certInfo.match(/Not Before: (.+)/);
const validToMatch = certInfo.match(/Not After : (.+)/);
const sanMatch = certInfo.match(/DNS:([^,\n]+)/g);
if (subjectMatch) log(`📝 Subject: ${subjectMatch[1].trim()}`, 'blue')
if (validFromMatch) log(`📅 Действителен с: ${validFromMatch[1].trim()}`, 'blue')
if (validToMatch) log(`📅 Действителен до: ${validToMatch[1].trim()}`, 'blue')
if (sanMatch) {
log(`🌐 Домены: ${sanMatch.map(d => d.replace('DNS:', '')).join(', ')}`, 'blue')
}
} catch (error) {
log('❌ Ошибка чтения информации о сертификате', 'red')
}
}
const deleteCertificates = () => {
let deleted = false
if (fs.existsSync(keyPath)) {
fs.unlinkSync(keyPath)
log(`🗑️ Удален ключ: ${keyPath}`, 'yellow')
deleted = true
}
if (fs.existsSync(certPath)) {
fs.unlinkSync(certPath)
log(`🗑️ Удален сертификат: ${certPath}`, 'yellow')
deleted = true
}
if (deleted) {
log('✅ SSL сертификаты удалены', 'green')
} else {
log(' SSL сертификаты не найдены', 'blue')
}
}
const checkCertificates = () => {
const keyExists = fs.existsSync(keyPath)
const certExists = fs.existsSync(certPath)
log('\n🔍 Проверка SSL сертификатов:', 'cyan')
log(`🔑 Ключ: ${keyExists ? '✅ Существует' : '❌ Не найден'}`, keyExists ? 'green' : 'red')
log(`📄 Сертификат: ${certExists ? '✅ Существует' : '❌ Не найден'}`, certExists ? 'green' : 'red')
if (keyExists && certExists) {
showCertInfo()
}
return keyExists && certExists
}
const showHelp = () => {
log('\n🔧 SSL Manager - Утилита для управления SSL сертификатами\n', 'cyan')
log('Использование:', 'yellow')
log(' node ssl-manager.js <команда> [опции]\n', 'blue')
log('Команды:', 'yellow')
log(' create [domain] [days] Создать новые сертификаты (по умолчанию: localhost, 365 дней)', 'blue')
log(' check Проверить существующие сертификаты', 'blue')
log(' info Показать информацию о сертификате', 'blue')
log(' delete Удалить существующие сертификаты', 'blue')
log(' help Показать эту справку\n', 'blue')
log('Примеры:', 'yellow')
log(' node ssl-manager.js create', 'green')
log(' node ssl-manager.js create mysite.local 30', 'green')
log(' node ssl-manager.js check', 'green')
}
// Основная логика
const command = process.argv[2]
const arg1 = process.argv[3]
const arg2 = process.argv[4]
// Проверяем наличие OpenSSL
if (!checkOpenSSL() && command !== 'help' && command !== 'check') {
log('❌ OpenSSL не найден в системе', 'red')
installInstructions()
process.exit(1)
}
switch (command) {
case 'create':
const domain = arg1 || 'localhost'
const days = parseInt(arg2) || 365
createCertificates(domain, days)
break
case 'check':
checkCertificates()
break
case 'info':
showCertInfo()
break
case 'delete':
deleteCertificates()
break
case 'help':
case undefined:
showHelp()
break
default:
log(`❌ Неизвестная команда: ${command}`, 'red')
showHelp()
process.exit(1)
}