Skip to content

Commit f4ddedf

Browse files
committed
team_repo: Pin "Let's Encrypt" intermediate certificate
https://team-api.infra.rust-lang.org is hosted on GitHub Pages, which uses Let's Encrypt as CA. The certificates for https://team-api.infra.rust-lang.org itself are short-lived and somewhat out of our control, but the intermediate certificate from Let's Encrypt can at least be pinned to reduce the risk of man in the middle attacks.
1 parent 316ba76 commit f4ddedf

File tree

5 files changed

+65
-3
lines changed

5 files changed

+65
-3
lines changed

src/bin/background-worker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn main() -> anyhow::Result<()> {
7878

7979
let emails = Emails::from_environment(&config);
8080
let fastly = Fastly::from_environment(client.clone());
81-
let team_repo = TeamRepoImpl::new(client);
81+
let team_repo = TeamRepoImpl::default();
8282

8383
let connection_pool = r2d2::Pool::builder()
8484
.max_size(10)

src/certs/lets-encrypt.pem

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
3+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
5+
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
6+
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
7+
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
8+
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
9+
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
10+
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
11+
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
12+
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
13+
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
14+
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
15+
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
16+
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
17+
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
18+
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
19+
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
20+
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
21+
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
22+
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
23+
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
24+
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
25+
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
26+
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
27+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
28+
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
29+
nLRbwHOoq7hHwg==
30+
-----END CERTIFICATE-----

src/certs/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub const LETS_ENCRYPT: &[u8] = include_bytes!("./lets-encrypt.pem");

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod admin;
3232
mod app;
3333
pub mod auth;
3434
pub mod boot;
35+
pub mod certs;
3536
pub mod ci;
3637
pub mod cloudfront;
3738
pub mod config;

src/team_repo.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
//! purposes. The [TeamRepoImpl] struct is the actual implementation of
66
//! the trait.
77
8+
use crate::certs;
89
use async_trait::async_trait;
910
use mockall::automock;
10-
use reqwest::Client;
11+
use reqwest::{Certificate, Client};
1112

1213
#[automock]
1314
#[async_trait]
@@ -35,11 +36,28 @@ pub struct TeamRepoImpl {
3536
}
3637

3738
impl TeamRepoImpl {
38-
pub fn new(client: Client) -> Self {
39+
fn new(client: Client) -> Self {
3940
TeamRepoImpl { client }
4041
}
4142
}
4243

44+
impl Default for TeamRepoImpl {
45+
fn default() -> Self {
46+
let client = build_client();
47+
TeamRepoImpl::new(client)
48+
}
49+
}
50+
51+
fn build_client() -> Client {
52+
let lets_encrypt_cert = Certificate::from_pem(certs::LETS_ENCRYPT).unwrap();
53+
54+
Client::builder()
55+
.tls_built_in_root_certs(false)
56+
.add_root_certificate(lets_encrypt_cert)
57+
.build()
58+
.unwrap()
59+
}
60+
4361
#[async_trait]
4462
impl TeamRepo for TeamRepoImpl {
4563
async fn get_team(&self, name: &str) -> anyhow::Result<Team> {
@@ -48,3 +66,15 @@ impl TeamRepo for TeamRepoImpl {
4866
Ok(response.json().await?)
4967
}
5068
}
69+
70+
#[cfg(test)]
71+
mod tests {
72+
use crate::team_repo::build_client;
73+
74+
/// This test is here to make sure that the client is built
75+
/// correctly without panicking.
76+
#[test]
77+
fn test_build_client() {
78+
let _client = build_client();
79+
}
80+
}

0 commit comments

Comments
 (0)