This commit is contained in:
2026-03-15 11:36:47 +08:00
parent 0ab1ececba
commit ff6becc72c
5 changed files with 140 additions and 18 deletions

33
Cargo.lock generated
View File

@@ -1898,6 +1898,8 @@ dependencies = [
"reqwest",
"rust_util",
"sequoia-openpgp",
"serde",
"serde_json",
"sha-1",
"tar",
"tiny-encrypt",
@@ -2666,18 +2668,28 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.216"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.216"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
@@ -2686,14 +2698,15 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.133"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
"zmij",
]
[[package]]
@@ -3873,6 +3886,12 @@ dependencies = [
"zstd",
]
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]]
name = "zopfli"
version = "0.8.1"

View File

@@ -29,3 +29,5 @@ tar = "0.4"
flate2 = "1.0"
rust_util = "0.6"
tiny-encrypt = { version = "1.8", default-features = false }
serde = { version = "1.0.228", features = ["serde_derive"] }
serde_json = "1.0.149"

View File

@@ -68,3 +68,18 @@ cd nettle
make
sudo make install
```
<br>
Use STS token resolver:
```json
{
"oss_config": {
"endpoint": "_endpoint",
"sts_token_resolver": ["assume-role.ts", "ROLE_ARN"],
"bucket": "_bucket",
"path": "_path"
}
}
```

View File

@@ -1,10 +1,9 @@
use chrono::Utc;
use json::JsonValue;
use rust_util::{new_box_ioerror, XResult};
use std::{
fs,
path::Path,
};
use rust_util::{new_box_ioerror, util_cmd, XResult};
use serde::Deserialize;
use std::process::Command;
use std::{fs, path::Path};
pub const NAME: &str = env!("CARGO_PKG_NAME");
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -37,11 +36,22 @@ const ETC_OSS_BACKUPD_CONFIG: &str = "/etc/oss-backupd/config.json";
}
*/
#[derive(Debug, Deserialize)]
pub struct StsResolverResponse {
pub mode: String,
pub access_key_id: String,
pub access_key_secret: String,
pub sts_token: String,
pub expiration: String,
}
#[derive(Debug, Clone)]
pub struct OSSConfig {
pub endpoint: Option<String>,
pub access_key_id: Option<String>,
pub access_key_secret: Option<String>,
pub security_token: Option<String>,
pub sts_token_resolver: Option<Vec<String>>,
pub bucket: Option<String>,
pub path: Option<String>,
}
@@ -184,6 +194,12 @@ fn parse_oss_backupd_config_item(
if oc.access_key_secret.is_none() && root_oc.access_key_secret.is_some() {
oc.access_key_secret = root_oc.access_key_secret.clone();
}
if oc.security_token.is_none() && root_oc.security_token.is_some() {
oc.security_token = root_oc.security_token.clone();
}
if oc.sts_token_resolver.is_none() && root_oc.sts_token_resolver.is_some() {
oc.sts_token_resolver = root_oc.sts_token_resolver.clone();
}
if oc.bucket.is_none() && root_oc.bucket.is_some() {
oc.bucket = root_oc.bucket.clone();
}
@@ -249,13 +265,68 @@ fn parse_sub_oss_config(json: &json::JsonValue) -> Option<OSSConfig> {
}
fn parse_oss_config(oss_config: &json::JsonValue) -> OSSConfig {
OSSConfig {
let mut oss_config = OSSConfig {
endpoint: get_string_value(oss_config, "endpoint"),
access_key_id: get_string_value(oss_config, "access_key_id"),
access_key_secret: get_string_value(oss_config, "access_key_secret"),
security_token: None,
sts_token_resolver: get_string_array_value(oss_config, "sts_token_resolver"),
bucket: get_string_value(oss_config, "bucket"),
path: get_string_value(oss_config, "path"),
};
if oss_config.sts_token_resolver.is_some()
&& oss_config.access_key_id.is_none()
&& oss_config.access_key_secret.is_none()
{
if let Some(sts_token_resolver) = &oss_config.sts_token_resolver {
if sts_token_resolver.len() > 0 {
let mut cmd = Command::new(&sts_token_resolver[0]);
for arg in sts_token_resolver.iter().skip(1) {
cmd.arg(arg);
}
match util_cmd::run_command_and_wait(&mut cmd) {
Ok(exit_status) => {
if exit_status.success() {
match cmd.output() {
Ok(output) => {
match serde_json::from_slice::<StsResolverResponse>(
output.stdout.as_slice(),
) {
Ok(sts_resolver_response) => {
oss_config.access_key_id = Some(sts_resolver_response.access_key_id);
oss_config.access_key_secret = Some(sts_resolver_response.access_key_secret);
oss_config.security_token = Some(sts_resolver_response.sts_token);
}
Err(err) => {
failure!(
"Parse {:?} response failed: {}",
sts_token_resolver,
err
);
}
}
}
Err(err) => {
failure!("Execute {:?} failed: {}", sts_token_resolver, err);
}
}
} else {
failure!(
"Execute {:?} exit failed: {}",
sts_token_resolver,
exit_status
);
}
}
Err(err) => {
failure!("Execute {:?} failed: {}", sts_token_resolver, err);
}
}
}
}
}
oss_config
}
fn get_string_value(json: &JsonValue, key: &str) -> Option<String> {
@@ -263,6 +334,20 @@ fn get_string_value(json: &JsonValue, key: &str) -> Option<String> {
value.as_str().map(|s| s.to_owned())
}
fn get_string_array_value(json: &JsonValue, key: &str) -> Option<Vec<String>> {
let value = &json[key];
if let JsonValue::Array(array) = value {
let mut arr = vec![];
for value in array {
if let Some(s) = value.as_str() {
arr.push(s.to_owned());
}
}
return Some(arr);
}
return None;
}
fn get_tiny_encrypt_value(json: &JsonValue) -> Option<TinyEncryptConfig> {
let tiny_encrypt = &json["tiny_encrypt"];
let config = get_string_value(tiny_encrypt, "config");
@@ -324,10 +409,11 @@ fn get_config_content(custom_oss_backupd_config: Option<&str>, verbose: bool) ->
}
};
}
let home_dot_oss_backupd_config = &get_user_home_dir(DOT_OSS_BACKUPD_CONFIG).unwrap_or_else(|e| {
warning!("Get user home error: {}", e);
String::new()
});
let home_dot_oss_backupd_config =
&get_user_home_dir(DOT_OSS_BACKUPD_CONFIG).unwrap_or_else(|e| {
warning!("Get user home error: {}", e);
String::new()
});
if !home_dot_oss_backupd_config.is_empty() {
let home_dot_oss_backupd_config_path = Path::new(home_dot_oss_backupd_config);
if home_dot_oss_backupd_config_path.exists() {

View File

@@ -16,7 +16,7 @@ use std::{
fs::{ self, File },
};
use std::path::PathBuf;
use rust_util::{XResult, util_time::*, util_msg::*};
use rust_util::{XResult, util_time::*};
use tiny_encrypt::CmdEncrypt;
use oss_util::*;
use config_util::*;