Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/dashmate/src/commands/ssl/cleanup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Listr } from 'listr2';
import { Flags } from '@oclif/core';
import ConfigBaseCommand from '../../oclif/command/ConfigBaseCommand.js';
import MuteOneLineError from '../../oclif/errors/MuteOneLineError.js';

export default class CleanupCommand extends ConfigBaseCommand {
static description = `Cleanup Zero SSL certificate

Cancel all drafted or pending validation certificates on ZeroSSL
`;

static flags = {
...ConfigBaseCommand.flags,
verbose: Flags.boolean({ char: 'v', description: 'use verbose mode for output', default: false }),
};

/**
* @param {Object} args
* @param {Object} flags
* @param {boolean} flags.verbose
* @param {Config} config
* @param {cleanupZeroSSLCertificatesTask} cleanupZeroSSLCertificatesTask
* @return {Promise<void>}
*/
async runWithDependencies(
args,
{
verbose: isVerbose,
},
config,
cleanupZeroSSLCertificatesTask,
) {
const tasks = new Listr(
[
{
title: 'Cleanup ZeroSSL certificate',
task: () => cleanupZeroSSLCertificatesTask(config),
},
],
{
renderer: isVerbose ? 'verbose' : 'default',
rendererOptions: {
showTimer: isVerbose,
clearOutput: false,
collapse: false,
showSubtasks: true,
removeEmptyLines: false,
},
},
);

try {
await tasks.run();
} catch (e) {
throw new MuteOneLineError(e);
}
}
}
2 changes: 1 addition & 1 deletion packages/dashmate/src/commands/ssl/obtain.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Certificate will be renewed if it is about to expire (see 'expiration-days' flag
[
{
title: 'Obtain ZeroSSL certificate',
task: async () => obtainZeroSSLCertificateTask(config),
task: () => obtainZeroSSLCertificateTask(config),
},
],
{
Expand Down
5 changes: 5 additions & 0 deletions packages/dashmate/src/createDIContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import analyseSystemResourcesFactory from './doctor/analyse/analyseSystemResourc
import analyseSamplesFactory from './doctor/analyseSamplesFactory.js';
import archiveSamples from './doctor/archiveSamples.js';
import unarchiveSamplesFactory from './doctor/unarchiveSamplesFactory.js';
import cleanupZeroSSLCertificatesTaskFactory
from './listr/tasks/ssl/zerossl/cleanupZeroSSLCertificatesTaskFactory.js';
import cancelCertificate from './ssl/zerossl/cancelCertificate.js';

import renderTemplateFactory from './templates/renderTemplateFactory.js';
import renderServiceTemplatesFactory from './templates/renderServiceTemplatesFactory.js';
Expand Down Expand Up @@ -206,6 +209,7 @@ export default async function createDIContainer(options = {}) {
downloadCertificate: asValue(downloadCertificate),
getCertificate: asValue(getCertificate),
listCertificates: asValue(listCertificates),
cancelCertificate: asValue(cancelCertificate),
createSelfSignedCertificate: asValue(createSelfSignedCertificate),
verificationServer: asClass(VerificationServer).singleton(),
});
Expand Down Expand Up @@ -299,6 +303,7 @@ export default async function createDIContainer(options = {}) {
enableCoreQuorumsTask: asFunction(enableCoreQuorumsTaskFactory).singleton(),
registerMasternodeGuideTask: asFunction(registerMasternodeGuideTaskFactory).singleton(),
obtainZeroSSLCertificateTask: asFunction(obtainZeroSSLCertificateTaskFactory).singleton(),
cleanupZeroSSLCertificatesTask: asFunction(cleanupZeroSSLCertificatesTaskFactory).singleton(),
obtainSelfSignedCertificateTask: asFunction(obtainSelfSignedCertificateTaskFactory).singleton(),
saveCertificateTask: asFunction(saveCertificateTaskFactory),
reindexNodeTask: asFunction(reindexNodeTaskFactory).singleton(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function scheduleRenewZeroSslCertificateFactory(
}

const job = new CronJob(expiresAt, async () => {
const tasks = await obtainZeroSSLCertificateTask(config);
const tasks = obtainZeroSSLCertificateTask(config);

await tasks.run({
expirationDays: Certificate.EXPIRATION_LIMIT_DAYS,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import chalk from 'chalk';
import { Listr } from 'listr2';
import { Observable } from 'rxjs';
import wait from '../../../../util/wait.js';

/**
* @param {listCertificates} listCertificates
* @param {cancelCertificate} cancelCertificate
* @return {cleanupZeroSSLCertificatesTask}
*/
export default function cleanupZeroSSLCertificatesTaskFactory(
listCertificates,
cancelCertificate,
) {
/**
* @typedef {cleanupZeroSSLCertificatesTask}
* @param {Config} config
* @return {Listr}
*/
function cleanupZeroSSLCertificatesTask(config) {
const apiKey = config.get('platform.gateway.ssl.providerConfigs.zerossl.apiKey', true);

return new Listr([
{
title: 'Collect drafted and pending validation certificates',
// Skips the check if force flag is set
task: async (ctx, task) => {
ctx.certificates = [];

let certificatesPerRequest = [];
let page = 1;

// Fetch all certificates in draft or pending validation status
// with pagination
do {
certificatesPerRequest = await listCertificates(apiKey, ['draft', 'pending_validation'], page);

ctx.certificates = ctx.certificates.concat(certificatesPerRequest);

page += 1;

// eslint-disable-next-line no-param-reassign
task.output = `Found ${ctx.certificates.length} certificates`;
} while (certificatesPerRequest.length === 1000);

ctx.total = ctx.certificates.length;
},
},
{
title: 'Cancel certificates',
skip: (ctx) => ctx.certificates.length === 0,
task: async (ctx, task) => {
// eslint-disable-next-line no-param-reassign
task.title = `Cancel ${ctx.certificates.length} certificates`;
ctx.canceled = 0;
ctx.errored = 0;
return new Observable(async (observer) => {
for (const certificate of ctx.certificates) {
try {
await cancelCertificate(apiKey, certificate.id);

ctx.canceled += 1;
} catch (e) {
ctx.errored += 1;

if (process.env.DEBUG) {
// eslint-disable-next-line no-console
console.warn(e);
}
}

observer.next(chalk`{green ${ctx.canceled}} / {red ${ctx.errored}} / ${ctx.total}`);

await wait(100);
}

if (ctx.errored > 0) {
observer.error(new Error('Some certificates were not canceled. Please try again.'));
} else {
observer.complete();
}

return this;
});
},
options: {
persistentOutput: true,
},
},
], {
rendererOptions: {
showErrorMessage: true,
},
});
}

return cleanupZeroSSLCertificatesTask;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export default function obtainZeroSSLCertificateTaskFactory(
/**
* @typedef {obtainZeroSSLCertificateTask}
* @param {Config} config
* @return {Promise<Listr>}
* @return {Listr}
*/
async function obtainZeroSSLCertificateTask(config) {
function obtainZeroSSLCertificateTask(config) {
return new Listr([
{
title: 'Check if certificate already exists and not expiring soon',
Expand Down
2 changes: 1 addition & 1 deletion packages/dashmate/src/ssl/zerossl/cancelCertificate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import requestApi from './requestApi';
import requestApi from './requestApi.js';

/**
* Get ZeroSSL certificate
Expand Down
10 changes: 8 additions & 2 deletions packages/dashmate/src/ssl/zerossl/listCertificates.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ import Certificate from './Certificate.js';
* @param {string} apiKey
* @param {String[]} [statuses] - possible values: draft, pending_validation, issued, cancelled,
* revoked, expired.
* @param {number} [page]
* @param {string} [search]
* @return {Promise<Certificate[]>}
*/

export default async function listCertificates(apiKey, statuses = [], search = undefined) {
let url = `https://api.zerossl.com/certificates?access_key=${apiKey}&limit=1000`;
export default async function listCertificates(
apiKey,
statuses = [],
page = 1,
search = undefined,
) {
let url = `https://api.zerossl.com/certificates?access_key=${apiKey}&limit=1000&page=${page}`;

if (statuses.length > 0) {
url += `&statuses=${statuses.join(',')}`;
Expand Down
Loading