1
0
Fork 0
mirror of synced 2026-06-05 18:38:19 +00:00

Add tls-inspection capability (#368)

This commit is contained in:
jatin 2024-01-30 01:36:18 +05:30 committed by GitHub
commit 4a63cdab74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 264 additions and 74 deletions

View file

@ -41,3 +41,9 @@ jobs:
env: env:
PAT: ${{ secrets.PAT }} PAT: ${{ secrets.PAT }}
canary: true canary: true
- name: Canary TLS test
uses: docker://ghcr.io/step-security/integration-test/int:latest
env:
PAT: ${{ secrets.PAT }}
canary-tls: true

View file

@ -22,3 +22,18 @@ jobs:
env: env:
PAT: ${{ secrets.PAT }} PAT: ${{ secrets.PAT }}
canary: true canary: true
int-tls-tests:
name: int tls tests
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Canary test
uses: docker://ghcr.io/step-security/integration-test/int:latest
env:
PAT: ${{ secrets.PAT }}
canary-tls: true

178
dist/pre/index.js vendored
View file

@ -20024,11 +20024,12 @@ exports.setSpanContext = setSpanContext;
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
var abortController = __nccwpck_require__(2557); var abortController = __nccwpck_require__(2557);
var crypto = __nccwpck_require__(6417); var crypto = __nccwpck_require__(6417);
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/** /**
* Creates an abortable promise. * Creates an abortable promise.
* @param buildPromise - A function that takes the resolve and reject functions as parameters. * @param buildPromise - A function that takes the resolve and reject functions as parameters.
@ -20069,7 +20070,6 @@ function createAbortablePromise(buildPromise, options) {
} }
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
const StandardAbortMessage = "The delay was aborted."; const StandardAbortMessage = "The delay was aborted.";
/** /**
* A wrapper for setTimeout that resolves a promise after timeInMs milliseconds. * A wrapper for setTimeout that resolves a promise after timeInMs milliseconds.
@ -20089,27 +20089,6 @@ function delay(timeInMs, options) {
}); });
} }
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* promise.race() wrapper that aborts rest of promises as soon as the first promise settles.
*/
async function cancelablePromiseRace(abortablePromiseBuilders, options) {
var _a, _b;
const aborter = new abortController.AbortController();
function abortHandler() {
aborter.abort();
}
(_a = options === null || options === void 0 ? void 0 : options.abortSignal) === null || _a === void 0 ? void 0 : _a.addEventListener("abort", abortHandler);
try {
return await Promise.race(abortablePromiseBuilders.map((p) => p({ abortSignal: aborter.signal })));
}
finally {
aborter.abort();
(_b = options === null || options === void 0 ? void 0 : options.abortSignal) === null || _b === void 0 ? void 0 : _b.removeEventListener("abort", abortHandler);
}
}
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license. // Licensed under the MIT license.
/** /**
@ -20146,7 +20125,6 @@ function isObject(input) {
} }
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/** /**
* Typeguard for an error object shape (has name and message) * Typeguard for an error object shape (has name and message)
* @param e - Something caught by a catch clause. * @param e - Something caught by a catch clause.
@ -20187,7 +20165,6 @@ function getErrorMessage(e) {
} }
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/** /**
* Generates a SHA-256 HMAC signature. * Generates a SHA-256 HMAC signature.
* @param key - The HMAC key represented as a base64 string, used to generate the cryptographic HMAC hash. * @param key - The HMAC key represented as a base64 string, used to generate the cryptographic HMAC hash.
@ -20312,20 +20289,16 @@ const isWebWorker = typeof self === "object" &&
(((_a = self.constructor) === null || _a === void 0 ? void 0 : _a.name) === "DedicatedWorkerGlobalScope" || (((_a = self.constructor) === null || _a === void 0 ? void 0 : _a.name) === "DedicatedWorkerGlobalScope" ||
((_b = self.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ServiceWorkerGlobalScope" || ((_b = self.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ServiceWorkerGlobalScope" ||
((_c = self.constructor) === null || _c === void 0 ? void 0 : _c.name) === "SharedWorkerGlobalScope"); ((_c = self.constructor) === null || _c === void 0 ? void 0 : _c.name) === "SharedWorkerGlobalScope");
/**
* A constant that indicates whether the environment the code is running is Node.JS.
*/
const isNode = typeof process !== "undefined" && Boolean(process.version) && Boolean((_d = process.versions) === null || _d === void 0 ? void 0 : _d.node);
/** /**
* A constant that indicates whether the environment the code is running is Deno. * A constant that indicates whether the environment the code is running is Deno.
*/ */
const isDeno = typeof Deno !== "undefined" && const isDeno = typeof Deno !== "undefined" &&
typeof Deno.version !== "undefined" && typeof Deno.version !== "undefined" &&
typeof Deno.version.deno !== "undefined"; typeof Deno.version.deno !== "undefined";
/**
* A constant that indicates whether the environment the code is running is Node.JS.
*/
const isNode = typeof process !== "undefined" &&
Boolean(process.version) &&
Boolean((_d = process.versions) === null || _d === void 0 ? void 0 : _d.node) &&
// Deno thought it was a good idea to spoof process.versions.node, see https://deno.land/std@0.177.0/node/process.ts?s=versions
!isDeno;
/** /**
* A constant that indicates whether the environment the code is running is Bun.sh. * A constant that indicates whether the environment the code is running is Bun.sh.
*/ */
@ -20345,7 +20318,14 @@ const isReactNative = typeof navigator !== "undefined" && (navigator === null ||
* @returns a string of the encoded string * @returns a string of the encoded string
*/ */
function uint8ArrayToString(bytes, format) { function uint8ArrayToString(bytes, format) {
return Buffer.from(bytes).toString(format); switch (format) {
case "utf-8":
return uint8ArrayToUtf8String(bytes);
case "base64":
return uint8ArrayToBase64(bytes);
case "base64url":
return uint8ArrayToBase64Url(bytes);
}
} }
/** /**
* The helper that transforms string to specific character encoded bytes array. * The helper that transforms string to specific character encoded bytes array.
@ -20354,10 +20334,58 @@ function uint8ArrayToString(bytes, format) {
* @returns a uint8array * @returns a uint8array
*/ */
function stringToUint8Array(value, format) { function stringToUint8Array(value, format) {
return Buffer.from(value, format); switch (format) {
case "utf-8":
return utf8StringToUint8Array(value);
case "base64":
return base64ToUint8Array(value);
case "base64url":
return base64UrlToUint8Array(value);
}
}
/**
* Decodes a Uint8Array into a Base64 string.
* @internal
*/
function uint8ArrayToBase64(bytes) {
return Buffer.from(bytes).toString("base64");
}
/**
* Decodes a Uint8Array into a Base64Url string.
* @internal
*/
function uint8ArrayToBase64Url(bytes) {
return Buffer.from(bytes).toString("base64url");
}
/**
* Decodes a Uint8Array into a javascript string.
* @internal
*/
function uint8ArrayToUtf8String(bytes) {
return Buffer.from(bytes).toString("utf-8");
}
/**
* Encodes a JavaScript string into a Uint8Array.
* @internal
*/
function utf8StringToUint8Array(value) {
return Buffer.from(value);
}
/**
* Encodes a Base64 string into a Uint8Array.
* @internal
*/
function base64ToUint8Array(value) {
return Buffer.from(value, "base64");
}
/**
* Encodes a Base64Url string into a Uint8Array.
* @internal
*/
function base64UrlToUint8Array(value) {
return Buffer.from(value, "base64url");
} }
exports.cancelablePromiseRace = cancelablePromiseRace;
exports.computeSha256Hash = computeSha256Hash; exports.computeSha256Hash = computeSha256Hash;
exports.computeSha256Hmac = computeSha256Hmac; exports.computeSha256Hmac = computeSha256Hmac;
exports.createAbortablePromise = createAbortablePromise; exports.createAbortablePromise = createAbortablePromise;
@ -71387,12 +71415,16 @@ var external_crypto_ = __nccwpck_require__(6417);
function verifyChecksum(downloadPath) { function verifyChecksum(downloadPath, is_tls) {
const fileBuffer = external_fs_.readFileSync(downloadPath); const fileBuffer = external_fs_.readFileSync(downloadPath);
const checksum = external_crypto_.createHash("sha256") const checksum = external_crypto_.createHash("sha256")
.update(fileBuffer) .update(fileBuffer)
.digest("hex"); // checksum of downloaded file .digest("hex"); // checksum of downloaded file
const expectedChecksum = "ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5 let expectedChecksum = "ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5
if (is_tls) {
expectedChecksum =
"204c82116e8c0eebf5409bb2b81aa5d96fe32f0c5abc1cb0364ee70937c32056"; // checksum for tls_agent
}
if (checksum !== expectedChecksum) { if (checksum !== expectedChecksum) {
lib_core.setFailed(`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`); lib_core.setFailed(`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`);
} }
@ -71453,6 +71485,11 @@ function isValidEvent() {
return RefKey in process.env && Boolean(process.env[RefKey]); return RefKey in process.env && Boolean(process.env[RefKey]);
} }
;// CONCATENATED MODULE: ./src/configs.ts
const STEPSECURITY_ENV = "agent"; // agent or int
const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
const STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";
;// CONCATENATED MODULE: ./src/policy-utils.ts ;// CONCATENATED MODULE: ./src/policy-utils.ts
var policy_utils_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { var policy_utils_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@ -71464,13 +71501,13 @@ var policy_utils_awaiter = (undefined && undefined.__awaiter) || function (thisA
}); });
}; };
const API_ENDPOINT = "https://agent.api.stepsecurity.io/v1";
function fetchPolicy(owner, policyName, idToken) { function fetchPolicy(owner, policyName, idToken) {
return policy_utils_awaiter(this, void 0, void 0, function* () { return policy_utils_awaiter(this, void 0, void 0, function* () {
if (idToken === "") { if (idToken === "") {
throw new Error("[PolicyFetch]: id-token in empty"); throw new Error("[PolicyFetch]: id-token in empty");
} }
let policyEndpoint = `${API_ENDPOINT}/github/${owner}/actions/policies/${policyName}`; let policyEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/policies/${policyName}`;
let httpClient = new lib.HttpClient(); let httpClient = new lib.HttpClient();
let headers = {}; let headers = {};
headers["Authorization"] = `Bearer ${idToken}`; headers["Authorization"] = `Bearer ${idToken}`;
@ -71573,6 +71610,46 @@ function arcCleanUp() {
cp.execSync(`echo "cleanup" > "${getRunnerTempDir()}/step_policy_cleanup"`); cp.execSync(`echo "cleanup" > "${getRunnerTempDir()}/step_policy_cleanup"`);
} }
;// CONCATENATED MODULE: ./src/tls-inspect.ts
var tls_inspect_awaiter = (undefined && undefined.__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());
});
};
function isTLSEnabled(owner) {
return tls_inspect_awaiter(this, void 0, void 0, function* () {
let tlsStatusEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/tls-inspection-status`;
let httpClient = new lib.HttpClient();
lib_core.info(`[!] Checking TLS_STATUS: ${owner}`);
let isEnabled = false;
try {
let resp = yield httpClient.get(tlsStatusEndpoint);
if (resp.message.statusCode === 200) {
isEnabled = true;
lib_core.info(`[!] TLS_ENABLED: ${owner}`);
}
else {
lib_core.info(`[!] TLS_NOT_ENABLED: ${owner}`);
}
}
catch (e) {
lib_core.info(`[!] Unable to check TLS_STATUS`);
}
return isEnabled;
});
}
function isGithubHosted() {
const runnerName = process.env.RUNNER_NAME || "";
return runnerName.startsWith("GitHub Actions");
}
;// CONCATENATED MODULE: ./src/setup.ts ;// CONCATENATED MODULE: ./src/setup.ts
var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@ -71601,6 +71678,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
(() => setup_awaiter(void 0, void 0, void 0, function* () { (() => setup_awaiter(void 0, void 0, void 0, function* () {
var _a, _b; var _a, _b;
try { try {
@ -71613,9 +71692,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
return; return;
} }
var correlation_id = v4(); var correlation_id = v4();
var env = "agent"; var api_url = STEPSECURITY_API_URL;
var api_url = `https://${env}.api.stepsecurity.io/v1`; var web_url = STEPSECURITY_WEB_URL;
var web_url = "https://app.stepsecurity.io";
let confg = { let confg = {
repo: process.env["GITHUB_REPOSITORY"], repo: process.env["GITHUB_REPOSITORY"],
run_id: process.env["GITHUB_RUN_ID"], run_id: process.env["GITHUB_RUN_ID"],
@ -71628,6 +71706,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
disable_sudo: lib_core.getBooleanInput("disable-sudo"), disable_sudo: lib_core.getBooleanInput("disable-sudo"),
disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"), disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"),
private: ((_b = (_a = github.context === null || github.context === void 0 ? void 0 : github.context.payload) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.private) || false, private: ((_b = (_a = github.context === null || github.context === void 0 ? void 0 : github.context.payload) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.private) || false,
is_github_hosted: isGithubHosted(),
}; };
let policyName = lib_core.getInput("policy"); let policyName = lib_core.getInput("policy");
if (policyName !== "") { if (policyName !== "") {
@ -71696,7 +71775,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
} }
const runnerName = process.env.RUNNER_NAME || ""; const runnerName = process.env.RUNNER_NAME || "";
lib_core.info(`RUNNER_NAME: ${runnerName}`); lib_core.info(`RUNNER_NAME: ${runnerName}`);
if (!runnerName.startsWith("GitHub Actions")) { if (!isGithubHosted()) {
external_fs_.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${external_os_.EOL}`, { external_fs_.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${external_os_.EOL}`, {
encoding: "utf8", encoding: "utf8",
}); });
@ -71743,8 +71822,15 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
// Note: to avoid github rate limiting // Note: to avoid github rate limiting
let token = lib_core.getInput("token"); let token = lib_core.getInput("token");
let auth = `token ${token}`; let auth = `token ${token}`;
const downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz", undefined, auth); let downloadPath;
verifyChecksum(downloadPath); // NOTE: verifying agent's checksum, before extracting if (yield isTLSEnabled(github.context.repo.owner)) {
downloadPath = yield tool_cache.downloadTool("https://packages.stepsecurity.io/github-hosted/harden-runner_1.1.0_linux_amd64.tar.gz");
verifyChecksum(downloadPath, true); // NOTE: verifying tls_agent's checksum, before extracting
}
else {
downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz", undefined, auth);
verifyChecksum(downloadPath, false); // NOTE: verifying agent's checksum, before extracting
}
const extractPath = yield tool_cache.extractTar(downloadPath); const extractPath = yield tool_cache.extractTar(downloadPath);
let cmd = "cp", args = [external_path_.join(extractPath, "agent"), "/home/agent/agent"]; let cmd = "cp", args = [external_path_.join(extractPath, "agent"), "/home/agent/agent"];
external_child_process_.execFileSync(cmd, args); external_child_process_.execFileSync(cmd, args);

File diff suppressed because one or more lines are too long

View file

@ -2,16 +2,21 @@ import * as core from "@actions/core";
import * as crypto from "crypto"; import * as crypto from "crypto";
import * as fs from "fs"; import * as fs from "fs";
export function verifyChecksum(downloadPath: string) { export function verifyChecksum(downloadPath: string, is_tls: boolean) {
const fileBuffer: Buffer = fs.readFileSync(downloadPath); const fileBuffer: Buffer = fs.readFileSync(downloadPath);
const checksum: string = crypto const checksum: string = crypto
.createHash("sha256") .createHash("sha256")
.update(fileBuffer) .update(fileBuffer)
.digest("hex"); // checksum of downloaded file .digest("hex"); // checksum of downloaded file
const expectedChecksum: string = let expectedChecksum: string =
"ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5 "ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5
if (is_tls) {
expectedChecksum =
"204c82116e8c0eebf5409bb2b81aa5d96fe32f0c5abc1cb0364ee70937c32056"; // checksum for tls_agent
}
if (checksum !== expectedChecksum) { if (checksum !== expectedChecksum) {
core.setFailed( core.setFailed(
`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}` `Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`

5
src/configs.ts Normal file
View file

@ -0,0 +1,5 @@
export const STEPSECURITY_ENV = "agent"; // agent or int
export const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
export const STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";

View file

@ -9,6 +9,7 @@ export interface Configuration {
disable_telemetry: boolean; disable_telemetry: boolean;
disable_sudo: boolean; disable_sudo: boolean;
disable_file_monitoring: boolean; disable_file_monitoring: boolean;
is_github_hosted: boolean;
private: string; private: string;
} }

View file

@ -1,6 +1,7 @@
import nock from "nock"; import nock from "nock";
import { API_ENDPOINT, fetchPolicy, mergeConfigs } from "./policy-utils"; import { fetchPolicy, mergeConfigs } from "./policy-utils";
import { Configuration, PolicyResponse } from "./interfaces"; import { Configuration, PolicyResponse } from "./interfaces";
import { STEPSECURITY_API_URL } from "./configs";
test("success: fetching policy", async () => { test("success: fetching policy", async () => {
let owner = "h0x0er"; let owner = "h0x0er";
@ -14,7 +15,7 @@ test("success: fetching policy", async () => {
disable_sudo: false, disable_sudo: false,
disable_file_monitoring: false, disable_file_monitoring: false,
}; };
const policyScope = nock(`${API_ENDPOINT}`) const policyScope = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/policies/${policyName}`) .get(`/github/${owner}/actions/policies/${policyName}`)
.reply(200, response); .reply(200, response);
@ -37,6 +38,7 @@ test("merge configs", async () => {
disable_sudo: false, disable_sudo: false,
disable_file_monitoring: false, disable_file_monitoring: false,
private: "true", private: "true",
is_github_hosted: true,
}; };
let policyResponse: PolicyResponse = { let policyResponse: PolicyResponse = {
owner: "h0x0er", owner: "h0x0er",
@ -60,6 +62,7 @@ test("merge configs", async () => {
disable_sudo: false, disable_sudo: false,
disable_file_monitoring: false, disable_file_monitoring: false,
private: "true", private: "true",
is_github_hosted: true,
}; };
localConfig = mergeConfigs(localConfig, policyResponse); localConfig = mergeConfigs(localConfig, policyResponse);

View file

@ -1,19 +1,17 @@
import { HttpClient } from "@actions/http-client"; import { HttpClient } from "@actions/http-client";
import { PolicyResponse, Configuration } from "./interfaces"; import { PolicyResponse, Configuration } from "./interfaces";
import { STEPSECURITY_API_URL } from "./configs";
export const API_ENDPOINT = "https://agent.api.stepsecurity.io/v1";
export async function fetchPolicy( export async function fetchPolicy(
owner: string, owner: string,
policyName: string, policyName: string,
idToken: string idToken: string
): Promise<PolicyResponse> { ): Promise<PolicyResponse> {
if (idToken === "") { if (idToken === "") {
throw new Error("[PolicyFetch]: id-token in empty"); throw new Error("[PolicyFetch]: id-token in empty");
} }
let policyEndpoint = `${API_ENDPOINT}/github/${owner}/actions/policies/${policyName}`; let policyEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/policies/${policyName}`;
let httpClient = new HttpClient(); let httpClient = new HttpClient();
@ -25,24 +23,24 @@ export async function fetchPolicy(
let err = undefined; let err = undefined;
let retry = 0; let retry = 0;
while(retry < 3){ while (retry < 3) {
try{ try {
console.log(`Attempt: ${retry+1}`) console.log(`Attempt: ${retry + 1}`);
response = await httpClient.getJson<PolicyResponse>( response = await httpClient.getJson<PolicyResponse>(
policyEndpoint, policyEndpoint,
headers headers
); );
break; break;
}catch(e){ } catch (e) {
err = e err = e;
} }
retry += 1 retry += 1;
await sleep(1000); await sleep(1000);
} }
if(response === undefined && err !== undefined){ if (response === undefined && err !== undefined) {
throw new Error(`[Policy Fetch] ${err}`) throw new Error(`[Policy Fetch] ${err}`);
}else{ } else {
return response.result; return response.result;
} }
} }

View file

@ -23,6 +23,8 @@ import * as cache from "@actions/cache";
import { getCacheEntry } from "@actions/cache/lib/internal/cacheHttpClient"; import { getCacheEntry } from "@actions/cache/lib/internal/cacheHttpClient";
import * as utils from "@actions/cache/lib/internal/cacheUtils"; import * as utils from "@actions/cache/lib/internal/cacheUtils";
import { isArcRunner, sendAllowedEndpoints } from "./arc-runner"; import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
import { STEPSECURITY_API_URL, STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted, isTLSEnabled } from "./tls-inspect";
(async () => { (async () => {
try { try {
@ -36,9 +38,8 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
} }
var correlation_id = uuidv4(); var correlation_id = uuidv4();
var env = "agent"; var api_url = STEPSECURITY_API_URL;
var api_url = `https://${env}.api.stepsecurity.io/v1`; var web_url = STEPSECURITY_WEB_URL;
var web_url = "https://app.stepsecurity.io";
let confg: Configuration = { let confg: Configuration = {
repo: process.env["GITHUB_REPOSITORY"], repo: process.env["GITHUB_REPOSITORY"],
@ -52,6 +53,7 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
disable_sudo: core.getBooleanInput("disable-sudo"), disable_sudo: core.getBooleanInput("disable-sudo"),
disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"), disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"),
private: context?.payload?.repository?.private || false, private: context?.payload?.repository?.private || false,
is_github_hosted: isGithubHosted(),
}; };
let policyName = core.getInput("policy"); let policyName = core.getInput("policy");
@ -143,7 +145,7 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
const runnerName = process.env.RUNNER_NAME || ""; const runnerName = process.env.RUNNER_NAME || "";
core.info(`RUNNER_NAME: ${runnerName}`); core.info(`RUNNER_NAME: ${runnerName}`);
if (!runnerName.startsWith("GitHub Actions")) { if (!isGithubHosted()) {
fs.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${EOL}`, { fs.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${EOL}`, {
encoding: "utf8", encoding: "utf8",
}); });
@ -199,18 +201,30 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
let token = core.getInput("token"); let token = core.getInput("token");
let auth = `token ${token}`; let auth = `token ${token}`;
const downloadPath: string = await tc.downloadTool( let downloadPath: string;
"https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz",
undefined, if (await isTLSEnabled(context.repo.owner)) {
auth downloadPath = await tc.downloadTool(
); "https://packages.stepsecurity.io/github-hosted/harden-runner_1.1.0_linux_amd64.tar.gz"
);
verifyChecksum(downloadPath, true); // NOTE: verifying tls_agent's checksum, before extracting
} else {
downloadPath = await tc.downloadTool(
"https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz",
undefined,
auth
);
verifyChecksum(downloadPath, false); // NOTE: verifying agent's checksum, before extracting
}
verifyChecksum(downloadPath); // NOTE: verifying agent's checksum, before extracting
const extractPath = await tc.extractTar(downloadPath); const extractPath = await tc.extractTar(downloadPath);
let cmd = "cp", let cmd = "cp",
args = [path.join(extractPath, "agent"), "/home/agent/agent"]; args = [path.join(extractPath, "agent"), "/home/agent/agent"];
cp.execFileSync(cmd, args); cp.execFileSync(cmd, args);
cp.execSync("chmod +x /home/agent/agent"); cp.execSync("chmod +x /home/agent/agent");
fs.writeFileSync("/home/agent/agent.json", confgStr); fs.writeFileSync("/home/agent/agent.json", confgStr);

29
src/tls-inspect.test.ts Normal file
View file

@ -0,0 +1,29 @@
import nock from "nock";
import { STEPSECURITY_API_URL } from "./configs";
import { isTLSEnabled } from "./tls-inspect";
test("tls-inspect enabled", async () => {
let owner = "h0x0er";
let expected = true;
const resp = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/tls-inspection-status`)
.reply(200, "");
let got = await isTLSEnabled(owner);
expect(got).toEqual(expected);
});
test("tls-inspect not enabled", async () => {
let owner = "step-security";
let expected = false;
const resp = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/tls-inspection-status`)
.reply(401, "");
let got = await isTLSEnabled(owner);
expect(got).toEqual(expected);
});

28
src/tls-inspect.ts Normal file
View file

@ -0,0 +1,28 @@
import { HttpClient } from "@actions/http-client";
import { STEPSECURITY_API_URL } from "./configs";
import * as core from "@actions/core";
export async function isTLSEnabled(owner: string): Promise<boolean> {
let tlsStatusEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/tls-inspection-status`;
let httpClient = new HttpClient();
core.info(`[!] Checking TLS_STATUS: ${owner}`);
let isEnabled = false;
try {
let resp = await httpClient.get(tlsStatusEndpoint);
if (resp.message.statusCode === 200) {
isEnabled = true;
core.info(`[!] TLS_ENABLED: ${owner}`);
} else {
core.info(`[!] TLS_NOT_ENABLED: ${owner}`);
}
} catch (e) {
core.info(`[!] Unable to check TLS_STATUS`);
}
return isEnabled;
}
export function isGithubHosted() {
const runnerName = process.env.RUNNER_NAME || "";
return runnerName.startsWith("GitHub Actions");
}