UNPKG

@openzeppelin/defender-serverless

Version:
170 lines (169 loc) 8.82 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const prompt_1 = __importDefault(require("prompt")); const logger_1 = __importDefault(require("../utils/logger")); const utils_1 = require("../utils"); class DefenderRemove { constructor(serverless, options, logging) { this.serverless = serverless; this.options = options; this.logging = logging; this.log = logger_1.default.getInstance(); this.hooks = { 'before:remove:remove': () => this.validateKeys(), 'remove:remove': this.requestConfirmation.bind(this), }; } validateKeys() { this.teamKey = (0, utils_1.getTeamAPIkeysOrThrow)(this.serverless); } async wrapper(context, resourceType, resources, retrieveExistingResources, onRemove, output = []) { try { this.log.progress('component-info', `Retrieving ${resourceType}`); const existing = (await retrieveExistingResources()).filter(e => (0, utils_1.isTemplateResource)(context, e, resourceType, resources ?? [])); this.log.progress('component-remove', `Removing ${resourceType} from Defender`); await onRemove(existing); output.push(...existing); } catch (e) { this.log.tryLogDefenderError(e); } } async requestConfirmation() { if (process.stdout.isTTY) { const properties = [ { name: 'confirm', validator: /^(y|n){1}$/i, warning: 'Confirmation must be `y` (yes) or `n` (no)', }, ]; prompt_1.default.start({ message: 'This action will remove your resources from Defender permanently. Are you sure you wish to continue [y/n]?', }); const { confirm } = await prompt_1.default.get(properties); if (confirm.toString().toLowerCase() !== 'y') { this.log.error('Confirmation not acquired. Terminating command'); return; } this.log.success('Confirmation acquired'); } await this.remove(); } async remove() { this.log.notice('========================================================'); const stackName = (0, utils_1.getStackName)(this.serverless); this.log.progress('remove', `Running Defender Remove on stack: ${stackName}`); const stdOut = { stack: stackName, sentinels: [], autotasks: [], contracts: [], relayers: [], notifications: [], categories: [], secrets: [], }; // Sentinels const sentinelClient = (0, utils_1.getSentinelClient)(this.teamKey); const listSentinels = () => sentinelClient.list().then(i => i.items); await this.wrapper(this.serverless, 'Sentinels', this.serverless.service.resources?.Resources?.sentinels, listSentinels, async (sentinels) => { await Promise.all(sentinels.map(async (e) => { this.log.progress('component-remove-extra', `Removing ${e.stackResourceId} (${e.subscriberId}) from Defender`); await sentinelClient.delete(e.subscriberId); this.log.success(`Removed ${e.stackResourceId} (${e.subscriberId})`); })); }, stdOut.sentinels); // Autotasks const autotaskClient = (0, utils_1.getAutotaskClient)(this.teamKey); const listAutotasks = () => autotaskClient.list().then(i => i.items); await this.wrapper(this.serverless, 'Autotasks', this.serverless.service.functions, listAutotasks, async (autotasks) => { await Promise.all(autotasks.map(async (e) => { this.log.progress('component-remove-extra', `Removing ${e.stackResourceId} (${e.autotaskId}) from Defender`); await autotaskClient.delete(e.autotaskId); this.log.success(`Removed ${e.stackResourceId} (${e.autotaskId})`); })); }, stdOut.autotasks); // Contracts const adminClient = (0, utils_1.getAdminClient)(this.teamKey); const listContracts = () => adminClient.listContracts(); await this.wrapper(this.serverless, 'Contracts', this.serverless.service.resources?.Resources?.contracts, listContracts, async (contracts) => { await Promise.all(contracts.map(async (e) => { const id = `${e.network}-${e.address}`; this.log.progress('component-remove-extra', `Removing ${id} (${e.name}) from Defender`); await adminClient.deleteContract(id); this.log.success(`Removed ${id} (${e.name})`); })); }, stdOut.contracts); try { // Relayer API keys const relayClient = (0, utils_1.getRelayClient)(this.teamKey); const listRelayers = (await relayClient.list()).items; const existingRelayers = listRelayers.filter(e => (0, utils_1.isTemplateResource)(this.serverless, e, 'Relayers', this.serverless.service.resources?.Resources?.relayers ?? [])); this.log.error('Deleting Relayers is currently only possible via the Defender UI.'); this.log.progress('component-info', `Retrieving Relayer API Keys`); await Promise.all(existingRelayers.map(async (relayer) => { this.log.progress('component-info', `Retrieving API Keys for relayer ${relayer.stackResourceId}`); const relayerApiKeys = await relayClient.listKeys(relayer.relayerId); await Promise.all(relayerApiKeys.map(async (e) => { this.log.progress('component-remove-extra', `Removing ${e.stackResourceId} (${e.keyId}) from Defender`); await relayClient.deleteKey(e.relayerId, e.keyId); this.log.success(`Removed ${e.stackResourceId} (${e.keyId})`); })); stdOut.relayers.push({ relayerId: relayer.relayerId, relayerApiKeys }); })); } catch (e) { this.log.tryLogDefenderError(e); } // Notifications const listNotifications = () => sentinelClient.listNotificationChannels(); await this.wrapper(this.serverless, 'Notifications', this.serverless.service.resources?.Resources?.notifications, listNotifications, async (notifications) => { await Promise.all(notifications.map(async (e) => { this.log.progress('component-remove-extra', `Removing ${e.stackResourceId} (${e.notificationId}) from Defender`); await sentinelClient.deleteNotificationChannel(e); this.log.success(`Removed ${e.stackResourceId} (${e.notificationId})`); })); }, stdOut.notifications); // Categories // Temporarily Disabled // const listNotificationCategories = () => sentinelClient.listNotificationCategories(); // await this.wrapper<YCategory, DefenderCategory>( // this.serverless, // 'Categories', // this.serverless.service.resources?.Resources?.categories, // listNotificationCategories, // async (categories: DefenderCategory[]) => { // await Promise.all( // categories.map(async (e) => { // this.log.progress( // 'component-remove-extra', // `Removing ${e.stackResourceId} (${e.categoryId}) from Defender`, // ); // await sentinelClient.deleteNotificationCategory(e.categoryId); // this.log.success(`Removed ${e.stackResourceId} (${e.categoryId})`); // }), // ); // }, // stdOut.categories, // ); // Secrets const listSecrets = () => autotaskClient.listSecrets().then(r => r.secretNames ?? []); const allSecrets = (0, utils_1.getConsolidatedSecrets)(this.serverless); await this.wrapper(this.serverless, 'Secrets', allSecrets, listSecrets, async (secrets) => { this.log.progress('component-remove-extra', `Removing (${secrets.join(', ')}) from Defender`); await autotaskClient.createSecrets({ deletes: secrets, secrets: {}, }); this.log.success(`Removed (${secrets.join(', ')})`); }, stdOut.secrets); this.log.notice('========================================================'); if (!process.stdout.isTTY) this.log.stdOut(JSON.stringify(stdOut, null, 2)); } } exports.default = DefenderRemove;