Browse Source

Cypress test for http and dns cert provision

Jamie Curnow 1 year ago
parent
commit
fe2d8895d6

+ 37 - 32
backend/internal/certificate.js

@@ -209,6 +209,7 @@ const internalCertificate = {
 										.patchAndFetchById(certificate.id, {
 											expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
 										})
+										.then(utils.omitRow(omissions()))
 										.then((saved_row) => {
 											// Add cert data for audit log
 											saved_row.meta = _.assign({}, saved_row.meta, {
@@ -732,29 +733,29 @@ const internalCertificate = {
 
 		return utils.exec('openssl x509 -in ' + certificate_file + ' -subject -noout')
 			.then((result) => {
+				// Examples:
+				// subject=CN = *.jc21.com
 				// subject=CN = something.example.com
 				const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim;
 				const match = regex.exec(result);
-
-				if (typeof match[1] === 'undefined') {
-					throw new error.ValidationError('Could not determine subject from certificate: ' + result);
+				if (match && typeof match[1] !== 'undefined') {
+					certData['cn'] = match[1];
 				}
-
-				certData['cn'] = match[1];
 			})
 			.then(() => {
 				return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout');
 			})
+
 			.then((result) => {
+				// Examples:
 				// issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
+				// issuer=C = US, O = Let's Encrypt, CN = E5
+				// issuer=O = NginxProxyManager, CN = NginxProxyManager Intermediate CA","O = NginxProxyManager, CN = NginxProxyManager Intermediate CA
 				const regex = /^(?:issuer=)?(.*)$/gim;
 				const match = regex.exec(result);
-
-				if (typeof match[1] === 'undefined') {
-					throw new error.ValidationError('Could not determine issuer from certificate: ' + result);
+				if (match && typeof match[1] !== 'undefined') {
+					certData['issuer'] = match[1];
 				}
-
-				certData['issuer'] = match[1];
 			})
 			.then(() => {
 				return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout');
@@ -829,16 +830,16 @@ const internalCertificate = {
 	requestLetsEncryptSsl: (certificate) => {
 		logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
-		const cmd = certbotCommand + ' certonly ' +
-			'--config "' + letsencryptConfig + '" ' +
+		const cmd = `${certbotCommand} certonly ` +
+			`--config '${letsencryptConfig}' ` +
 			'--work-dir "/tmp/letsencrypt-lib" ' +
 			'--logs-dir "/tmp/letsencrypt-log" ' +
-			'--cert-name "npm-' + certificate.id + '" ' +
+			`--cert-name "npm-${certificate.id}" ` +
 			'--agree-tos ' +
 			'--authenticator webroot ' +
-			'--email "' + certificate.meta.letsencrypt_email + '" ' +
+			`--email '${certificate.meta.letsencrypt_email}' ` +
 			'--preferred-challenges "dns,http" ' +
-			'--domains "' + certificate.domain_names.join(',') + '" ' +
+			`--domains "${certificate.domain_names.join(',')}" ` +
 			(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
 			(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
 
@@ -871,25 +872,26 @@ const internalCertificate = {
 		const hasConfigArg = certificate.meta.dns_provider !== 'route53';
 
 		let mainCmd = certbotCommand + ' certonly ' +
-			'--config "' + letsencryptConfig + '" ' +
+			`--config '${letsencryptConfig}' ` +
 			'--work-dir "/tmp/letsencrypt-lib" ' +
 			'--logs-dir "/tmp/letsencrypt-log" ' +
-			'--cert-name "npm-' + certificate.id + '" ' +
+			`--cert-name 'npm-${certificate.id}' ` +
 			'--agree-tos ' +
-			'--email "' + certificate.meta.letsencrypt_email + '" ' +
-			'--domains "' + certificate.domain_names.join(',') + '" ' +
-			'--authenticator ' + dnsPlugin.full_plugin_name + ' ' +
+			`--email '${certificate.meta.letsencrypt_email}' ` +
+			`--domains '${certificate.domain_names.join(',')}' ` +
+			`--authenticator '${dnsPlugin.full_plugin_name}' ` +
 			(
 				hasConfigArg
-					? '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"'
+					? `--${dnsPlugin.full_plugin_name}-credentials '${credentialsLocation}' `
 					: ''
 			) +
 			(
 				certificate.meta.propagation_seconds !== undefined
-					? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
+					? `--${dnsPlugin.full_plugin_name}-propagation-seconds '${certificate.meta.propagation_seconds}' `
 					: ''
 			) +
-			(letsencryptStaging ? ' --staging' : '');
+			(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
+			(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
 
 		// Prepend the path to the credentials file as an environment variable
 		if (certificate.meta.dns_provider === 'route53') {
@@ -966,14 +968,15 @@ const internalCertificate = {
 		logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
 		const cmd = certbotCommand + ' renew --force-renewal ' +
-			'--config "' + letsencryptConfig + '" ' +
+			`--config '${letsencryptConfig}' ` +
 			'--work-dir "/tmp/letsencrypt-lib" ' +
 			'--logs-dir "/tmp/letsencrypt-log" ' +
-			'--cert-name "npm-' + certificate.id + '" ' +
+			`--cert-name 'npm-${certificate.id}' ` +
 			'--preferred-challenges "dns,http" ' +
 			'--no-random-sleep-on-renew ' +
 			'--disable-hook-validation ' +
-			(letsencryptStaging ? '--staging' : '');
+			(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
+			(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
 
 		logger.info('Command:', cmd);
 
@@ -998,13 +1001,14 @@ const internalCertificate = {
 		logger.info(`Renewing Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
 
 		let mainCmd = certbotCommand + ' renew --force-renewal ' +
-			'--config "' + letsencryptConfig + '" ' +
+			`--config "${letsencryptConfig}" ` +
 			'--work-dir "/tmp/letsencrypt-lib" ' +
 			'--logs-dir "/tmp/letsencrypt-log" ' +
-			'--cert-name "npm-' + certificate.id + '" ' +
+			`--cert-name 'npm-${certificate.id}' ` +
 			'--disable-hook-validation ' +
 			'--no-random-sleep-on-renew ' +
-			(letsencryptStaging ? ' --staging' : '');
+			(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
+			(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
 
 		// Prepend the path to the credentials file as an environment variable
 		if (certificate.meta.dns_provider === 'route53') {
@@ -1030,12 +1034,13 @@ const internalCertificate = {
 		logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
 
 		const mainCmd = certbotCommand + ' revoke ' +
-			'--config "' + letsencryptConfig + '" ' +
+			`--config '${letsencryptConfig}' ` +
 			'--work-dir "/tmp/letsencrypt-lib" ' +
 			'--logs-dir "/tmp/letsencrypt-log" ' +
-			'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
+			`--cert-path '/etc/letsencrypt/live/npm-${certificate.id}/fullchain.pem' ` +
 			'--delete-after-revoke ' +
-			(letsencryptStaging ? '--staging' : '');
+			(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
+			(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
 
 		// Don't fail command if file does not exist
 		const delete_credentialsCmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;

+ 15 - 12
backend/schema/components/certificate-object.json

@@ -45,11 +45,13 @@
 			"type": "object",
 			"additionalProperties": false,
 			"properties": {
-				"letsencrypt_email": {
-					"type": "string"
+				"certificate": {
+					"type": "string",
+					"minLength": 1
 				},
-				"letsencrypt_agree": {
-					"type": "boolean"
+				"certificate_key": {
+					"type": "string",
+					"minLength": 1
 				},
 				"dns_challenge": {
 					"type": "boolean"
@@ -60,17 +62,18 @@
 				"dns_provider_credentials": {
 					"type": "string"
 				},
+				"letsencrypt_agree": {
+					"type": "boolean"
+				},
+				"letsencrypt_certificate": {
+					"type": "object"
+				},
+				"letsencrypt_email": {
+					"type": "string"
+				},
 				"propagation_seconds": {
 					"type": "integer",
 					"minimum": 0
-				},
-				"certificate": {
-					"type": "string",
-					"minLength": 1
-				},
-				"certificate_key": {
-					"type": "string",
-					"minLength": 1
 				}
 			}
 		}

+ 61 - 0
test/cypress/e2e/api/FullCertProvision.cy.js

@@ -0,0 +1,61 @@
+/// <reference types="cypress" />
+
+describe('Full Certificate Provisions', () => {
+	let token;
+
+	before(() => {
+		cy.getToken().then((tok) => {
+			token = tok;
+		});
+	});
+
+	it.only('Should be able to create new http certificate', function() {
+		cy.task('backendApiPost', {
+			token: token,
+			path:  '/api/nginx/certificates',
+			data:  {
+				domain_names: [
+					'website1.example.com'
+				],
+				meta: {
+					letsencrypt_email: '[email protected]',
+					letsencrypt_agree: true,
+					dns_challenge: false
+				},
+				provider: 'letsencrypt'
+			}
+		}).then((data) => {
+			cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
+			expect(data).to.have.property('id');
+			expect(data.id).to.be.greaterThan(0);
+			expect(data.provider).to.be.equal('letsencrypt');
+		});
+	});
+
+	it('Should be able to create new DNS certificate with Powerdns', function() {
+		cy.task('backendApiPost', {
+			token: token,
+			path:  '/api/certificates',
+			data:  {
+				domain_names: [
+					'website2.example.com'
+				],
+				meta: {
+					letsencrypt_email: "[email protected]",
+					dns_challenge: true,
+					dns_provider: 'powerdns',
+					dns_provider_credentials: 'dns_powerdns_api_url = http://ns1.pdns:8081\r\ndns_powerdns_api_key = npm',
+					letsencrypt_agree: true
+				},
+				provider: 'letsencrypt'
+			}
+		}).then((data) => {
+			cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
+			expect(data).to.have.property('id');
+			expect(data.id).to.be.greaterThan(0);
+			expect(data.provider).to.be.equal('letsencrypt');
+			expect(data.meta.dns_provider).to.be.equal('powerdns');
+		});
+	});
+
+});

+ 1 - 1
test/cypress/plugins/backendApi/client.js

@@ -7,7 +7,7 @@ const BackendApi = function(config, token) {
 
 	this.axios = axios.create({
 		baseURL: config.baseUrl,
-		timeout: 5000,
+		timeout: 60000,
 	});
 };