gcloud_auth/token_source/
compute_identity_source.rs1use async_trait::async_trait;
2use serde::Deserialize;
3use time::OffsetDateTime;
4use urlencoding::encode;
5
6use google_cloud_metadata::{METADATA_FLAVOR_KEY, METADATA_GOOGLE, METADATA_HOST_ENV, METADATA_IP};
7
8use crate::error::Error;
9use crate::token::Token;
10use crate::token_source::{default_http_client, TokenSource};
11
12#[derive(Clone)]
19pub struct ComputeIdentitySource {
20 token_url: String,
21 client: reqwest::Client,
22}
23
24impl std::fmt::Debug for ComputeIdentitySource {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 f.debug_struct("ComputeIdentitySource")
27 .field("token_url", &self.token_url)
28 .finish_non_exhaustive()
29 }
30}
31
32impl ComputeIdentitySource {
33 pub(crate) fn new(audience: &str) -> Result<ComputeIdentitySource, Error> {
34 let host = match std::env::var(METADATA_HOST_ENV) {
35 Ok(s) => s,
36 Err(_e) => METADATA_IP.to_string(),
37 };
38
39 Ok(ComputeIdentitySource {
40 token_url: format!(
41 "http://{}/computeMetadata/v1/instance/service-accounts/default/identity?audience={}&format=full",
42 host,
43 encode(audience)
44 ),
45 client: default_http_client(),
46 })
47 }
48}
49
50#[derive(Deserialize)]
51struct ExpClaim {
52 exp: i64,
53}
54
55#[async_trait]
56impl TokenSource for ComputeIdentitySource {
57 async fn token(&self) -> Result<Token, Error> {
58 let jwt = self
59 .client
60 .get(self.token_url.to_string())
61 .header(METADATA_FLAVOR_KEY, METADATA_GOOGLE)
62 .send()
63 .await?
64 .text()
65 .await?;
66
67 let token = jsonwebtoken::dangerous::insecure_decode::<ExpClaim>(jwt.as_bytes())?;
69 Ok(Token {
70 access_token: jwt,
71 token_type: "Bearer".into(),
72 expiry: OffsetDateTime::from_unix_timestamp(token.claims.exp).ok(),
73 })
74 }
75}