Skip to content

Commit 6a60627

Browse files
committed
Cypress test for Streams
and updated cypress + packages
1 parent b4793d3 commit 6a60627

File tree

8 files changed

+245
-17
lines changed

8 files changed

+245
-17
lines changed

backend/internal/stream.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const internalHost = require('./host');
99
const {castJsonIfNeed} = require('../lib/helpers');
1010

1111
function omissions () {
12-
return ['is_deleted'];
12+
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
1313
}
1414

1515
const internalStream = {

backend/models/stream.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const now = require('./now_helper');
88
Model.knex(db);
99

1010
const boolFields = [
11+
'enabled',
1112
'is_deleted',
1213
'tcp_forwarding',
1314
'udp_forwarding',

backend/schema/components/stream-object.json

+14-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
"incoming_port": {
2020
"type": "integer",
2121
"minimum": 1,
22-
"maximum": 65535,
23-
"if": {"properties": {"tcp_forwarding": {"const": true}}},
24-
"then": {"not": {"oneOf": [{"const": 80}, {"const": 443}]}}
22+
"maximum": 65535
2523
},
2624
"forwarding_host": {
2725
"anyOf": [
@@ -60,6 +58,19 @@
6058
},
6159
"meta": {
6260
"type": "object"
61+
},
62+
"owner": {
63+
"$ref": "./user-object.json"
64+
},
65+
"certificate": {
66+
"oneOf": [
67+
{
68+
"type": "null"
69+
},
70+
{
71+
"$ref": "./certificate-object.json"
72+
}
73+
]
6374
}
6475
}
6576
}

docker/docker-compose.ci.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ services:
2222
test: ["CMD", "/usr/bin/check-health"]
2323
interval: 10s
2424
timeout: 3s
25+
expose:
26+
- '80-81/tcp'
27+
- '443/tcp'
28+
- '1500-1503/tcp'
2529
networks:
2630
fulltest:
2731
aliases:
@@ -97,7 +101,7 @@ services:
97101
HTTP_PROXY: 'squid:3128'
98102
HTTPS_PROXY: 'squid:3128'
99103
volumes:
100-
- 'cypress_logs:/results'
104+
- 'cypress_logs:/test/results'
101105
- './dev/resolv.conf:/etc/resolv.conf:ro'
102106
- '/etc/localtime:/etc/localtime:ro'
103107
command: cypress run --browser chrome --config-file=cypress/config/ci.js

docker/scripts/install-s6

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ BLUE='\E[1;34m'
88
GREEN='\E[1;32m'
99
RESET='\E[0m'
1010

11-
S6_OVERLAY_VERSION=3.1.5.0
11+
S6_OVERLAY_VERSION=3.2.0.2
1212
TARGETPLATFORM=${1:-linux/amd64}
1313

1414
# Determine the correct binary file for the architecture given

test/cypress/Dockerfile

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
FROM cypress/included:13.9.0
2-
3-
COPY --chown=1000 ./test /test
1+
FROM cypress/included:14.0.1
42

53
# Disable Cypress CLI colors
64
ENV FORCE_COLOR=0
@@ -12,12 +10,13 @@ RUN wget "https://github.com/testssl/testssl.sh/archive/refs/tags/v3.2rc4.tar.gz
1210
&& mv /tmp/testssl.sh-3.2rc4 /testssl \
1311
&& rm /tmp/testssl.tgz \
1412
&& apt-get update \
15-
&& apt-get install -y bsdmainutils \
13+
&& apt-get install -y bsdmainutils curl dnsutils \
1614
&& apt-get clean \
1715
&& rm -rf /var/lib/apt/lists/* \
1816
&& wget "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64" -O /bin/mkcert \
1917
&& chmod +x /bin/mkcert
2018

19+
COPY --chown=1000 ./test /test
2120
WORKDIR /test
2221
RUN yarn install && yarn cache clean
2322
ENTRYPOINT []

test/cypress/e2e/api/Streams.cy.js

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/// <reference types="cypress" />
2+
3+
describe('Streams', () => {
4+
let token;
5+
6+
before(() => {
7+
cy.getToken().then((tok) => {
8+
token = tok;
9+
// Set default site content
10+
cy.task('backendApiPut', {
11+
token: token,
12+
path: '/api/settings/default-site',
13+
data: {
14+
value: 'html',
15+
meta: {
16+
html: '<p>yay it works</p>'
17+
},
18+
},
19+
}).then((data) => {
20+
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
21+
});
22+
});
23+
24+
// Create a custom cert pair
25+
cy.exec('mkcert -cert-file=/test/cypress/fixtures/website1.pem -key-file=/test/cypress/fixtures/website1.key.pem website1.example.com').then((result) => {
26+
expect(result.code).to.eq(0);
27+
// Install CA
28+
cy.exec('mkcert -install').then((result) => {
29+
expect(result.code).to.eq(0);
30+
});
31+
});
32+
33+
cy.exec('rm -f /test/results/testssl.json');
34+
});
35+
36+
it('Should be able to create TCP Stream', function() {
37+
cy.task('backendApiPost', {
38+
token: token,
39+
path: '/api/nginx/streams',
40+
data: {
41+
incoming_port: 1500,
42+
forwarding_host: '127.0.0.1',
43+
forwarding_port: 80,
44+
certificate_id: 0,
45+
meta: {
46+
dns_provider_credentials: "",
47+
letsencrypt_agree: false,
48+
dns_challenge: true
49+
},
50+
tcp_forwarding: true,
51+
udp_forwarding: false
52+
}
53+
}).then((data) => {
54+
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
55+
expect(data).to.have.property('id');
56+
expect(data.id).to.be.greaterThan(0);
57+
expect(data).to.have.property('enabled', true);
58+
expect(data).to.have.property('tcp_forwarding', true);
59+
expect(data).to.have.property('udp_forwarding', false);
60+
61+
cy.exec('curl --noproxy -- http://website1.example.com:1500').then((result) => {
62+
expect(result.code).to.eq(0);
63+
expect(result.stdout).to.contain('yay it works');
64+
});
65+
});
66+
});
67+
68+
it('Should be able to create UDP Stream', function() {
69+
cy.task('backendApiPost', {
70+
token: token,
71+
path: '/api/nginx/streams',
72+
data: {
73+
incoming_port: 1501,
74+
forwarding_host: '127.0.0.1',
75+
forwarding_port: 80,
76+
certificate_id: 0,
77+
meta: {
78+
dns_provider_credentials: "",
79+
letsencrypt_agree: false,
80+
dns_challenge: true
81+
},
82+
tcp_forwarding: false,
83+
udp_forwarding: true
84+
}
85+
}).then((data) => {
86+
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
87+
expect(data).to.have.property('id');
88+
expect(data.id).to.be.greaterThan(0);
89+
expect(data).to.have.property('enabled', true);
90+
expect(data).to.have.property('tcp_forwarding', false);
91+
expect(data).to.have.property('udp_forwarding', true);
92+
});
93+
});
94+
95+
it('Should be able to create TCP/UDP Stream', function() {
96+
cy.task('backendApiPost', {
97+
token: token,
98+
path: '/api/nginx/streams',
99+
data: {
100+
incoming_port: 1502,
101+
forwarding_host: '127.0.0.1',
102+
forwarding_port: 80,
103+
certificate_id: 0,
104+
meta: {
105+
dns_provider_credentials: "",
106+
letsencrypt_agree: false,
107+
dns_challenge: true
108+
},
109+
tcp_forwarding: true,
110+
udp_forwarding: true
111+
}
112+
}).then((data) => {
113+
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
114+
expect(data).to.have.property('id');
115+
expect(data.id).to.be.greaterThan(0);
116+
expect(data).to.have.property('enabled', true);
117+
expect(data).to.have.property('tcp_forwarding', true);
118+
expect(data).to.have.property('udp_forwarding', true);
119+
120+
cy.exec('curl --noproxy -- http://website1.example.com:1502').then((result) => {
121+
expect(result.code).to.eq(0);
122+
expect(result.stdout).to.contain('yay it works');
123+
});
124+
});
125+
});
126+
127+
it('Should be able to create SSL TCP Stream', function() {
128+
let certID = 0;
129+
130+
// Create custom cert
131+
cy.task('backendApiPost', {
132+
token: token,
133+
path: '/api/nginx/certificates',
134+
data: {
135+
provider: "other",
136+
nice_name: "Custom Certificate for SSL Stream",
137+
},
138+
}).then((data) => {
139+
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
140+
expect(data).to.have.property('id');
141+
certID = data.id;
142+
143+
// Upload files
144+
cy.task('backendApiPostFiles', {
145+
token: token,
146+
path: `/api/nginx/certificates/${certID}/upload`,
147+
files: {
148+
certificate: 'website1.pem',
149+
certificate_key: 'website1.key.pem',
150+
},
151+
}).then((data) => {
152+
cy.validateSwaggerSchema('post', 200, '/nginx/certificates/{certID}/upload', data);
153+
expect(data).to.have.property('certificate');
154+
expect(data).to.have.property('certificate_key');
155+
156+
// Create the stream
157+
cy.task('backendApiPost', {
158+
token: token,
159+
path: '/api/nginx/streams',
160+
data: {
161+
incoming_port: 1503,
162+
forwarding_host: '127.0.0.1',
163+
forwarding_port: 80,
164+
certificate_id: certID,
165+
meta: {
166+
dns_provider_credentials: "",
167+
letsencrypt_agree: false,
168+
dns_challenge: true
169+
},
170+
tcp_forwarding: true,
171+
udp_forwarding: false
172+
}
173+
}).then((data) => {
174+
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
175+
expect(data).to.have.property('id');
176+
expect(data.id).to.be.greaterThan(0);
177+
expect(data).to.have.property("enabled", true);
178+
expect(data).to.have.property('tcp_forwarding', true);
179+
expect(data).to.have.property('udp_forwarding', false);
180+
expect(data).to.have.property('certificate_id', certID);
181+
182+
// Check the ssl termination
183+
cy.task('log', '[testssl.sh] Running ...');
184+
cy.exec('/testssl/testssl.sh --quiet --add-ca="$(/bin/mkcert -CAROOT)/rootCA.pem" --jsonfile=/test/results/testssl.json website1.example.com:1503', {
185+
timeout: 120000, // 2 minutes
186+
}).then((result) => {
187+
cy.task('log', '[testssl.sh] ' + result.stdout);
188+
189+
const allowedSeverities = ["INFO", "OK", "LOW", "MEDIUM"];
190+
const ignoredIDs = [
191+
'cert_chain_of_trust',
192+
'cert_extlifeSpan',
193+
'cert_revocation',
194+
'overall_grade',
195+
];
196+
197+
cy.readFile('/test/results/testssl.json').then((data) => {
198+
// Parse each array item
199+
for (let i = 0; i < data.length; i++) {
200+
const item = data[i];
201+
if (ignoredIDs.includes(item.id)) {
202+
continue;
203+
}
204+
expect(item.severity).to.be.oneOf(allowedSeverities);
205+
}
206+
});
207+
});
208+
});
209+
});
210+
});
211+
});
212+
213+
});

test/package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
"description": "",
55
"main": "index.js",
66
"dependencies": {
7-
"@jc21/cypress-swagger-validation": "^0.3.1",
8-
"axios": "^1.7.7",
9-
"cypress": "^13.15.0",
10-
"cypress-multi-reporters": "^1.6.4",
7+
"@jc21/cypress-swagger-validation": "^0.3.2",
8+
"axios": "^1.7.9",
9+
"cypress": "^14.0.1",
10+
"cypress-multi-reporters": "^2.0.5",
1111
"cypress-wait-until": "^3.0.2",
12-
"eslint": "^9.12.0",
12+
"eslint": "^9.19.0",
1313
"eslint-plugin-align-assignments": "^1.1.2",
1414
"eslint-plugin-chai-friendly": "^1.0.1",
15-
"eslint-plugin-cypress": "^3.5.0",
15+
"eslint-plugin-cypress": "^4.1.0",
1616
"form-data": "^4.0.1",
1717
"lodash": "^4.17.21",
18-
"mocha": "^10.7.3",
18+
"mocha": "^11.1.0",
1919
"mocha-junit-reporter": "^2.2.1"
2020
},
2121
"scripts": {

0 commit comments

Comments
 (0)