Skip to content

Commit 06f5b5a

Browse files
committed
Merge pull request #3736 from elixir-lang/emj-csv-sign
Fetch archive/escript with version in filename
2 parents ae61d0a + e04ea0c commit 06f5b5a

File tree

4 files changed

+121
-11
lines changed

4 files changed

+121
-11
lines changed

lib/mix/lib/mix/local.ex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ defmodule Mix.Local do
7676

7777
@doc """
7878
Fetches the given signed CSV files, verify and return the matching
79-
Elixir version with checksum.
79+
Elixir version, artifact version and artifact's checksum.
8080
8181
Used to install both Rebar and Hex from S3.
8282
"""
83-
def find_matching_elixir_version_from_signed_csv!(name, path) do
83+
def find_matching_versions_from_signed_csv!(name, path) do
8484
csv = read_path!(name, path)
8585

8686
signature =
@@ -96,7 +96,8 @@ defmodule Mix.Local do
9696
Mix.raise "Could not install #{name} because Mix could not verify authenticity " <>
9797
"of metadata file at #{path}. This may happen because a proxy or some " <>
9898
"entity is interfering with the download or because you don't have a " <>
99-
"public key to verify the download"
99+
"public key to verify the download. Add the corresponding public key " <>
100+
"or try again later"
100101
end
101102
end
102103

@@ -125,9 +126,9 @@ defmodule Mix.Local do
125126
|> Enum.find_value(entries, &find_version(&1, current_version))
126127
end
127128

128-
defp find_version([_, digest|versions], current_version) do
129+
defp find_version([artifact_version, digest|versions], current_version) do
129130
if version = Enum.find(versions, &Version.compare(&1, current_version) != :gt) do
130-
{version, digest}
131+
{version, artifact_version, digest}
131132
end
132133
end
133134
end

lib/mix/lib/mix/tasks/local.hex.ex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule Mix.Tasks.Local.Hex do
33

44
@hex_s3 "https://s3.amazonaws.com/s3.hex.pm"
55
@hex_list_url @hex_s3 <> "/installs/hex-1.x.csv"
6-
@hex_archive_url @hex_s3 <> "/installs/[VERSION]/hex.ez"
6+
@hex_archive_url @hex_s3 <> "/installs/[ELIXIR_VERSION]/hex-[HEX_VERSION].ez"
77

88
@shortdoc "Installs Hex locally"
99

