mirror of
https://github.com/step-security/harden-runner.git
synced 2026-06-06 09:17:06 +00:00
Compare commits
9 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03369ff6e2 | ||
|
|
b750996025 | ||
|
|
d4ca02bcc4 |
||
|
|
fc9d972ad4 | ||
|
|
27f4fdf2ed | ||
|
|
4f41e47d74 | ||
|
|
0827586e44 | ||
|
|
f5cfd3fe85 | ||
|
|
abb3730f28 |
11 changed files with 2761 additions and 60578 deletions
19
dist/index.js
vendored
19
dist/index.js
vendored
|
|
@ -2913,8 +2913,8 @@ function addSummary() {
|
|||
if (tableEntries.length === 0) {
|
||||
return;
|
||||
}
|
||||
const insightsRow = `<h4><a href="${insights_url}">View Full Runtime Security Report & Recommended Policy</a></h4>`;
|
||||
yield core.summary.addSeparator().addRaw(`<h2>StepSecurity Report</h2>`);
|
||||
const insightsRow = `<p><b><a href="${insights_url}">📄 View Full Runtime Security Report & Recommended Policy</a></b></p>`;
|
||||
yield core.summary.addSeparator().addRaw(`<h2>🛡 StepSecurity Report</h2>`);
|
||||
tableEntries.sort((a, b) => {
|
||||
if (a.status === "❌ Blocked" && b.status !== "❌ Blocked") {
|
||||
return -1;
|
||||
|
|
@ -2928,8 +2928,9 @@ function addSummary() {
|
|||
});
|
||||
tableEntries = tableEntries.slice(0, 3);
|
||||
yield core.summary.addRaw(`
|
||||
<p>Preview of the network events that occurred on the GitHub-hosted runner during this workflow run.</p>
|
||||
<h3>🌐 Network Events</h3>
|
||||
<blockquote>
|
||||
<p>Preview of the outbound network calls during this workflow run.</p></blockquote>
|
||||
<h3>Network Events</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -2941,22 +2942,22 @@ function addSummary() {
|
|||
<tbody>
|
||||
${tableEntries
|
||||
.map((entry) => `<tr>
|
||||
<td>${entry.process}</td>
|
||||
<td><code>${entry.process}</code></td>
|
||||
<td>${entry.domain.replace(/\.$/, "")}</td>
|
||||
<td>${entry.status}</td>
|
||||
</tr>`)
|
||||
.join("")}
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
${insightsRow}
|
||||
`);
|
||||
yield core.summary
|
||||
.addRaw(`<p>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a></p>`)
|
||||
.addRaw(`<p><i>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a>.</i></p>`)
|
||||
.addSeparator()
|
||||
.write();
|
||||
});
|
||||
|
|
|
|||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
58564
dist/post/index.js
vendored
58564
dist/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
0
dist/post/cache.txt → dist/pre/cache.txt
vendored
0
dist/post/cache.txt → dist/pre/cache.txt
vendored
532
dist/pre/index.js
vendored
532
dist/pre/index.js
vendored
|
|
@ -17,6 +17,227 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"]
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 7799:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const path = __importStar(__nccwpck_require__(5622));
|
||||
const utils = __importStar(__nccwpck_require__(1518));
|
||||
const cacheHttpClient = __importStar(__nccwpck_require__(8245));
|
||||
const tar_1 = __nccwpck_require__(6490);
|
||||
class ValidationError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'ValidationError';
|
||||
Object.setPrototypeOf(this, ValidationError.prototype);
|
||||
}
|
||||
}
|
||||
exports.ValidationError = ValidationError;
|
||||
class ReserveCacheError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'ReserveCacheError';
|
||||
Object.setPrototypeOf(this, ReserveCacheError.prototype);
|
||||
}
|
||||
}
|
||||
exports.ReserveCacheError = ReserveCacheError;
|
||||
function checkPaths(paths) {
|
||||
if (!paths || paths.length === 0) {
|
||||
throw new ValidationError(`Path Validation Error: At least one directory or file path is required`);
|
||||
}
|
||||
}
|
||||
function checkKey(key) {
|
||||
if (key.length > 512) {
|
||||
throw new ValidationError(`Key Validation Error: ${key} cannot be larger than 512 characters.`);
|
||||
}
|
||||
const regex = /^[^,]*$/;
|
||||
if (!regex.test(key)) {
|
||||
throw new ValidationError(`Key Validation Error: ${key} cannot contain commas.`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* isFeatureAvailable to check the presence of Actions cache service
|
||||
*
|
||||
* @returns boolean return true if Actions cache service feature is available, otherwise false
|
||||
*/
|
||||
function isFeatureAvailable() {
|
||||
return !!process.env['ACTIONS_CACHE_URL'];
|
||||
}
|
||||
exports.isFeatureAvailable = isFeatureAvailable;
|
||||
/**
|
||||
* Restores cache from keys
|
||||
*
|
||||
* @param paths a list of file paths to restore from the cache
|
||||
* @param primaryKey an explicit key for restoring the cache
|
||||
* @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key
|
||||
* @param downloadOptions cache download options
|
||||
* @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform
|
||||
* @returns string returns the key for the cache hit, otherwise returns undefined
|
||||
*/
|
||||
function restoreCache(paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
checkPaths(paths);
|
||||
restoreKeys = restoreKeys || [];
|
||||
const keys = [primaryKey, ...restoreKeys];
|
||||
core.debug('Resolved Keys:');
|
||||
core.debug(JSON.stringify(keys));
|
||||
if (keys.length > 10) {
|
||||
throw new ValidationError(`Key Validation Error: Keys are limited to a maximum of 10.`);
|
||||
}
|
||||
for (const key of keys) {
|
||||
checkKey(key);
|
||||
}
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
let archivePath = '';
|
||||
try {
|
||||
// path are needed to compute version
|
||||
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
|
||||
compressionMethod,
|
||||
enableCrossOsArchive
|
||||
});
|
||||
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
|
||||
// Cache not found
|
||||
return undefined;
|
||||
}
|
||||
archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
// Download the cache from the cache entry
|
||||
yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options);
|
||||
if (core.isDebug()) {
|
||||
yield tar_1.listTar(archivePath, compressionMethod);
|
||||
}
|
||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||
yield tar_1.extractTar(archivePath, compressionMethod);
|
||||
core.info('Cache restored successfully');
|
||||
return cacheEntry.cacheKey;
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else {
|
||||
// Supress all non-validation cache related errors because caching should be optional
|
||||
core.warning(`Failed to restore: ${error.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
try {
|
||||
yield utils.unlinkFile(archivePath);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
exports.restoreCache = restoreCache;
|
||||
/**
|
||||
* Saves a list of files with the specified key
|
||||
*
|
||||
* @param paths a list of file paths to be cached
|
||||
* @param key an explicit key for restoring the cache
|
||||
* @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform
|
||||
* @param options cache upload options
|
||||
* @returns number returns cacheId if the cache was saved successfully and throws an error if save fails
|
||||
*/
|
||||
function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
checkPaths(paths);
|
||||
checkKey(key);
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
let cacheId = -1;
|
||||
const cachePaths = yield utils.resolvePaths(paths);
|
||||
core.debug('Cache Paths:');
|
||||
core.debug(`${JSON.stringify(cachePaths)}`);
|
||||
if (cachePaths.length === 0) {
|
||||
throw new Error(`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`);
|
||||
}
|
||||
const archiveFolder = yield utils.createTempDirectory();
|
||||
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
try {
|
||||
yield tar_1.createTar(archiveFolder, cachePaths, compressionMethod);
|
||||
if (core.isDebug()) {
|
||||
yield tar_1.listTar(archivePath, compressionMethod);
|
||||
}
|
||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||
core.debug(`File Size: ${archiveFileSize}`);
|
||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`);
|
||||
}
|
||||
core.debug('Reserving Cache');
|
||||
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
||||
compressionMethod,
|
||||
enableCrossOsArchive,
|
||||
cacheSize: archiveFileSize
|
||||
});
|
||||
if ((_a = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.result) === null || _a === void 0 ? void 0 : _a.cacheId) {
|
||||
cacheId = (_b = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.result) === null || _b === void 0 ? void 0 : _b.cacheId;
|
||||
}
|
||||
else if ((reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.statusCode) === 400) {
|
||||
throw new Error((_d = (_c = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _c === void 0 ? void 0 : _c.message) !== null && _d !== void 0 ? _d : `Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the data cap limit, not saving cache.`);
|
||||
}
|
||||
else {
|
||||
throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${(_e = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _e === void 0 ? void 0 : _e.message}`);
|
||||
}
|
||||
core.debug(`Saving Cache (ID: ${cacheId})`);
|
||||
yield cacheHttpClient.saveCache(cacheId, archivePath, options);
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else if (typedError.name === ReserveCacheError.name) {
|
||||
core.info(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
else {
|
||||
core.warning(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
try {
|
||||
yield utils.unlinkFile(archivePath);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
||||
return cacheId;
|
||||
});
|
||||
}
|
||||
exports.saveCache = saveCache;
|
||||
//# sourceMappingURL=cache.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8245:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
|
|
@ -875,6 +1096,268 @@ exports.retryHttpClientResponse = retryHttpClientResponse;
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6490:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const exec_1 = __nccwpck_require__(1514);
|
||||
const io = __importStar(__nccwpck_require__(7436));
|
||||
const fs_1 = __nccwpck_require__(5747);
|
||||
const path = __importStar(__nccwpck_require__(5622));
|
||||
const utils = __importStar(__nccwpck_require__(1518));
|
||||
const constants_1 = __nccwpck_require__(8840);
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
// Returns tar path and type: BSD or GNU
|
||||
function getTarPath() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
switch (process.platform) {
|
||||
case 'win32': {
|
||||
const gnuTar = yield utils.getGnuTarPathOnWindows();
|
||||
const systemTar = constants_1.SystemTarPathOnWindows;
|
||||
if (gnuTar) {
|
||||
// Use GNUtar as default on windows
|
||||
return { path: gnuTar, type: constants_1.ArchiveToolType.GNU };
|
||||
}
|
||||
else if (fs_1.existsSync(systemTar)) {
|
||||
return { path: systemTar, type: constants_1.ArchiveToolType.BSD };
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'darwin': {
|
||||
const gnuTar = yield io.which('gtar', false);
|
||||
if (gnuTar) {
|
||||
// fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527
|
||||
return { path: gnuTar, type: constants_1.ArchiveToolType.GNU };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
path: yield io.which('tar', true),
|
||||
type: constants_1.ArchiveToolType.BSD
|
||||
};
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Default assumption is GNU tar is present in path
|
||||
return {
|
||||
path: yield io.which('tar', true),
|
||||
type: constants_1.ArchiveToolType.GNU
|
||||
};
|
||||
});
|
||||
}
|
||||
// Return arguments for tar as per tarPath, compressionMethod, method type and os
|
||||
function getTarArgs(tarPath, compressionMethod, type, archivePath = '') {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const args = [`"${tarPath.path}"`];
|
||||
const cacheFileName = utils.getCacheFileName(compressionMethod);
|
||||
const tarFile = 'cache.tar';
|
||||
const workingDirectory = getWorkingDirectory();
|
||||
// Speficic args for BSD tar on windows for workaround
|
||||
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
|
||||
compressionMethod !== constants_1.CompressionMethod.Gzip &&
|
||||
IS_WINDOWS;
|
||||
// Method specific args
|
||||
switch (type) {
|
||||
case 'create':
|
||||
args.push('--posix', '-cf', BSD_TAR_ZSTD
|
||||
? tarFile
|
||||
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--exclude', BSD_TAR_ZSTD
|
||||
? tarFile
|
||||
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--files-from', constants_1.ManifestFilename);
|
||||
break;
|
||||
case 'extract':
|
||||
args.push('-xf', BSD_TAR_ZSTD
|
||||
? tarFile
|
||||
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'));
|
||||
break;
|
||||
case 'list':
|
||||
args.push('-tf', BSD_TAR_ZSTD
|
||||
? tarFile
|
||||
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P');
|
||||
break;
|
||||
}
|
||||
// Platform specific args
|
||||
if (tarPath.type === constants_1.ArchiveToolType.GNU) {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
args.push('--force-local');
|
||||
break;
|
||||
case 'darwin':
|
||||
args.push('--delay-directory-restore');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return args;
|
||||
});
|
||||
}
|
||||
// Returns commands to run tar and compression program
|
||||
function getCommands(compressionMethod, type, archivePath = '') {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let args;
|
||||
const tarPath = yield getTarPath();
|
||||
const tarArgs = yield getTarArgs(tarPath, compressionMethod, type, archivePath);
|
||||
const compressionArgs = type !== 'create'
|
||||
? yield getDecompressionProgram(tarPath, compressionMethod, archivePath)
|
||||
: yield getCompressionProgram(tarPath, compressionMethod);
|
||||
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
|
||||
compressionMethod !== constants_1.CompressionMethod.Gzip &&
|
||||
IS_WINDOWS;
|
||||
if (BSD_TAR_ZSTD && type !== 'create') {
|
||||
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')];
|
||||
}
|
||||
else {
|
||||
args = [[...tarArgs].join(' '), [...compressionArgs].join(' ')];
|
||||
}
|
||||
if (BSD_TAR_ZSTD) {
|
||||
return args;
|
||||
}
|
||||
return [args.join(' ')];
|
||||
});
|
||||
}
|
||||
function getWorkingDirectory() {
|
||||
var _a;
|
||||
return (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd();
|
||||
}
|
||||
// Common function for extractTar and listTar to get the compression method
|
||||
function getDecompressionProgram(tarPath, compressionMethod, archivePath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// -d: Decompress.
|
||||
// unzstd is equivalent to 'zstd -d'
|
||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
||||
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
|
||||
compressionMethod !== constants_1.CompressionMethod.Gzip &&
|
||||
IS_WINDOWS;
|
||||
switch (compressionMethod) {
|
||||
case constants_1.CompressionMethod.Zstd:
|
||||
return BSD_TAR_ZSTD
|
||||
? [
|
||||
'zstd -d --long=30 --force -o',
|
||||
constants_1.TarFilename,
|
||||
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||
]
|
||||
: [
|
||||
'--use-compress-program',
|
||||
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
|
||||
];
|
||||
case constants_1.CompressionMethod.ZstdWithoutLong:
|
||||
return BSD_TAR_ZSTD
|
||||
? [
|
||||
'zstd -d --force -o',
|
||||
constants_1.TarFilename,
|
||||
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||
]
|
||||
: ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'];
|
||||
default:
|
||||
return ['-z'];
|
||||
}
|
||||
});
|
||||
}
|
||||
// Used for creating the archive
|
||||
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
|
||||
// zstdmt is equivalent to 'zstd -T0'
|
||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
||||
// Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
|
||||
function getCompressionProgram(tarPath, compressionMethod) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const cacheFileName = utils.getCacheFileName(compressionMethod);
|
||||
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
|
||||
compressionMethod !== constants_1.CompressionMethod.Gzip &&
|
||||
IS_WINDOWS;
|
||||
switch (compressionMethod) {
|
||||
case constants_1.CompressionMethod.Zstd:
|
||||
return BSD_TAR_ZSTD
|
||||
? [
|
||||
'zstd -T0 --long=30 --force -o',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
constants_1.TarFilename
|
||||
]
|
||||
: [
|
||||
'--use-compress-program',
|
||||
IS_WINDOWS ? '"zstd -T0 --long=30"' : 'zstdmt --long=30'
|
||||
];
|
||||
case constants_1.CompressionMethod.ZstdWithoutLong:
|
||||
return BSD_TAR_ZSTD
|
||||
? [
|
||||
'zstd -T0 --force -o',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
constants_1.TarFilename
|
||||
]
|
||||
: ['--use-compress-program', IS_WINDOWS ? '"zstd -T0"' : 'zstdmt'];
|
||||
default:
|
||||
return ['-z'];
|
||||
}
|
||||
});
|
||||
}
|
||||
// Executes all commands as separate processes
|
||||
function execCommands(commands, cwd) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const command of commands) {
|
||||
try {
|
||||
yield exec_1.exec(command, undefined, {
|
||||
cwd,
|
||||
env: Object.assign(Object.assign({}, process.env), { MSYS: 'winsymlinks:nativestrict' })
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`${command.split(' ')[0]} failed with error: ${error === null || error === void 0 ? void 0 : error.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// List the contents of a tar
|
||||
function listTar(archivePath, compressionMethod) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const commands = yield getCommands(compressionMethod, 'list', archivePath);
|
||||
yield execCommands(commands);
|
||||
});
|
||||
}
|
||||
exports.listTar = listTar;
|
||||
// Extract a tar
|
||||
function extractTar(archivePath, compressionMethod) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// Create directory to extract tar into
|
||||
const workingDirectory = getWorkingDirectory();
|
||||
yield io.mkdirP(workingDirectory);
|
||||
const commands = yield getCommands(compressionMethod, 'extract', archivePath);
|
||||
yield execCommands(commands);
|
||||
});
|
||||
}
|
||||
exports.extractTar = extractTar;
|
||||
// Create a tar
|
||||
function createTar(archiveFolder, sourceDirectories, compressionMethod) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// Write source directories to manifest.txt to avoid command length limits
|
||||
fs_1.writeFileSync(path.join(archiveFolder, constants_1.ManifestFilename), sourceDirectories.join('\n'));
|
||||
const commands = yield getCommands(compressionMethod, 'create');
|
||||
yield execCommands(commands, archiveFolder);
|
||||
});
|
||||
}
|
||||
exports.createTar = createTar;
|
||||
//# sourceMappingURL=tar.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6215:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
|
|
@ -69085,8 +69568,8 @@ function addSummary() {
|
|||
if (tableEntries.length === 0) {
|
||||
return;
|
||||
}
|
||||
const insightsRow = `<h4><a href="${insights_url}">View Full Runtime Security Report & Recommended Policy</a></h4>`;
|
||||
yield core.summary.addSeparator().addRaw(`<h2>StepSecurity Report</h2>`);
|
||||
const insightsRow = `<p><b><a href="${insights_url}">📄 View Full Runtime Security Report & Recommended Policy</a></b></p>`;
|
||||
yield core.summary.addSeparator().addRaw(`<h2>🛡 StepSecurity Report</h2>`);
|
||||
tableEntries.sort((a, b) => {
|
||||
if (a.status === "❌ Blocked" && b.status !== "❌ Blocked") {
|
||||
return -1;
|
||||
|
|
@ -69100,8 +69583,9 @@ function addSummary() {
|
|||
});
|
||||
tableEntries = tableEntries.slice(0, 3);
|
||||
yield core.summary.addRaw(`
|
||||
<p>Preview of the network events that occurred on the GitHub-hosted runner during this workflow run.</p>
|
||||
<h3>🌐 Network Events</h3>
|
||||
<blockquote>
|
||||
<p>Preview of the outbound network calls during this workflow run.</p></blockquote>
|
||||
<h3>Network Events</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -69113,22 +69597,22 @@ function addSummary() {
|
|||
<tbody>
|
||||
${tableEntries
|
||||
.map((entry) => `<tr>
|
||||
<td>${entry.process}</td>
|
||||
<td><code>${entry.process}</code></td>
|
||||
<td>${entry.domain.replace(/\.$/, "")}</td>
|
||||
<td>${entry.status}</td>
|
||||
</tr>`)
|
||||
.join("")}
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
${insightsRow}
|
||||
`);
|
||||
yield core.summary
|
||||
.addRaw(`<p>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a></p>`)
|
||||
.addRaw(`<p><i>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a>.</i></p>`)
|
||||
.addSeparator()
|
||||
.write();
|
||||
});
|
||||
|
|
@ -69280,18 +69764,29 @@ function sleep(ms) {
|
|||
});
|
||||
}
|
||||
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/cache/lib/cache.js
|
||||
var cache = __nccwpck_require__(7799);
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/cache/lib/internal/cacheHttpClient.js
|
||||
var cacheHttpClient = __nccwpck_require__(8245);
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/cache/lib/internal/cacheUtils.js
|
||||
var cacheUtils = __nccwpck_require__(1518);
|
||||
;// CONCATENATED MODULE: ./src/arc-runner.ts
|
||||
|
||||
|
||||
function isArcRunner() {
|
||||
const runnerUserAgent = process.env["GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT"];
|
||||
let isARC = false;
|
||||
if (!runnerUserAgent) {
|
||||
return false;
|
||||
isARC = false;
|
||||
}
|
||||
return runnerUserAgent.includes("actions-runner-controller/");
|
||||
else {
|
||||
isARC = runnerUserAgent.includes("actions-runner-controller/");
|
||||
}
|
||||
return isARC || isSecondaryPod();
|
||||
}
|
||||
function isSecondaryPod() {
|
||||
const workDir = "/__w";
|
||||
return external_fs_.existsSync(workDir);
|
||||
}
|
||||
function getRunnerTempDir() {
|
||||
const isTest = process.env["isTest"];
|
||||
|
|
@ -69350,6 +69845,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
|
|||
|
||||
|
||||
|
||||
|
||||
(() => setup_awaiter(void 0, void 0, void 0, function* () {
|
||||
var _a, _b;
|
||||
try {
|
||||
|
|
@ -69404,11 +69900,17 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
|
|||
if (confg.disable_telemetry !== true && confg.disable_telemetry !== false) {
|
||||
lib_core.setFailed("disable-telemetry must be a boolean value");
|
||||
}
|
||||
if (isValidEvent()) {
|
||||
if (isValidEvent() && confg.egress_policy === "block") {
|
||||
try {
|
||||
let compressionMethod = yield cacheUtils.getCompressionMethod();
|
||||
let cacheFilePath = external_path_.join(__dirname, "cache.txt");
|
||||
cacheFilePath = cacheFilePath.replace("/pre/", "/post/");
|
||||
const cacheResult = yield cache.saveCache([external_path_.join(__dirname, "cache.txt")], cacheKey);
|
||||
console.log(cacheResult);
|
||||
}
|
||||
catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
try {
|
||||
const compressionMethod = yield cacheUtils.getCompressionMethod();
|
||||
const cacheFilePath = external_path_.join(__dirname, "cache.txt");
|
||||
lib_core.info(`cacheFilePath ${cacheFilePath}`);
|
||||
const cacheEntry = yield (0,cacheHttpClient.getCacheEntry)([cacheKey], [cacheFilePath], {
|
||||
compressionMethod: compressionMethod,
|
||||
|
|
|
|||
2
dist/pre/index.js.map
vendored
2
dist/pre/index.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,14 +1,24 @@
|
|||
import * as cp from "child_process";
|
||||
import * as fs from "fs";
|
||||
import { sleep } from "./setup";
|
||||
|
||||
export function isArcRunner(): boolean {
|
||||
const runnerUserAgent = process.env["GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT"];
|
||||
|
||||
let isARC = false;
|
||||
|
||||
if (!runnerUserAgent) {
|
||||
return false;
|
||||
isARC = false;
|
||||
} else {
|
||||
isARC = runnerUserAgent.includes("actions-runner-controller/");
|
||||
}
|
||||
|
||||
return runnerUserAgent.includes("actions-runner-controller/");
|
||||
return isARC || isSecondaryPod();
|
||||
}
|
||||
|
||||
function isSecondaryPod(): boolean {
|
||||
const workDir = "/__w";
|
||||
return fs.existsSync(workDir);
|
||||
}
|
||||
|
||||
function getRunnerTempDir(): string {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import * as fs from "fs";
|
||||
import * as cp from "child_process";
|
||||
import * as core from "@actions/core";
|
||||
import * as common from "./common";
|
||||
import isDocker from "is-docker";
|
||||
import * as cache from "@actions/cache";
|
||||
import { cacheFile, cacheKey, isValidEvent } from "./cache";
|
||||
import path from "path";
|
||||
import { arcCleanUp, isArcRunner, removeStepPolicyFiles } from "./arc-runner";
|
||||
|
||||
(async () => {
|
||||
|
|
@ -18,18 +14,6 @@ import { arcCleanUp, isArcRunner, removeStepPolicyFiles } from "./arc-runner";
|
|||
return;
|
||||
}
|
||||
|
||||
if (isValidEvent()) {
|
||||
try {
|
||||
const cacheResult = await cache.saveCache(
|
||||
[path.join(__dirname, "cache.txt")],
|
||||
cacheKey
|
||||
);
|
||||
console.log(cacheResult);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
}
|
||||
|
||||
if (isArcRunner()) {
|
||||
console.log(`[!] ${common.ARC_RUNNER_MESSAGE}`);
|
||||
arcCleanUp();
|
||||
|
|
@ -54,8 +38,8 @@ import { arcCleanUp, isArcRunner, removeStepPolicyFiles } from "./arc-runner";
|
|||
JSON.stringify({ event: "post" })
|
||||
);
|
||||
|
||||
var doneFile = "/home/agent/done.json";
|
||||
var counter = 0;
|
||||
const doneFile = "/home/agent/done.json";
|
||||
let counter = 0;
|
||||
while (true) {
|
||||
if (!fs.existsSync(doneFile)) {
|
||||
counter++;
|
||||
|
|
@ -71,7 +55,7 @@ import { arcCleanUp, isArcRunner, removeStepPolicyFiles } from "./arc-runner";
|
|||
}
|
||||
}
|
||||
|
||||
var log = "/home/agent/agent.log";
|
||||
const log = "/home/agent/agent.log";
|
||||
if (fs.existsSync(log)) {
|
||||
console.log("log:");
|
||||
var content = fs.readFileSync(log, "utf-8");
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ export async function addSummary() {
|
|||
return;
|
||||
}
|
||||
|
||||
const insightsRow = `<h4><a href="${insights_url}">View Full Runtime Security Report & Recommended Policy</a></h4>`;
|
||||
const insightsRow = `<p><b><a href="${insights_url}">📄 View Full Runtime Security Report & Recommended Policy</a></b></p>`;
|
||||
|
||||
await core.summary.addSeparator().addRaw(`<h2>StepSecurity Report</h2>`);
|
||||
await core.summary.addSeparator().addRaw(`<h2>🛡 StepSecurity Report</h2>`);
|
||||
|
||||
tableEntries.sort((a, b) => {
|
||||
if (a.status === "❌ Blocked" && b.status !== "❌ Blocked") {
|
||||
|
|
@ -118,8 +118,9 @@ export async function addSummary() {
|
|||
tableEntries = tableEntries.slice(0, 3);
|
||||
|
||||
await core.summary.addRaw(`
|
||||
<p>Preview of the network events that occurred on the GitHub-hosted runner during this workflow run.</p>
|
||||
<h3>🌐 Network Events</h3>
|
||||
<blockquote>
|
||||
<p>Preview of the outbound network calls during this workflow run.</p></blockquote>
|
||||
<h3>Network Events</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -132,16 +133,16 @@ export async function addSummary() {
|
|||
${tableEntries
|
||||
.map(
|
||||
(entry) => `<tr>
|
||||
<td>${entry.process}</td>
|
||||
<td><code>${entry.process}</code></td>
|
||||
<td>${entry.domain.replace(/\.$/, "")}</td>
|
||||
<td>${entry.status}</td>
|
||||
</tr>`
|
||||
)
|
||||
.join("")}
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
<td><code>...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -150,7 +151,7 @@ export async function addSummary() {
|
|||
|
||||
await core.summary
|
||||
.addRaw(
|
||||
`<p>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a></p>`
|
||||
`<p><i>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a>.</i></p>`
|
||||
)
|
||||
.addSeparator()
|
||||
.write();
|
||||
|
|
|
|||
19
src/setup.ts
19
src/setup.ts
|
|
@ -19,7 +19,7 @@ import {
|
|||
} from "./cache";
|
||||
import { Configuration, PolicyResponse } from "./interfaces";
|
||||
import { fetchPolicy, mergeConfigs } from "./policy-utils";
|
||||
|
||||
import * as cache from "@actions/cache";
|
||||
import { getCacheEntry } from "@actions/cache/lib/internal/cacheHttpClient";
|
||||
import * as utils from "@actions/cache/lib/internal/cacheUtils";
|
||||
import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
|
||||
|
|
@ -93,13 +93,20 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
|
|||
core.setFailed("disable-telemetry must be a boolean value");
|
||||
}
|
||||
|
||||
if (isValidEvent()) {
|
||||
if (isValidEvent() && confg.egress_policy === "block") {
|
||||
try {
|
||||
let compressionMethod: CompressionMethod =
|
||||
const cacheResult = await cache.saveCache(
|
||||
[path.join(__dirname, "cache.txt")],
|
||||
cacheKey
|
||||
);
|
||||
console.log(cacheResult);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
try {
|
||||
const compressionMethod: CompressionMethod =
|
||||
await utils.getCompressionMethod();
|
||||
|
||||
let cacheFilePath = path.join(__dirname, "cache.txt");
|
||||
cacheFilePath = cacheFilePath.replace("/pre/", "/post/");
|
||||
const cacheFilePath = path.join(__dirname, "cache.txt");
|
||||
core.info(`cacheFilePath ${cacheFilePath}`);
|
||||
const cacheEntry: ArtifactCacheEntry = await getCacheEntry(
|
||||
[cacheKey],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue