diff --git a/Cargo.lock b/Cargo.lock index c942a2b1db..47d78b6e7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,15 @@ name = "antidote" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "argon2rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.4" @@ -116,6 +125,15 @@ name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-buffer" version = "0.3.3" @@ -159,7 +177,6 @@ name = "cargo-registry" version = "0.2.2" dependencies = [ "ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo-registry-s3 0.2.0", "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "civet 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "comrak 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -197,6 +214,9 @@ dependencies = [ "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_core 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_credential 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_s3 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -209,16 +229,6 @@ dependencies = [ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cargo-registry-s3" -version = "0.2.0" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cc" version = "1.0.3" @@ -464,6 +474,15 @@ name = "crossbeam-utils" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crypto-mac" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crypto-mac" version = "0.6.2" @@ -531,9 +550,9 @@ name = "derive-error-chain" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_fmt_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -614,6 +633,16 @@ dependencies = [ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "docopt" version = "0.8.1" @@ -768,6 +797,31 @@ dependencies = [ "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "filetime" version = "0.1.14" @@ -920,6 +974,15 @@ name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "hmac" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hmac" version = "0.6.2" @@ -1235,6 +1298,11 @@ dependencies = [ "digest 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "md5" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "0.1.11" @@ -1574,7 +1642,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.6" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1603,7 +1671,7 @@ name = "quote" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1686,6 +1754,17 @@ dependencies = [ "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_users" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "0.1.80" @@ -1791,6 +1870,55 @@ name = "route-recognizer" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rusoto_core" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_credential 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rusoto_credential" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rusoto_s3" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_core 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.5" @@ -1844,6 +1972,11 @@ name = "scoped-tls" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -1970,6 +2103,17 @@ dependencies = [ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.2.2" @@ -2054,10 +2198,10 @@ dependencies = [ [[package]] name = "syn" -version = "0.14.2" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2070,6 +2214,17 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syntex_fmt_macros" version = "0.5.0" @@ -2592,12 +2747,21 @@ dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xml-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc0ea12b4977283c563e78eaf227b024d89d72a6394040fad4063899bfcfb48" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" +"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" @@ -2608,6 +2772,7 @@ dependencies = [ "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" @@ -2642,6 +2807,7 @@ dependencies = [ "checksum crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3486aefc4c0487b9cb52372c97df0a48b8c249514af1ee99703bf70d2f2ceda1" "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" +"checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958" "checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" "checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c" "checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55" @@ -2657,6 +2823,7 @@ dependencies = [ "checksum diesel_ltree 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5be92b29f9c84222bc20759c0f45e3a0cfb390da8ce98a10a1414894eceafea" "checksum diesel_migrations 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b42c35d1ce9e8d57a3e7001b4127f2bc1b073a89708bb7019f5be27c991c28" "checksum digest 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b29c278aa8fd30796bd977169e8004b4aa88cdcd2f32a6eb22bc2d5d38df94a" +"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" "checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d6f0e2bb24d163428d8031d3ebd2d2bd903ad933205a97d0f18c7c1aade380f3" "checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc" @@ -2675,6 +2842,9 @@ dependencies = [ "checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" +"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "aa75ec8f7927063335a9583e7fa87b0110bb888cf766dc01b54c0ff70d760c8e" "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" @@ -2693,6 +2863,7 @@ dependencies = [ "checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa" "checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e" "checksum hmac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb895368093a17d136b1d9eecdb607c7aa038a452e646c74e37ded2da106285" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba3a1fd1857a714d410c191364c5d7bf8a6487c0ab5575146d37dd7eb17ef523" @@ -2728,6 +2899,7 @@ dependencies = [ "checksum markup5ever 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf89d3e0486c32c9d99521455ddf9a438910a1ce2bd376936086edc15dff5fc" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum md-5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9402eaae33a9e144ce18ef488a0e4ca19869673c7bcdbbfe2030fdc3f84211cd" +"checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e01e64d9017d18e7fc09d8e4fe0e28ff6931019e979fb8019319db7ca827f8a6" @@ -2766,7 +2938,7 @@ dependencies = [ "checksum pq-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfb5e575ef93a1b7b2a381d47ba7c5d4e4f73bff37cee932195de769aad9a54" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" +"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" @@ -2780,6 +2952,7 @@ dependencies = [ "checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493" "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e" @@ -2790,6 +2963,9 @@ dependencies = [ "checksum reqwest 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4265be4dad32ffa4be2cea9c8ecb5e096feca6b4ff024482bfc0f64b6019b2f" "checksum ring 0.11.1 (git+https://github.com/SergioBenitez/ring?branch=v0.11)" = "" "checksum route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3255338088df8146ba63d60a9b8e3556f1146ce2973bc05a75181a42ce2256" +"checksum rusoto_core 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dac3a75644426c7d4116e85dd314d5be26400f06d40d5673511d69a1168101f6" +"checksum rusoto_credential 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6b31eb8789afa4e601fa4677cab6886cbf8830b765f4da5cff2ba24ab485bfe" +"checksum rusoto_s3 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d3d30772fe4432d78bd100299b6063c2e74f89886f87a65518d2d66680bbcf0" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" @@ -2798,6 +2974,7 @@ dependencies = [ "checksum schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f" "checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" +"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" "checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" @@ -2813,6 +2990,7 @@ dependencies = [ "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" "checksum serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1e67ce320daa7e494c578e34d4b00689f23bb94512fe0ca0dfaf02ea53fb67" "checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650" +"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum socket2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b4896961171cd3317c7e9603d88f379f8c6e45342212235d356496680c68fd" @@ -2823,8 +3001,9 @@ dependencies = [ "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" -"checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum syntex_fmt_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5386bdc48758d136af85b3880548e1f3a9fad8d7dc2b38bdb48c36a9cdefc0" "checksum tar 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6af6b94659f9a571bf769a5b71f54079393585ee0bfdd71b691be22d7d6b1d18" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" @@ -2886,3 +3065,4 @@ dependencies = [ "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb373b92de38a4301d66bec009929b4fb83120ea1c4a401be89dbe0b9777443" +"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" diff --git a/Cargo.toml b/Cargo.toml index 8d86087bd4..c058fe2a75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ rustdoc-args = [ ] [dependencies] -cargo-registry-s3 = { path = "src/s3", version = "0.2.0" } rand = "0.3" git2 = "0.6.4" flate2 = "1.0" @@ -39,6 +38,7 @@ openssl = "0.9.14" oauth2 = "0.3" log = "0.3" env_logger = "0.5" +futures = "0.1.24" hex = "0.3" htmlescape = "0.3.1" license-exprs = "^1.4" @@ -47,6 +47,9 @@ toml = "0.4" diesel = { version = "1.3.0", features = ["postgres", "serde_json", "chrono", "r2d2"] } diesel_full_text_search = "1.0.0" diesel_ltree = "0.1.3" +rusoto_core = "0.34.0" +rusoto_credential = "0.13.0" +rusoto_s3 = "0.34.0" serde_json = "1.0.0" serde_derive = "1.0.0" serde = "1.0.0" diff --git a/docker-compose.yml b/docker-compose.yml index e760c2335a..d917472675 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: volumes: # Mount the src/ directory so we don't have to rebuild the Docker image # when we want to change some code - - ./src:/app/src:ro + - ./src:/app/src - index:/app/tmp - cargo-cache:/usr/local/cargo/registry @@ -37,7 +37,7 @@ services: build: context: . dockerfile: frontend.Dockerfile - entrypoint: npm run start --proxy http://backend:8888 + entrypoint: npm run start -- --proxy http://backend:8888 links: - backend ports: diff --git a/frontend.Dockerfile b/frontend.Dockerfile index ad17141109..e6861c83b7 100644 --- a/frontend.Dockerfile +++ b/frontend.Dockerfile @@ -5,4 +5,7 @@ COPY package.json /app COPY . /app +RUN npm install -g ember-cli +RUN npm install + ENTRYPOINT ["npm", "run", "start:staging"] diff --git a/src/bin/render-readmes.rs b/src/bin/render-readmes.rs index 87dbb4cf6a..031bf65418 100644 --- a/src/bin/render-readmes.rs +++ b/src/bin/render-readmes.rs @@ -146,7 +146,6 @@ fn main() { config .uploader .upload( - &reqwest::Client::new(), &readme_path, readme.into_bytes(), "text/html", diff --git a/src/config.rs b/src/config.rs index 03561ba111..a44a9f1720 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,7 @@ -use s3; - use std::env; use std::path::PathBuf; -use {env, Env, Replica, Uploader}; +use {env, Env, Replica, S3UploaderBuilder, Uploader}; #[derive(Clone, Debug)] pub struct Config { @@ -38,6 +36,7 @@ impl Default for Config { /// - `S3_REGION`: The region in which the bucket was created. Optional if US standard. /// - `S3_ACCESS_KEY`: The access key to interact with S3. Optional if running a mirror. /// - `S3_SECRET_KEY`: The secret key to interact with S3. Optional if running a mirror. + /// - `S3_HOST`: The S3 host to use. Optional. /// - `SESSION_KEY`: The key used to sign and encrypt session cookies. /// - `GH_CLIENT_ID`: The client ID of the associated GitHub application. /// - `GH_CLIENT_SECRET`: The client secret of the associated GitHub application. @@ -56,22 +55,17 @@ impl Default for Config { } else { Env::Development }; + let uploader = match (cargo_env, mirror) { (Env::Production, Replica::Primary) => { // `env` panics if these vars are not set, and in production for a primary instance, // that's what we want since we don't want to be able to start the server if the // server doesn't know where to upload crates. - Uploader::S3 { - bucket: s3::Bucket::new( - env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env("S3_ACCESS_KEY"), - env("S3_SECRET_KEY"), - &api_protocol, - ), - cdn: env::var("S3_CDN").ok(), - proxy: None, - } + S3UploaderBuilder::new(env("S3_BUCKET"), env("S3_ACCESS_KEY"), env("S3_SECRET_KEY")) + .region(env::var("S3_REGION").ok()) + .host(env::var("S3_HOST").ok()) + .cdn(env::var("S3_CDN").ok()) + .build() } (Env::Production, Replica::ReadOnlyMirror) => { // Read-only mirrors don't need access key or secret key since by definition, @@ -82,17 +76,17 @@ impl Default for Config { // // Read-only mirrors definitely need bucket though, so that they know where // to serve crate files from. - Uploader::S3 { - bucket: s3::Bucket::new( - env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env::var("S3_ACCESS_KEY").unwrap_or_default(), - env::var("S3_SECRET_KEY").unwrap_or_default(), - &api_protocol, - ), - cdn: env::var("S3_CDN").ok(), - proxy: None, - } + let mut s3_builder = S3UploaderBuilder::new( + env("S3_BUCKET"), + env::var("S3_ACCESS_KEY").unwrap_or_default(), + env::var("S3_SECRET_KEY").unwrap_or_default(), + ); + + s3_builder + .region(env::var("S3_REGION").ok()) + .host(env::var("S3_HOST").ok()) + .cdn(env::var("S3_CDN").ok()) + .build() } // In Development mode, either running as a primary instance or a read-only mirror _ => { @@ -102,17 +96,18 @@ impl Default for Config { // and read from S3 like production does. All values except for bucket are // optional, like production read-only mirrors. println!("Using S3 uploader"); - Uploader::S3 { - bucket: s3::Bucket::new( - env("S3_BUCKET"), - env::var("S3_REGION").ok(), - env::var("S3_ACCESS_KEY").unwrap_or_default(), - env::var("S3_SECRET_KEY").unwrap_or_default(), - &api_protocol, - ), - cdn: env::var("S3_CDN").ok(), - proxy: None, - } + + let mut s3_builder = S3UploaderBuilder::new( + env("S3_BUCKET"), + env::var("S3_ACCESS_KEY").unwrap_or_default(), + env::var("S3_SECRET_KEY").unwrap_or_default(), + ); + + s3_builder + .region(env::var("S3_REGION").ok()) + .host(env::var("S3_HOST").ok()) + .cdn(env::var("S3_CDN").ok()) + .build() } else { // If we don't set the `S3_BUCKET` variable, we'll use a development-only // uploader that makes it possible to run and publish to a locally-running diff --git a/src/git.rs b/src/git.rs index 238c1a5fb5..e500af4bb1 100644 --- a/src/git.rs +++ b/src/git.rs @@ -206,11 +206,19 @@ where pub fn credentials( _user: &str, - _user_from_url: Option<&str>, + user_from_url: Option<&str>, _cred: git2::CredentialType, ) -> Result { match (env::var("GIT_HTTP_USER"), env::var("GIT_HTTP_PWD")) { (Ok(u), Ok(p)) => git2::Cred::userpass_plaintext(&u, &p), - _ => Err(git2::Error::from_str("no authentication set")), + _ => { + // If there is no user, or password, try and use SSH keys using + // the SSH agent. + if let Some(user) = user_from_url { + git2::Cred::ssh_key_from_agent(user) + } else { + Err(git2::Error::from_str("no authentication set")) + } + } } } diff --git a/src/lib.rs b/src/lib.rs index af543888d3..79fadf5dbc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate diesel_full_text_search; extern crate diesel_ltree; extern crate dotenv; extern crate flate2; +extern crate futures; extern crate git2; extern crate hex; extern crate htmlescape; @@ -32,7 +33,9 @@ extern crate oauth2; extern crate openssl; extern crate rand; extern crate reqwest; -extern crate s3; +extern crate rusoto_core; +extern crate rusoto_credential; +extern crate rusoto_s3; extern crate scheduled_thread_pool; extern crate semver; extern crate serde; @@ -53,7 +56,7 @@ extern crate conduit_router; extern crate conduit_static; extern crate cookie; -pub use self::uploaders::{Bomb, Uploader}; +pub use self::uploaders::{Bomb, S3UploaderBuilder, Uploader}; pub use app::App; pub use config::Config; diff --git a/src/middleware/security_headers.rs b/src/middleware/security_headers.rs index bc3b4646ef..0881c58c9f 100644 --- a/src/middleware/security_headers.rs +++ b/src/middleware/security_headers.rs @@ -22,12 +22,10 @@ impl SecurityHeaders { let s3_host = match *uploader { Uploader::S3 { - ref bucket, - ref cdn, - .. + ref host, ref cdn, .. } => match *cdn { Some(ref s) => s.clone(), - None => bucket.host(), + None => host.clone(), }, _ => unreachable!( "This middleware should only be used in the production environment, \ diff --git a/src/s3/Cargo.toml b/src/s3/Cargo.toml deleted file mode 100644 index dde27e6085..0000000000 --- a/src/s3/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] - -name = "cargo-registry-s3" -version = "0.2.0" -authors = ["Alex Crichton "] -license = "MIT OR Apache-2.0" -repository = "https://github.com/rust-lang/crates.io" -description = "Interaction between crates.io and S3 for storing crate files" - -[lib] - -name = "s3" -path = "lib.rs" - -[dependencies] -base64 = "0.6" -chrono = "0.4" -openssl = "0.9" -reqwest = "0.9.1" diff --git a/src/s3/lib.rs b/src/s3/lib.rs deleted file mode 100644 index c6bb2e56d4..0000000000 --- a/src/s3/lib.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![deny(warnings)] - -extern crate base64; -extern crate chrono; -extern crate openssl; -extern crate reqwest; - -use base64::encode; -use chrono::prelude::Utc; -use openssl::hash::MessageDigest; -use openssl::pkey::PKey; -use openssl::sign::Signer; -use reqwest::header; - -#[derive(Clone, Debug)] -pub struct Bucket { - name: String, - region: Option, - access_key: String, - secret_key: String, - proto: String, -} - -impl Bucket { - pub fn new( - name: String, - region: Option, - access_key: String, - secret_key: String, - proto: &str, - ) -> Bucket { - Bucket { - name, - region, - access_key, - secret_key, - proto: proto.to_string(), - } - } - - pub fn put( - &self, - client: &reqwest::Client, - path: &str, - content: Vec, - content_type: &str, - ) -> reqwest::Result { - let path = if path.starts_with('/') { - &path[1..] - } else { - path - }; - let date = Utc::now().to_rfc2822().to_string(); - let auth = self.auth("PUT", &date, path, "", content_type); - let url = self.url(path); - - client - .put(&url) - .header(header::AUTHORIZATION, auth) - .header(header::CONTENT_TYPE, content_type) - .header(header::DATE, date) - .body(content) - .send()? - .error_for_status() - } - - pub fn delete( - &self, - client: &reqwest::Client, - path: &str, - ) -> reqwest::Result { - let path = if path.starts_with('/') { - &path[1..] - } else { - path - }; - let date = Utc::now().to_rfc2822().to_string(); - let auth = self.auth("DELETE", &date, path, "", ""); - let url = self.url(path); - - client - .delete(&url) - .header(header::DATE, date) - .header(header::AUTHORIZATION, auth) - .send()? - .error_for_status() - } - - pub fn host(&self) -> String { - format!( - "{}.s3{}.amazonaws.com", - self.name, - match self.region { - Some(ref r) if r != "" => format!("-{}", r), - Some(_) => String::new(), - None => String::new(), - } - ) - } - - fn auth(&self, verb: &str, date: &str, path: &str, md5: &str, content_type: &str) -> String { - let string = format!( - "{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}", - verb = verb, - md5 = md5, - ty = content_type, - date = date, - headers = "", - resource = format!("/{}/{}", self.name, path) - ); - let signature = { - let key = PKey::hmac(self.secret_key.as_bytes()).unwrap(); - let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap(); - signer.update(string.as_bytes()).unwrap(); - encode(&signer.sign_to_vec().unwrap()[..]) - }; - format!("AWS {}:{}", self.access_key, signature) - } - - fn url(&self, path: &str) -> String { - format!("{}://{}/{}", self.proto, self.host(), path) - } -} diff --git a/src/tests/all.rs b/src/tests/all.rs index 6a179e1362..fbf750170b 100644 --- a/src/tests/all.rs +++ b/src/tests/all.rs @@ -16,7 +16,6 @@ extern crate flate2; extern crate git2; #[macro_use] extern crate lazy_static; -extern crate s3; extern crate semver; extern crate serde; #[macro_use] @@ -142,17 +141,16 @@ fn app() -> ( // sniff/record it, but everywhere else we use https let api_protocol = String::from("http"); - let uploader = cargo_registry::Uploader::S3 { - bucket: s3::Bucket::new( - String::from("alexcrichton-test"), - None, - std::env::var("S3_ACCESS_KEY").unwrap_or_default(), - std::env::var("S3_SECRET_KEY").unwrap_or_default(), - &api_protocol, - ), - proxy: Some(proxy), - cdn: None, - }; + let s3_builder = cargo_registry::S3UploaderBuilder::new( + String::from("alexcrichton-test"), + std::env::var("S3_ACCESS_KEY").unwrap_or_default(), + std::env::var("S3_SECRET_KEY").unwrap_or_default(), + ); + + let uploader = s3_builder + .proto(String::from("http")) + .proxy(Some(proxy)) + .build(); let config = cargo_registry::Config { uploader, diff --git a/src/uploaders.rs b/src/uploaders.rs index 10f8f87c3e..5b575813e5 100644 --- a/src/uploaders.rs +++ b/src/uploaders.rs @@ -1,8 +1,6 @@ use conduit::Request; use flate2::read::GzDecoder; use openssl::hash::{Hasher, MessageDigest}; -use reqwest; -use s3; use semver; use tar; @@ -10,20 +8,32 @@ use util::LimitErrorReader; use util::{human, internal, CargoResult, ChainError, Maximums}; use std::env; +use std::fmt; use std::fs::{self, File}; use std::io::{Read, Write}; use std::sync::Arc; +use futures::future::{result, FutureResult}; +use futures::{Future, Poll}; + +use rusoto_core::request::HttpClient; +use rusoto_core::{ProvideAwsCredentials, Region}; +use rusoto_credential::{AwsCredentials, CredentialsError}; +use rusoto_s3::{DeleteObjectRequest, PutObjectRequest, S3Client, S3}; + use app::App; + use middleware::app::RequestApp; use models::Crate; -#[derive(Clone, Debug)] +#[derive(Clone)] pub enum Uploader { /// For production usage, uploads and redirects to s3. /// For test usage with a proxy. S3 { - bucket: s3::Bucket, + client: Arc, + bucket: String, + host: String, cdn: Option, proxy: Option, }, @@ -36,6 +46,16 @@ pub enum Uploader { NoOp, } +impl fmt::Debug for Uploader { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Uploader::S3 { .. } => write!(f, "Uploader::S3"), + Uploader::Local => write!(f, "Uploader::Local"), + Uploader::NoOp => write!(f, "Uploader::NoOp"), + } + } +} + impl Uploader { pub fn proxy(&self) -> Option<&str> { match *self { @@ -51,16 +71,18 @@ impl Uploader { pub fn crate_location(&self, crate_name: &str, version: &str) -> Option { match *self { Uploader::S3 { + ref host, ref bucket, ref cdn, .. } => { let host = match *cdn { Some(ref s) => s.clone(), - None => bucket.host(), + None => host.clone(), }; + let path = Uploader::crate_path(crate_name, version); - Some(format!("https://{}/{}", host, path)) + Some(format!("https://{}/{}/{}", host, bucket, path)) } Uploader::Local => Some(format!("/{}", Uploader::crate_path(crate_name, version))), Uploader::NoOp => None, @@ -74,16 +96,17 @@ impl Uploader { pub fn readme_location(&self, crate_name: &str, version: &str) -> Option { match *self { Uploader::S3 { + ref host, ref bucket, ref cdn, .. } => { let host = match *cdn { Some(ref s) => s.clone(), - None => bucket.host(), + None => host.clone(), }; let path = Uploader::readme_path(crate_name, version); - Some(format!("https://{}/{}", host, path)) + Some(format!("https://{}/{}/{}", host, bucket, path)) } Uploader::Local => Some(format!("/{}", Uploader::readme_path(crate_name, version))), Uploader::NoOp => None, @@ -107,17 +130,29 @@ impl Uploader { /// and its checksum. pub fn upload( &self, - client: &reqwest::Client, path: &str, body: Vec, content_type: &str, ) -> CargoResult<(Option, Vec)> { let hash = hash(&body); match *self { - Uploader::S3 { ref bucket, .. } => { - bucket - .put(&client, path, body, content_type) - .map_err(|e| internal(&format_args!("failed to upload to S3: {}", e)))?; + Uploader::S3 { + ref client, + ref bucket, + .. + } => { + let req = PutObjectRequest { + bucket: bucket.to_string(), + key: path.to_string(), + content_type: Some(content_type.to_string()), + body: Some(body.to_vec().into()), + ..Default::default() + }; + + client.put_object(req).sync().chain_error(|| { + internal(&format_args!("failed to upload to S3: `{}`", path)) + })?; + Ok((Some(String::from(path)), hash)) } Uploader::Local => { @@ -148,7 +183,7 @@ impl Uploader { let mut body = Vec::new(); LimitErrorReader::new(req.body(), maximums.max_upload_size).read_to_end(&mut body)?; verify_tarball(krate, vers, &body, maximums.max_unpack_size)?; - self.upload(&app.http_client()?, &path, body, "application/x-tar")? + self.upload(&path, body, "application/x-tar")? }; // We create the bomb for the crate file before uploading the readme so that if the // readme upload fails, the uploaded crate file is automatically deleted. @@ -158,12 +193,7 @@ impl Uploader { }; let (readme_path, _) = if let Some(rendered) = readme { let path = Uploader::readme_path(&krate.name, &vers.to_string()); - self.upload( - &app.http_client()?, - &path, - rendered.into_bytes(), - "text/html", - )? + self.upload(&path, rendered.as_bytes().to_vec(), "text/html")? } else { (None, vec![]) }; @@ -178,10 +208,23 @@ impl Uploader { } /// Deletes an uploaded file. - fn delete(&self, app: &Arc, path: &str) -> CargoResult<()> { + fn delete(&self, path: &str) -> CargoResult<()> { match *self { - Uploader::S3 { ref bucket, .. } => { - bucket.delete(&app.http_client()?, path)?; + Uploader::S3 { + ref client, + ref bucket, + .. + } => { + let req = DeleteObjectRequest { + bucket: bucket.to_string(), + key: path.to_string(), + ..Default::default() + }; + + client.delete_object(req).sync().chain_error(|| { + internal(&format_args!("failed to upload to S3: `{}`", path)) + })?; + Ok(()) } Uploader::Local => { @@ -193,6 +236,132 @@ impl Uploader { } } +#[derive(Clone, Debug)] +pub struct S3CredentialsProvider { + access_key: String, + secret_key: String, +} + +impl S3CredentialsProvider { + fn new(access_key: String, secret_key: String) -> S3CredentialsProvider { + S3CredentialsProvider { + access_key, + secret_key, + } + } +} + +/// Provides AWS credentials from an S3CredentialsProvider object as a Future. +#[derive(Debug)] +pub struct S3CredentialsProviderFuture { + inner: FutureResult, +} + +impl Future for S3CredentialsProviderFuture { + type Item = AwsCredentials; + type Error = CredentialsError; + + fn poll(&mut self) -> Poll { + self.inner.poll() + } +} + +impl ProvideAwsCredentials for S3CredentialsProvider { + type Future = S3CredentialsProviderFuture; + + fn credentials(&self) -> Self::Future { + let access_key = self.access_key.clone(); + let secret_key = self.secret_key.clone(); + + S3CredentialsProviderFuture { + inner: result(Ok(AwsCredentials::new(access_key, secret_key, None, None))), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct S3UploaderBuilder { + bucket: String, + access_key: String, + secret_key: String, + proto: String, + region: Option, + host: Option, + cdn: Option, + proxy: Option, +} + +impl S3UploaderBuilder { + pub fn new(bucket: String, access_key: String, secret_key: String) -> S3UploaderBuilder { + S3UploaderBuilder { + bucket, + access_key, + secret_key, + proto: "https".into(), + ..Default::default() + } + } + + pub fn proto(mut self, proto: String) -> S3UploaderBuilder { + self.proto = proto; + self + } + + pub fn region(mut self, region: Option) -> S3UploaderBuilder { + self.region = region; + self + } + + pub fn host(mut self, host: Option) -> S3UploaderBuilder { + self.host = host; + self + } + + pub fn cdn(mut self, cdn: Option) -> S3UploaderBuilder { + self.cdn = cdn; + self + } + + pub fn proxy(mut self, proxy: Option) -> S3UploaderBuilder { + self.proxy = proxy; + self + } + + pub fn build(self) -> Uploader { + let host = self.host.clone().unwrap_or_else(|| { + format!( + "{}://{}.s3{}.amazonaws.com", + self.proto, + self.bucket, + match self.region { + Some(ref r) if r != "" => format!("-{}", r), + Some(_) => String::new(), + None => String::new(), + } + ) + }); + + // Use the custom handler as we always provide an endpoint to connect to. + let region = Region::Custom { + name: self.region.unwrap_or_else(|| "us-east-1".to_string()), + endpoint: host.clone(), + }; + + let dispatcher = HttpClient::new().expect("failed to create request dispatcher"); + let credentials = S3CredentialsProvider::new(self.access_key, self.secret_key); + + let s3client = S3Client::new_with(dispatcher, credentials, region); + + Uploader::S3 { + client: Arc::new(s3client), + bucket: self.bucket, + host, + cdn: self.cdn, + proxy: self.proxy, + } + } +} + // Can't derive Debug because of App. #[allow(missing_debug_implementations)] pub struct Bomb { @@ -203,7 +372,7 @@ pub struct Bomb { impl Drop for Bomb { fn drop(&mut self) { if let Some(ref path) = self.path { - if let Err(e) = self.app.config.uploader.delete(&self.app, path) { + if let Err(e) = self.app.config.uploader.delete(path) { println!("unable to delete {}, {:?}", path, e); } } diff --git a/src/util/errors.rs b/src/util/errors.rs index 30377993c7..e8df03bf4b 100644 --- a/src/util/errors.rs +++ b/src/util/errors.rs @@ -164,6 +164,7 @@ impl From for Box { } } } + // ============================================================================= // Concrete errors