@@ -3,19 +3,28 @@ import { promises as fs } from "fs";
3
3
import path from "path" ;
4
4
5
5
import * as core from "@actions/core" ;
6
+ import * as exec from "@actions/exec" ;
6
7
import * as tc from "@actions/tool-cache" ;
7
8
import * as http from "@actions/http-client" ;
8
9
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
+
9
14
function getRunner ( ) : string {
10
15
const platform = os . platform ( ) as string ;
11
16
switch ( platform ) {
12
- case "windows " :
17
+ case "win32 " :
13
18
return "windows-2019" ;
14
19
case "darwin" :
15
20
return "macos-10.15" ;
16
21
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
+ }
19
28
default :
20
29
throw new Error ( "Unsupported OS" ) ;
21
30
}
@@ -24,7 +33,7 @@ function getRunner(): string {
24
33
function getExt ( ) : string {
25
34
const platform = os . platform ( ) as string ;
26
35
switch ( platform ) {
27
- case "windows " :
36
+ case "win32 " :
28
37
return ".exe" ;
29
38
default :
30
39
return "" ;
@@ -46,27 +55,12 @@ async function resolveVersion(crate: string): Promise<string> {
46
55
}
47
56
48
57
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" ;
64
58
const runner = getRunner ( ) ;
65
59
const ext = getExt ( ) ;
66
60
67
61
core . debug ( `Determined current Actions runner OS: ${ runner } ` ) ;
68
62
69
- return `https://s3. ${ s3Region } .amazonaws.com/ ${ s3Bucket } /${ crate } /${ runner } /${ crate } -${ version } ${ ext } ` ;
63
+ return `${ CLOUDFRONT_ROOT } /${ crate } /${ runner } /${ crate } -${ version } ${ ext } ` ;
70
64
}
71
65
72
66
function targetPath ( crate : string ) : string {
@@ -76,6 +70,18 @@ function targetPath(crate: string): string {
76
70
return path . join ( os . homedir ( ) , ".cargo" , "bin" , filename ) ;
77
71
}
78
72
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
+
79
85
export async function downloadFromCache (
80
86
crate : string ,
81
87
version : string
@@ -86,18 +92,38 @@ export async function downloadFromCache(
86
92
core . info ( `Newest ${ crate } version available at crates.io: ${ version } ` ) ;
87
93
}
88
94
const url = buildUrl ( crate , version ) ;
95
+ const signatureUrl = `${ url } .sig` ;
96
+
89
97
const path = targetPath ( crate ) ;
98
+ const signaturePath = `${ path } .sig` ;
90
99
91
100
core . debug ( `Constructed S3 URL for ${ crate } : ${ url } ` ) ;
92
- core . info ( `Downloading ${ crate } == ${ version } into ${ path } ` ) ;
93
101
94
102
try {
95
103
await fs . access ( path ) ;
96
104
97
105
core . warning ( `Crate ${ crate } already exist at ${ path } ` ) ;
98
106
} 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 } ` ) ;
100
111
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
+
101
127
await fs . chmod ( path , 0o755 ) ;
102
128
}
103
129
}
0 commit comments