mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 09:40:32 +00:00
* add crates homepage,description,keywords,categories,documentation * add readme * modify version 0.0.3 * cargo fmt * fix: yaml.docker-compose.security.no-new-privileges.no-new-privileges-docker-compose.yml (#63) * Feature up/ilm (#61) * fix delete-marker expiration. add api_restore. * remove target return 204 * log level * fix: make lint build and clippy happy (#71) Signed-off-by: yihong0618 <zouzou0208@gmail.com> * fix: make ci and local use the same toolchain (#72) Signed-off-by: yihong0618 <zouzou0208@gmail.com> * feat: optimize GitHub Actions workflows with performance improvements (#77) * feat: optimize GitHub Actions workflows with performance improvements - Rename workflows with more descriptive names - Add unified setup action for consistent environment setup - Optimize caching strategy with Swatinem/rust-cache@v2 - Implement skip-check mechanism to avoid duplicate builds - Simplify matrix builds with better include/exclude logic - Add intelligent build strategy checks - Optimize Docker multi-arch builds - Improve artifact naming and retention - Add performance testing with benchmark support - Enhance security audit with dependency scanning - Change Chinese comments to English for better maintainability Performance improvements: - CI testing: ~35 min (42% faster) - Build release: ~60 min (50% faster) - Docker builds: ~45 min (50% faster) - Security audit: ~8 min (47% faster) * fix: correct secrets context usage in GitHub Actions workflow - Move environment variables to job level to fix secrets access issue - Fix unrecognized named-value 'secrets' error in if condition - Ensure OSS upload step can properly check for required secrets * fix: resolve GitHub API rate limit by adding authentication token - Add github-token input to setup action to authenticate GitHub API requests - Pass GITHUB_TOKEN to all setup action usages to avoid rate limiting - Fix arduino/setup-protoc@v3 API access issues in CI/CD workflows - Ensure protoc installation can successfully access GitHub releases API * fix:make bucket err (#85) * Rename DEVELOPMENT.md to CONTRIBUTING.md * Create issue-translator.yml (#89) Enable Issues Translator * fix(dockerfile): correct env variable names for access/secret key and improve compatibility (#90) * fix: restore Zig and cargo-zigbuild caching in GitHub Actions setup action (#92) * fix: restore Zig and cargo-zigbuild caching in GitHub Actions setup action Use mlugg/setup-zig and taiki-e/cache-cargo-install-action to speed up cross-compilation tool installation and avoid repeated downloads. All comments and code are in English. * fix: use correct taiki-e/install-action for cargo-zigbuild Use taiki-e/install-action@cargo-zigbuild instead of taiki-e/cache-cargo-install-action@v2 to match the original implementation from PR #77. * refactor: remove explicit Zig version to use latest stable * Create CODE_OF_CONDUCT.md * Create SECURITY.md * Update issue templates * Create CLA.md * docs: update PR template to English version * fix: improve data scanner random sleep calculation - Fix random number generation API usage - Adjust sleep calculation to follow MinIO pattern - Ensure proper random range for scanner cycles Signed-off-by: junxiang Mu <1948535941@qq.com> * fix: soupprt ipv6 * improve log * add client ip log * Update rustfs/src/console.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * improve code * feat: unify package format to zip for all platforms --------- Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: junxiang Mu <1948535941@qq.com> Co-authored-by: kira-offgrid <kira@offgridsec.com> Co-authored-by: likewu <likewu@126.com> Co-authored-by: laoliu <lygn128@163.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: 安正超 <anzhengchao@gmail.com> Co-authored-by: weisd <im@weisd.in> Co-authored-by: Yone <zhiyu@live.cn> Co-authored-by: loverustfs <155562731+loverustfs@users.noreply.github.com> Co-authored-by: junxiang Mu <1948535941@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
128 lines
6.0 KiB
Rust
128 lines
6.0 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use rsa::Pkcs1v15Encrypt;
|
|
use rsa::{
|
|
RsaPrivateKey, RsaPublicKey,
|
|
pkcs8::{DecodePrivateKey, DecodePublicKey},
|
|
rand_core::OsRng,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::io::{Error, Result};
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
|
pub struct Token {
|
|
pub name: String, // Application ID
|
|
pub expired: u64, // Expiry time (UNIX timestamp)
|
|
}
|
|
|
|
/// Public key generation Token
|
|
/// [token] Token object
|
|
/// [key] Public key string
|
|
/// Returns the encrypted string processed by base64
|
|
pub fn gencode(token: &Token, key: &str) -> Result<String> {
|
|
let data = serde_json::to_vec(token)?;
|
|
let public_key = RsaPublicKey::from_public_key_pem(key).map_err(Error::other)?;
|
|
let encrypted_data = public_key.encrypt(&mut OsRng, Pkcs1v15Encrypt, &data).map_err(Error::other)?;
|
|
Ok(base64_simd::URL_SAFE_NO_PAD.encode_to_string(&encrypted_data))
|
|
}
|
|
|
|
/// Private key resolution Token
|
|
/// [token] Encrypted string processed by base64
|
|
/// [key] Private key string
|
|
/// Return to the Token object
|
|
pub fn parse(token: &str, key: &str) -> Result<Token> {
|
|
let encrypted_data = base64_simd::URL_SAFE_NO_PAD
|
|
.decode_to_vec(token.as_bytes())
|
|
.map_err(Error::other)?;
|
|
let private_key = RsaPrivateKey::from_pkcs8_pem(key).map_err(Error::other)?;
|
|
let decrypted_data = private_key.decrypt(Pkcs1v15Encrypt, &encrypted_data).map_err(Error::other)?;
|
|
let res: Token = serde_json::from_slice(&decrypted_data)?;
|
|
Ok(res)
|
|
}
|
|
|
|
pub fn parse_license(license: &str) -> Result<Token> {
|
|
parse(license, TEST_PRIVATE_KEY)
|
|
// match parse(license, TEST_PRIVATE_KEY) {
|
|
// Ok(token) => {
|
|
// if token.expired > SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() {
|
|
// Ok(token)
|
|
// } else {
|
|
// Err("Token expired".into())
|
|
// }
|
|
// }
|
|
// Err(e) => Err(e),
|
|
// }
|
|
}
|
|
|
|
static TEST_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCj86SrJIuxSxR6\nBJ/dlJEUIj6NeBRnhLQlCDdovuz61+7kJXVcxaR66w4m8W7SLEUP+IlPtnn6vmiG\n7XMhGNHIr7r1JsEVVLhZmL3tKI66DEZl786ZhG81BWqUlmcooIPS8UEPZNqJXLuz\nVGhxNyVGbj/tV7QC2pSISnKaixc+nrhxvo7w56p5qrm9tik0PjTgfZsUePkoBsSN\npoRkAauS14MAzK6HGB75CzG3dZqXUNWSWVocoWtQbZUwFGXyzU01ammsHQDvc2xu\nK1RQpd1qYH5bOWZ0N0aPFwT0r59HztFXg9sbjsnuhO1A7OiUOkc6iGVuJ0wm/9nA\nwZIBqzgjAgMBAAECggEAPMpeSEbotPhNw2BrllE76ec4omPfzPJbiU+em+wPGoNu\nRJHPDnMKJbl6Kd5jZPKdOOrCnxfd6qcnQsBQa/kz7+GYxMV12l7ra+1Cnujm4v0i\nLTHZvPpp8ZLsjeOmpF3AAzsJEJgon74OqtOlVjVIUPEYKvzV9ijt4gsYq0zfdYv0\nhrTMzyrGM4/UvKLsFIBROAfCeWfA7sXLGH8JhrRAyDrtCPzGtyyAmzoHKHtHafcB\nuyPFw/IP8otAgpDk5iiQPNkH0WwzAQIm12oHuNUa66NwUK4WEjXTnDg8KeWLHHNv\nIfN8vdbZchMUpMIvvkr7is315d8f2cHCB5gEO+GWAQKBgQDR/0xNll+FYaiUKCPZ\nvkOCAd3l5mRhsqnjPQ/6Ul1lAyYWpoJSFMrGGn/WKTa/FVFJRTGbBjwP+Mx10bfb\ngUg2GILDTISUh54fp4zngvTi9w4MWGKXrb7I1jPkM3vbJfC/v2fraQ/r7qHPpO2L\nf6ZbGxasIlSvr37KeGoelwcAQQKBgQDH3hmOTS2Hl6D4EXdq5meHKrfeoicGN7m8\noQK7u8iwn1R9zK5nh6IXxBhKYNXNwdCQtBZVRvFjjZ56SZJb7lKqa1BcTsgJfZCy\nnI3Uu4UykrECAH8AVCVqBXUDJmeA2yE+gDAtYEjvhSDHpUfWxoGHr0B/Oqk2Lxc/\npRy1qV5fYwKBgBWSL/hYVf+RhIuTg/s9/BlCr9SJ0g3nGGRrRVTlWQqjRCpXeFOO\nJzYqSq9pFGKUggEQxoOyJEFPwVDo9gXqRcyov+Xn2kaXl7qQr3yoixc1YZALFDWY\nd1ySBEqQr0xXnV9U/gvEgwotPRnjSzNlLWV2ZuHPtPtG/7M0o1H5GZMBAoGAKr3N\nW0gX53o+my4pCnxRQW+aOIsWq1a5aqRIEFudFGBOUkS2Oz+fI1P1GdrRfhnnfzpz\n2DK+plp/vIkFOpGhrf4bBlJ2psjqa7fdANRFLMaAAfyXLDvScHTQTCcnVUAHQPVq\n2BlSH56pnugyj7SNuLV6pnql+wdhAmRN2m9o1h8CgYAbX2juSr4ioXwnYjOUdrIY\n4+ERvHcXdjoJmmPcAm4y5NbSqLXyU0FQmplNMt2A5LlniWVJ9KNdjAQUt60FZw/+\nr76LdxXaHNZghyx0BOs7mtq5unSQXamZ8KixasfhE9uz3ij1jXjG6hafWkS8/68I\nuWbaZqgvy7a9oPHYlKH7Jg==\n-----END PRIVATE KEY-----\n";
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use rsa::{
|
|
RsaPrivateKey,
|
|
pkcs8::{EncodePrivateKey, EncodePublicKey, LineEnding},
|
|
};
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
#[test]
|
|
fn test_gencode_and_parse() {
|
|
let mut rng = OsRng;
|
|
let bits = 2048;
|
|
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("Failed to generate private key");
|
|
let public_key = RsaPublicKey::from(&private_key);
|
|
|
|
let private_key_pem = private_key.to_pkcs8_pem(LineEnding::LF).unwrap();
|
|
let public_key_pem = public_key.to_public_key_pem(LineEnding::LF).unwrap();
|
|
|
|
let token = Token {
|
|
name: "test_app".to_string(),
|
|
expired: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 3600, // 1 hour from now
|
|
};
|
|
|
|
let encoded = gencode(&token, &public_key_pem).expect("Failed to encode token");
|
|
|
|
let decoded = parse(&encoded, &private_key_pem).expect("Failed to decode token");
|
|
|
|
assert_eq!(token.name, decoded.name);
|
|
assert_eq!(token.expired, decoded.expired);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_invalid_token() {
|
|
let private_key_pem = RsaPrivateKey::new(&mut OsRng, 2048)
|
|
.expect("Failed to generate private key")
|
|
.to_pkcs8_pem(LineEnding::LF)
|
|
.unwrap();
|
|
|
|
let invalid_token = "invalid_base64_token";
|
|
let result = parse(invalid_token, &private_key_pem);
|
|
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_gencode_with_invalid_key() {
|
|
let token = Token {
|
|
name: "test_app".to_string(),
|
|
expired: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 3600, // 1 hour from now
|
|
};
|
|
|
|
let invalid_key = "invalid_public_key";
|
|
let result = gencode(&token, invalid_key);
|
|
|
|
assert!(result.is_err());
|
|
}
|
|
}
|