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
40 changes: 40 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>,
/// Allow opendal to send requests without signing when credentials are not
/// loaded.
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,15 @@ impl GcsBuilder {
};
self
}

/// Allow anonymous requests.
///
/// This is typically used for buckets which are open to the public or GCS
/// 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 +316,12 @@ 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()
.with_disable_well_known_location();
}

let scope = if let Some(scope) = &self.config.scope {
scope
} else {
Expand All @@ -304,6 +339,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 +356,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
35 changes: 23 additions & 12 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,23 +91,30 @@ 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
let cred = self
.credential_loader
.load()
.map_err(new_request_credential_error)?;

if let Some(cred) = cred {
Ok(cred)
} else {
Err(Error::new(
ErrorKind::ConfigInvalid,
"no valid credential found",
))
return Ok(Some(cred));
}

if self.allow_anonymous {
return Ok(None);
}

Err(Error::new(
ErrorKind::ConfigInvalid,
"no valid credential found",
))
}

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