Skip to content

Commit fe2d889

Browse files
committed
Cypress test for http and dns cert provision
1 parent 5bdc058 commit fe2d889

File tree

4 files changed

+114
-45
lines changed

4 files changed

+114
-45
lines changed

backend/internal/certificate.js

+37-32
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ const internalCertificate = {
209209
.patchAndFetchById(certificate.id, {
210210
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
211211
})
212+
.then(utils.omitRow(omissions()))
212213
.then((saved_row) => {
213214
// Add cert data for audit log
214215
saved_row.meta = _.assign({}, saved_row.meta, {
@@ -732,29 +733,29 @@ const internalCertificate = {
732733

733734
return utils.exec('openssl x509 -in ' + certificate_file + ' -subject -noout')
734735
.then((result) => {
736+
// Examples:
737+
// subject=CN = *.jc21.com
735738
// subject=CN = something.example.com
736739
const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim;
737740
const match = regex.exec(result);
738-
739-
if (typeof match[1] === 'undefined') {
740-
throw new error.ValidationError('Could not determine subject from certificate: ' + result);
741+
if (match && typeof match[1] !== 'undefined') {
742+
certData['cn'] = match[1];
741743
}
742-
743-
certData['cn'] = match[1];
744744
})
745745
.then(() => {
746746
return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout');
747747
})
748+
748749
.then((result) => {
750+
// Examples:
749751
// issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
752+
// issuer=C = US, O = Let's Encrypt, CN = E5
753+
// issuer=O = NginxProxyManager, CN = NginxProxyManager Intermediate CA","O = NginxProxyManager, CN = NginxProxyManager Intermediate CA
750754
const regex = /^(?:issuer=)?(.*)$/gim;
751755
const match = regex.exec(result);
752-
753-
if (typeof match[1] === 'undefined') {
754-
throw new error.ValidationError('Could not determine issuer from certificate: ' + result);
756+
if (match && typeof match[1] !== 'undefined') {
757+
certData['issuer'] = match[1];
755758
}
756-
757-
certData['issuer'] = match[1];
758759
})
759760
.then(() => {
760761
return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout');
@@ -829,16 +830,16 @@ const internalCertificate = {
829830
requestLetsEncryptSsl: (certificate) => {
830831
logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
831832

832-
const cmd = certbotCommand + ' certonly ' +
833-
'--config "' + letsencryptConfig + '" ' +
833+
const cmd = `${certbotCommand} certonly ` +
834+
`--config '${letsencryptConfig}' ` +
834835
'--work-dir "/tmp/letsencrypt-lib" ' +
835836
'--logs-dir "/tmp/letsencrypt-log" ' +
836-
'--cert-name "npm-' + certificate.id + '" ' +
837+
`--cert-name "npm-${certificate.id}" ` +
837838
'--agree-tos ' +
838839
'--authenticator webroot ' +
839-
'--email "' + certificate.meta.letsencrypt_email + '" ' +
840+
`--email '${certificate.meta.letsencrypt_email}' ` +
840841
'--preferred-challenges "dns,http" ' +
841-
'--domains "' + certificate.domain_names.join(',') + '" ' +
842+
`--domains "${certificate.domain_names.join(',')}" ` +
842843
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
843844
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
844845

@@ -871,25 +872,26 @@ const internalCertificate = {
871872
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
872873

873874
let mainCmd = certbotCommand + ' certonly ' +
874-
'--config "' + letsencryptConfig + '" ' +
875+
`--config '${letsencryptConfig}' ` +
875876
'--work-dir "/tmp/letsencrypt-lib" ' +
876877
'--logs-dir "/tmp/letsencrypt-log" ' +
877-
'--cert-name "npm-' + certificate.id + '" ' +
878+
`--cert-name 'npm-${certificate.id}' ` +
878879
'--agree-tos ' +
879-
'--email "' + certificate.meta.letsencrypt_email + '" ' +
880-
'--domains "' + certificate.domain_names.join(',') + '" ' +
881-
'--authenticator ' + dnsPlugin.full_plugin_name + ' ' +
880+
`--email '${certificate.meta.letsencrypt_email}' ` +
881+
`--domains '${certificate.domain_names.join(',')}' ` +
882+
`--authenticator '${dnsPlugin.full_plugin_name}' ` +
882883
(
883884
hasConfigArg
884-
? '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"'
885+
? `--${dnsPlugin.full_plugin_name}-credentials '${credentialsLocation}' `
885886
: ''
886887
) +
887888
(
888889
certificate.meta.propagation_seconds !== undefined
889-
? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
890+
? `--${dnsPlugin.full_plugin_name}-propagation-seconds '${certificate.meta.propagation_seconds}' `
890891
: ''
891892
) +
892-
(letsencryptStaging ? ' --staging' : '');
893+
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
894+
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
893895

894896
// Prepend the path to the credentials file as an environment variable
895897
if (certificate.meta.dns_provider === 'route53') {
@@ -966,14 +968,15 @@ const internalCertificate = {
966968
logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
967969

968970
const cmd = certbotCommand + ' renew --force-renewal ' +
969-
'--config "' + letsencryptConfig + '" ' +
971+
`--config '${letsencryptConfig}' ` +
970972
'--work-dir "/tmp/letsencrypt-lib" ' +
971973
'--logs-dir "/tmp/letsencrypt-log" ' +
972-
'--cert-name "npm-' + certificate.id + '" ' +
974+
`--cert-name 'npm-${certificate.id}' ` +
973975
'--preferred-challenges "dns,http" ' +
974976
'--no-random-sleep-on-renew ' +
975977
'--disable-hook-validation ' +
976-
(letsencryptStaging ? '--staging' : '');
978+
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
979+
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
977980

978981
logger.info('Command:', cmd);
979982

@@ -998,13 +1001,14 @@ const internalCertificate = {
9981001
logger.info(`Renewing Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
9991002

10001003
let mainCmd = certbotCommand + ' renew --force-renewal ' +
1001-
'--config "' + letsencryptConfig + '" ' +
1004+
`--config "${letsencryptConfig}" ` +
10021005
'--work-dir "/tmp/letsencrypt-lib" ' +
10031006
'--logs-dir "/tmp/letsencrypt-log" ' +
1004-
'--cert-name "npm-' + certificate.id + '" ' +
1007+
`--cert-name 'npm-${certificate.id}' ` +
10051008
'--disable-hook-validation ' +
10061009
'--no-random-sleep-on-renew ' +
1007-
(letsencryptStaging ? ' --staging' : '');
1010+
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
1011+
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
10081012

10091013
// Prepend the path to the credentials file as an environment variable
10101014
if (certificate.meta.dns_provider === 'route53') {
@@ -1030,12 +1034,13 @@ const internalCertificate = {
10301034
logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
10311035

10321036
const mainCmd = certbotCommand + ' revoke ' +
1033-
'--config "' + letsencryptConfig + '" ' +
1037+
`--config '${letsencryptConfig}' ` +
10341038
'--work-dir "/tmp/letsencrypt-lib" ' +
10351039
'--logs-dir "/tmp/letsencrypt-log" ' +
1036-
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
1040+
`--cert-path '/etc/letsencrypt/live/npm-${certificate.id}/fullchain.pem' ` +
10371041
'--delete-after-revoke ' +
1038-
(letsencryptStaging ? '--staging' : '');
1042+
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
1043+
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
10391044

10401045
// Don't fail command if file does not exist
10411046
const delete_credentialsCmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;

backend/schema/components/certificate-object.json

+15-12
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@
4545
"type": "object",
4646
"additionalProperties": false,
4747
"properties": {
48-
"letsencrypt_email": {
49-
"type": "string"
48+
"certificate": {
49+
"type": "string",
50+
"minLength": 1
5051
},
51-
"letsencrypt_agree": {
52-
"type": "boolean"
52+
"certificate_key": {
53+
"type": "string",
54+
"minLength": 1
5355
},
5456
"dns_challenge": {
5557
"type": "boolean"
@@ -60,17 +62,18 @@
6062
"dns_provider_credentials": {
6163
"type": "string"
6264
},
65+
"letsencrypt_agree": {
66+
"type": "boolean"
67+
},
68+
"letsencrypt_certificate": {
69+
"type": "object"
70+
},
71+
"letsencrypt_email": {
72+
"type": "string"
73+
},
6374
"propagation_seconds": {
6475
"type": "integer",
6576
"minimum": 0
66-
},
67-
"certificate": {
68-
"type": "string",
69-
"minLength": 1
70-
},
71-
"certificate_key": {
72-
"type": "string",
73-
"minLength": 1
7477
}
7578
}
7679
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// <reference types="cypress" />
2+
3+
describe('Full Certificate Provisions', () => {
4+
let token;
5+
6+
before(() => {
7+
cy.getToken().then((tok) => {
8+
token = tok;
9+
});
10+
});
11+
12+
it.only('Should be able to create new http certificate', function() {
13+
cy.task('backendApiPost', {
14+
token: token,
15+
path: '/api/nginx/certificates',
16+
data: {
17+
domain_names: [
18+
'website1.example.com'
19+
],
20+
meta: {
21+
letsencrypt_email: 'admin@example.com',
22+
letsencrypt_agree: true,
23+
dns_challenge: false
24+
},
25+
provider: 'letsencrypt'
26+
}
27+
}).then((data) => {
28+
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
29+
expect(data).to.have.property('id');
30+
expect(data.id).to.be.greaterThan(0);
31+
expect(data.provider).to.be.equal('letsencrypt');
32+
});
33+
});
34+
35+
it('Should be able to create new DNS certificate with Powerdns', function() {
36+
cy.task('backendApiPost', {
37+
token: token,
38+
path: '/api/certificates',
39+
data: {
40+
domain_names: [
41+
'website2.example.com'
42+
],
43+
meta: {
44+
letsencrypt_email: "admin@example.com",
45+
dns_challenge: true,
46+
dns_provider: 'powerdns',
47+
dns_provider_credentials: 'dns_powerdns_api_url = http://ns1.pdns:8081\r\ndns_powerdns_api_key = npm',
48+
letsencrypt_agree: true
49+
},
50+
provider: 'letsencrypt'
51+
}
52+
}).then((data) => {
53+
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
54+
expect(data).to.have.property('id');
55+
expect(data.id).to.be.greaterThan(0);
56+
expect(data.provider).to.be.equal('letsencrypt');
57+
expect(data.meta.dns_provider).to.be.equal('powerdns');
58+
});
59+
});
60+
61+
});

test/cypress/plugins/backendApi/client.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const BackendApi = function(config, token) {
77

88
this.axios = axios.create({
99
baseURL: config.baseUrl,
10-
timeout: 5000,
10+
timeout: 60000,
1111
});
1212
};
1313

0 commit comments

Comments
 (0)