Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gcs): allow unauthenticated requests #4965

Merged
merged 11 commits into from
Aug 7, 2024
37 changes: 37 additions & 0 deletions core/src/services/gcs/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ pub struct GcsConfig {
pub predefined_acl: Option<String>,
/// The default storage class used by gcs.
pub default_storage_class: Option<String>,
/// Explicitly allow anonymous access, such as for publicly available buckets
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved
/// which do not require authentication.
pub allow_anonymous: bool,
/// Disable attempting to load credentials from the GCE metadata server when
/// running within Google Cloud.
pub disable_vm_metadata: bool,
/// Disable loading configuration from the environment.
pub disable_config_load: bool,
}

impl Debug for GcsConfig {
Expand Down Expand Up @@ -205,6 +213,18 @@ impl GcsBuilder {
self
}

/// Disable attempting to load credentials from the GCE metadata server.
pub fn disable_vm_metadata(mut self) -> Self {
self.config.disable_vm_metadata = true;
self
}

/// Disable loading configuration from the environment.
pub fn disable_config_load(mut self) -> Self {
self.config.disable_config_load = true;
self
}

/// Set the predefined acl for GCS.
///
/// Available values are:
Expand Down Expand Up @@ -234,6 +254,14 @@ impl GcsBuilder {
};
self
}

/// Explicitly disable authentication.
///
/// This is typically only done for testing purposes against storage emulators.
pub fn allow_anonymous(mut self) -> Self {
self.config.allow_anonymous = true;
self
}
}

impl Builder for GcsBuilder {
Expand Down Expand Up @@ -287,6 +315,10 @@ impl Builder for GcsBuilder {
cred_loader = cred_loader.with_disable_well_known_location();
}

if self.config.disable_config_load {
cred_loader = cred_loader.with_disable_env();
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved
}

let scope = if let Some(scope) = &self.config.scope {
scope
} else {
Expand All @@ -304,6 +336,10 @@ impl Builder for GcsBuilder {
token_loader = token_loader.with_customized_token_loader(loader)
}

if self.config.disable_vm_metadata {
token_loader = token_loader.with_disable_vm_metadata(true);
}

let signer = GoogleSigner::new("storage");

let backend = GcsBackend {
Expand All @@ -317,6 +353,7 @@ impl Builder for GcsBuilder {
credential_loader: cred_loader,
predefined_acl: self.config.predefined_acl.clone(),
default_storage_class: self.config.default_storage_class.clone(),
allow_anonymous: self.config.allow_anonymous,
}),
};

Expand Down
25 changes: 18 additions & 7 deletions core/src/services/gcs/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub struct GcsCore {

pub predefined_acl: Option<String>,
pub default_storage_class: Option<String>,

pub allow_anonymous: bool,
}

impl Debug for GcsCore {
Expand Down Expand Up @@ -89,14 +91,18 @@ impl GcsCore {
}
}

fn load_credential(&self) -> Result<GoogleCredential> {
fn load_credential(&self) -> Result<Option<GoogleCredential>> {
jdockerty marked this conversation as resolved.
Show resolved Hide resolved
if self.allow_anonymous {
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved
return Ok(None);
}

let cred = self
.credential_loader
.load()
.map_err(new_request_credential_error)?;

if let Some(cred) = cred {
Ok(cred)
Ok(Some(cred))
} else {
Err(Error::new(
ErrorKind::ConfigInvalid,
Expand All @@ -106,6 +112,9 @@ impl GcsCore {
}

pub async fn sign<T>(&self, req: &mut Request<T>) -> Result<()> {
if self.allow_anonymous {
return Ok(());
}
let cred = self.load_token().await?;

self.signer
Expand All @@ -124,11 +133,13 @@ impl GcsCore {
}

pub async fn sign_query<T>(&self, req: &mut Request<T>, duration: Duration) -> Result<()> {
let cred = self.load_credential()?;

self.signer
.sign_query(req, duration, &cred)
.map_err(new_request_sign_error)?;
if let Some(cred) = self.load_credential()? {
self.signer
.sign_query(req, duration, &cred)
.map_err(new_request_sign_error)?;
} else {
return Ok(());
}

// Always remove host header, let users' client to set it based on HTTP
// version.
Expand Down
Loading