fix(ci): the cleanup script forced TLS onto a plaintext endpoint (#324) #339
@@ -11,7 +11,8 @@
|
|||||||
* harmless one.
|
* harmless one.
|
||||||
*
|
*
|
||||||
* Environment:
|
* Environment:
|
||||||
* GITEA_HOST origin of the instance, e.g. https://gitea.example.com
|
* GITEA_HOST origin of the instance, scheme included, e.g.
|
||||||
|
* https://gitea.example.com or http://gitea:3000
|
||||||
* GITEA_REPO "owner/name"
|
* GITEA_REPO "owner/name"
|
||||||
* GITEA_ACCESS_TOKEN token permitted to delete runs
|
* GITEA_ACCESS_TOKEN token permitted to delete runs
|
||||||
* KEEP_DAYS keep runs newer than this many days (default 7)
|
* KEEP_DAYS keep runs newer than this many days (default 7)
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
|
const http = require('http');
|
||||||
const { URL } = require('url');
|
const { URL } = require('url');
|
||||||
|
|
||||||
const HOST = process.env.GITEA_HOST;
|
const HOST = process.env.GITEA_HOST;
|
||||||
@@ -39,12 +41,41 @@ if (!Number.isFinite(KEEP_DAYS) || KEEP_DAYS < 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const origin = new URL(HOST);
|
const origin = new URL(HOST);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transport GITEA_HOST actually asks for, rather than the one assumed.
|
||||||
|
*
|
||||||
|
* This was hardcoded to https, which worked when the host was typed by hand and
|
||||||
|
* failed the moment the workflow started taking it from `github.server_url`.
|
||||||
|
* Inside the runner that is the address act_runner reaches Gitea on, which here
|
||||||
|
* is plain HTTP on a container port — and a TLS handshake sent to a plaintext
|
||||||
|
* port does not fail as a connection error. It fails as:
|
||||||
|
*
|
||||||
|
* write EPROTO ... ssl3_get_record:wrong version number
|
||||||
|
*
|
||||||
|
* which reads like a TLS misconfiguration and sends you looking at certificates
|
||||||
|
* and protocol versions. It is neither. The server answered in cleartext and
|
||||||
|
* OpenSSL tried to parse that as a TLS record.
|
||||||
|
*
|
||||||
|
* So the scheme is honoured rather than guessed, and the default port follows
|
||||||
|
* from it. Anything other than the two is refused up front: this script only
|
||||||
|
* speaks HTTP, and a URL naming some other scheme is a mistake worth reporting
|
||||||
|
* as one instead of failing later inside a request.
|
||||||
|
*/
|
||||||
|
if (origin.protocol !== 'https:' && origin.protocol !== 'http:') {
|
||||||
|
console.error(`GITEA_HOST must be an http or https URL, got ${HOST}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const secure = origin.protocol === 'https:';
|
||||||
|
const transport = secure ? https : http;
|
||||||
|
const PORT = origin.port || (secure ? 443 : 80);
|
||||||
|
|
||||||
const BASE = `/api/v1/repos/${REPO}/actions/runs`;
|
const BASE = `/api/v1/repos/${REPO}/actions/runs`;
|
||||||
|
|
||||||
function call(method, path) {
|
function call(method, path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const req = https.request(
|
const req = transport.request(
|
||||||
{ hostname: origin.hostname, port: origin.port || 443, path, method, headers: { Authorization: `token ${TOKEN}` } },
|
{ hostname: origin.hostname, port: PORT, path, method, headers: { Authorization: `token ${TOKEN}` } },
|
||||||
(res) => {
|
(res) => {
|
||||||
let body = '';
|
let body = '';
|
||||||
res.on('data', (d) => (body += d));
|
res.on('data', (d) => (body += d));
|
||||||
@@ -126,6 +157,11 @@ function selectDoomed(runs, cutoffMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
// Printed before the first request rather than after it succeeds. A transport
|
||||||
|
// failure here says nothing about where it was pointed, and the last one cost
|
||||||
|
// a round trip to find out that the answer was "somewhere plaintext".
|
||||||
|
console.log(`endpoint : ${origin.protocol}//${origin.hostname}:${PORT}`);
|
||||||
|
|
||||||
const runs = await listAllRuns();
|
const runs = await listAllRuns();
|
||||||
const cutoffMs = Date.now() - KEEP_DAYS * 86400000;
|
const cutoffMs = Date.now() - KEEP_DAYS * 86400000;
|
||||||
const { doomed, kept } = selectDoomed(runs, cutoffMs);
|
const { doomed, kept } = selectDoomed(runs, cutoffMs);
|
||||||
|
|||||||
Reference in New Issue
Block a user