Skip to content
This repository was archived by the owner on Oct 13, 2023. It is now read-only.

Commit bde3069

Browse files
committed
Signature verification of the downloaded files
1 parent db7cf7a commit bde3069

File tree

6 files changed

+76
-34
lines changed

6 files changed

+76
-34
lines changed

action.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'rust-cargo-install'
2-
description: '"Install a Rust binary as fast as possible'
2+
description: 'Install a Rust binary as fast as possible'
33
author: 'actions-rs team'
44
branding:
55
icon: play-circle
@@ -13,6 +13,16 @@ inputs:
1313
required: false
1414
default: 'latest'
1515

16+
# These inputs are not used/implemented yet
17+
use-tool-cache:
18+
description: Use tool cache to speed up installation (not used yet)
19+
required: false
20+
default: false
21+
use-cache:
22+
description: Store installed binary in the GitHub Actions cache (not used yet)
23+
required: false
24+
default: true
25+
1626
runs:
1727
using: 'node12'
1828
main: 'dist/index.js'

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
"dependencies": {
3131
"@actions-rs/core": "0.0.9",
3232
"@actions/core": "^1.2.3",
33+
"@actions/exec": "^1.0.3",
3334
"@actions/http-client": "^1.0.6",
34-
"@actions/tool-cache": "^1.3.3",
35-
"which": "^2.0.2"
35+
"@actions/tool-cache": "^1.3.3"
3636
},
3737
"devDependencies": {
3838
"@types/jest": "^25.1.4",

public.pem

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsWm/fSobUwf2FmPEVNgT
3+
h4k5DBCiBEhrGmPladEExygSwB3v3r0Qt5075uCsI+OCk39Onp5z2MB0QNUxVUFZ
4+
cCqLRh58/NYfnpakyZEzcwjitHVBRSPkpheWIMw+dHzIc6kcxJrS0TDI3qzryFBD
5+
gT1uISYlCGjoTw2UskFpFcZiEf0K+xsIFe4Fky1sqyX0HNzng+FdSb7Qav60VExS
6+
RAcqF38VTU1yxdvTrxAa+0Stb9bUqQG3FoJsWxsFmElkM7g+YpINQLSOOixRSr+u
7+
yeOlMmYQmF64XdFl2lwj4e3xLIp5ha7qhaEOFHZMHkMSvvR9o9BGN4RUNXSSM7N5
8+
pnB5CrOj2E3rnLQwsTjqyU6qQhdaA4T3pks2d9gfR313pYM/XF6g4SnjRQkgMNq7
9+
/lG11hxap8ugvF98mVbYCzN46qH7ax1Ent+JqKSv0WNou0C4lognM1RiKbUPp257
10+
MVz74xPp2cD0MZkPdFb40QqBSGGNDzilUVVVjc4/KqDgQvk99gk3OJYij3IWkfKP
11+
rf6Jd2SJWectoNFRY8PpZiiOYlFPJ/y1VMbx7NuY3w3kkzCI+FbrwAdzEpv1WrBK
12+
dwZxpLha7uq+DzlLPMvYT+J8gLQRhAwgJ6ztXGibyV/t5vm0ZS/9dX5X4DKkmSCr
13+
gOkQxnGLs0Qze8UK4nj+ebUCAwEAAQ==
14+
-----END PUBLIC KEY-----

src/download.ts

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,28 @@ import { promises as fs } from "fs";
33
import path from "path";
44

55
import * as core from "@actions/core";
6+
import * as exec from "@actions/exec";
67
import * as tc from "@actions/tool-cache";
78
import * as http from "@actions/http-client";
89

10+
const CLOUDFRONT_ROOT = "https://d1ad61wkrfbmp3.cloudfront.net";
11+
// Path, assuming we are executing from the repo root
12+
const CACHE_PUBLIC_KEY = "public.pem";
13+
914
function getRunner(): string {
1015
const platform = os.platform() as string;
1116
switch (platform) {
12-
case "windows":
17+
case "win32":
1318
return "windows-2019";
1419
case "darwin":
1520
return "macos-10.15";
1621
case "linux":
17-
// TODO: Handle `ubuntu-16.04`
18-
return "ubuntu-18.04";
22+
// TODO: Is there better way to determine Actions runner OS?
23+
if (os.release().startsWith("4.15")) {
24+
return "ubuntu-16.04";
25+
} else {
26+
return "ubuntu-18.04";
27+
}
1928
default:
2029
throw new Error("Unsupported OS");
2130
}
@@ -24,7 +33,7 @@ function getRunner(): string {
2433
function getExt(): string {
2534
const platform = os.platform() as string;
2635
switch (platform) {
27-
case "windows":
36+
case "win32":
2837
return ".exe";
2938
default:
3039
return "";
@@ -46,27 +55,12 @@ async function resolveVersion(crate: string): Promise<string> {
4655
}
4756

4857
function buildUrl(crate: string, version: string): string {
49-
/**
50-
* !!! READ THIS IMPORTANT NOTICE !!!
51-
*
52-
* In case you want to use that binary cache bucket
53-
* for your purposes, please, don't do that.
54-
*
55-
* It is strictly private and intended to be used
56-
* by `@actions-rs` only.
57-
* There are no stable folders, naming structure,
58-
* bucket name or even the AWS region used.
59-
* You are not doing yourself better
60-
* by trying to trick everyone, just stop right now.
61-
*/
62-
const s3Region = "us-east-2";
63-
const s3Bucket = "actions-rs.install.binary-cache";
6458
const runner = getRunner();
6559
const ext = getExt();
6660

6761
core.debug(`Determined current Actions runner OS: ${runner}`);
6862

69-
return `https://s3.${s3Region}.amazonaws.com/${s3Bucket}/${crate}/${runner}/${crate}-${version}${ext}`;
63+
return `${CLOUDFRONT_ROOT}/${crate}/${runner}/${crate}-${version}${ext}`;
7064
}
7165

7266
function targetPath(crate: string): string {
@@ -76,6 +70,18 @@ function targetPath(crate: string): string {
7670
return path.join(os.homedir(), ".cargo", "bin", filename);
7771
}
7872

73+
async function verify(crate: string, signature: string): Promise<void> {
74+
await exec.exec("openssl", [
75+
"dgst",
76+
"-sha256",
77+
"-verify",
78+
CACHE_PUBLIC_KEY,
79+
"-signature",
80+
signature,
81+
crate,
82+
]);
83+
}
84+
7985
export async function downloadFromCache(
8086
crate: string,
8187
version: string
@@ -86,18 +92,38 @@ export async function downloadFromCache(
8692
core.info(`Newest ${crate} version available at crates.io: ${version}`);
8793
}
8894
const url = buildUrl(crate, version);
95+
const signatureUrl = `${url}.sig`;
96+
8997
const path = targetPath(crate);
98+
const signaturePath = `${path}.sig`;
9099

91100
core.debug(`Constructed S3 URL for ${crate}: ${url}`);
92-
core.info(`Downloading ${crate} == ${version} into ${path}`);
93101

94102
try {
95103
await fs.access(path);
96104

97105
core.warning(`Crate ${crate} already exist at ${path}`);
98106
} catch (error) {
99-
core.debug(`Downloading ${url} into ${path}`);
107+
core.info(`Downloading ${crate} signature into ${signaturePath}`);
108+
await tc.downloadTool(signatureUrl, signaturePath);
109+
110+
core.info(`Downloading ${crate} == ${version} into ${path}`);
100111
await tc.downloadTool(url, path);
112+
113+
try {
114+
core.info("Starting signature verification process");
115+
await verify(path, signaturePath);
116+
} catch (error) {
117+
core.warning(
118+
`Unable to validate signature for downloaded ${crate}!`
119+
);
120+
121+
// Remove downloaded files, as they are now considered dangerous now
122+
await fs.unlink(path);
123+
await fs.unlink(signaturePath);
124+
throw error;
125+
}
126+
101127
await fs.chmod(path, 0o755);
102128
}
103129
}

0 commit comments

Comments
 (0)