34个版本 (稳定)
1.14.0 | 2024年7月12日 |
---|---|
1.12.0 | 2024年1月2日 |
1.10.1 | 2023年10月1日 |
1.8.0 | 2023年4月13日 |
0.10.0 | 2022年7月31日 |
#86 在 密码学
每月1,085次下载
135KB
3K SLoC
Rust Secret Vault
库提供以下crate
- 通用秘密值类型 - 一种简单的秘密类型实现,支持安全的序列化(serde和proto)。
- 秘密保险库 - 提供一个内存存储库,用于存储与应用程序秘密集成的外部秘密来源。
秘密保险库
库支持来自以下来源的秘密
- Google Cloud Secret Manager
- Amazon Secrets Manager
- 环境变量
- 文件来源(主要设计为读取作为文件挂载的K8S秘密)
- 由密码学伪随机数生成器生成的临时可用秘密生成器
特性
- 从定义的来源读取/缓存已注册的秘密及其元数据到内存中;
- 使用AEAD密码学进行内存加密(可选);
- 自动从来源刷新秘密的支持(可选);
- 可扩展和强类型API,可以实现任何类型的来源;
- 使用Google/AWS KMS 信封加密进行内存加密(可选);
- 多来源支持;
- 性能关键秘密的快照;
快速入门
Cargo.toml
[dependencies]
secret-vault = { version = "1.8", features=["..."] }
secret-vault-type = { version = "0.3" }
有关版本问题的安全考虑,请参阅以下内容。
Secret Vault提供的可选功能
gcp-secretmanager
用于Google Secret Manager支持aws-secretmanager
用于Amazon Secret Manager支持ring-aead-encryption
用于使用Ring AEAD加密支持gcp-kms-encryption
用于Google KMS信封加密支持aws-kms-encryption
用于Amazon KMS信封加密支持serde
用于serde序列化支持ahash
用于基于AHashMap的映射和快照
使用AEAD加密的GCP示例
// Describing secrets and marking them non-required
// since this is only example and they don't exist in your project
let secret1 = SecretVaultRef::new("test-secret1".into()).with_required(false);
let secret2 = SecretVaultRef::new("test-secret2".into())
.with_secret_version("1".into())
.with_required(false);
// Building the vault
let vault = SecretVaultBuilder::with_source(
gcp::GcpSecretManagerSource::new(&config_env_var("PROJECT_ID")?).await?,
)
.with_encryption(ring_encryption::SecretVaultRingAeadEncryption::new()?)
.with_secret_refs(vec![&secret1, &secret2])
.build()?;
// Load secrets from the source
vault.refresh().await?;
// Reading the secret values
let secret: Option<Secret> = vault.get_secret_by_ref(&secret1).await?;
// Or if you require it available
let secret: Secret = vault.require_secret_by_ref(&secret1).await?;
println!("Received secret: {:?}", secret);
// Using the Viewer API to share only methods able to read secrets
let vault_viewer = vault.viewer();
vault_viewer.get_secret_by_ref(&secret2).await?;
要运行此示例,请使用环境变量
# PROJECT_ID=<your-google-project-id> cargo run --example gcloud_secret_manager_vault
所有示例均可在secret-vault/examples目录中找到。
全局使用 SecretVaultRef
由于它们不包含任何敏感信息,在您的应用程序内部全局使用这些引用是很方便的。为了便于使用,请考虑使用如 lazy_static
或 once_cell
这样的crate。
use once_cell::sync::Lazy;
pub static MY_SECRET_REF: Lazy<SecretVaultRef> = Lazy::new(|| {
SecretVaultRef::new("my-secret".into())
});
多个来源
该库支持使用命名空间的概念同时从多个来源读取。
let secret_aws_namespace: SecretNamespace = "aws".into();
let secret_env_namespace: SecretNamespace = "env".into();
SecretVaultBuilder::with_source(
MultipleSecretsSources::new()
.add_source(&secret_env_namespace, InsecureEnvSource::new())
.add_source(&secret_aws_namespace,
aws::AwsSecretManagerSource::new(&config_env_var("ACCOUNT_ID")?).await?
)
)
let secret_ref_aws = SecretVaultRef::new("test-secret-xRnpry".into()).with_namespace(secret_aws_namespace.clone());
let secret_ref_env = SecretVaultRef::new("user".into()).with_namespace(secret_env_namespace.clone());
vault.register_secrets_refs(vec![&secret_ref_aws, &secret_ref_env]).refresh().await?;
从 GCP/AWS 密钥管理器读取秘密元数据
默认情况下,由于需要更多权限,从秘密中读取元数据(如标签和过期日期)是禁用的。要启用它,请使用选项(GCP 示例)。
// Building the vault
let vault = SecretVaultBuilder::with_source(
gcp::GcpSecretManagerSource::with_options(
gcp::GcpSecretManagerSourceOptions::new(config_env_var("PROJECT_ID")?)
.with_read_metadata(true),
)
.await?,
)
安全考虑和风险
OSS
开源代码是通过软件开发者的自愿协作创建的。原始作者许可代码,以便任何人都可以查看、修改和分发其新版本。您应该使用与商业产品相同的程序和工具来管理所有OSS。始终培训您的员工了解网络安全最佳实践,这可以帮助他们安全地使用和管理软件产品。您不应仅依赖个人,特别是像这样的项目,读取敏感信息。
版本控制
请不要使用广泛的版本依赖管理,以免在没有审计更改的情况下自动包含新版本的依赖项。
使用 IAM 和服务帐户在 GCP/AWS 中保护您的秘密
不要将所有秘密暴露给应用程序。使用 IAM 和不同的服务帐户,仅按需提供访问权限。
零化、保护内存和加密并不提供100%的安全性
在协议层(例如,官方亚马逊 SDK)上仍然存在分配,没有 KMS,内存中仍有会话密钥等。
因此,不要认为这是一个针对所有可能攻击的完全安全解决方案。没有在硬件/OS级别(例如,Intel SGX 项目)实现额外的支持,某些攻击的缓解是不可能的。
一般来说,将其视为减轻某些风险的小额外努力,但请记住,这不是您唯一应该依赖的解决方案。
目前可用的最安全设置/配置是
- GCP 密钥管理器 + KMS 封装加密和 AEAD
因为在 GCP 中,还有额外的努力在 Google Cloud SDK 中提供了与该库的集成。这是 Google 没有为 Rust 提供官方 SDK 的一个意外副作用。
快照
对于性能关键的秘密,有快照支持,减少了加密带来的开销
- 因此,快照始终解密
- 异步运行时和可能的网络调用(例如,KMS 等)
- RwLock 同步
要使秘密可用于快照,您需要显式使用 with_allow_in_snapshots
为秘密引用启用它。有关完整示例,请参阅 hashmap_snapshot.rs 并验证以下性能差异。
性能
测试配置
- 最多 1000 个生成的秘密
- CPU: Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz
加密、未加密保险库和快照读取性能的比较
read-secrets-perf-simple-vault
time: [143.53 ns 144.16 ns 144.77 ns]
read-secrets-perf-encrypted-vault
time: [338.62 ns 339.29 ns 340.22 ns]
read-secrets-perf-std-hash-snapshot
time: [89.188 ns 89.221 ns 89.266 ns]
read-secrets-perf-ahash-snapshot
time: [68.096 ns 68.202 ns 68.339 ns]
无需停机即可轮换应用程序秘密策略
这主要是特定于应用程序的领域,但一般思路是至少有两个秘密版本
- 当前/最新版本的秘密,将用于您应用程序中的新交易/请求/数据。
- 之前的版本仍需有效以便交互。
然后您有配置/版本管理两种选项
- 使用您应用程序中包含这些版本的某些配置,并在需要轮换时重新部署您的应用程序。这意味着它将在开始时触发刷新所有密钥。推荐用于大多数情况,因为这种方法更易于审计且更具声明性。
- 使用
SecretVaultAutoRefresher
(或您自己的实现) 自动更新密钥及其版本,而不需要重新部署。
许可
Apache软件许可(ASL)
作者
Abdulla Abdurakhmanov
依赖项
~4–40MB
~583K SLoC