google_cloud_auth/token_source/
compute_token_source.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
use async_trait::async_trait;
use urlencoding::encode;

use google_cloud_metadata::{METADATA_FLAVOR_KEY, METADATA_GOOGLE, METADATA_HOST_ENV, METADATA_IP};

use crate::error::Error;
use crate::token::Token;
use crate::token_source::InternalToken;
use crate::token_source::{default_http_client, TokenSource};

#[allow(dead_code)]
#[derive(Debug)]
pub struct ComputeTokenSource {
    token_url: String,
    client: reqwest::Client,
}

impl ComputeTokenSource {
    pub(crate) fn new(scope: &str) -> Result<ComputeTokenSource, Error> {
        let host = match std::env::var(METADATA_HOST_ENV) {
            Ok(s) => s,
            Err(_e) => METADATA_IP.to_string(),
        };

        Ok(ComputeTokenSource {
            token_url: format!(
                "http://{}/computeMetadata/v1/instance/service-accounts/default/token?scopes={}",
                host,
                encode(scope)
            ),
            client: default_http_client(),
        })
    }
}

#[async_trait]
impl TokenSource for ComputeTokenSource {
    async fn token(&self) -> Result<Token, Error> {
        let it = self
            .client
            .get(self.token_url.to_string())
            .header(METADATA_FLAVOR_KEY, METADATA_GOOGLE)
            .send()
            .await?
            .json::<InternalToken>()
            .await?;
        return Ok(it.to_token(time::OffsetDateTime::now_utc()));
    }
}