mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-05-01 03:22:29 +00:00
Compare commits
3 Commits
3b89d5f380
...
929ac3bd7c
Author | SHA1 | Date | |
---|---|---|---|
|
929ac3bd7c | ||
|
f48e1b46a8 | ||
|
351ba8dacd |
10
Jenkinsfile
vendored
10
Jenkinsfile
vendored
@ -127,6 +127,11 @@ pipeline {
|
|||||||
junit 'test/results/junit/*'
|
junit 'test/results/junit/*'
|
||||||
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
||||||
}
|
}
|
||||||
|
unstable {
|
||||||
|
dir(path: 'testing/results') {
|
||||||
|
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Test Mysql') {
|
stage('Test Mysql') {
|
||||||
@ -155,6 +160,11 @@ pipeline {
|
|||||||
junit 'test/results/junit/*'
|
junit 'test/results/junit/*'
|
||||||
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
||||||
}
|
}
|
||||||
|
unstable {
|
||||||
|
dir(path: 'testing/results') {
|
||||||
|
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('MultiArch Build') {
|
stage('MultiArch Build') {
|
||||||
|
@ -3,27 +3,29 @@ const fs = require('fs');
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
const tempWrite = require('temp-write');
|
const tempWrite = require('temp-write');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
const archiver = require('archiver');
|
||||||
|
const path = require('path');
|
||||||
|
const { isArray } = require('lodash');
|
||||||
const logger = require('../logger').ssl;
|
const logger = require('../logger').ssl;
|
||||||
const config = require('../lib/config');
|
const config = require('../lib/config');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
const utils = require('../lib/utils');
|
const utils = require('../lib/utils');
|
||||||
|
const certbot = require('../lib/certbot');
|
||||||
const certificateModel = require('../models/certificate');
|
const certificateModel = require('../models/certificate');
|
||||||
const tokenModel = require('../models/token');
|
const tokenModel = require('../models/token');
|
||||||
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
||||||
const internalAuditLog = require('./audit-log');
|
const internalAuditLog = require('./audit-log');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
const certbot = require('../lib/certbot');
|
|
||||||
const archiver = require('archiver');
|
|
||||||
const path = require('path');
|
|
||||||
const { isArray } = require('lodash');
|
|
||||||
|
|
||||||
const letsencryptStaging = config.useLetsencryptStaging();
|
const letsencryptStaging = config.useLetsencryptStaging();
|
||||||
|
const letsencryptServer = config.useLetsencryptServer();
|
||||||
const letsencryptConfig = '/etc/letsencrypt.ini';
|
const letsencryptConfig = '/etc/letsencrypt.ini';
|
||||||
const certbotCommand = 'certbot';
|
const certbotCommand = 'certbot';
|
||||||
|
|
||||||
function omissions() {
|
function omissions() {
|
||||||
return ['is_deleted'];
|
return ['is_deleted', 'owner.is_deleted'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const internalCertificate = {
|
const internalCertificate = {
|
||||||
@ -837,7 +839,8 @@ const internalCertificate = {
|
|||||||
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
||||||
'--preferred-challenges "dns,http" ' +
|
'--preferred-challenges "dns,http" ' +
|
||||||
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
||||||
(letsencryptStaging ? '--staging' : '');
|
(letsencryptStaging ? '--staging' : '') +
|
||||||
|
(letsencryptServer !== null ? `--server '${letsencryptServer}'` : '');
|
||||||
|
|
||||||
logger.info('Command:', cmd);
|
logger.info('Command:', cmd);
|
||||||
|
|
||||||
|
@ -180,5 +180,15 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
useLetsencryptStaging: function () {
|
useLetsencryptStaging: function () {
|
||||||
return !!process.env.LE_STAGING;
|
return !!process.env.LE_STAGING;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string|null}
|
||||||
|
*/
|
||||||
|
useLetsencryptServer: function () {
|
||||||
|
if (process.env.LE_SERVER) {
|
||||||
|
return process.env.LE_SERVER;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -24,13 +24,23 @@
|
|||||||
"description": "Nice Name for the custom certificate"
|
"description": "Nice Name for the custom certificate"
|
||||||
},
|
},
|
||||||
"domain_names": {
|
"domain_names": {
|
||||||
"$ref": "../common.json#/properties/domain_names"
|
"description": "Domain Names separated by a comma",
|
||||||
|
"type": "array",
|
||||||
|
"maxItems": 100,
|
||||||
|
"uniqueItems": true,
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expires_on": {
|
"expires_on": {
|
||||||
"description": "Date and time of expiration",
|
"description": "Date and time of expiration",
|
||||||
"readOnly": true,
|
"readOnly": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"$ref": "./user-object.json"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -51,12 +61,16 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"propagation_seconds": {
|
"propagation_seconds": {
|
||||||
"anyOf": [
|
"type": "integer",
|
||||||
{
|
"minimum": 0
|
||||||
"type": "integer",
|
},
|
||||||
"minimum": 0
|
"certificate": {
|
||||||
}
|
"type": "string",
|
||||||
]
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"certificate_key": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,25 @@
|
|||||||
"certificate_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd\nqACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w\nrbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge\nYz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ\noxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z\nEo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X\nzGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU\nia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6\nYHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe\na0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu\nW0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw\no72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW\nH8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+\nN+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh\nELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU\nMDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31\nqjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq\ncMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9\nvMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO\nutTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V\ng0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1\nmJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq\nYatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8\nEQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk\n8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM\nRrKmPK/msHKK/sVHiL+NFqo=\n-----END PRIVATE KEY-----\n"
|
"certificate_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd\nqACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w\nrbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge\nYz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ\noxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z\nEo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X\nzGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU\nia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6\nYHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe\na0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu\nW0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw\no72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW\nH8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+\nN+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh\nELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU\nMDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31\nqjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq\ncMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9\nvMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO\nutTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V\ng0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1\nmJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq\nYatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8\nEQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk\n8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM\nRrKmPK/msHKK/sVHiL+NFqo=\n-----END PRIVATE KEY-----\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["certificate", "certificate_key"],
|
||||||
|
"properties": {
|
||||||
|
"certificate": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"certificate_key": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"intermediate_certificate": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
||||||
|
|
||||||
|
FROM nginxproxymanager/testca AS testca
|
||||||
|
FROM letsencrypt/pebble AS pebbleca
|
||||||
FROM nginxproxymanager/nginx-full:certbot-node
|
FROM nginxproxymanager/nginx-full:certbot-node
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
@ -45,6 +47,8 @@ RUN yarn install \
|
|||||||
|
|
||||||
# add late to limit cache-busting by modifications
|
# add late to limit cache-busting by modifications
|
||||||
COPY docker/rootfs /
|
COPY docker/rootfs /
|
||||||
|
COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem
|
||||||
|
COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt
|
||||||
|
|
||||||
# Remove frontend service not required for prod, dev nginx config as well
|
# Remove frontend service not required for prod, dev nginx config as well
|
||||||
RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \
|
RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
FROM nginxproxymanager/testca AS testca
|
||||||
|
FROM letsencrypt/pebble AS pebbleca
|
||||||
FROM nginxproxymanager/nginx-full:certbot-node
|
FROM nginxproxymanager/nginx-full:certbot-node
|
||||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
||||||
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
||||||
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||||
@ -17,17 +20,20 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
|||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Task
|
# Task
|
||||||
RUN cd /usr \
|
WORKDIR /usr
|
||||||
&& curl -sL https://taskfile.dev/install.sh | sh \
|
RUN curl -sL https://taskfile.dev/install.sh | sh
|
||||||
&& cd /root
|
WORKDIR /root
|
||||||
|
|
||||||
COPY rootfs /
|
COPY rootfs /
|
||||||
RUN rm -f /etc/nginx/conf.d/production.conf
|
|
||||||
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
|
||||||
|
|
||||||
# s6 overlay
|
|
||||||
COPY scripts/install-s6 /tmp/install-s6
|
COPY scripts/install-s6 /tmp/install-s6
|
||||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
RUN rm -f /etc/nginx/conf.d/production.conf \
|
||||||
|
&& chmod 644 /etc/logrotate.d/nginx-proxy-manager \
|
||||||
|
&& /tmp/install-s6 "${TARGETPLATFORM}" \
|
||||||
|
&& rm -f /tmp/install-s6
|
||||||
|
|
||||||
|
# Certs for testing purposes
|
||||||
|
COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem
|
||||||
|
COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 443
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
|
@ -9,6 +9,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
DEBUG: 'true'
|
DEBUG: 'true'
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
|
# Required for DNS Certificate provisioning in CI
|
||||||
|
LE_SERVER: 'https://ca.internal/acme/acme/directory'
|
||||||
|
REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt'
|
||||||
volumes:
|
volumes:
|
||||||
- 'npm_data_ci:/data'
|
- 'npm_data_ci:/data'
|
||||||
- 'npm_le_ci:/etc/letsencrypt'
|
- 'npm_le_ci:/etc/letsencrypt'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
|
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
|
||||||
services:
|
services:
|
||||||
|
|
||||||
npm:
|
fullstack:
|
||||||
image: nginxproxymanager:dev
|
image: nginxproxymanager:dev
|
||||||
container_name: npm_core
|
container_name: npm_core
|
||||||
build:
|
build:
|
||||||
@ -33,12 +33,20 @@ services:
|
|||||||
DB_MYSQL_NAME: 'npm'
|
DB_MYSQL_NAME: 'npm'
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
# DB_SQLITE_FILE: "/data/database.sqlite"
|
||||||
# DISABLE_IPV6: "true"
|
# DISABLE_IPV6: "true"
|
||||||
|
# Required for DNS Certificate provisioning testing:
|
||||||
|
LE_SERVER: 'https://ca.internal/acme/acme/directory'
|
||||||
|
REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt'
|
||||||
volumes:
|
volumes:
|
||||||
- npm_data:/data
|
- npm_data:/data
|
||||||
- le_data:/etc/letsencrypt
|
- le_data:/etc/letsencrypt
|
||||||
|
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||||
- ../backend:/app
|
- ../backend:/app
|
||||||
- ../frontend:/app/frontend
|
- ../frontend:/app/frontend
|
||||||
- ../global:/app/global
|
- ../global:/app/global
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/usr/bin/check-health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
@ -58,6 +66,23 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
|
|
||||||
|
stepca:
|
||||||
|
image: jc21/testca
|
||||||
|
volumes:
|
||||||
|
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||||
|
- '/etc/localtime:/etc/localtime:ro'
|
||||||
|
networks:
|
||||||
|
nginx_proxy_manager:
|
||||||
|
aliases:
|
||||||
|
- ca.internal
|
||||||
|
|
||||||
|
dnsrouter:
|
||||||
|
image: jc21/dnsrouter
|
||||||
|
volumes:
|
||||||
|
- ./dev/dnsrouter-config.json.tmp:/dnsrouter-config.json:ro
|
||||||
|
networks:
|
||||||
|
- nginx_proxy_manager
|
||||||
|
|
||||||
swagger:
|
swagger:
|
||||||
image: swaggerapi/swagger-ui:latest
|
image: swaggerapi/swagger-ui:latest
|
||||||
container_name: npm_swagger
|
container_name: npm_swagger
|
||||||
@ -67,19 +92,78 @@ services:
|
|||||||
URL: "http://npm:81/api/schema"
|
URL: "http://npm:81/api/schema"
|
||||||
PORT: '80'
|
PORT: '80'
|
||||||
depends_on:
|
depends_on:
|
||||||
- npm
|
- fullstack
|
||||||
|
|
||||||
squid:
|
squid:
|
||||||
image: ubuntu/squid
|
image: ubuntu/squid
|
||||||
container_name: npm_squid
|
container_name: npm_squid
|
||||||
volumes:
|
volumes:
|
||||||
- './dev/squid.conf:/etc/squid/squid.conf:ro'
|
- './dev/squid.conf:/etc/squid/squid.conf:ro'
|
||||||
|
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||||
- '/etc/localtime:/etc/localtime:ro'
|
- '/etc/localtime:/etc/localtime:ro'
|
||||||
networks:
|
networks:
|
||||||
- nginx_proxy_manager
|
- nginx_proxy_manager
|
||||||
ports:
|
ports:
|
||||||
- 8128:3128
|
- 8128:3128
|
||||||
|
|
||||||
|
pdns:
|
||||||
|
image: pschiffe/pdns-mysql
|
||||||
|
volumes:
|
||||||
|
- '/etc/localtime:/etc/localtime:ro'
|
||||||
|
environment:
|
||||||
|
PDNS_master: 'yes'
|
||||||
|
PDNS_api: 'yes'
|
||||||
|
PDNS_api_key: 'npm'
|
||||||
|
PDNS_webserver: 'yes'
|
||||||
|
PDNS_webserver_address: '0.0.0.0'
|
||||||
|
PDNS_webserver_password: 'npm'
|
||||||
|
PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||||
|
PDNS_version_string: 'anonymous'
|
||||||
|
PDNS_default_ttl: 1500
|
||||||
|
PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||||
|
PDNS_gmysql_host: pdns-db
|
||||||
|
PDNS_gmysql_port: 3306
|
||||||
|
PDNS_gmysql_user: pdns
|
||||||
|
PDNS_gmysql_password: pdns
|
||||||
|
PDNS_gmysql_dbname: pdns
|
||||||
|
depends_on:
|
||||||
|
- pdns-db
|
||||||
|
networks:
|
||||||
|
nginx_proxy_manager:
|
||||||
|
aliases:
|
||||||
|
- ns1.pdns
|
||||||
|
- ns2.pdns
|
||||||
|
|
||||||
|
pdns-db:
|
||||||
|
image: mariadb
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: 'pdns'
|
||||||
|
MYSQL_DATABASE: 'pdns'
|
||||||
|
MYSQL_USER: 'pdns'
|
||||||
|
MYSQL_PASSWORD: 'pdns'
|
||||||
|
volumes:
|
||||||
|
- 'pdns_mysql:/var/lib/mysql'
|
||||||
|
- '/etc/localtime:/etc/localtime:ro'
|
||||||
|
- './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro'
|
||||||
|
networks:
|
||||||
|
- nginx_proxy_manager
|
||||||
|
|
||||||
|
cypress:
|
||||||
|
image: "npm_dev_cypress"
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: test/cypress/Dockerfile
|
||||||
|
environment:
|
||||||
|
HTTP_PROXY: 'squid:3128'
|
||||||
|
HTTPS_PROXY: 'squid:3128'
|
||||||
|
volumes:
|
||||||
|
- '../test/results:/results'
|
||||||
|
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||||
|
- '/etc/localtime:/etc/localtime:ro'
|
||||||
|
command: cypress run --browser chrome --config-file=cypress/config/ci.js
|
||||||
|
networks:
|
||||||
|
- nginx_proxy_manager
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
npm_data:
|
npm_data:
|
||||||
name: npm_core_data
|
name: npm_core_data
|
||||||
@ -87,6 +171,8 @@ volumes:
|
|||||||
name: npm_le_data
|
name: npm_le_data
|
||||||
db_data:
|
db_data:
|
||||||
name: npm_db_data
|
name: npm_db_data
|
||||||
|
pdns_mysql:
|
||||||
|
name: npm_pdns_mysql
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
nginx_proxy_manager:
|
nginx_proxy_manager:
|
||||||
|
@ -15,3 +15,13 @@ COMPOSE_PROJECT_NAME="npmdev"
|
|||||||
COMPOSE_FILE="docker/docker-compose.dev.yml"
|
COMPOSE_FILE="docker/docker-compose.dev.yml"
|
||||||
|
|
||||||
export COMPOSE_FILE COMPOSE_PROJECT_NAME
|
export COMPOSE_FILE COMPOSE_PROJECT_NAME
|
||||||
|
|
||||||
|
# $1: container_name
|
||||||
|
get_container_ip () {
|
||||||
|
local container_name=$1
|
||||||
|
local container
|
||||||
|
local ip
|
||||||
|
container=$(docker-compose ps --all -q "${container_name}" | tail -n1)
|
||||||
|
ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
|
||||||
|
echo "$ip"
|
||||||
|
}
|
||||||
|
13
scripts/cypress-dev
Executable file
13
scripts/cypress-dev
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
. "$DIR/.common.sh"
|
||||||
|
|
||||||
|
# Ensure docker-compose exists
|
||||||
|
if hash docker-compose 2>/dev/null; then
|
||||||
|
cd "${DIR}/.."
|
||||||
|
rm -rf "$DIR/../test/results"
|
||||||
|
docker-compose up --build cypress
|
||||||
|
else
|
||||||
|
echo -e "${RED}❯ docker-compose command is not available${RESET}"
|
||||||
|
fi
|
@ -7,8 +7,43 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
if hash docker-compose 2>/dev/null; then
|
if hash docker-compose 2>/dev/null; then
|
||||||
cd "${DIR}/.."
|
cd "${DIR}/.."
|
||||||
echo -e "${BLUE}❯ ${CYAN}Starting Dev Stack ...${RESET}"
|
echo -e "${BLUE}❯ ${CYAN}Starting Dev Stack ...${RESET}"
|
||||||
|
echo -e "${BLUE}❯ $(docker-compose config)${RESET}"
|
||||||
|
|
||||||
docker-compose up -d --remove-orphans --force-recreate --build
|
# Bring up a stack, in steps so we can inject IPs everywhere
|
||||||
|
docker-compose up -d pdns pdns-db
|
||||||
|
PDNS_IP=$(get_container_ip "pdns")
|
||||||
|
echo -e "${BLUE}❯ ${YELLOW}PDNS IP is ${PDNS_IP}${RESET}"
|
||||||
|
|
||||||
|
# adjust the dnsrouter config
|
||||||
|
LOCAL_DNSROUTER_CONFIG="$DIR/../docker/dev/dnsrouter-config.json"
|
||||||
|
rm -rf "$LOCAL_DNSROUTER_CONFIG.tmp"
|
||||||
|
# IMPORTANT: changes to dnsrouter-config.json will affect this line:
|
||||||
|
jq --arg a "$PDNS_IP" '.servers[0].upstreams[1].upstream = $a' "$LOCAL_DNSROUTER_CONFIG" > "$LOCAL_DNSROUTER_CONFIG.tmp"
|
||||||
|
|
||||||
|
docker-compose up -d dnsrouter
|
||||||
|
DNSROUTER_IP=$(get_container_ip "dnsrouter")
|
||||||
|
echo -e "${BLUE}❯ ${YELLOW}DNS Router IP is ${DNSROUTER_IP}"
|
||||||
|
|
||||||
|
if [ "${DNSROUTER_IP:-}" = "" ]; then
|
||||||
|
echo -e "${RED}❯ ERROR: DNS Router IP is not set${RESET}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# mount the resolver
|
||||||
|
LOCAL_RESOLVE="$DIR/../docker/dev/resolv.conf"
|
||||||
|
rm -rf "${LOCAL_RESOLVE}"
|
||||||
|
printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}"
|
||||||
|
|
||||||
|
# bring up all remaining containers, except cypress!
|
||||||
|
docker-compose up -d --remove-orphans stepca squid
|
||||||
|
docker-compose pull db
|
||||||
|
docker-compose up -d --remove-orphans --pull=never fullstack
|
||||||
|
docker-compose up -d --remove-orphans swagger
|
||||||
|
|
||||||
|
# docker-compose up -d --remove-orphans --force-recreate --build
|
||||||
|
|
||||||
|
# wait for main container to be healthy
|
||||||
|
bash "$DIR/wait-healthy" "$(docker-compose ps --all -q fullstack)" 120
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Admin UI: http://127.0.0.1:3081${RESET}"
|
echo -e "${CYAN}Admin UI: http://127.0.0.1:3081${RESET}"
|
||||||
|
@ -15,7 +15,7 @@ module.exports = defineConfig({
|
|||||||
return require("../plugins/index.js")(on, config);
|
return require("../plugins/index.js")(on, config);
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
swaggerBase: 'http://fullstack:81/api/schema',
|
swaggerBase: '{{baseUrl}}/api/schema?ts=' + Date.now(),
|
||||||
},
|
},
|
||||||
baseUrl: 'http://fullstack:81',
|
baseUrl: 'http://fullstack:81',
|
||||||
}
|
}
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
const { defineConfig } = require('cypress');
|
|
||||||
|
|
||||||
module.exports = defineConfig({
|
|
||||||
requestTimeout: 30000,
|
|
||||||
defaultCommandTimeout: 20000,
|
|
||||||
reporter: 'cypress-multi-reporters',
|
|
||||||
reporterOptions: {
|
|
||||||
configFile: 'multi-reporter.json'
|
|
||||||
},
|
|
||||||
video: false,
|
|
||||||
videosFolder: 'results/videos',
|
|
||||||
screenshotsFolder: 'results/screenshots',
|
|
||||||
e2e: {
|
|
||||||
setupNodeEvents(on, config) {
|
|
||||||
return require("../plugins/index.js")(on, config);
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
swaggerBase: 'http://npm:81/api/schema',
|
|
||||||
},
|
|
||||||
baseUrl: 'http://npm:81',
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,7 +1,8 @@
|
|||||||
/// <reference types="Cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
describe('Certificates endpoints', () => {
|
describe('Certificates endpoints', () => {
|
||||||
let token;
|
let token;
|
||||||
|
let certID;
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
cy.getToken().then((tok) => {
|
cy.getToken().then((tok) => {
|
||||||
@ -24,6 +25,54 @@ describe('Certificates endpoints', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Custom certificate lifecycle', function() {
|
||||||
|
// Create custom cert
|
||||||
|
cy.task('backendApiPost', {
|
||||||
|
token: token,
|
||||||
|
path: '/api/nginx/certificates',
|
||||||
|
data: {
|
||||||
|
provider: "other",
|
||||||
|
nice_name: "Test Certificate",
|
||||||
|
},
|
||||||
|
}).then((data) => {
|
||||||
|
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
|
||||||
|
expect(data).to.have.property('id');
|
||||||
|
certID = data.id;
|
||||||
|
|
||||||
|
// Upload files
|
||||||
|
cy.task('backendApiPostFiles', {
|
||||||
|
token: token,
|
||||||
|
path: `/api/nginx/certificates/${certID}/upload`,
|
||||||
|
files: {
|
||||||
|
certificate: 'test.example.com.pem',
|
||||||
|
certificate_key: 'test.example.com-key.pem',
|
||||||
|
},
|
||||||
|
}).then((data) => {
|
||||||
|
cy.validateSwaggerSchema('post', 200, '/nginx/certificates/{certID}/upload', data);
|
||||||
|
expect(data).to.have.property('certificate');
|
||||||
|
expect(data).to.have.property('certificate_key');
|
||||||
|
|
||||||
|
// Get all certs
|
||||||
|
cy.task('backendApiGet', {
|
||||||
|
token: token,
|
||||||
|
path: '/api/nginx/certificates?expand=owner'
|
||||||
|
}).then((data) => {
|
||||||
|
cy.validateSwaggerSchema('get', 200, '/nginx/certificates', data);
|
||||||
|
expect(data.length).to.be.greaterThan(0);
|
||||||
|
|
||||||
|
// Delete cert
|
||||||
|
cy.task('backendApiDelete', {
|
||||||
|
token: token,
|
||||||
|
path: `/api/nginx/certificates/${certID}`
|
||||||
|
}).then((data) => {
|
||||||
|
cy.validateSwaggerSchema('delete', 200, '/nginx/certificates/{certID}', data);
|
||||||
|
expect(data).to.be.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() {
|
it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() {
|
||||||
cy.task('backendApiPost', {
|
cy.task('backendApiPost', {
|
||||||
token: token,
|
token: token,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/// <reference types="Cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
describe('Basic API checks', () => {
|
describe('Basic API checks', () => {
|
||||||
it('Should return a valid health payload', function () {
|
it('Should return a valid health payload', function () {
|
||||||
@ -12,7 +12,7 @@ describe('Basic API checks', () => {
|
|||||||
|
|
||||||
it('Should return a valid schema payload', function () {
|
it('Should return a valid schema payload', function () {
|
||||||
cy.task('backendApiGet', {
|
cy.task('backendApiGet', {
|
||||||
path: '/api/schema',
|
path: '/api/schema?ts=' + Date.now(),
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
expect(data.openapi).to.be.equal('3.1.0');
|
expect(data.openapi).to.be.equal('3.1.0');
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/// <reference types="Cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
describe('Hosts endpoints', () => {
|
describe('Hosts endpoints', () => {
|
||||||
let token;
|
let token;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/// <reference types="Cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
describe('Users endpoints', () => {
|
describe('Users endpoints', () => {
|
||||||
let token;
|
let token;
|
||||||
|
@ -80,7 +80,7 @@ BackendApi.prototype._handleError = function(err, resolve, reject, returnOnError
|
|||||||
* @returns {Promise<object>}
|
* @returns {Promise<object>}
|
||||||
*/
|
*/
|
||||||
BackendApi.prototype.request = function (method, path, returnOnError, data) {
|
BackendApi.prototype.request = function (method, path, returnOnError, data) {
|
||||||
logger(method.toUpperCase(), this.config.baseUrl + path);
|
logger(method.toUpperCase(), path);
|
||||||
const options = this._prepareOptions(returnOnError);
|
const options = this._prepareOptions(returnOnError);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const {SwaggerValidation} = require('@jc21/cypress-swagger-validation');
|
const { SwaggerValidation } = require('@jc21/cypress-swagger-validation');
|
||||||
|
|
||||||
module.exports = (on, config) => {
|
module.exports = (on, config) => {
|
||||||
// Replace swaggerBase config var wildcard
|
// Replace swaggerBase config var wildcard
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jc21/cypress-swagger-validation": "^0.2.7",
|
"@jc21/cypress-swagger-validation": "^0.3.1",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"cypress": "^13.15.0",
|
"cypress": "^13.15.0",
|
||||||
"cypress-multi-reporters": "^1.6.4",
|
"cypress-multi-reporters": "^1.6.4",
|
||||||
@ -19,8 +19,8 @@
|
|||||||
"mocha-junit-reporter": "^2.2.1"
|
"mocha-junit-reporter": "^2.2.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/dev.js",
|
"cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/ci.js",
|
||||||
"cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/dev.js"
|
"cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/ci.js"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
@ -11,14 +11,13 @@
|
|||||||
call-me-maybe "^1.0.1"
|
call-me-maybe "^1.0.1"
|
||||||
js-yaml "^3.13.1"
|
js-yaml "^3.13.1"
|
||||||
|
|
||||||
"@apidevtools/json-schema-ref-parser@9.0.9":
|
"@apidevtools/json-schema-ref-parser@^11.7.2":
|
||||||
version "9.0.9"
|
version "11.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
|
||||||
integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
|
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jsdevtools/ono" "^7.1.3"
|
"@jsdevtools/ono" "^7.1.3"
|
||||||
"@types/json-schema" "^7.0.6"
|
"@types/json-schema" "^7.0.15"
|
||||||
call-me-maybe "^1.0.1"
|
|
||||||
js-yaml "^4.1.0"
|
js-yaml "^4.1.0"
|
||||||
|
|
||||||
"@apidevtools/openapi-schemas@^2.1.0":
|
"@apidevtools/openapi-schemas@^2.1.0":
|
||||||
@ -167,15 +166,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
|
||||||
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
|
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
|
||||||
|
|
||||||
"@jc21/cypress-swagger-validation@^0.2.7":
|
"@jc21/cypress-swagger-validation@^0.3.1":
|
||||||
version "0.2.7"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.2.7.tgz#64642b12d98b884df8c30b72852162941285d2af"
|
resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.3.1.tgz#1cdd49850a20f876ed62149623f99988264751be"
|
||||||
integrity sha512-4EQ0gfigRwVVl3DnVYbR48/EKGnn7oH5YYdMzf6zqypO+bqYvDHu9kgk/WqkGlT/aauGQ7e0YGMo8ZvR7mL0Ng==
|
integrity sha512-Vdt1gLfj8p0tJhA42Cfn43XBbsKocNfVCEVSwkn7RmZgWUyRKjqhBBRTVa9cKZTozyg8Co/yhBMsNyjmHFVXtQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@apidevtools/json-schema-ref-parser" "^11.7.2"
|
||||||
"@apidevtools/swagger-parser" "^10.1.0"
|
"@apidevtools/swagger-parser" "^10.1.0"
|
||||||
ajv "^8.17.1"
|
ajv "^8.17.1"
|
||||||
|
axios "^1.7.7"
|
||||||
json-schema "^0.4.0"
|
json-schema "^0.4.0"
|
||||||
json-schema-ref-parser "^9.0.9"
|
|
||||||
jsonpath "^1.1.1"
|
jsonpath "^1.1.1"
|
||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
openapi-types "^12.1.3"
|
openapi-types "^12.1.3"
|
||||||
@ -196,7 +196,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||||
|
|
||||||
"@types/json-schema@^7.0.15", "@types/json-schema@^7.0.6":
|
"@types/json-schema@^7.0.15":
|
||||||
version "7.0.15"
|
version "7.0.15"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||||
@ -1468,13 +1468,6 @@ json-buffer@3.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||||
|
|
||||||
json-schema-ref-parser@^9.0.9:
|
|
||||||
version "9.0.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f"
|
|
||||||
integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==
|
|
||||||
dependencies:
|
|
||||||
"@apidevtools/json-schema-ref-parser" "9.0.9"
|
|
||||||
|
|
||||||
json-schema-traverse@^0.4.1:
|
json-schema-traverse@^0.4.1:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user