Skip to content

Commit

Permalink
Detecting Google Project ID with auxiliary function: GoogleEnvironmen…
Browse files Browse the repository at this point in the history
…t::detect_google_project_id()
  • Loading branch information
abdolence committed Jul 24, 2022
1 parent 9993ce4 commit 14046a8
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 33 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Looks for credentials in the following places, preferring the first location fou
- A JSON file in a location known to the gcloud command-line tool.
- On Google Compute Engine, it fetches credentials from the metadata server.


## Fork
The library is a fork of [mechiru/googapis](https://github.com/mechiru/googapis) and [mechiru/gouth](https://github.com/mechiru/gouth) to keep up with
the updates and API proto descriptions from Google more frequently and simplify dependencies management.
Expand Down
7 changes: 5 additions & 2 deletions examples/firestore-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use gcloud_sdk::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let google_project_id = std::env::var("PROJECT_ID")?;

// Debug logging
let subscriber = tracing_subscriber::fmt()
.with_env_filter("gcloud_sdk=debug")
.finish();
tracing::subscriber::set_global_default(subscriber)?;

// Detect Google project ID using environment variables PROJECT_ID/GCP_PROJECT_ID
// or GKE metadata server when the app runs inside GKE
let google_project_id = GoogleEnvironment::detect_google_project_id().await
.expect("No Google Project ID detected. Please specify it explicitly using env variable: PROJECT_ID");

let cloud_resource_prefix = format!("projects/{}/databases/(default)", google_project_id);

let firestore_client: GoogleApi<FirestoreClient<GoogleAuthMiddleware>> =
Expand Down
7 changes: 5 additions & 2 deletions examples/secrets-manager-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use gcloud_sdk::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let google_project_id = std::env::var("PROJECT_ID")?;

// Debug logging
let subscriber = tracing_subscriber::fmt()
.with_env_filter("gcloud_sdk=debug")
.finish();
tracing::subscriber::set_global_default(subscriber)?;

// Detect Google project ID using environment variables PROJECT_ID/GCP_PROJECT_ID
// or GKE metadata server when the app runs inside GKE
let google_project_id = GoogleEnvironment::detect_google_project_id().await
.expect("No Google Project ID detected. Please specify it explicitly using env variable: PROJECT_ID");

let secrets_client: GoogleApi<SecretManagerServiceClient<GoogleAuthMiddleware>> =
GoogleApi::from_function(
SecretManagerServiceClient::new,
Expand Down
2 changes: 1 addition & 1 deletion gcloud-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gcloud-sdk"
version = "0.17.0"
version = "0.17.1"
authors = ["mechiru <[email protected]>", "Abdulla Abdurakhmanov <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down
75 changes: 50 additions & 25 deletions gcloud-sdk/src/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ where
google_api_url, token_scopes
);

let channel = init_google_services_channel(google_api_url).await?;
let channel = GoogleEnvironment::init_google_services_channel(google_api_url).await?;

let token_generator =
GoogleAuthTokenGenerator::new(token_source_type, token_scopes).await?;
Expand Down Expand Up @@ -124,29 +124,54 @@ where
pub type GoogleAuthMiddleware = GoogleAuthMiddlewareService<Channel>;
pub type GoogleApi<C> = GoogleApiClient<GoogleApiClientBuilderFunction<C>, C>;

async fn init_google_services_channel(
api_url: &'static str,
) -> Result<Channel, crate::error::Error> {
let domain_name = api_url.to_string().replace("https://", "");
let tls_config = init_google_services_channel_tls_config(domain_name);

Ok(Channel::from_static(api_url)
.tls_config(tls_config)?
.connect_timeout(Duration::from_secs(30))
.tcp_keepalive(Some(Duration::from_secs(5)))
.keep_alive_timeout(Duration::from_secs(60))
.http2_keep_alive_interval(Duration::from_secs(10))
.keep_alive_while_idle(true)
.connect()
.await?)
}
pub struct GoogleEnvironment;

impl GoogleEnvironment {
pub async fn detect_google_project_id() -> Option<String> {
let for_env = std::env::var("PROJECT_ID")
.ok()
.or_else(|| std::env::var("GCP_PROJECT_ID").ok());
if for_env.is_some() {
debug!("Detected GCP Project ID using environment variables");
for_env
} else {
let metadata_server = crate::token_source::metadata::Metadata::new(vec![
"https://www.googleapis.com/auth/cloud-platform".into(),
]);
let metadata_result = metadata_server.detect_google_project_id().await;
if metadata_result.is_some() {
debug!("Detected GCP Project ID using GKE metadata server");
} else {
debug!("No GCP Project ID detected in this environment. Please specify it explicitly using environment variables: `PROJECT_ID` or `GCP_PROJECT_ID`");
}
metadata_result
}
}

fn init_google_services_channel_tls_config(
domain_name: String,
) -> tonic::transport::ClientTlsConfig {
tonic::transport::ClientTlsConfig::new()
.ca_certificate(tonic::transport::Certificate::from_pem(
crate::apis::CERTIFICATES,
))
.domain_name(domain_name)
pub async fn init_google_services_channel(
api_url: &'static str,
) -> Result<Channel, crate::error::Error> {
let domain_name = api_url.to_string().replace("https://", "");
let tls_config = Self::init_google_services_channel_tls_config(domain_name);

Ok(Channel::from_static(api_url)
.tls_config(tls_config)?
.connect_timeout(Duration::from_secs(30))
.tcp_keepalive(Some(Duration::from_secs(5)))
.keep_alive_timeout(Duration::from_secs(60))
.http2_keep_alive_interval(Duration::from_secs(10))
.keep_alive_while_idle(true)
.connect()
.await?)
}

pub fn init_google_services_channel_tls_config(
domain_name: String,
) -> tonic::transport::ClientTlsConfig {
tonic::transport::ClientTlsConfig::new()
.ca_certificate(tonic::transport::Certificate::from_pem(
crate::apis::CERTIFICATES,
))
.domain_name(domain_name)
}
}
8 changes: 6 additions & 2 deletions gcloud-sdk/src/token_source/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ pub struct Metadata {
}

impl Metadata {
fn new(scopes: impl Into<Vec<String>>) -> Self {
pub fn new(scopes: impl Into<Vec<String>>) -> Self {
Self::with_account(scopes, "default")
}

fn with_account(scopes: impl Into<Vec<String>>, account: &'static str) -> Self {
pub fn with_account(scopes: impl Into<Vec<String>>, account: &'static str) -> Self {
Self {
account,
scopes: scopes.into(),
Expand All @@ -38,6 +38,10 @@ impl Metadata {
};
format!("instance/service-accounts/{}/token?{}", self.account, query)
}

pub async fn detect_google_project_id(&self) -> Option<String> {
self.gcemeta_client.project_id().await.ok()
}
}

impl From<Metadata> for BoxSource {
Expand Down
2 changes: 1 addition & 1 deletion gcloud-sdk/src/token_source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use chrono::prelude::*;

pub mod auth_token_generator;
mod credentials;
mod metadata;
pub mod metadata;

use serde::{Deserialize, Serialize};

Expand Down

0 comments on commit 14046a8

Please sign in to comment.