Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue to get cache endpoint #253

Merged
merged 2 commits into from Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
452 changes: 251 additions & 201 deletions dist/post/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/post/index.js.map

Large diffs are not rendered by default.

69,442 changes: 62,112 additions & 7,330 deletions dist/pre/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/pre/index.js.map

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "step-security-harden-runner",
"version": "2.2.0",
"version": "2.2.1",
"description": "Security agent for GitHub-hosted runner to monitor the build process",
"main": "index.js",
"scripts": {
Expand All @@ -23,7 +23,7 @@
},
"homepage": "https://github.com/step-security/harden-runner#readme",
"dependencies": {
"@actions/cache": "^3.0.4",
"@actions/cache": "^3.1.4",
"@actions/core": "^1.5.0",
"@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0",
Expand Down
99 changes: 0 additions & 99 deletions src/cache.ts
@@ -1,112 +1,13 @@
import * as core from "@actions/core";
import { HttpClient } from "@actions/http-client";
import { RequestOptions } from "@actions/http-client/lib/interfaces";
import { BearerCredentialHandler } from "@actions/http-client/lib/auth";
import * as crypto from "crypto";

const versionSalt = "1.0";
export const cacheKey = "harden-runner-cacheKey";
export const cacheFile = "/home/agent/cache.txt";

function getCacheApiUrl(resource: string): string {
const baseUrl: string = process.env["ACTIONS_CACHE_URL"] || "";
if (!baseUrl) {
throw new Error("Cache Service Url not found, unable to restore cache.");
}

const url = `${baseUrl}_apis/artifactcache/${resource}`;
core.debug(`Resource Url: ${url}`);
return url;
}

function createAcceptHeader(type: string, apiVersion: string): string {
return `${type};api-version=${apiVersion}`;
}

function getRequestOptions(): RequestOptions {
const token = process.env["ACTIONS_RUNTIME_TOKEN"] || "";

const requestOptions: RequestOptions = {
headers: {
Accept: createAcceptHeader("application/json", "6.0-preview.1"),
Authorization: `Bearer ${token}`,
},
};

return requestOptions;
}

function createHttpClient(): HttpClient {
const token = process.env["ACTIONS_RUNTIME_TOKEN"] || "";
const bhandler = new BearerCredentialHandler(token);
return new HttpClient("actions/cache", [bhandler], getRequestOptions());
}

export function getCacheVersion(
paths: string[],
compressionMethod?: CompressionMethod
): string {
const components = paths.concat(
!compressionMethod || compressionMethod === CompressionMethod.Gzip
? []
: [compressionMethod]
);

// Add salt to cache version to support breaking changes in cache entry
components.push(versionSalt);

return crypto.createHash("sha256").update(components.join("|")).digest("hex");
}

export async function getCacheEntry(
keys: string[],
paths: string[],
options?: InternalCacheOptions
): Promise<ArtifactCacheEntry | null> {
const httpClient = createHttpClient();
const version = getCacheVersion(paths, options?.compressionMethod);
const resource = `cache?keys=${encodeURIComponent(
keys.join(",")
)}&version=${version}`;

const response = await httpClient.getJson<ArtifactCacheEntry>(
getCacheApiUrl(resource)
);
if (response.statusCode === 204) {
throw new Error("Request returned 204 status");
}
if (!isSuccessStatusCode(response.statusCode)) {
throw new Error(`Cache service responded with ${response.statusCode}`);
}

const cacheResult = response.result;
const cacheDownloadUrl = cacheResult?.archiveLocation;
if (!cacheDownloadUrl) {
throw new Error("Cache still be done, but not found.");
}

return cacheResult;
}

export interface InternalCacheOptions {
compressionMethod?: CompressionMethod;
cacheSize?: number;
}

export interface ArtifactCacheEntry {
cacheKey?: string;
scope?: string;
creationTime?: string;
archiveLocation?: string;
}

function isSuccessStatusCode(statusCode?: number): boolean {
if (!statusCode) {
return false;
}
return statusCode >= 200 && statusCode < 300;
}

export enum CompressionMethod {
Gzip = "gzip",
// Long range mode was added to zstd in v1.3.2.
Expand Down
14 changes: 9 additions & 5 deletions src/setup.ts
Expand Up @@ -11,13 +11,16 @@ import isDocker from "is-docker";
import { context } from "@actions/github";
import { EOL } from "os";
import {
cacheFile,
ArtifactCacheEntry,
cacheKey,
cacheFile,
CompressionMethod,
getCacheEntry,
isValidEvent,
} from "./cache";

import {getCacheEntry} from "@actions/cache/lib/internal/cacheHttpClient"
import * as utils from '@actions/cache/lib/internal/cacheUtils'

(async () => {
try {
if (process.platform !== "linux") {
Expand Down Expand Up @@ -90,15 +93,16 @@ import {

if (isValidEvent()) {
try {
const cacheEntry = await getCacheEntry([cacheKey], [cacheFile], {
compressionMethod: CompressionMethod.ZstdWithoutLong,
let compressionMethod:CompressionMethod = await utils.getCompressionMethod()
const cacheEntry:ArtifactCacheEntry = await getCacheEntry([cacheKey], [cacheFile], {
compressionMethod: compressionMethod,
});
const url = new URL(cacheEntry.archiveLocation);
core.info(`Adding cacheHost: ${url.hostname}:443 to allowed-endpoints`);
confg.allowed_endpoints += ` ${url.hostname}:443`;
} catch (exception) {
// some exception has occurred.
core.info("Unable to fetch cacheURL");
core.info(`Unable to fetch cacheURL`);
if (confg.egress_policy === "block") {
core.info("Switching egress-policy to audit mode");
confg.egress_policy = "audit";
Expand Down