google_cloud_ai/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use jsonwebtoken::{encode, Algorithm, EncodingKey, Header};
use serde::{Deserialize, Serialize};

#[path = "google/protos.rs"]
pub mod google_cloud_ai {}

#[derive(Debug, Serialize, Deserialize)]
struct Token {
    access_token: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    iss: String,
    scope: String,
    aud: String,
    exp: usize,
    iat: usize,
}

pub async fn get_token() -> String {
    let client = reqwest::Client::new();

    let response = client.get("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
    .header("Metadata-Flavor", "Google")
    .send()
    .await
    .unwrap();

    let result = response.json::<Token>().await.unwrap();

    return result.access_token;
}

pub async fn get_service_account_token(email: String, rsa_pem: String) -> String {
    let timestamp = chrono::Utc::now();

    let iat_value = timestamp.timestamp().try_into().unwrap();
    let exp_value = (timestamp.timestamp() + 3600).try_into().unwrap();

    let claims = Claims {
        iss: email,
        scope: String::from("https://www.googleapis.com/auth/datastore"),
        aud: String::from("https://oauth2.googleapis.com/token"),
        exp: exp_value,
        iat: iat_value,
    };

    let mut headers = Header::new(Algorithm::RS256);

    headers.typ = Some("JWT".to_string());

    let token = encode(
        &headers,
        &claims,
        &EncodingKey::from_rsa_pem(rsa_pem.as_ref()).unwrap(),
    )
    .unwrap();

    let client = reqwest::Client::new();

    let resp = client
        .post("https://oauth2.googleapis.com/token")
        .header("Content-Type", "application/x-www-form-urlencoded")
        .body(format!(
            "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion={}",
            token
        ))
        .send()
        .await
        .unwrap();

    let result = resp.json::<Token>().await.unwrap();

    return result.access_token;
}