From 0a2088977be928d6721ca35fce906a7664449e70 Mon Sep 17 00:00:00 2001 From: Bsian Date: Mon, 30 Dec 2019 16:40:23 +0000 Subject: [PATCH] Added subcommand --- src/commands/cwg.ts | 3 +- src/commands/cwg_updatecert.ts | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/commands/cwg_updatecert.ts diff --git a/src/commands/cwg.ts b/src/commands/cwg.ts index 502f51f..b7a4ade 100644 --- a/src/commands/cwg.ts +++ b/src/commands/cwg.ts @@ -4,6 +4,7 @@ import { Client } from '..'; import Create from './cwg_create'; import Data from './cwg_data'; import Delete from './cwg_delete'; +import UpdateCert from './cwg_updatecert'; export default class CWG extends Command { constructor(client: Client) { @@ -12,7 +13,7 @@ export default class CWG extends Command { this.description = 'Manages aspects for the CWG.'; this.usage = `Run ${this.client.config.prefix}${this.name} [subcommand] for usage information`; this.permissions = { roles: ['446104438969466890'] }; - this.subcmds = [Create, Data, Delete]; + this.subcmds = [Create, Data, Delete, UpdateCert]; this.enabled = true; } diff --git a/src/commands/cwg_updatecert.ts b/src/commands/cwg_updatecert.ts new file mode 100644 index 0000000..7f2b6aa --- /dev/null +++ b/src/commands/cwg_updatecert.ts @@ -0,0 +1,63 @@ +import { writeFile } from 'fs-extra'; +import axios from 'axios'; +import { Message } from 'eris'; +import { Command } from '../class'; +import { Client } from '..'; + +export default class CWG_UpdateCert extends Command { + constructor(client: Client) { + super(client); + this.name = 'updatecert'; + this.description = 'Update a CWG certificate'; + this.usage = `${this.client.config.prefix}cwg updatecert [Domain | Port] [Cert Chain] [Private Key] || Use snippets raw URL`; + this.permissions = { roles: ['525441307037007902'] }; + this.aliases = ['update', 'updatecrt', 'renew', 'renewcert', 'renewcrt']; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + if (!args[2]) return this.client.commands.get('help').run(message, ['cwg', this.name]); + const dom = await this.client.db.Domain.findOne({ $or: [{ domain: args[0] }, { port: Number(args[0]) || '' }] }); + if (!dom) return message.channel.createMessage(`***${this.client.stores.emojis.error} The domain or port you provided could not be found.***`); + const { domain, port, x509 } = dom; + const { cert, key } = x509; + + const urls = args.slice(1, 3); // eslint-disable-line + if (urls.some((l) => !l.includes('snippets.cloud.libraryofcode.org/raw/'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid snippets URL***`); + const tasks = urls.map((l) => axios({ method: 'GET', url: l })); + const response = await Promise.all(tasks); + const certAndPrivateKey: string[] = response.map((r) => r.data); + + if (!this.isValidCertificateChain(certAndPrivateKey[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Certificate Chain***`); + if (!this.isValidPrivateKey(certAndPrivateKey[1])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Private Key***`); + + const writeTasks = [writeFile(cert, certAndPrivateKey[0], { encoding: 'utf8' }), writeFile(key, certAndPrivateKey[1], { encoding: 'utf8' })]; + await Promise.all(writeTasks); + + return message.channel.createMessage(`${this.client.stores.emojis.success} ***Updated certificate certificate for ${domain} on port ${port}`); + } catch (error) { + return this.client.util.handleError(error, message, this); + } + } + + public checkOccurance(text: string, query: string) { + return (text.match(new RegExp(query, 'g')) || []).length; + } + + public isValidCertificateChain(cert: string) { + if (!cert.startsWith('-----BEGIN CERTIFICATE-----')) return false; + if (!cert.endsWith('-----END CERTIFICATE-----')) return false; + if (this.checkOccurance(cert, '-----BEGIN CERTIFICATE-----') !== 2) return false; + if (this.checkOccurance(cert, '-----END CERTIFICATE-----') !== 2) return false; + return true; + } + + public isValidPrivateKey(key: string) { + if (!key.startsWith('-----BEGIN PRIVATE KEY-----')) return false; + if (!key.endsWith('-----END PRIVATE KEY-----')) return false; + if (this.checkOccurance(key, '-----BEGIN PRIVATE KEY-----') !== 1) return false; + if (this.checkOccurance(key, '-----END PRIVATE KEY-----') !== 1) return false; + return true; + } +}