Compare commits

...
19 Commits
Author SHA1 Message Date
Varun Sharma 1bc9dd9157 Merge pull request #630 from sailikhith-stepsecurity/win_agent
Update sha reference for windows agent
2026-01-23 10:40:19 -08:00
sailikhith-stepsecurity c5b9cdae75 update sha reference 2026-01-24 00:07:08 +05:30
Varun Sharma a72fb98737 Merge pull request #629 from sailikhith-stepsecurity/win_agent
Update SHA reference to windows agent
2026-01-22 23:47:35 -08:00
sailikhith-stepsecurity d9e4f5adfc remove sha256 prefix from Windows agent checksum 2026-01-23 13:04:27 +05:30
sailikhith-stepsecurity 5b9a29627b Updated sha reference 2026-01-23 13:01:22 +05:30
Varun Sharma 726ed13970 Merge pull request #626 from sailikhith-stepsecurity/win_agent
Add support for monitoring wf runs on windows
2026-01-20 19:10:27 -08:00
sailikhith-stepsecurity 35cc9f998f resolve review comments 2026-01-19 22:22:07 +05:30
sailikhith-stepsecurity a092fc63bd updated commitsha 2026-01-19 15:18:59 +05:30
sailikhith-stepsecurity c54c9a4406 add build changes 2026-01-19 15:00:49 +05:30
sailikhith-stepsecurity d11b063e55 add functionality to download agent from github and update checksum 2026-01-19 14:59:10 +05:30
sailikhith-stepsecurity 276bb94451 Add windows installation changes 2026-01-19 10:00:09 +05:30
Varun Sharma 20cf305ff2 Merge pull request #622 from step-security/feature/custom-property-skip
Feature/custom property skip
2025-12-09 11:28:11 -08:00
Varun Sharma c51e8eeb6c feat: skip agent install and post step on subsequent runs for GitHub-hosted runners 2025-12-07 22:01:18 -08:00
Varun Sharma e152b90204 feat: skip harden-runner based on repository custom property 2025-12-07 21:54:18 -08:00
Varun Sharma ee1faec052 feat: replace skip-harden-runner with skip-on-custom-property input 2025-12-07 21:54:10 -08:00
Varun Sharma 1dc7c17646 feat: add skip-harden-runner input to conditionally skip execution 2025-12-07 21:54:01 -08:00
Varun Sharma df199fb7be Merge pull request #620 from step-security/rc-29
Release v2.13.3
2025-12-01 20:45:08 -08:00
Varun Sharma 03d096a772 update agent 2025-11-30 21:07:45 -08:00
Varun Sharma 40901073af fix: update agent 2025-11-30 07:46:48 -08:00
12 changed files with 9123 additions and 138 deletions
+4291 -2
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+4421 -43
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+107 -20
View File
@@ -85250,6 +85250,7 @@ function addSummary() {
const STATUS_HARDEN_RUNNER_UNAVAILABLE = "409";
const CONTAINER_MESSAGE = "This job is running in a container. Such jobs can be monitored by installing Harden Runner in a custom VM image for GitHub-hosted runners.";
const UBUNTU_MESSAGE = "This job is not running in a GitHub Actions Hosted Runner Ubuntu VM. Harden Runner is only supported on Ubuntu VM. This job will not be monitored.";
const UNSUPPORTED_PLATFORM_MESSAGE = "This job is not running on a supported platform. Harden Runner supports Linux (Ubuntu) and Windows runners. This job will not be monitored.";
const SELF_HOSTED_RUNNER_MESSAGE = "This job is running on a self-hosted runner.";
const HARDEN_RUNNER_UNAVAILABLE_MESSAGE = "Sorry, we are currently experiencing issues with the Harden Runner installation process. It is currently unavailable.";
const ARC_RUNNER_MESSAGE = "Workflow is currently being executed in ARC based runner.";
@@ -85495,24 +85496,33 @@ var external_crypto_ = __nccwpck_require__(6982);
const CHECKSUMS = {
tls: {
amd64: "603d6a0dabb60a7c8f651d7f5b53258fa64162424a77da9884d9032b3e71d6b1",
arm64: "fdc7504a3210dc67fc8393969b0f3c98df593c7884c83ed6d1c0ec84070801aa",
amd64: "2a5be06ab620340f6957ddd180450caab414671c8b7da1996d8e2755c1cd49fa",
arm64: "e9d0ccf3e4e62ba15ff208ef6e0afa0ad5e323c3dfc50527342f436a85e65a55",
},
non_tls: {
amd64: "336093af8ebe969567b66fd035af3bd4f7e1c723ce680d6b4b5b2a1f79bc329e", // v0.14.2
},
windows: {
amd64: "9e4fde66331be3261ae6ff954e531e94335b5774ac7e105f0126b391ee1c6d66", // v1.0.0-int
},
};
function verifyChecksum(downloadPath, isTLS, variant) {
function verifyChecksum(downloadPath, isTLS, variant, platform) {
const fileBuffer = external_fs_.readFileSync(downloadPath);
const checksum = external_crypto_.createHash("sha256")
.update(fileBuffer)
.digest("hex"); // checksum of downloaded file
let expectedChecksum = "";
if (isTLS) {
expectedChecksum = CHECKSUMS["tls"][variant];
}
else {
expectedChecksum = CHECKSUMS["non_tls"][variant];
switch (platform) {
case "linux":
expectedChecksum = isTLS
? CHECKSUMS["tls"][variant]
: CHECKSUMS["non_tls"][variant];
break;
case "win32":
expectedChecksum = CHECKSUMS["windows"][variant];
break;
default:
throw new Error(`Unsupported platform: ${platform}`);
}
if (checksum !== expectedChecksum) {
lib_core.setFailed(`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`);
@@ -85549,7 +85559,7 @@ function installAgent(isTLS, configStr) {
encoding: "utf8",
});
if (isTLS) {
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.7.6/harden-runner_1.7.6_linux_${variant}.tar.gz`, undefined, auth);
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.7.9/harden-runner_1.7.9_linux_${variant}.tar.gz`, undefined, auth);
}
else {
if (variant === "arm64") {
@@ -85558,7 +85568,7 @@ function installAgent(isTLS, configStr) {
}
downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.14.2/agent_0.14.2_linux_amd64.tar.gz", undefined, auth);
}
verifyChecksum(downloadPath, isTLS, variant);
verifyChecksum(downloadPath, isTLS, variant, process.platform);
const extractPath = yield tool_cache.extractTar(downloadPath);
let cmd = "cp", args = [external_path_.join(extractPath, "agent"), "/home/agent/agent"];
external_child_process_.execFileSync(cmd, args);
@@ -85576,6 +85586,59 @@ function installAgent(isTLS, configStr) {
return true;
});
}
function installWindowsAgent(configStr) {
return install_agent_awaiter(this, void 0, void 0, function* () {
const token = lib_core.getInput("token", { required: true });
const auth = `token ${token}`;
const variant = process.arch === "x64" ? "amd64" : "arm64";
if (variant === "arm64") {
console.log(ARM64_RUNNER_MESSAGE);
return false;
}
const agentDir = "C:\\agent";
lib_core.info(`Creating agent directory: ${agentDir}`);
if (!external_fs_.existsSync(agentDir)) {
external_fs_.mkdirSync(agentDir, { recursive: true });
}
external_fs_.appendFileSync(process.env.GITHUB_STATE, `agentDir=${agentDir}${external_os_.EOL}`, {
encoding: "utf8",
});
const agentExePath = external_path_.join(agentDir, "agent.exe");
const downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-releases/releases/download/v1.0.0-int/harden-runner-agent-windows_int_windows_amd64.tar.gz `, undefined, auth);
verifyChecksum(downloadPath, false, variant, process.platform);
const extractPath = yield tool_cache.extractTar(downloadPath);
const extractedAgentPath = external_path_.join(extractPath, "agent.exe");
external_fs_.copyFileSync(extractedAgentPath, agentExePath);
lib_core.info(`Copied agent from ${extractedAgentPath} to ${agentExePath}`);
const configPath = external_path_.join(agentDir, "config.json");
external_fs_.writeFileSync(configPath, configStr);
lib_core.info(`Created config file: ${configPath}`);
lib_core.info("Starting Windows Agent...");
try {
const logPath = external_path_.join(agentDir, "agent.log");
const logStream = external_fs_.openSync(logPath, 'a');
lib_core.info(`Agent logs will be written to: ${logPath}`);
const agentProcess = external_child_process_.spawn(agentExePath, [], {
cwd: agentDir,
detached: true,
stdio: ['ignore', logStream, logStream],
windowsHide: false,
shell: false
});
const pidFile = external_path_.join(agentDir, "agent.pid");
external_fs_.writeFileSync(pidFile, agentProcess.pid.toString());
lib_core.info(`Agent process started with PID: ${agentProcess.pid}`);
lib_core.info(`PID saved to: ${pidFile}`);
agentProcess.unref();
lib_core.info("Windows Agent process started successfully");
return true;
}
catch (error) {
lib_core.setFailed(`Failed to start Windows agent process: ${error.message}`);
return false;
}
});
}
;// CONCATENATED MODULE: ./src/setup.ts
var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
@@ -85609,11 +85672,16 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
(() => setup_awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
var _a, _b, _c, _d;
try {
console.log("[harden-runner] pre-step");
if (process.platform !== "linux") {
console.log(UBUNTU_MESSAGE);
const customProperties = ((_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.custom_properties) || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux" && process.platform !== "win32") {
console.log(UNSUPPORTED_PLATFORM_MESSAGE);
return;
}
if (isGithubHosted() && isDocker()) {
@@ -85635,7 +85703,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
disable_sudo: lib_core.getBooleanInput("disable-sudo"),
disable_sudo_and_containers: lib_core.getBooleanInput("disable-sudo-and-containers"),
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: ((_d = (_c = github.context === null || github.context === void 0 ? void 0 : github.context.payload) === null || _c === void 0 ? void 0 : _c.repository) === null || _d === void 0 ? void 0 : _d.private) || false,
is_github_hosted: isGithubHosted(),
is_debug: lib_core.isDebug(),
one_time_key: "",
@@ -85775,6 +85843,10 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
}
return;
}
if (isGithubHosted() && external_fs_.existsSync("/home/agent/agent.status")) {
console.log("Agent already installed, skipping installation");
return;
}
let _http = new lib.HttpClient();
let statusCode;
_http.requestOptions = { socketTimeout: 3 * 1000 };
@@ -85811,14 +85883,29 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
return;
}
const confgStr = JSON.stringify(confg);
external_child_process_.execSync("sudo mkdir -p /home/agent");
chownForFolder(process.env.USER, "/home/agent");
let isTLS = yield isTLSEnabled(github.context.repo.owner);
const agentInstalled = yield installAgent(isTLS, confgStr);
// install agent based on platform
let agentInstalled = false;
let statusFile;
let logFile;
if (process.platform === "win32") {
// Windows installation
lib_core.info("Installing Windows Agent...");
agentInstalled = yield installWindowsAgent(confgStr);
const agentDir = process.env.STATE_agentDir || "C:\\agent";
statusFile = external_path_.join(agentDir, "agent.status");
logFile = external_path_.join(agentDir, "agent.log");
}
else {
// Linux installation
external_child_process_.execSync("sudo mkdir -p /home/agent");
chownForFolder(process.env.USER, "/home/agent");
let isTLS = yield isTLSEnabled(github.context.repo.owner);
agentInstalled = yield installAgent(isTLS, confgStr);
statusFile = "/home/agent/agent.status";
logFile = "/home/agent/agent.log";
}
if (agentInstalled) {
// Check that the file exists locally
var statusFile = "/home/agent/agent.status";
var logFile = "/home/agent/agent.log";
var counter = 0;
while (true) {
if (!external_fs_.existsSync(statusFile)) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+18 -7
View File
@@ -4,18 +4,22 @@ import * as fs from "fs";
const CHECKSUMS = {
tls: {
amd64: "603d6a0dabb60a7c8f651d7f5b53258fa64162424a77da9884d9032b3e71d6b1", // v1.7.6
arm64: "fdc7504a3210dc67fc8393969b0f3c98df593c7884c83ed6d1c0ec84070801aa",
amd64: "2a5be06ab620340f6957ddd180450caab414671c8b7da1996d8e2755c1cd49fa", // v1.7.9
arm64: "e9d0ccf3e4e62ba15ff208ef6e0afa0ad5e323c3dfc50527342f436a85e65a55",
},
non_tls: {
amd64: "336093af8ebe969567b66fd035af3bd4f7e1c723ce680d6b4b5b2a1f79bc329e", // v0.14.2
},
windows: {
amd64: "9e4fde66331be3261ae6ff954e531e94335b5774ac7e105f0126b391ee1c6d66", // v1.0.0-int
},
};
export function verifyChecksum(
downloadPath: string,
isTLS: boolean,
variant: string
variant: string,
platform: string
) {
const fileBuffer: Buffer = fs.readFileSync(downloadPath);
const checksum: string = crypto
@@ -25,10 +29,17 @@ export function verifyChecksum(
let expectedChecksum: string = "";
if (isTLS) {
expectedChecksum = CHECKSUMS["tls"][variant];
} else {
expectedChecksum = CHECKSUMS["non_tls"][variant];
switch (platform) {
case "linux":
expectedChecksum = isTLS
? CHECKSUMS["tls"][variant]
: CHECKSUMS["non_tls"][variant];
break;
case "win32":
expectedChecksum = CHECKSUMS["windows"][variant];
break;
default:
throw new Error(`Unsupported platform: ${platform}`);
}
if (checksum !== expectedChecksum) {
+157 -50
View File
@@ -1,14 +1,22 @@
import * as fs from "fs";
import * as cp from "child_process";
import * as path from "path";
import * as common from "./common";
import isDocker from "is-docker";
import { isARCRunner } from "./arc-runner";
import { isGithubHosted } from "./tls-inspect";
import { context } from "@actions/github";
(async () => {
console.log("[harden-runner] post-step");
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux" && process.platform !== "win32") {
console.log(common.UNSUPPORTED_PLATFORM_MESSAGE);
return;
}
if (isGithubHosted() && isDocker()) {
@@ -29,7 +37,9 @@ import { isGithubHosted } from "./tls-inspect";
return;
}
if (process.env.STATE_isTLS === "false" && process.arch === "arm64") {
if (process.platform === "linux" && process.env.STATE_isTLS === "false" && process.arch === "arm64") {
return;
} else if (process.platform === "win32" && process.arch === "arm64") {
return;
}
@@ -40,66 +50,163 @@ import { isGithubHosted } from "./tls-inspect";
console.log(common.HARDEN_RUNNER_UNAVAILABLE_MESSAGE);
return;
}
if (process.platform === "linux") {
if (isGithubHosted() && fs.existsSync("/home/agent/post_event.json")) {
console.log("Post step already executed, skipping");
return;
}
fs.writeFileSync(
"/home/agent/post_event.json",
JSON.stringify({ event: "post" })
);
fs.writeFileSync(
"/home/agent/post_event.json",
JSON.stringify({ event: "post" })
);
const doneFile = "/home/agent/done.json";
let counter = 0;
while (true) {
if (!fs.existsSync(doneFile)) {
counter++;
if (counter > 10) {
console.log("timed out");
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);
} // The file *does* exist
else {
break;
}
await sleep(1000);
} // The file *does* exist
else {
break;
}
}
const log = "/home/agent/agent.log";
if (fs.existsSync(log)) {
console.log("log:");
var content = fs.readFileSync(log, "utf-8");
console.log(content);
}
const log = "/home/agent/agent.log";
if (fs.existsSync(log)) {
console.log("log:");
const content = fs.readFileSync(log, "utf-8");
console.log(content);
}
const daemonLog = "/home/agent/daemon.log";
if (fs.existsSync(daemonLog)) {
console.log("daemonLog:");
var content = fs.readFileSync(daemonLog, "utf-8");
console.log(content);
}
const daemonLog = "/home/agent/daemon.log";
if (fs.existsSync(daemonLog)) {
console.log("daemonLog:");
const content = fs.readFileSync(daemonLog, "utf-8");
console.log(content);
}
var status = "/home/agent/agent.status";
if (fs.existsSync(status)) {
console.log("status:");
var content = fs.readFileSync(status, "utf-8");
console.log(content);
}
const status = "/home/agent/agent.status";
if (fs.existsSync(status)) {
console.log("status:");
const content = fs.readFileSync(status, "utf-8");
console.log(content);
}
var disable_sudo = process.env.STATE_disableSudo;
var disable_sudo_and_containers = process.env.STATE_disableSudoAndContainers;
const disable_sudo = process.env.STATE_disableSudo;
const disable_sudo_and_containers = process.env.STATE_disableSudoAndContainers;
if (disable_sudo !== "true" && disable_sudo_and_containers !== "true") {
try {
var journalLog = cp.execSync(
"sudo journalctl -u agent.service --lines=1000",
{
encoding: "utf8",
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
if (disable_sudo !== "true" && disable_sudo_and_containers !== "true") {
try {
const journalLog = cp.execSync(
"sudo journalctl -u agent.service --lines=1000",
{
encoding: "utf8",
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
}
);
console.log("agent.service log:");
console.log(journalLog);
} catch (error) {
console.log("Warning: Could not fetch service logs:", error.message);
}
}
} else if (process.platform === "win32") {
// windows cleanup
const agentDir = process.env.STATE_agentDir || "C:\\agent";
const postEventFile = path.join(agentDir, "post_event.json");
if (isGithubHosted() && fs.existsSync(postEventFile)) {
console.log("Windows post step already executed, skipping");
return;
}
const p = cp.spawn(
"powershell.exe",
["-NoProfile", "-NonInteractive", "-Command", "query user; exit $LASTEXITCODE"],
{ stdio: ["ignore", "pipe", "pipe"], shell: false, windowsHide: true }
);
p.unref();
fs.writeFileSync(postEventFile, JSON.stringify({ event: "post" }));
const doneFile = path.join(agentDir, "done.json");
let counter = 0;
while (true) {
if (!fs.existsSync(doneFile)) {
counter++;
if (counter > 10) {
console.log("timed out");
break;
}
);
console.log("agent.service log:");
console.log(journalLog);
await sleep(1000);
} else {
break;
}
}
console.log("stopping windows agent process...");
const pidFile = path.join(agentDir, "agent.pid");
try {
if (!fs.existsSync(pidFile)) {
console.log("PID file not found. Agent may not be running.");
return;
}
const pid = parseInt(fs.readFileSync(pidFile, "utf8").trim());
console.log(`agent PID from file: ${pid}`);
try {
process.kill(pid, 0); // signal 0 just checks if process exists
} catch {
console.log("agent process not running.");
fs.unlinkSync(pidFile);
return;
}
console.log(`stopping agent process (PID: ${pid})...`);
process.kill(pid, 'SIGINT');
let gracefulShutdown = false;
for (let i = 0; i < 10; i++) {
await sleep(1000);
try {
process.kill(pid, 0); // check if still exists
} catch {
gracefulShutdown = true;
console.log("agent process stopped gracefully");
break;
}
}
if (!gracefulShutdown) {
console.log("graceful shutdown timeout (10s), forcing termination...");
process.kill(pid, 'SIGKILL');
console.log("agent process terminated forcefully");
}
if (fs.existsSync(pidFile)) {
fs.unlinkSync(pidFile);
console.log("PID file cleaned up");
}
} catch (error) {
console.log("Warning: Could not fetch service logs:", error.message);
console.log("warning: error stopping agent process:", error.message);
}
const log = path.join(agentDir, "agent.log");
if (fs.existsSync(log)) {
console.log("agent log:");
const content = fs.readFileSync(log, "utf-8");
console.log(content);
}
}
+3
View File
@@ -131,6 +131,9 @@ export const CONTAINER_MESSAGE =
export const UBUNTU_MESSAGE =
"This job is not running in a GitHub Actions Hosted Runner Ubuntu VM. Harden Runner is only supported on Ubuntu VM. This job will not be monitored.";
export const UNSUPPORTED_PLATFORM_MESSAGE =
"This job is not running on a supported platform. Harden Runner supports Linux (Ubuntu) and Windows runners. This job will not be monitored.";
export const SELF_HOSTED_RUNNER_MESSAGE =
"This job is running on a self-hosted runner.";
+9 -2
View File
@@ -3,11 +3,18 @@ import * as core from "@actions/core";
import isDocker from "is-docker";
import { STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted } from "./tls-inspect";
import { context } from "@actions/github";
(async () => {
console.log("[harden-runner] main-step");
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux" && process.platform !== "win32") {
console.log(common.UNSUPPORTED_PLATFORM_MESSAGE);
return;
}
if (isGithubHosted() && isDocker()) {
+77 -2
View File
@@ -25,7 +25,7 @@ export async function installAgent(
if (isTLS) {
downloadPath = await tc.downloadTool(
`https://github.com/step-security/agent-ebpf/releases/download/v1.7.6/harden-runner_1.7.6_linux_${variant}.tar.gz`,
`https://github.com/step-security/agent-ebpf/releases/download/v1.7.9/harden-runner_1.7.9_linux_${variant}.tar.gz`,
undefined,
auth
);
@@ -41,7 +41,7 @@ export async function installAgent(
);
}
verifyChecksum(downloadPath, isTLS, variant);
verifyChecksum(downloadPath, isTLS, variant, process.platform);
const extractPath = await tc.extractTar(downloadPath);
@@ -65,3 +65,78 @@ export async function installAgent(
cp.execSync("sudo service agent start", { timeout: 15000 });
return true;
}
export async function installWindowsAgent(
configStr: string
): Promise<boolean> {
const token = core.getInput("token", { required: true });
const auth = `token ${token}`;
const variant = process.arch === "x64" ? "amd64" : "arm64";
if (variant === "arm64") {
console.log(ARM64_RUNNER_MESSAGE);
return false;
}
const agentDir = "C:\\agent";
core.info(`Creating agent directory: ${agentDir}`);
if (!fs.existsSync(agentDir)) {
fs.mkdirSync(agentDir, { recursive: true });
}
fs.appendFileSync(
process.env.GITHUB_STATE,
`agentDir=${agentDir}${EOL}`,
{
encoding: "utf8",
}
);
const agentExePath = path.join(agentDir, "agent.exe");
const downloadPath = await tc.downloadTool(
`https://github.com/step-security/agent-releases/releases/download/v1.0.0-int/harden-runner-agent-windows_int_windows_amd64.tar.gz `,
undefined,
auth
);
verifyChecksum(downloadPath, false, variant, process.platform);
const extractPath = await tc.extractTar(downloadPath);
const extractedAgentPath = path.join(extractPath, "agent.exe");
fs.copyFileSync(extractedAgentPath, agentExePath);
core.info(`Copied agent from ${extractedAgentPath} to ${agentExePath}`);
const configPath = path.join(agentDir, "config.json");
fs.writeFileSync(configPath, configStr);
core.info(`Created config file: ${configPath}`);
core.info("Starting Windows Agent...");
try {
const logPath = path.join(agentDir, "agent.log");
const logStream = fs.openSync(logPath, 'a');
core.info(`Agent logs will be written to: ${logPath}`);
const agentProcess = cp.spawn(agentExePath, [], {
cwd: agentDir,
detached: true,
stdio: ['ignore', logStream, logStream],
windowsHide: false,
shell: false
});
const pidFile = path.join(agentDir, "agent.pid");
fs.writeFileSync(pidFile, agentProcess.pid.toString());
core.info(`Agent process started with PID: ${agentProcess.pid}`);
core.info(`PID saved to: ${pidFile}`);
agentProcess.unref();
core.info("Windows Agent process started successfully");
return true;
} catch (error) {
core.setFailed(
`Failed to start Windows agent process: ${error.message}`
);
return false;
}
}
+37 -9
View File
@@ -27,7 +27,7 @@ import * as utils from "@actions/cache/lib/internal/cacheUtils";
import { isARCRunner, sendAllowedEndpoints } from "./arc-runner";
import { STEPSECURITY_API_URL, STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted, isTLSEnabled } from "./tls-inspect";
import { installAgent } from "./install-agent";
import { installAgent, installWindowsAgent } from "./install-agent";
interface MonitorResponse {
runner_ip_address?: string;
@@ -39,8 +39,14 @@ interface MonitorResponse {
try {
console.log("[harden-runner] pre-step");
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux" && process.platform !== "win32") {
console.log(common.UNSUPPORTED_PLATFORM_MESSAGE);
return;
}
if (isGithubHosted() && isDocker()) {
@@ -257,6 +263,11 @@ interface MonitorResponse {
return;
}
if (isGithubHosted() && fs.existsSync("/home/agent/agent.status")) {
console.log("Agent already installed, skipping installation");
return;
}
let _http = new httpm.HttpClient();
let statusCode: number | undefined;
_http.requestOptions = { socketTimeout: 3 * 1000 };
@@ -311,17 +322,34 @@ interface MonitorResponse {
}
const confgStr = JSON.stringify(confg);
cp.execSync("sudo mkdir -p /home/agent");
chownForFolder(process.env.USER, "/home/agent");
// install agent based on platform
let agentInstalled = false;
let statusFile: string;
let logFile: string;
let isTLS = await isTLSEnabled(context.repo.owner);
if (process.platform === "win32") {
// Windows installation
core.info("Installing Windows Agent...");
agentInstalled = await installWindowsAgent(confgStr);
const agentInstalled = await installAgent(isTLS, confgStr);
const agentDir = process.env.STATE_agentDir || "C:\\agent";
statusFile = path.join(agentDir, "agent.status");
logFile = path.join(agentDir, "agent.log");
} else {
// Linux installation
cp.execSync("sudo mkdir -p /home/agent");
chownForFolder(process.env.USER, "/home/agent");
let isTLS = await isTLSEnabled(context.repo.owner);
agentInstalled = await installAgent(isTLS, confgStr);
statusFile = "/home/agent/agent.status";
logFile = "/home/agent/agent.log";
}
if (agentInstalled) {
// Check that the file exists locally
var statusFile = "/home/agent/agent.status";
var logFile = "/home/agent/agent.log";
var counter = 0;
while (true) {
if (!fs.existsSync(statusFile)) {