added BYOS (Bring Your Own SERVICE_ACCOUNT) for GCS authentication (#3262)

This commit is contained in:
Akash Shanmugaraj
2024-01-27 18:27:12 +05:30
committed by GitHub
parent 83bbe4ec37
commit aeb6acf640
10 changed files with 88 additions and 12 deletions

View File

@@ -164,12 +164,14 @@ pub unsafe extern "C" fn tc_server_new_sync(
///
/// ```c
/// EXTERN_C struct TCServer *tc_server_new_gcp(struct TCString bucket,
/// struct TCString credential_path,
/// struct TCString encryption_secret,
/// struct TCString *error_out);
/// ```
#[no_mangle]
pub unsafe extern "C" fn tc_server_new_gcp(
bucket: TCString,
credential_path_argument: TCString,
encryption_secret: TCString,
error_out: *mut TCString,
) -> *mut TCServer {
@@ -180,15 +182,27 @@ pub unsafe extern "C" fn tc_server_new_gcp(
// - bucket ownership is transferred to this function
let bucket = unsafe { TCString::val_from_arg(bucket) }.into_string()?;
// SAFETY:
// - credential_path is valid (promised by caller)
// - credential_path ownership is transferred to this function
let credential_path =
unsafe { TCString::val_from_arg(credential_path_argument) }.into_string()?;
let credential_path = if credential_path.is_empty() {
None
} else {
Some(credential_path)
};
// SAFETY:
// - encryption_secret is valid (promised by caller)
// - encryption_secret ownership is transferred to this function
let encryption_secret = unsafe { TCString::val_from_arg(encryption_secret) }
.as_bytes()
.to_vec();
let server_config = ServerConfig::Gcp {
bucket,
credential_path,
encryption_secret,
};
let server = server_config.into_server()?;

View File

@@ -446,6 +446,7 @@ EXTERN_C struct TCServer *tc_server_new_sync(struct TCString origin,
//
// The server must be freed after it is used - tc_replica_sync does not automatically free it.
EXTERN_C struct TCServer *tc_server_new_gcp(struct TCString bucket,
struct TCString credential_path,
struct TCString encryption_secret,
struct TCString *error_out);

View File

@@ -1,5 +1,6 @@
use super::service::{ObjectInfo, Service};
use crate::errors::Result;
use google_cloud_storage::client::google_cloud_auth::credentials::CredentialsFile;
use google_cloud_storage::client::{Client, ClientConfig};
use google_cloud_storage::http::error::ErrorResponse;
use google_cloud_storage::http::Error as GcsError;
@@ -25,9 +26,17 @@ fn is_http_error<T>(query: u16, res: &std::result::Result<T, http::Error>) -> bo
}
impl GcpService {
pub(in crate::server) fn new(bucket: String) -> Result<Self> {
pub(in crate::server) fn new(bucket: String, credential_path: Option<String>) -> Result<Self> {
let rt = Runtime::new()?;
let config = rt.block_on(ClientConfig::default().with_auth())?;
let credentialpathstring = credential_path.clone().unwrap();
let config: ClientConfig = if credential_path.unwrap() == "" {
rt.block_on(ClientConfig::default().with_auth())?
} else {
let credentials = rt.block_on(CredentialsFile::new_from_file(credentialpathstring))?;
rt.block_on(ClientConfig::default().with_credentials(credentials))?
};
Ok(Self {
client: Client::new(config),
rt,
@@ -244,10 +253,16 @@ mod tests {
let Ok(bucket) = std::env::var("GCP_TEST_BUCKET") else {
return None;
};
let Ok(credential_path) = std::env::var("GCP_TEST_CREDENTIAL_PATH") else {
return None;
};
let prefix = Uuid::new_v4();
Some((GcpService::new(bucket).unwrap(), move |n: &_| {
format!("{}-{}", prefix.as_simple(), n).into_bytes()
}))
Some((
GcpService::new(bucket, Some(credential_path)).unwrap(),
move |n: &_| format!("{}-{}", prefix.as_simple(), n).into_bytes(),
))
}
#[test]

View File

@@ -37,7 +37,12 @@ pub enum ServerConfig {
/// Bucket in which to store the task data. This bucket must not be used for any other
/// purpose.
bucket: String,
/// Path to a GCP credential file, in JSON format. This is required for GCP access incase
/// some other application already makes use of Application Default Credentials.
/// See https://cloud.google.com/docs/authentication#service-accounts for more details.
/// See https://cloud.google.com/iam/docs/keys-create-delete for instructions on how to
/// create a service account key.
credential_path: Option<String>,
/// Private encryption secret used to encrypt all data sent to the server. This can
/// be any suitably un-guessable string of bytes.
encryption_secret: Vec<u8>,
@@ -58,9 +63,10 @@ impl ServerConfig {
#[cfg(feature = "server-gcp")]
ServerConfig::Gcp {
bucket,
credential_path,
encryption_secret,
} => Box::new(CloudServer::new(
GcpService::new(bucket)?,
GcpService::new(bucket, credential_path)?,
encryption_secret,
)?),
})