add third-party runner support via bravo agent
Detect Depot/Namespace/Warp/Blacksmith runners and install the bravo agent variant. Bravo install mirrors installAgentForSelfHosted: TLS gate via isTLSEnabled, hand-picked config literal with random api_key, correlation_id set to RUNNER_NAME so it matches server-side correlation derived from job logs (is_github_hosted=true keeps the agent from overriding correlation_id to customer-hostname). Bumps agent-ebpf to v1.8.1 and macOS installer to v0.0.5.
This commit is contained in:
parent
6c3c2f2c1c
commit
20c37511ec
11 changed files with 352 additions and 25 deletions
13
dist/index.js
vendored
13
dist/index.js
vendored
|
|
@ -31913,6 +31913,19 @@ function isAgentInstalled(platform) {
|
|||
function shouldDeployAgentOnSelfHosted(deployOnSelfHostedVm, isContainer, agentAlreadyInstalled) {
|
||||
return deployOnSelfHostedVm && !isContainer && !agentAlreadyInstalled;
|
||||
}
|
||||
function detectThirdPartyRunnerProvider() {
|
||||
var _a;
|
||||
if (process.env["DEPOT_RUNNER"] === "1")
|
||||
return "depot";
|
||||
if (process.env["NAMESPACE_GITHUB_RUNTIME"])
|
||||
return "namespace";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
if (runnerName.startsWith("blacksmith-"))
|
||||
return "blacksmith";
|
||||
return null;
|
||||
}
|
||||
function utils_getAnnotationLogs(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
|
|
|
|||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
52
dist/post/index.js
vendored
52
dist/post/index.js
vendored
|
|
@ -31919,6 +31919,19 @@ function isAgentInstalled(platform) {
|
|||
function shouldDeployAgentOnSelfHosted(deployOnSelfHostedVm, isContainer, agentAlreadyInstalled) {
|
||||
return deployOnSelfHostedVm && !isContainer && !agentAlreadyInstalled;
|
||||
}
|
||||
function detectThirdPartyRunnerProvider() {
|
||||
var _a;
|
||||
if (process.env["DEPOT_RUNNER"] === "1")
|
||||
return "depot";
|
||||
if (process.env["NAMESPACE_GITHUB_RUNTIME"])
|
||||
return "namespace";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
if (runnerName.startsWith("blacksmith-"))
|
||||
return "blacksmith";
|
||||
return null;
|
||||
}
|
||||
function getAnnotationLogs(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
|
|
@ -32205,6 +32218,7 @@ var cleanup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _
|
|||
console.log(`[!] ${ARC_RUNNER_MESSAGE}`);
|
||||
return;
|
||||
}
|
||||
const thirdPartyProvider = detectThirdPartyRunnerProvider();
|
||||
if (process.env.STATE_selfHosted === "true") {
|
||||
return;
|
||||
}
|
||||
|
|
@ -32218,7 +32232,12 @@ var cleanup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _
|
|||
}
|
||||
switch (process.platform) {
|
||||
case "linux":
|
||||
yield handleLinuxCleanup();
|
||||
if (thirdPartyProvider) {
|
||||
yield handleAgentBravoCleanup();
|
||||
}
|
||||
else {
|
||||
yield handleLinuxCleanup();
|
||||
}
|
||||
break;
|
||||
case "win32":
|
||||
yield handleWindowsCleanup();
|
||||
|
|
@ -32234,6 +32253,37 @@ var cleanup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _
|
|||
console.log(exception);
|
||||
}
|
||||
}))();
|
||||
function handleAgentBravoCleanup() {
|
||||
return cleanup_awaiter(this, void 0, void 0, function* () {
|
||||
external_child_process_.execFileSync("/usr/bin/echo", ["step_policy_jobend"]);
|
||||
const doneFile = "/home/agent/done.json";
|
||||
let counter = 0;
|
||||
while (true) {
|
||||
if (!external_fs_.existsSync(doneFile)) {
|
||||
counter++;
|
||||
if (counter > 10) {
|
||||
console.log("timed out");
|
||||
break;
|
||||
}
|
||||
yield sleep(1000);
|
||||
}
|
||||
else {
|
||||
console.log(external_fs_.readFileSync(doneFile, "utf-8"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
const log = "/home/agent/agent.log";
|
||||
if (external_fs_.existsSync(log)) {
|
||||
console.log("log:");
|
||||
console.log(external_fs_.readFileSync(log, "utf-8"));
|
||||
}
|
||||
const status = "/home/agent/agent.status";
|
||||
if (external_fs_.existsSync(status)) {
|
||||
console.log("status:");
|
||||
console.log(external_fs_.readFileSync(status, "utf-8"));
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleLinuxCleanup() {
|
||||
return cleanup_awaiter(this, void 0, void 0, function* () {
|
||||
if (process.env.STATE_isTLS === "false" && process.arch === "arm64") {
|
||||
|
|
|
|||
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
126
dist/pre/index.js
vendored
126
dist/pre/index.js
vendored
|
|
@ -84976,6 +84976,7 @@ __nccwpck_require__.r(__webpack_exports__);
|
|||
|
||||
// EXPORTS
|
||||
__nccwpck_require__.d(__webpack_exports__, {
|
||||
installAgentForBravo: () => (/* binding */ installAgentForBravo),
|
||||
installAgentForSelfHosted: () => (/* binding */ installAgentForSelfHosted),
|
||||
sleep: () => (/* binding */ setup_sleep)
|
||||
});
|
||||
|
|
@ -85037,6 +85038,19 @@ function isAgentInstalled(platform) {
|
|||
function shouldDeployAgentOnSelfHosted(deployOnSelfHostedVm, isContainer, agentAlreadyInstalled) {
|
||||
return deployOnSelfHostedVm && !isContainer && !agentAlreadyInstalled;
|
||||
}
|
||||
function detectThirdPartyRunnerProvider() {
|
||||
var _a;
|
||||
if (process.env["DEPOT_RUNNER"] === "1")
|
||||
return "depot";
|
||||
if (process.env["NAMESPACE_GITHUB_RUNTIME"])
|
||||
return "namespace";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
if (runnerName.startsWith("blacksmith-"))
|
||||
return "blacksmith";
|
||||
return null;
|
||||
}
|
||||
function utils_getAnnotationLogs(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
|
|
@ -85441,19 +85455,23 @@ var external_crypto_ = __nccwpck_require__(6982);
|
|||
|
||||
const CHECKSUMS = {
|
||||
tls: {
|
||||
amd64: "86d042adcdc03eb1ea50d35d265da47622a6d0aedef9657f84ce1eb7f04d6057",
|
||||
arm64: "ea1074a2358d50db9a9fe18ae3971b87305cda63f262c494a5f43b25f4e524ce",
|
||||
amd64: "6105000c6c61f4a3ca27ed3a2796baa206bdb1eb83f0463adb0ec7e565af6e1c",
|
||||
arm64: "0992da262be06580335725263ba6ee5c009dfd0448a948b7768ec077fdb9d3d8",
|
||||
},
|
||||
non_tls: {
|
||||
amd64: "4aaaeebbe10e619d8ce13e8cc4a1acbafc8f891e8cdd319984480b9ec08407b8", // v0.15.0
|
||||
},
|
||||
darwin: "797399a3a3f6f9c4c000a02e0d8c7b16499129c9bdc2ad9cf2a10072c10654fb",
|
||||
bravo: {
|
||||
amd64: "2eeaa1b3cfb05adea0a4e2a36e342ccaf95b41aeb82a6a6e217d2971c15f5553",
|
||||
arm64: "8d7035ffbda165ad86de8bd00bf861c038e4a9e6d501adadc53a265945882533",
|
||||
},
|
||||
darwin: "fe26a1f6af4afe9f1a854d8633832f5d18ab542827003cae445b3a64021d612c",
|
||||
windows: {
|
||||
amd64: "e98f8b9cf9ecf6566f1e16a470fbe4aef01610a644fd8203a1bab3ff142186c8", // v1.0.0
|
||||
},
|
||||
};
|
||||
// verifyChecksum returns true if checksum is valid
|
||||
function verifyChecksum(downloadPath, isTLS, variant, platform) {
|
||||
function verifyChecksum(downloadPath, isTLS, variant, platform, agentType = "default") {
|
||||
const fileBuffer = external_fs_.readFileSync(downloadPath);
|
||||
const checksum = external_crypto_.createHash("sha256")
|
||||
.update(fileBuffer)
|
||||
|
|
@ -85461,9 +85479,14 @@ function verifyChecksum(downloadPath, isTLS, variant, platform) {
|
|||
let expectedChecksum = "";
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
expectedChecksum = isTLS
|
||||
? CHECKSUMS["tls"][variant]
|
||||
: CHECKSUMS["non_tls"][variant];
|
||||
if (agentType === "bravo") {
|
||||
expectedChecksum = CHECKSUMS["bravo"][variant];
|
||||
}
|
||||
else {
|
||||
expectedChecksum = isTLS
|
||||
? CHECKSUMS["tls"][variant]
|
||||
: CHECKSUMS["non_tls"][variant];
|
||||
}
|
||||
break;
|
||||
case "darwin":
|
||||
expectedChecksum = CHECKSUMS["darwin"];
|
||||
|
|
@ -85513,7 +85536,7 @@ function installAgent(isTLS, configStr) {
|
|||
encoding: "utf8",
|
||||
});
|
||||
if (isTLS) {
|
||||
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.0/harden-runner_1.8.0_linux_${variant}.tar.gz`, undefined, auth);
|
||||
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.1/harden-runner_1.8.1_linux_${variant}.tar.gz`, undefined, auth);
|
||||
}
|
||||
else {
|
||||
if (variant === "arm64") {
|
||||
|
|
@ -85542,6 +85565,51 @@ function installAgent(isTLS, configStr) {
|
|||
return true;
|
||||
});
|
||||
}
|
||||
function installAgentBravo(configStr) {
|
||||
return install_agent_awaiter(this, void 0, void 0, function* () {
|
||||
// Note: to avoid github rate limiting
|
||||
const token = lib_core.getInput("token", { required: true });
|
||||
const auth = `token ${token}`;
|
||||
const variant = process.arch === "x64" ? "amd64" : "arm64";
|
||||
const downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.1/harden-runner-bravo_1.8.1_linux_${variant}.tar.gz`, undefined, auth);
|
||||
if (!verifyChecksum(downloadPath, true, variant, "linux", "bravo")) {
|
||||
return false;
|
||||
}
|
||||
const extractPath = yield tool_cache.extractTar(downloadPath);
|
||||
external_child_process_.execFileSync("cp", [external_path_.join(extractPath, "agent"), "/home/agent/agent"]);
|
||||
external_child_process_.execSync("chmod +x /home/agent/agent");
|
||||
external_fs_.writeFileSync("/home/agent/agent.json", configStr);
|
||||
const logStream = external_fs_.openSync("/home/agent/agent.stdout", "a");
|
||||
const agentProcess = external_child_process_.spawn("sudo", ["/home/agent/agent"], {
|
||||
cwd: "/home/agent",
|
||||
detached: true,
|
||||
stdio: ["ignore", logStream, logStream],
|
||||
});
|
||||
agentProcess.unref();
|
||||
const agentStatus = "/home/agent/agent.status";
|
||||
const deadline = Date.now() + 10000;
|
||||
while (true) {
|
||||
if (!external_fs_.existsSync(agentStatus)) {
|
||||
if (Date.now() >= deadline) {
|
||||
console.log("timed out waiting for bravo agent");
|
||||
if (external_fs_.existsSync("/home/agent/agent.stdout")) {
|
||||
console.log(external_fs_.readFileSync("/home/agent/agent.stdout", "utf-8"));
|
||||
}
|
||||
if (external_fs_.existsSync("/home/agent/agent.log")) {
|
||||
console.log(external_fs_.readFileSync("/home/agent/agent.log", "utf-8"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
yield new Promise((resolve) => setTimeout(resolve, 300));
|
||||
}
|
||||
else {
|
||||
console.log(external_fs_.readFileSync(agentStatus, "utf-8"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
function installMacosAgent(configStr) {
|
||||
return install_agent_awaiter(this, void 0, void 0, function* () {
|
||||
const token = lib_core.getInput("token", { required: true });
|
||||
|
|
@ -85557,7 +85625,7 @@ function installMacosAgent(configStr) {
|
|||
external_fs_.writeFileSync("/opt/step-security/agent.json", configStr);
|
||||
lib_core.info("✓ Successfully created agent.json at /opt/step-security/agent.json");
|
||||
// Download installer package
|
||||
const downloadUrl = "https://github.com/step-security/agent-releases/releases/download/v0.0.4-mac/macos-installer-0.0.4.tar.gz";
|
||||
const downloadUrl = "https://github.com/step-security/agent-releases/releases/download/v0.0.5-mac/macos-installer-0.0.5.tar.gz";
|
||||
lib_core.info(`Downloading macOS installer.. : ${downloadUrl}`);
|
||||
const downloadPath = yield tool_cache.downloadTool(downloadUrl, undefined, auth);
|
||||
lib_core.info(`✓ Successfully downloaded installer to: ${downloadPath}`);
|
||||
|
|
@ -85896,6 +85964,12 @@ var __rest = (undefined && undefined.__rest) || function (s, e) {
|
|||
const runnerName = process.env.RUNNER_NAME || "";
|
||||
lib_core.info(`RUNNER_NAME: ${runnerName}`);
|
||||
if (!isGithubHosted()) {
|
||||
const thirdPartyProvider = detectThirdPartyRunnerProvider();
|
||||
if (thirdPartyProvider) {
|
||||
lib_core.info(`Detected ${thirdPartyProvider} runner environment. Installing agent-bravo.`);
|
||||
yield installAgentForBravo(github.context.repo.owner, confg);
|
||||
return;
|
||||
}
|
||||
external_fs_.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${external_os_.EOL}`, {
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
|
@ -86097,6 +86171,40 @@ function installAgentForSelfHosted(owner, confg) {
|
|||
}
|
||||
});
|
||||
}
|
||||
function installAgentForBravo(owner, confg) {
|
||||
var _a;
|
||||
return setup_awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
console.log("Installing Harden Runner bravo agent for third-party runner");
|
||||
let isTLS = yield isTLSEnabled(owner);
|
||||
if (!isTLS) {
|
||||
console.log("TLS is not enabled for this organization. Bravo agent installation skipped.");
|
||||
return;
|
||||
}
|
||||
const bravoConfig = {
|
||||
customer: owner,
|
||||
correlation_id: (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : v4(),
|
||||
working_directory: confg.working_directory,
|
||||
api_url: confg.api_url,
|
||||
api_key: v4(),
|
||||
allowed_endpoints: confg.allowed_endpoints,
|
||||
egress_policy: confg.egress_policy,
|
||||
disable_telemetry: confg.disable_telemetry,
|
||||
disable_sudo: confg.disable_sudo,
|
||||
disable_sudo_and_containers: confg.disable_sudo_and_containers,
|
||||
disable_file_monitoring: confg.disable_file_monitoring,
|
||||
is_github_hosted: true,
|
||||
};
|
||||
const bravoConfigStr = JSON.stringify(bravoConfig);
|
||||
external_child_process_.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
yield installAgentBravo(bravoConfigStr);
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Failed to install bravo agent: ${error.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
|
|
|
|||
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
|
|
@ -4,13 +4,17 @@ import * as fs from "fs";
|
|||
|
||||
const CHECKSUMS = {
|
||||
tls: {
|
||||
amd64: "86d042adcdc03eb1ea50d35d265da47622a6d0aedef9657f84ce1eb7f04d6057", // v1.8.0
|
||||
arm64: "ea1074a2358d50db9a9fe18ae3971b87305cda63f262c494a5f43b25f4e524ce",
|
||||
amd64: "6105000c6c61f4a3ca27ed3a2796baa206bdb1eb83f0463adb0ec7e565af6e1c", // v1.8.1
|
||||
arm64: "0992da262be06580335725263ba6ee5c009dfd0448a948b7768ec077fdb9d3d8",
|
||||
},
|
||||
non_tls: {
|
||||
amd64: "4aaaeebbe10e619d8ce13e8cc4a1acbafc8f891e8cdd319984480b9ec08407b8", // v0.15.0
|
||||
},
|
||||
darwin: "797399a3a3f6f9c4c000a02e0d8c7b16499129c9bdc2ad9cf2a10072c10654fb", // v0.0.4
|
||||
bravo: {
|
||||
amd64: "2eeaa1b3cfb05adea0a4e2a36e342ccaf95b41aeb82a6a6e217d2971c15f5553", // v1.8.1
|
||||
arm64: "8d7035ffbda165ad86de8bd00bf861c038e4a9e6d501adadc53a265945882533",
|
||||
},
|
||||
darwin: "fe26a1f6af4afe9f1a854d8633832f5d18ab542827003cae445b3a64021d612c", // v0.0.5
|
||||
windows: {
|
||||
amd64: "e98f8b9cf9ecf6566f1e16a470fbe4aef01610a644fd8203a1bab3ff142186c8", // v1.0.0
|
||||
},
|
||||
|
|
@ -21,7 +25,8 @@ export function verifyChecksum(
|
|||
downloadPath: string,
|
||||
isTLS: boolean,
|
||||
variant: string,
|
||||
platform: string
|
||||
platform: string,
|
||||
agentType: "default" | "bravo" = "default"
|
||||
) {
|
||||
const fileBuffer: Buffer = fs.readFileSync(downloadPath);
|
||||
const checksum: string = crypto
|
||||
|
|
@ -33,9 +38,13 @@ export function verifyChecksum(
|
|||
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
expectedChecksum = isTLS
|
||||
? CHECKSUMS["tls"][variant]
|
||||
: CHECKSUMS["non_tls"][variant];
|
||||
if (agentType === "bravo") {
|
||||
expectedChecksum = CHECKSUMS["bravo"][variant];
|
||||
} else {
|
||||
expectedChecksum = isTLS
|
||||
? CHECKSUMS["tls"][variant]
|
||||
: CHECKSUMS["non_tls"][variant];
|
||||
}
|
||||
break;
|
||||
case "darwin":
|
||||
expectedChecksum = CHECKSUMS["darwin"];
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import isDocker from "is-docker";
|
|||
import { isARCRunner } from "./arc-runner";
|
||||
import { isGithubHosted } from "./tls-inspect";
|
||||
import { context } from "@actions/github";
|
||||
import { isPlatformSupported, isAgentInstalled } from "./utils";
|
||||
import { isPlatformSupported, isAgentInstalled, detectThirdPartyRunnerProvider } from "./utils";
|
||||
|
||||
(async () => {
|
||||
console.log("[harden-runner] post-step");
|
||||
|
|
@ -31,6 +31,8 @@ import { isPlatformSupported, isAgentInstalled } from "./utils";
|
|||
return;
|
||||
}
|
||||
|
||||
const thirdPartyProvider = detectThirdPartyRunnerProvider();
|
||||
|
||||
if (process.env.STATE_selfHosted === "true") {
|
||||
return;
|
||||
}
|
||||
|
|
@ -49,7 +51,11 @@ import { isPlatformSupported, isAgentInstalled } from "./utils";
|
|||
|
||||
switch (process.platform) {
|
||||
case "linux":
|
||||
await handleLinuxCleanup();
|
||||
if (thirdPartyProvider) {
|
||||
await handleAgentBravoCleanup();
|
||||
} else {
|
||||
await handleLinuxCleanup();
|
||||
}
|
||||
break;
|
||||
case "win32":
|
||||
await handleWindowsCleanup();
|
||||
|
|
@ -66,6 +72,38 @@ import { isPlatformSupported, isAgentInstalled } from "./utils";
|
|||
}
|
||||
})();
|
||||
|
||||
async function handleAgentBravoCleanup() {
|
||||
cp.execFileSync("/usr/bin/echo", ["step_policy_jobend"]);
|
||||
|
||||
const doneFile = "/home/agent/done.json";
|
||||
let counter = 0;
|
||||
while (true) {
|
||||
if (!fs.existsSync(doneFile)) {
|
||||
counter++;
|
||||
if (counter > 10) {
|
||||
console.log("timed out");
|
||||
break;
|
||||
}
|
||||
await sleep(1000);
|
||||
} else {
|
||||
console.log(fs.readFileSync(doneFile, "utf-8"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const log = "/home/agent/agent.log";
|
||||
if (fs.existsSync(log)) {
|
||||
console.log("log:");
|
||||
console.log(fs.readFileSync(log, "utf-8"));
|
||||
}
|
||||
|
||||
const status = "/home/agent/agent.status";
|
||||
if (fs.existsSync(status)) {
|
||||
console.log("status:");
|
||||
console.log(fs.readFileSync(status, "utf-8"));
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLinuxCleanup() {
|
||||
if (process.env.STATE_isTLS === "false" && process.arch === "arm64") {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export async function installAgent(
|
|||
|
||||
if (isTLS) {
|
||||
downloadPath = await tc.downloadTool(
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.0/harden-runner_1.8.0_linux_${variant}.tar.gz`,
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.1/harden-runner_1.8.1_linux_${variant}.tar.gz`,
|
||||
undefined,
|
||||
auth
|
||||
);
|
||||
|
|
@ -69,6 +69,60 @@ export async function installAgent(
|
|||
return true;
|
||||
}
|
||||
|
||||
export async function installAgentBravo(configStr: string): Promise<boolean> {
|
||||
// Note: to avoid github rate limiting
|
||||
const token = core.getInput("token", { required: true });
|
||||
const auth = `token ${token}`;
|
||||
|
||||
const variant = process.arch === "x64" ? "amd64" : "arm64";
|
||||
const downloadPath = await tc.downloadTool(
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.1/harden-runner-bravo_1.8.1_linux_${variant}.tar.gz`,
|
||||
undefined,
|
||||
auth
|
||||
);
|
||||
|
||||
if (!verifyChecksum(downloadPath, true, variant, "linux", "bravo")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const extractPath = await tc.extractTar(downloadPath);
|
||||
cp.execFileSync("cp", [path.join(extractPath, "agent"), "/home/agent/agent"]);
|
||||
|
||||
cp.execSync("chmod +x /home/agent/agent");
|
||||
|
||||
fs.writeFileSync("/home/agent/agent.json", configStr);
|
||||
|
||||
const logStream = fs.openSync("/home/agent/agent.stdout", "a");
|
||||
const agentProcess = cp.spawn("sudo", ["/home/agent/agent"], {
|
||||
cwd: "/home/agent",
|
||||
detached: true,
|
||||
stdio: ["ignore", logStream, logStream],
|
||||
});
|
||||
agentProcess.unref();
|
||||
|
||||
const agentStatus = "/home/agent/agent.status";
|
||||
const deadline = Date.now() + 10000;
|
||||
while (true) {
|
||||
if (!fs.existsSync(agentStatus)) {
|
||||
if (Date.now() >= deadline) {
|
||||
console.log("timed out waiting for bravo agent");
|
||||
if (fs.existsSync("/home/agent/agent.stdout")) {
|
||||
console.log(fs.readFileSync("/home/agent/agent.stdout", "utf-8"));
|
||||
}
|
||||
if (fs.existsSync("/home/agent/agent.log")) {
|
||||
console.log(fs.readFileSync("/home/agent/agent.log", "utf-8"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
} else {
|
||||
console.log(fs.readFileSync(agentStatus, "utf-8"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function installMacosAgent(configStr: string): Promise<boolean> {
|
||||
const token = core.getInput("token", { required: true });
|
||||
const auth = `token ${token}`;
|
||||
|
|
@ -89,7 +143,7 @@ export async function installMacosAgent(configStr: string): Promise<boolean> {
|
|||
|
||||
// Download installer package
|
||||
const downloadUrl =
|
||||
"https://github.com/step-security/agent-releases/releases/download/v0.0.4-mac/macos-installer-0.0.4.tar.gz";
|
||||
"https://github.com/step-security/agent-releases/releases/download/v0.0.5-mac/macos-installer-0.0.5.tar.gz";
|
||||
core.info(`Downloading macOS installer.. : ${downloadUrl}`);
|
||||
const downloadPath = await tc.downloadTool(downloadUrl, undefined, auth);
|
||||
core.info(`✓ Successfully downloaded installer to: ${downloadPath}`);
|
||||
|
|
|
|||
46
src/setup.ts
46
src/setup.ts
|
|
@ -33,11 +33,12 @@ import {
|
|||
import { isGithubHosted, isTLSEnabled } from "./tls-inspect";
|
||||
import {
|
||||
installAgent,
|
||||
installAgentBravo,
|
||||
installMacosAgent,
|
||||
installWindowsAgent,
|
||||
} from "./install-agent";
|
||||
|
||||
import { chownForFolder, isAgentInstalled, isPlatformSupported, shouldDeployAgentOnSelfHosted } from "./utils";
|
||||
import { chownForFolder, detectThirdPartyRunnerProvider, isAgentInstalled, isPlatformSupported, shouldDeployAgentOnSelfHosted } from "./utils";
|
||||
|
||||
interface MonitorResponse {
|
||||
runner_ip_address?: string;
|
||||
|
|
@ -289,6 +290,13 @@ interface MonitorResponse {
|
|||
const runnerName = process.env.RUNNER_NAME || "";
|
||||
core.info(`RUNNER_NAME: ${runnerName}`);
|
||||
if (!isGithubHosted()) {
|
||||
const thirdPartyProvider = detectThirdPartyRunnerProvider();
|
||||
if (thirdPartyProvider) {
|
||||
core.info(`Detected ${thirdPartyProvider} runner environment. Installing agent-bravo.`);
|
||||
await installAgentForBravo(context.repo.owner, confg);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${EOL}`, {
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
|
@ -528,3 +536,39 @@ export async function installAgentForSelfHosted(owner: string, confg: Configurat
|
|||
console.log(`Failed to install agent for self-hosted runner: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function installAgentForBravo(owner: string, confg: Configuration) {
|
||||
try {
|
||||
console.log("Installing Harden Runner bravo agent for third-party runner");
|
||||
|
||||
let isTLS = await isTLSEnabled(owner);
|
||||
|
||||
if (!isTLS) {
|
||||
console.log("TLS is not enabled for this organization. Bravo agent installation skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
const bravoConfig = {
|
||||
customer: owner,
|
||||
correlation_id: process.env["RUNNER_NAME"] ?? uuidv4(),
|
||||
working_directory: confg.working_directory,
|
||||
api_url: confg.api_url,
|
||||
api_key: uuidv4(),
|
||||
allowed_endpoints: confg.allowed_endpoints,
|
||||
egress_policy: confg.egress_policy,
|
||||
disable_telemetry: confg.disable_telemetry,
|
||||
disable_sudo: confg.disable_sudo,
|
||||
disable_sudo_and_containers: confg.disable_sudo_and_containers,
|
||||
disable_file_monitoring: confg.disable_file_monitoring,
|
||||
is_github_hosted: true,
|
||||
};
|
||||
const bravoConfigStr = JSON.stringify(bravoConfig);
|
||||
|
||||
cp.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
|
||||
await installAgentBravo(bravoConfigStr);
|
||||
} catch (error) {
|
||||
console.log(`Failed to install bravo agent: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
src/utils.ts
11
src/utils.ts
|
|
@ -40,6 +40,17 @@ export function shouldDeployAgentOnSelfHosted(
|
|||
return deployOnSelfHostedVm && !isContainer && !agentAlreadyInstalled;
|
||||
}
|
||||
|
||||
export type ThirdPartyRunnerProvider = "depot" | "namespace" | "warp" | "blacksmith";
|
||||
|
||||
export function detectThirdPartyRunnerProvider(): ThirdPartyRunnerProvider | null {
|
||||
if (process.env["DEPOT_RUNNER"] === "1") return "depot";
|
||||
if (process.env["NAMESPACE_GITHUB_RUNTIME"]) return "namespace";
|
||||
const runnerName = process.env["RUNNER_NAME"] ?? "";
|
||||
if (runnerName.startsWith("warp-")) return "warp";
|
||||
if (runnerName.startsWith("blacksmith-")) return "blacksmith";
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getAnnotationLogs(platform: NodeJS.Platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue