Upload Plugin: check if the plugin can be uploadable
Gitlab: #10
Change-Id: I9b5d44179c32a0d2bf4c1ddeaf2fb9e0fde059da
diff --git a/src/controllers/plugins.controller.ts b/src/controllers/plugins.controller.ts
index 6586199..0368283 100644
--- a/src/controllers/plugins.controller.ts
+++ b/src/controllers/plugins.controller.ts
@@ -247,6 +247,67 @@
}
}
);
+ /**
+ * @swagger
+ *
+ * /upload/{arch}/{id}:
+ * get:
+ * summary: Verify if the plugin is already uploaded with the same issuer
+ * description: Verify if the plugin is already uploaded with the same issuer
+ * tags: [Example, Time]
+ * parameters:
+ * - name: id
+ * in: path
+ * description: The ID of the plugin to be downloaded.
+ * required: true
+ * schema:
+ * type: string
+ * - name: arch
+ * in: path
+ * description: The architecture for which the plugin is requested.
+ * required: true
+ * schema:
+ * type: string
+ * responses:
+ * '200':
+ * description: The plugin is uploadable.
+ * '400':
+ * description: Bad request - When the 'id', 'arch' parameter or the 'Authorization' http header is missing.
+ * '403':
+ * description: Forbidden - When the plugin is already uploaded with a different issuer.
+ * '500':
+ * description: Internal server error - Something went wrong on the server.
+ *
+ */
+
+ // GET /upload/:arch/:id
+ this.router.get('/upload/:arch/:id', (req: Request, res: Response) => {
+ try {
+ const clientCertificate = req.get('Authorization');
+ if (
+ req.params.id === undefined ||
+ req.params.arch === undefined ||
+ clientCertificate === undefined
+ ) {
+ res.status(StatusCodes.BAD_REQUEST).send();
+ return;
+ }
+ this.pluginsManager
+ .isPluginUploadable(
+ req.params.id,
+ req.params.arch,
+ Buffer.from(clientCertificate, 'base64')
+ )
+ .then(isUploadable =>
+ res
+ .status(isUploadable ? StatusCodes.OK : StatusCodes.FORBIDDEN)
+ .send()
+ )
+ .catch(() => res.status(StatusCodes.INTERNAL_SERVER_ERROR).send());
+ } catch (e) {
+ res.status(StatusCodes.INTERNAL_SERVER_ERROR).send();
+ }
+ });
/**
* @swagger
diff --git a/src/services/certificate.manager.service.ts b/src/services/certificate.manager.service.ts
index 20eb1f8..5b402b5 100644
--- a/src/services/certificate.manager.service.ts
+++ b/src/services/certificate.manager.service.ts
@@ -66,10 +66,7 @@
return Buffer.compare(signature, checkSignature) === 0;
}
- private async readCertificate(
- path: string,
- file: string
- ): Promise<X509Certificate> {
+ async readCertificate(path: string, file: string): Promise<X509Certificate> {
return await this.fileManager
.readArchive(path, file)
.then((content: Buffer) => {
@@ -90,4 +87,16 @@
return acc;
}, {});
}
+
+ isSameKey(issuer: X509Certificate, plugin: X509Certificate): boolean {
+ const key1Formatted = issuer.publicKey.export({
+ format: 'pem',
+ type: 'pkcs1',
+ });
+ const key2Formatted = plugin.publicKey.export({
+ format: 'pem',
+ type: 'pkcs1',
+ });
+ return key1Formatted === key2Formatted;
+ }
}
diff --git a/src/services/plugins.manager.service.ts b/src/services/plugins.manager.service.ts
index 18a5414..bf96f84 100644
--- a/src/services/plugins.manager.service.ts
+++ b/src/services/plugins.manager.service.ts
@@ -23,6 +23,7 @@
import {CertificateManager} from './certificate.manager.service';
import {ArchitectureManager} from './architecture.manager';
import {basename, extname} from 'path';
+import {X509Certificate} from 'crypto';
@Service()
export class PluginsManager {
@@ -253,6 +254,27 @@
};
}
+ async isPluginUploadable(
+ id: string,
+ arch: string,
+ requestCertificate: Buffer
+ ): Promise<boolean> {
+ const requestedCertificate = new X509Certificate(requestCertificate);
+ const remotePlugin = await this.findPlugin(id, arch);
+ const remotePluginPath = await this.getPluginPath(id, arch);
+ if (remotePlugin === undefined || remotePluginPath === undefined) {
+ return true;
+ }
+ const remoteCertificate = await this.certificateManager.readCertificate(
+ remotePluginPath,
+ id + '.crt'
+ );
+ return this.certificateManager.isSameKey(
+ requestedCertificate,
+ remoteCertificate
+ );
+ }
+
async getVersions(): Promise<Array<{id: string; version: string}>> {
if (this.plugins.length === 0) {
await this.setPlugins();