@@ -19,8 +19,14 @@ defmodule Mix.Tasks.Local.Hex do
1919
"""
2020
@spec run(OptionParser.argv) :: boolean
2121
def run(args) do
22-
{version, sha512} = Mix.Local.find_matching_elixir_version_from_signed_csv!("Hex", @hex_list_url)
23-
url = String.replace(@hex_archive_url, "[VERSION]", version)
22+
{elixir_version, hex_version, sha512} =
23+
Mix.Local.find_matching_versions_from_signed_csv!("Hex", @hex_list_url)
24+
25+
url =
26+
@hex_archive_url
27+
|> String.replace("[ELIXIR_VERSION]", elixir_version)
28+
|> String.replace("[HEX_VERSION]", hex_version)
29+
2430
Mix.Tasks.Archive.Install.run [url, "--sha512", sha512 | args]
2531
end
2632
end

lib/mix/lib/mix/tasks/local.rebar.ex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule Mix.Tasks.Local.Rebar do
33

44
@rebar_s3 "https://s3.amazonaws.com/s3.hex.pm"
55
@rebar_list_url @rebar_s3 <> "/installs/rebar-1.x.csv"
6-
@rebar_escript_url @rebar_s3 <> "/installs/[VERSION]/rebar"
6+
@rebar_escript_url @rebar_s3 <> "/installs/[ELIXIR_VERSION]/rebar-[REBAR_VERSION]"
77

88
@shortdoc "Installs rebar locally"
99

@@ -68,8 +68,14 @@ defmodule Mix.Tasks.Local.Rebar do
6868
end
6969

7070
defp install_from_s3(opts) do
71-
{version, sha512} = Mix.Local.find_matching_elixir_version_from_signed_csv!("Rebar", @rebar_list_url)
72-
url = String.replace(@rebar_escript_url, "[VERSION]", version)
71+
{elixir_version, rebar_version, sha512} =
72+
Mix.Local.find_matching_versions_from_signed_csv!("Rebar", @rebar_list_url)
73+
74+
url =
75+
@rebar_escript_url
76+
|> String.replace("[ELIXIR_VERSION]", elixir_version)
77+
|> String.replace("[REBAR_VERSION]", rebar_version)
78+
7379
install_from_path(url, Keyword.put(opts, :sha512, sha512))
7480
end
7581
end

lib/mix/test/mix/local_test.exs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
Code.require_file "../test_helper.exs", __DIR__
2+
3+
defmodule Mix.LocalTest do
4+
use MixTest.Case, async: true
5+
6+
# openssl rsa -in elixirest.pem -pubout > elixirest.pub
7+
@public_key """
8+
-----BEGIN PUBLIC KEY-----
9+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA37moKP1dGGLhsP3d8Fwv
10+
W25SoYZUY2K+Iq7A0OBV36Rnb8yW3BWjfh5YtmPvUCfYUbNCW2HTMMgBntkQ4YmN
11+
B9tHVZazl2uX9lGCfZZPFc/9umvKRojCPkMN81MfTxqnY0oaLHr6DB86RsWHB+ld
12+
782Xf+nd9q3LFdUl8SGlKX7uzfVWd4EWYNcL7aLeLSupZWeNg8uVmY3zua0EgIlQ
13+
XryalIOZb/R+pwprWZoftCl+20FGYi/mJpo/idFtXsR0sJKF4X0W3NORT9RIRbs9
14+
WdjiFi+eIP7Nm8KSF4pbaXCqSmVf9cgvUuGTxc9/P5GcIPAlkcsSrE5peLyUCk5f
15+
2QIDAQAB
16+
-----END PUBLIC KEY-----
17+
"""
18+
19+
# openssl genrsa -aes256 -out elixirtest.pem -passout stdin 2048
20+
@private_key """
21+
-----BEGIN RSA PRIVATE KEY-----
22+
Proc-Type: 4,ENCRYPTED
23+
DEK-Info: AES-256-CBC,48BA5153DA2F120ECE063B33C1204A49
24+
25+
5gp3daNWujH7o9S/dJQEt9TYTRP0pPZtU55PlZrzWt52optr7XHW/ENOm84g5J70
26+
QCPELp12jfQsNiPwbVWXKy2zD3QlNiAelf65hqLWJTWli7XIXfdP46VXOu67OKf9
27+
Ziw4HQ+AdBEwFt20wJst77iy17sNlyxp5DhNDonnSizzIowgUAJkoNI5aBUU6D8X
28+
KTSIftZW35Z4SudkazdoHepEfItZTI8mB4rvfn71Q4oOBA1rAuUUmdPWoPBfUHDa
29+
hvIp2T2Q8zZYqm0+SjDxZUYOOreE7fuf5NSLhHHt7+jyWQmtaVxnOWms72G+9xT0
30+
NGmOEB0WEg1kBsUbYOXXwyCAZhNA6MaKCtgjQczRTK+geS1xNaFc9FDEk3ZjN4Z8
31+
PxrKQoqo+2aQGVcatZWCom80Dci3bIv7iZNA/y1rjfBn+MeitMOGscP7/CBrJAbI
32+
bh1mvCu0McSnqlN0a+EuCVfJQYFMzjibpRVzKAST0QeaxXd5QxHfcPFPBLOpiVWc
33+
NjHaZsHORyoJbUKGA4rgOiSB63mv7SDRA2mvxWpwV/+6MuwBah6t6CGoEsAr1Hbn
34+
1ySt5w27bw3QEf2KTiuxDubo8UrF0eYzP5A9MH8vRpSRZHg8T3SBVfPJ/pM16Lnn
35+
5BaMUdxDFJeet5HUYoke9Zm3udh2BvwGiKhzc9Pbw/EcsCcvChMimRTasqTaRf+S
36+
uIm0Un7o+7kTuvBo2y87j2urCEUzft5QqEynbkR7p3vZnwoLLj+supXh3V8ivW4s
37+
Z6ql+ukRcWd/ode+lbSiYfAJCLc1tCqJ3kTnMnADJBlL0TX7YnwBwWuwwPuZgeAv
38+
F6nnBE1SBQ1WK+bjSVzIqmNFqsZw34wgpnz2heX0q8msF5pzd6EIeA+uz86k8XYh
39+
4eVZYGXxa4Exodh/MqEpRuN1ytWDXvHULh0gml7xwZC3R50UD8uBNt5RGjXUkjXc
40+
V0atKuvgzVlsB4xbDhVP7EVYHBF02NfNOsvo7kh0Yl1IcT/42UaCGYuU1o9zotPv
41+
9b3SHz/HOmBVj2uCdR5XZ4EolP5Iv9vqIDt9DsuDpOyO+AFOww0FnJNCQ1Hmfb0T
42+
qBYPv994oSPYLCGR4a8i/xfmmV8KbAIVEgK3AMbz8RxKr3WBWXWnzQdr4+y4EG24
43+
hSnR52XQ42edv/fkqf9ez+fKNQ9i7PtlPE96Q21NeLMNKHh43X8hJFDh+oPz3Aio
44+
YSNMCZnoyRdrjBRCsVBpnyoLmuhWwG9RlcrEj3G0BxYPh/weaBOAKAHjSr28yuUj
45+
yIa8uddszC6XHSiVUgu7SGO8gQmq++eNdckjX/pEug5MjcWLUqaUg6+YLFWY6NLf
46+
uDPOYuivq7ErtKTvP2xl3TBEDKhdfqxA2+RFxbBDmKjffZnRkcknQsxhlzAdbg22
47+
Jwa2B1nrfjJpX5F+1Av2jHQGbIKMqZzv8fo1binMKpptFzokbWEOjcPCb3tPuomG
48+
ZRkW3qO2pdyYX2N7VXYG9tGi2HrN/oFrWnHPoYF23v85V8WxNkODOCpTz85e6R5v
49+
PVu+FCNFj5weEOTRhtEQyJo7mU5qIRwYeZvVxiC6W+XeFs95wdBE/Lvpg8yZ8D9d
50+
-----END RSA PRIVATE KEY-----
51+
"""
52+
53+
@csv """
54+
1.2.5,ABC,0.9.0
55+
1.2.3,DEF,1.0.0
56+
1.2.4,GHI,1.0.0
57+
"""
58+
59+
# openssl dgst -sha512 -sign elixirtest.pem hex-1.x.csv | openssl base64 > elixirtest.csv.signed
60+
@csv_signed """
61+
VRydmXOdEXQcKJu/SK/nKnE00T+s/T4mpXrYROMSXhD/s8ClvdimnGg61ie3YBS6
62+
LXOjlEhbtMHRM2rTOUvv4z7FcyzwvSxSjunlVi2g3c1pVOZ78MonnYhGb44tZw/q
63+
SOVmV+jJhc9EZFMIAAM3plMoyssyw2pMh7ZB/DxCQTIem3Qf0Ujzc2bYkLVlw7R+
64+
1Rn6dcYEgCzyldVkAUMaYBwieyweWALA+YVDCMudJJK2J7p1OnuoPSVV+N3OkB/Z
65+
T6Jj5ljD+54XnuxAMcgCoF9lpOwXscnw/Ma+8JqIoWo0jNFE3ji+8dGCUzQUdSe8
66+
llLXgJJE2tGpDhEXBA3idg==
67+
"""
68+
69+
setup_all do
70+
File.mkdir_p!(Mix.PublicKey.public_keys_path)
71+
72+
Path.join(Mix.PublicKey.public_keys_path, "test_key.pub")
73+
|> File.write!(@public_key)
74+
end
75+
76+
test "select correct versions from csv" do
77+
in_tmp "select correct versions from csv", fn ->
78+
File.write!("csv", @csv)
79+
File.write!("csv.signed", @csv_signed)
80+
81+
assert {"1.0.0", "1.2.4", "GHI"} =
82+
Mix.Local.find_matching_versions_from_signed_csv!("name", "csv")
83+
end
84+
end
85+
86+
test "raise on bad signature" do
87+
in_tmp "raise on bad signature", fn ->
88+
csv_signed = String.replace(@csv_signed, "VRy", "BAD")
89+
File.write!("csv", @csv)
90+
File.write!("csv.signed", csv_signed)
91+
92+
assert_raise Mix.Error, fn ->
93+
Mix.Local.find_matching_versions_from_signed_csv!("name", "csv")
94+
end
95+
end
96+
end
97+
end

0 commit comments

Comments
 (0)