diff --git a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
index 448b999143d3..ad1c1a557af4 100644
--- a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
+++ b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
@@ -187,7 +187,9 @@ class Azblob implements ServiceConfig {
*/
public final String encryptionAlgorithm;
/**
- * The encryption key of Azblob service backend.
+ * The Base64-encoded AES-256 customer-provided encryption key.
+ * The key must decode to exactly 32 bytes. Building an operator returns
+ * ConfigInvalid for invalid Base64 or a different decoded length.
*/
public final String encryptionKey;
/**
diff --git a/bindings/python/python/opendal/config.py b/bindings/python/python/opendal/config.py
index 2bc02ffd1439..b03821195cc6 100644
--- a/bindings/python/python/opendal/config.py
+++ b/bindings/python/python/opendal/config.py
@@ -96,7 +96,7 @@ class AzblobConfig(TypedDict):
encryption_algorithm: NotRequired[str]
"""The encryption algorithm of Azblob service backend."""
encryption_key: NotRequired[str]
- """The encryption key of Azblob service backend."""
+ """The Base64-encoded AES-256 customer-provided encryption key. The key must decode to exactly 32 bytes. Building an operator returns `ConfigInvalid` for invalid Base64 or a different decoded length."""
encryption_key_sha256: NotRequired[str]
"""The encryption key sha256 of Azblob service backend."""
endpoint: NotRequired[str]
diff --git a/core/services/azblob/src/backend.rs b/core/services/azblob/src/backend.rs
index 5208c4350521..1f8da3aeaca7 100644
--- a/core/services/azblob/src/backend.rs
+++ b/core/services/azblob/src/backend.rs
@@ -150,7 +150,9 @@ impl AzblobBuilder {
///
/// # Args
///
- /// `v`: Base64-encoded key that matches algorithm specified in `encryption_algorithm`.
+ /// `v`: Base64-encoded AES-256 key that decodes to exactly 32 bytes.
+ /// Building an operator returns [`ErrorKind::ConfigInvalid`] if the key
+ /// is not valid Base64 or has a different decoded length.
///
/// # Note
///
@@ -212,7 +214,9 @@ impl AzblobBuilder {
///
/// # Args
///
- /// `key`: Base64-encoded SHA256 digest of the key specified in encryption_key.
+ /// `key`: Raw AES-256 key containing exactly 32 bytes.
+ /// Building an operator returns [`ErrorKind::ConfigInvalid`] if the key
+ /// has a different length.
///
/// # Note
///
@@ -347,13 +351,32 @@ impl Builder for AzblobBuilder {
}
}
- let encryption_key =
- match &self.config.encryption_key {
- None => None,
- Some(v) => Some(build_header_value(v).map_err(|err| {
+ let encryption_key = match &self.config.encryption_key {
+ None => None,
+ Some(v) => {
+ let key = BASE64_STANDARD.decode(v).map_err(|_| {
+ Error::new(
+ ErrorKind::ConfigInvalid,
+ "encryption_key must be valid Base64",
+ )
+ .with_operation("Builder::build")
+ .with_context("service", AZBLOB_SCHEME)
+ .with_context("key", "encryption_key")
+ })?;
+ if key.len() != 32 {
+ return Err(Error::new(
+ ErrorKind::ConfigInvalid,
+ "encryption_key must decode to exactly 32 bytes",
+ )
+ .with_operation("Builder::build")
+ .with_context("service", AZBLOB_SCHEME)
+ .with_context("key", "encryption_key"));
+ }
+ Some(build_header_value(v).map_err(|err| {
err.with_context("key", "server_side_encryption_customer_key")
- })?),
- };
+ })?)
+ }
+ };
let encryption_key_sha256 = match &self.config.encryption_key_sha256 {
None => None,
@@ -663,3 +686,66 @@ impl Service for AzblobBackend {
)))
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn invalid_encoded_customer_keys_are_rejected() {
+ for key in [
+ String::new(),
+ "not-base64!".to_string(),
+ BASE64_STANDARD.encode([42; 16]),
+ BASE64_STANDARD.encode([42; 31]),
+ BASE64_STANDARD.encode([42; 33]),
+ BASE64_STANDARD.encode([42; 64]),
+ ] {
+ let config = AzblobConfig {
+ container: "test".to_string(),
+ endpoint: Some("https://test.blob.core.windows.net".to_string()),
+ encryption_key: Some(key.clone()),
+ ..Default::default()
+ };
+ let err = Operator::from_config(config).expect_err("invalid key must fail to build");
+ assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
+ let message = format!("{err:?}");
+ assert!(message.contains("encryption_key"));
+ if !key.is_empty() {
+ assert!(!message.contains(&key));
+ }
+ }
+ }
+
+ #[test]
+ fn invalid_raw_customer_keys_are_rejected() {
+ for len in [0, 16, 31, 33, 64] {
+ let builder = AzblobBuilder::default()
+ .container("test")
+ .endpoint("https://test.blob.core.windows.net")
+ .server_side_encryption_with_customer_key(&vec![42; len]);
+ let err = Operator::new(builder).expect_err("invalid key must fail to build");
+ assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
+ }
+ }
+
+ #[test]
+ fn valid_customer_keys_build() {
+ let key = [42; 32];
+ let builder = AzblobBuilder::default()
+ .container("test")
+ .endpoint("https://test.blob.core.windows.net")
+ .server_side_encryption_with_customer_key(&key);
+ Operator::new(builder).expect("32-byte raw key must build");
+
+ let config = AzblobConfig {
+ container: "test".to_string(),
+ endpoint: Some("https://test.blob.core.windows.net".to_string()),
+ encryption_key: Some(BASE64_STANDARD.encode(key)),
+ encryption_key_sha256: Some(BASE64_STANDARD.encode(Sha256::digest(key))),
+ encryption_algorithm: Some("AES256".to_string()),
+ ..Default::default()
+ };
+ Operator::from_config(config).expect("Base64-encoded 32-byte key must build");
+ }
+}
diff --git a/core/services/azblob/src/config.rs b/core/services/azblob/src/config.rs
index 0e8933ba2193..b9654f772eff 100644
--- a/core/services/azblob/src/config.rs
+++ b/core/services/azblob/src/config.rs
@@ -57,7 +57,10 @@ pub struct AzblobConfig {
)]
pub account_key: Option,
- /// The encryption key of Azblob service backend.
+ /// The Base64-encoded AES-256 customer-provided encryption key.
+ ///
+ /// The key must decode to exactly 32 bytes. Building an operator returns
+ /// `ConfigInvalid` for invalid Base64 or a different decoded length.
pub encryption_key: Option,
/// The encryption key sha256 of Azblob service backend.
diff --git a/website/data/services.json b/website/data/services.json
index d3aa21b40c95..008ae0add998 100644
--- a/website/data/services.json
+++ b/website/data/services.json
@@ -227,7 +227,7 @@
"type": "string",
"required": false,
"group": "General",
- "comments": "The encryption key of Azblob service backend."
+ "comments": "The Base64-encoded AES-256 customer-provided encryption key.\n\nThe key must decode to exactly 32 bytes. Building an operator returns\n`ConfigInvalid` for invalid Base64 or a different decoded length."
},
{
"name": "encryption_key_sha256",
@@ -274,37 +274,37 @@
"binding": "rust",
"language": "rust",
"minimal": "use opendal::Operator;\n\nlet operator = Operator::via_iter(\"azblob\", [\n (\"container\".to_string(), \"...\".to_string()),\n])?;",
- "full": "use opendal::Operator;\n\nlet operator = Operator::via_iter(\"azblob\", [\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The container name of Azblob service backend.\n (\"container\".to_string(), \"...\".to_string()),\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://accountname.blob.core.windows.net`\n // - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The account name of Azblob service backend.\n // (\"account_name\".to_string(), \"...\".to_string()),\n\n // The account key of Azblob service backend.\n // (\"account_key\".to_string(), \"...\".to_string()),\n\n // The encryption key of Azblob service backend.\n // (\"encryption_key\".to_string(), \"...\".to_string()),\n\n // The encryption key sha256 of Azblob service backend.\n // (\"encryption_key_sha256\".to_string(), \"...\".to_string()),\n\n // The encryption algorithm of Azblob service backend.\n // (\"encryption_algorithm\".to_string(), \"...\".to_string()),\n\n // The sas token of Azblob service backend.\n // (\"sas_token\".to_string(), \"...\".to_string()),\n\n // Skip signature will skip loading credentials and signing requests.\n // (\"skip_signature\".to_string(), \"true\".to_string()),\n])?;"
+ "full": "use opendal::Operator;\n\nlet operator = Operator::via_iter(\"azblob\", [\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // (\"root\".to_string(), \"...\".to_string()),\n\n // The container name of Azblob service backend.\n (\"container\".to_string(), \"...\".to_string()),\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://accountname.blob.core.windows.net`\n // - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n // (\"endpoint\".to_string(), \"...\".to_string()),\n\n // The account name of Azblob service backend.\n // (\"account_name\".to_string(), \"...\".to_string()),\n\n // The account key of Azblob service backend.\n // (\"account_key\".to_string(), \"...\".to_string()),\n\n // The Base64-encoded AES-256 customer-provided encryption key.\n //\n // The key must decode to exactly 32 bytes. Building an operator returns\n // `ConfigInvalid` for invalid Base64 or a different decoded length.\n // (\"encryption_key\".to_string(), \"...\".to_string()),\n\n // The encryption key sha256 of Azblob service backend.\n // (\"encryption_key_sha256\".to_string(), \"...\".to_string()),\n\n // The encryption algorithm of Azblob service backend.\n // (\"encryption_algorithm\".to_string(), \"...\".to_string()),\n\n // The sas token of Azblob service backend.\n // (\"sas_token\".to_string(), \"...\".to_string()),\n\n // Skip signature will skip loading credentials and signing requests.\n // (\"skip_signature\".to_string(), \"true\".to_string()),\n])?;"
},
{
"binding": "java",
"language": "java",
"minimal": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap config = new HashMap<>();\nconfig.put(\"container\", \"...\");\nOperator operator = Operator.of(\"azblob\", config);",
- "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap config = new HashMap<>();\n// The root of Azblob service backend.\n//\n// All operations will happen under this root.\n// config.put(\"root\", \"...\");\n\n// The container name of Azblob service backend.\nconfig.put(\"container\", \"...\");\n\n// The endpoint of Azblob service backend.\n//\n// Endpoint must be full uri, e.g.\n//\n// - Azblob: `https://accountname.blob.core.windows.net`\n// - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n// config.put(\"endpoint\", \"...\");\n\n// The account name of Azblob service backend.\n// config.put(\"account_name\", \"...\");\n\n// The account key of Azblob service backend.\n// config.put(\"account_key\", \"...\");\n\n// The encryption key of Azblob service backend.\n// config.put(\"encryption_key\", \"...\");\n\n// The encryption key sha256 of Azblob service backend.\n// config.put(\"encryption_key_sha256\", \"...\");\n\n// The encryption algorithm of Azblob service backend.\n// config.put(\"encryption_algorithm\", \"...\");\n\n// The sas token of Azblob service backend.\n// config.put(\"sas_token\", \"...\");\n\n// Skip signature will skip loading credentials and signing requests.\n// config.put(\"skip_signature\", \"true\");\nOperator operator = Operator.of(\"azblob\", config);"
+ "full": "import java.util.HashMap;\nimport java.util.Map;\nimport org.apache.opendal.Operator;\n\nMap config = new HashMap<>();\n// The root of Azblob service backend.\n//\n// All operations will happen under this root.\n// config.put(\"root\", \"...\");\n\n// The container name of Azblob service backend.\nconfig.put(\"container\", \"...\");\n\n// The endpoint of Azblob service backend.\n//\n// Endpoint must be full uri, e.g.\n//\n// - Azblob: `https://accountname.blob.core.windows.net`\n// - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n// config.put(\"endpoint\", \"...\");\n\n// The account name of Azblob service backend.\n// config.put(\"account_name\", \"...\");\n\n// The account key of Azblob service backend.\n// config.put(\"account_key\", \"...\");\n\n// The Base64-encoded AES-256 customer-provided encryption key.\n//\n// The key must decode to exactly 32 bytes. Building an operator returns\n// `ConfigInvalid` for invalid Base64 or a different decoded length.\n// config.put(\"encryption_key\", \"...\");\n\n// The encryption key sha256 of Azblob service backend.\n// config.put(\"encryption_key_sha256\", \"...\");\n\n// The encryption algorithm of Azblob service backend.\n// config.put(\"encryption_algorithm\", \"...\");\n\n// The sas token of Azblob service backend.\n// config.put(\"sas_token\", \"...\");\n\n// Skip signature will skip loading credentials and signing requests.\n// config.put(\"skip_signature\", \"true\");\nOperator operator = Operator.of(\"azblob\", config);"
},
{
"binding": "python",
"language": "python",
"minimal": "import opendal\n\noperator = opendal.Operator(\n \"azblob\",\n container=\"...\",\n)",
- "full": "import opendal\n\noperator = opendal.Operator(\n \"azblob\",\n # The root of Azblob service backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # The container name of Azblob service backend.\n container=\"...\",\n\n # The endpoint of Azblob service backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - Azblob: `https://accountname.blob.core.windows.net`\n # - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n # endpoint=\"...\",\n\n # The account name of Azblob service backend.\n # account_name=\"...\",\n\n # The account key of Azblob service backend.\n # account_key=\"...\",\n\n # The encryption key of Azblob service backend.\n # encryption_key=\"...\",\n\n # The encryption key sha256 of Azblob service backend.\n # encryption_key_sha256=\"...\",\n\n # The encryption algorithm of Azblob service backend.\n # encryption_algorithm=\"...\",\n\n # The sas token of Azblob service backend.\n # sas_token=\"...\",\n\n # Skip signature will skip loading credentials and signing requests.\n # skip_signature=\"true\",\n)"
+ "full": "import opendal\n\noperator = opendal.Operator(\n \"azblob\",\n # The root of Azblob service backend.\n #\n # All operations will happen under this root.\n # root=\"...\",\n\n # The container name of Azblob service backend.\n container=\"...\",\n\n # The endpoint of Azblob service backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - Azblob: `https://accountname.blob.core.windows.net`\n # - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n # endpoint=\"...\",\n\n # The account name of Azblob service backend.\n # account_name=\"...\",\n\n # The account key of Azblob service backend.\n # account_key=\"...\",\n\n # The Base64-encoded AES-256 customer-provided encryption key.\n #\n # The key must decode to exactly 32 bytes. Building an operator returns\n # `ConfigInvalid` for invalid Base64 or a different decoded length.\n # encryption_key=\"...\",\n\n # The encryption key sha256 of Azblob service backend.\n # encryption_key_sha256=\"...\",\n\n # The encryption algorithm of Azblob service backend.\n # encryption_algorithm=\"...\",\n\n # The sas token of Azblob service backend.\n # sas_token=\"...\",\n\n # Skip signature will skip loading credentials and signing requests.\n # skip_signature=\"true\",\n)"
},
{
"binding": "nodejs",
"language": "javascript",
"minimal": "import { Operator } from \"opendal\";\n\nconst operator = new Operator(\"azblob\", {\n container: \"...\",\n});",
- "full": "import { Operator } from \"opendal\";\n\nconst operator = new Operator(\"azblob\", {\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // The container name of Azblob service backend.\n container: \"...\",\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://accountname.blob.core.windows.net`\n // - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n // endpoint: \"...\",\n\n // The account name of Azblob service backend.\n // account_name: \"...\",\n\n // The account key of Azblob service backend.\n // account_key: \"...\",\n\n // The encryption key of Azblob service backend.\n // encryption_key: \"...\",\n\n // The encryption key sha256 of Azblob service backend.\n // encryption_key_sha256: \"...\",\n\n // The encryption algorithm of Azblob service backend.\n // encryption_algorithm: \"...\",\n\n // The sas token of Azblob service backend.\n // sas_token: \"...\",\n\n // Skip signature will skip loading credentials and signing requests.\n // skip_signature: \"true\",\n});"
+ "full": "import { Operator } from \"opendal\";\n\nconst operator = new Operator(\"azblob\", {\n // The root of Azblob service backend.\n //\n // All operations will happen under this root.\n // root: \"...\",\n\n // The container name of Azblob service backend.\n container: \"...\",\n\n // The endpoint of Azblob service backend.\n //\n // Endpoint must be full uri, e.g.\n //\n // - Azblob: `https://accountname.blob.core.windows.net`\n // - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n // endpoint: \"...\",\n\n // The account name of Azblob service backend.\n // account_name: \"...\",\n\n // The account key of Azblob service backend.\n // account_key: \"...\",\n\n // The Base64-encoded AES-256 customer-provided encryption key.\n //\n // The key must decode to exactly 32 bytes. Building an operator returns\n // `ConfigInvalid` for invalid Base64 or a different decoded length.\n // encryption_key: \"...\",\n\n // The encryption key sha256 of Azblob service backend.\n // encryption_key_sha256: \"...\",\n\n // The encryption algorithm of Azblob service backend.\n // encryption_algorithm: \"...\",\n\n // The sas token of Azblob service backend.\n // sas_token: \"...\",\n\n // Skip signature will skip loading credentials and signing requests.\n // skip_signature: \"true\",\n});"
},
{
"binding": "ruby",
"language": "ruby",
"minimal": "require \"opendal\"\n\noperator = OpenDal::Operator.new(\"azblob\", {\n \"container\" => \"...\",\n})",
- "full": "require \"opendal\"\n\noperator = OpenDal::Operator.new(\"azblob\", {\n # The root of Azblob service backend.\n #\n # All operations will happen under this root.\n # \"root\" => \"...\",\n\n # The container name of Azblob service backend.\n \"container\" => \"...\",\n\n # The endpoint of Azblob service backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - Azblob: `https://accountname.blob.core.windows.net`\n # - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n # \"endpoint\" => \"...\",\n\n # The account name of Azblob service backend.\n # \"account_name\" => \"...\",\n\n # The account key of Azblob service backend.\n # \"account_key\" => \"...\",\n\n # The encryption key of Azblob service backend.\n # \"encryption_key\" => \"...\",\n\n # The encryption key sha256 of Azblob service backend.\n # \"encryption_key_sha256\" => \"...\",\n\n # The encryption algorithm of Azblob service backend.\n # \"encryption_algorithm\" => \"...\",\n\n # The sas token of Azblob service backend.\n # \"sas_token\" => \"...\",\n\n # Skip signature will skip loading credentials and signing requests.\n # \"skip_signature\" => \"true\",\n})"
+ "full": "require \"opendal\"\n\noperator = OpenDal::Operator.new(\"azblob\", {\n # The root of Azblob service backend.\n #\n # All operations will happen under this root.\n # \"root\" => \"...\",\n\n # The container name of Azblob service backend.\n \"container\" => \"...\",\n\n # The endpoint of Azblob service backend.\n #\n # Endpoint must be full uri, e.g.\n #\n # - Azblob: `https://accountname.blob.core.windows.net`\n # - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n # \"endpoint\" => \"...\",\n\n # The account name of Azblob service backend.\n # \"account_name\" => \"...\",\n\n # The account key of Azblob service backend.\n # \"account_key\" => \"...\",\n\n # The Base64-encoded AES-256 customer-provided encryption key.\n #\n # The key must decode to exactly 32 bytes. Building an operator returns\n # `ConfigInvalid` for invalid Base64 or a different decoded length.\n # \"encryption_key\" => \"...\",\n\n # The encryption key sha256 of Azblob service backend.\n # \"encryption_key_sha256\" => \"...\",\n\n # The encryption algorithm of Azblob service backend.\n # \"encryption_algorithm\" => \"...\",\n\n # The sas token of Azblob service backend.\n # \"sas_token\" => \"...\",\n\n # Skip signature will skip loading credentials and signing requests.\n # \"skip_signature\" => \"true\",\n})"
},
{
"binding": "go",
"language": "go",
"minimal": "import (\n\t\"github.com/apache/opendal-go-services/azblob\"\n\topendal \"github.com/apache/opendal/bindings/go\"\n)\n\noperator, err := opendal.NewOperator(azblob.Scheme, opendal.OperatorOptions{\n\t\"container\": \"...\",\n})",
- "full": "import (\n\t\"github.com/apache/opendal-go-services/azblob\"\n\topendal \"github.com/apache/opendal/bindings/go\"\n)\n\noperator, err := opendal.NewOperator(azblob.Scheme, opendal.OperatorOptions{\n\t// The root of Azblob service backend.\n\t//\n\t// All operations will happen under this root.\n\t// \"root\": \"...\",\n\n\t// The container name of Azblob service backend.\n\t\"container\": \"...\",\n\n\t// The endpoint of Azblob service backend.\n\t//\n\t// Endpoint must be full uri, e.g.\n\t//\n\t// - Azblob: `https://accountname.blob.core.windows.net`\n\t// - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n\t// \"endpoint\": \"...\",\n\n\t// The account name of Azblob service backend.\n\t// \"account_name\": \"...\",\n\n\t// The account key of Azblob service backend.\n\t// \"account_key\": \"...\",\n\n\t// The encryption key of Azblob service backend.\n\t// \"encryption_key\": \"...\",\n\n\t// The encryption key sha256 of Azblob service backend.\n\t// \"encryption_key_sha256\": \"...\",\n\n\t// The encryption algorithm of Azblob service backend.\n\t// \"encryption_algorithm\": \"...\",\n\n\t// The sas token of Azblob service backend.\n\t// \"sas_token\": \"...\",\n\n\t// Skip signature will skip loading credentials and signing requests.\n\t// \"skip_signature\": \"true\",\n})"
+ "full": "import (\n\t\"github.com/apache/opendal-go-services/azblob\"\n\topendal \"github.com/apache/opendal/bindings/go\"\n)\n\noperator, err := opendal.NewOperator(azblob.Scheme, opendal.OperatorOptions{\n\t// The root of Azblob service backend.\n\t//\n\t// All operations will happen under this root.\n\t// \"root\": \"...\",\n\n\t// The container name of Azblob service backend.\n\t\"container\": \"...\",\n\n\t// The endpoint of Azblob service backend.\n\t//\n\t// Endpoint must be full uri, e.g.\n\t//\n\t// - Azblob: `https://accountname.blob.core.windows.net`\n\t// - Azurite: `http://127.0.0.1:10000/devstoreaccount1`\n\t// \"endpoint\": \"...\",\n\n\t// The account name of Azblob service backend.\n\t// \"account_name\": \"...\",\n\n\t// The account key of Azblob service backend.\n\t// \"account_key\": \"...\",\n\n\t// The Base64-encoded AES-256 customer-provided encryption key.\n\t//\n\t// The key must decode to exactly 32 bytes. Building an operator returns\n\t// `ConfigInvalid` for invalid Base64 or a different decoded length.\n\t// \"encryption_key\": \"...\",\n\n\t// The encryption key sha256 of Azblob service backend.\n\t// \"encryption_key_sha256\": \"...\",\n\n\t// The encryption algorithm of Azblob service backend.\n\t// \"encryption_algorithm\": \"...\",\n\n\t// The sas token of Azblob service backend.\n\t// \"sas_token\": \"...\",\n\n\t// Skip signature will skip loading credentials and signing requests.\n\t// \"skip_signature\": \"true\",\n})"
}
]
},