This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new d9eba0ad feat(services/oss): Add server side encryption support for
oss (#2092)
d9eba0ad is described below
commit d9eba0ad866cdaa945fb16b43682b787836b4b12
Author: leenstx <[email protected]>
AuthorDate: Mon Apr 24 21:55:38 2023 +0800
feat(services/oss): Add server side encryption support for oss (#2092)
* Add server side encryption support for oss #1981
* Add server side encryption support for oss #1981
add doc
---
core/src/services/oss/backend.rs | 62 +++++++++++++++++++++++++++++++++++++++-
core/src/services/oss/core.rs | 48 +++++++++++++++++++++++++++++--
2 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index 8748c7dd..f6e21394 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -114,6 +114,10 @@ pub struct OssBuilder {
presign_endpoint: Option<String>,
bucket: String,
+ // sse options
+ server_side_encryption: Option<String>,
+ server_side_encryption_key_id: Option<String>,
+
// authenticate options
access_key_id: Option<String>,
access_key_secret: Option<String>,
@@ -253,6 +257,41 @@ impl OssBuilder {
};
Ok((endpoint, host))
}
+
+ /// Set server_side_encryption for this backend.
+ ///
+ /// Available values: `AES256`, `KMS`.
+ ///
+ /// Reference:
<https://www.alibabacloud.com/help/en/object-storage-service/latest/server-side-encryption-5>
+ /// Brief explanation:
+ /// There are two server-side encryption methods available:
+ /// SSE-AES256:
+ /// 1. Configure the bucket encryption mode as OSS-managed and specify
the encryption algorithm as AES256.
+ /// 2. Include the `x-oss-server-side-encryption` parameter in the
request and set its value to AES256.
+ /// SSE-KMS:
+ /// 1. To use this service, you need to first enable KMS.
+ /// 2. Configure the bucket encryption mode as KMS, and specify the
specific CMK ID for BYOK (Bring Your Own Key)
+ /// or not specify the specific CMK ID for OSS-managed KMS key.
+ /// 3. Include the `x-oss-server-side-encryption` parameter in the
request and set its value to KMS.
+ /// 4. If a specific CMK ID is specified, include the
`x-oss-server-side-encryption-key-id` parameter in the request, and set its
value to the specified CMK ID.
+ pub fn server_side_encryption(&mut self, v: &str) -> &mut Self {
+ if !v.is_empty() {
+ self.server_side_encryption = Some(v.to_string())
+ }
+ self
+ }
+
+ /// Set server_side_encryption_key_id for this backend.
+ ///
+ /// # Notes
+ ///
+ /// This option only takes effect when server_side_encryption equals to
KMS.
+ pub fn server_side_encryption_key_id(&mut self, v: &str) -> &mut Self {
+ if !v.is_empty() {
+ self.server_side_encryption_key_id = Some(v.to_string())
+ }
+ self
+ }
}
impl Builder for OssBuilder {
@@ -270,7 +309,10 @@ impl Builder for OssBuilder {
map.get("access_key_id").map(|v| builder.access_key_id(v));
map.get("access_key_secret")
.map(|v| builder.access_key_secret(v));
-
+ map.get("server_side_encryption")
+ .map(|v| builder.server_side_encryption(v));
+ map.get("server_side_encryption_key_id")
+ .map(|v| builder.server_side_encryption_key_id(v));
builder
}
@@ -310,6 +352,22 @@ impl Builder for OssBuilder {
};
debug!("backend use presign_endpoint: {}", &presign_endpoint);
+ let server_side_encryption = match &self.server_side_encryption {
+ None => None,
+ Some(v) => Some(
+ build_header_value(v)
+ .map_err(|err| err.with_context("key",
"server_side_encryption"))?,
+ ),
+ };
+
+ let server_side_encryption_key_id = match
&self.server_side_encryption_key_id {
+ None => None,
+ Some(v) => Some(
+ build_header_value(v)
+ .map_err(|err| err.with_context("key",
"server_side_encryption_key_id"))?,
+ ),
+ };
+
let mut cfg = AliyunConfig::default();
// Load cfg from env first.
cfg = cfg.from_env();
@@ -338,6 +396,8 @@ impl Builder for OssBuilder {
signer,
loader,
client,
+ server_side_encryption,
+ server_side_encryption_key_id,
}),
})
}
diff --git a/core/src/services/oss/core.rs b/core/src/services/oss/core.rs
index 1129f72e..8a4670e7 100644
--- a/core/src/services/oss/core.rs
+++ b/core/src/services/oss/core.rs
@@ -27,6 +27,8 @@ use http::header::CONTENT_TYPE;
use http::header::IF_MATCH;
use http::header::IF_NONE_MATCH;
use http::header::RANGE;
+use http::HeaderName;
+use http::HeaderValue;
use http::Request;
use http::Response;
use reqsign::AliyunCredential;
@@ -40,6 +42,10 @@ use crate::raw::*;
use crate::*;
mod constants {
+ pub const X_OSS_SERVER_SIDE_ENCRYPTION: &str =
"x-oss-server-side-encryption";
+
+ pub const X_OSS_SERVER_SIDE_ENCRYPTION_KEY_ID: &str =
"x-oss-server-side-encryption-key-id";
+
pub const RESPONSE_CONTENT_DISPOSITION: &str =
"response-content-disposition";
}
@@ -53,6 +59,9 @@ pub struct OssCore {
pub endpoint: String,
pub presign_endpoint: String,
+ pub server_side_encryption: Option<HeaderValue>,
+ pub server_side_encryption_key_id: Option<HeaderValue>,
+
pub client: HttpClient,
pub loader: AliyunLoader,
pub signer: AliyunOssSigner,
@@ -110,6 +119,31 @@ impl OssCore {
pub async fn send(&self, req: Request<AsyncBody>) ->
Result<Response<IncomingAsyncBody>> {
self.client.send(req).await
}
+
+ /// Set sse headers
+ /// # Note
+ /// According to the OSS documentation, only PutObject, CopyObject, and
InitiateMultipartUpload may require to be set.
+ pub fn insert_sse_headers(&self, mut req: http::request::Builder) ->
http::request::Builder {
+ if let Some(v) = &self.server_side_encryption {
+ let mut v = v.clone();
+ v.set_sensitive(true);
+
+ req = req.header(
+
HeaderName::from_static(constants::X_OSS_SERVER_SIDE_ENCRYPTION),
+ v,
+ )
+ }
+ if let Some(v) = &self.server_side_encryption_key_id {
+ let mut v = v.clone();
+ v.set_sensitive(true);
+
+ req = req.header(
+
HeaderName::from_static(constants::X_OSS_SERVER_SIDE_ENCRYPTION_KEY_ID),
+ v,
+ )
+ }
+ req
+ }
}
impl OssCore {
@@ -144,6 +178,9 @@ impl OssCore {
req = req.header(CACHE_CONTROL, cache_control)
}
+ // set sse headers
+ req = self.insert_sse_headers(req);
+
let req = req.body(body).map_err(new_request_build_error)?;
Ok(req)
}
@@ -333,8 +370,13 @@ impl OssCore {
);
let source = format!("/{}/{}", self.bucket,
percent_encode_path(&source));
- let mut req = Request::put(&url)
- .header("x-oss-copy-source", source)
+ let mut req = Request::put(&url);
+
+ req = self.insert_sse_headers(req);
+
+ req = req.header("x-oss-copy-source", source);
+
+ let mut req = req
.body(AsyncBody::Empty)
.map_err(new_request_build_error)?;
@@ -438,7 +480,7 @@ impl OssCore {
if let Some(cache_control) = cache_control {
req = req.header(CACHE_CONTROL, cache_control);
}
-
+ req = self.insert_sse_headers(req);
let mut req = req.body(body).map_err(new_request_build_error)?;
self.sign(&mut req).await?;
Ok(req)