fnox-security-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Fnox - Security Best Practices

Fnox - 安全最佳实践

Security guidelines and best practices for managing secrets with Fnox.
使用Fnox管理密钥的安全指南与最佳实践。

Encryption Fundamentals

加密基础

Always Encrypt Sensitive Data

始终加密敏感数据

toml
undefined
toml
undefined

Bad: Plain text secrets committed to git

错误:将明文密钥提交至Git

[secrets] DATABASE_PASSWORD = "super-secret-password" API_KEY = "sk-live-12345"
[secrets] DATABASE_PASSWORD = "super-secret-password" API_KEY = "sk-live-12345"

Good: Encrypted secrets

正确:加密后的密钥

[providers.age] type = "age" public_keys = ["age1ql3z..."]
[secrets] DATABASE_PASSWORD = { provider = "age", value = "age[...]" } API_KEY = { provider = "age", value = "age[...]" }
undefined
[providers.age] type = "age" public_keys = ["age1ql3z..."]
[secrets] DATABASE_PASSWORD = { provider = "age", value = "age[...]" } API_KEY = { provider = "age", value = "age[...]" }
undefined

Use Strong Encryption

使用强加密算法

bash
undefined
bash
undefined

Good: age encryption (modern, secure)

推荐:age加密(现代、安全)

age-keygen -o ~/.config/fnox/keys/identity.txt
age-keygen -o ~/.config/fnox/keys/identity.txt

Good: Cloud KMS (managed encryption)

推荐:云KMS(托管式加密)

[providers.kms] type = "aws-kms" key_id = "arn:aws:kms:us-east-1:..."
undefined
[providers.kms] type = "aws-kms" key_id = "arn:aws:kms:us-east-1:..."
undefined

Key Management

密钥管理

Protect Private Keys

保护私钥安全

bash
undefined
bash
undefined

Store age private key securely

安全存储age私钥

chmod 600 ~/.config/fnox/keys/identity.txt
chmod 600 ~/.config/fnox/keys/identity.txt

Never commit private keys

切勿提交私钥

echo "*.txt" >> ~/.config/fnox/keys/.gitignore
undefined
echo "*.txt" >> ~/.config/fnox/keys/.gitignore
undefined

Separate Public and Private Keys

分离公钥与私钥

toml
undefined
toml
undefined

fnox.toml (committed) - public keys only

fnox.toml(可提交)- 仅包含公钥

[providers.age] type = "age" public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[providers.age] type = "age" public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]

fnox.local.toml (gitignored) - private keys

fnox.local.toml(需忽略Git提交)- 包含私钥

[providers.age] identity = "~/.config/fnox/keys/identity.txt"
undefined
[providers.age] identity = "~/.config/fnox/keys/identity.txt"
undefined

Rotate Keys Regularly

定期轮换密钥

bash
undefined
bash
undefined

Generate new age key

生成新的age密钥

age-keygen -o ~/.config/fnox/keys/identity-2025.txt
age-keygen -o ~/.config/fnox/keys/identity-2025.txt

Re-encrypt all secrets with new key

使用新密钥重新加密所有密钥

fnox get --all | fnox set --provider age-new
undefined
fnox get --all | fnox set --provider age-new
undefined

Access Control

访问控制

Use Least Privilege

遵循最小权限原则

toml
undefined
toml
undefined

Good: Separate secrets by environment

推荐:按环境分离密钥

[profiles.production] [profiles.production.providers.prod-secrets] type = "aws-sm" region = "us-east-1"
[profiles.production.secrets] DATABASE_URL = { provider = "prod-secrets", value = "prod/db" }
[profiles.development] [profiles.development.secrets] DATABASE_URL = "postgresql://localhost/dev" # Non-sensitive
undefined
[profiles.production] [profiles.production.providers.prod-secrets] type = "aws-sm" region = "us-east-1"
[profiles.production.secrets] DATABASE_URL = { provider = "prod-secrets", value = "prod/db" }
[profiles.development] [profiles.development.secrets] DATABASE_URL = "postgresql://localhost/dev" # 非敏感内容
undefined

Team Access Control

团队访问控制

toml
undefined
toml
undefined

Multiple age recipients for team

为团队设置多个age接收方

[providers.age] type = "age" public_keys = [ "age1ql3z...", # Alice (admin) "age1qw4r...", # Bob (developer)

Don't include contractors or temporary team members

]
undefined
[providers.age] type = "age" public_keys = [ "age1ql3z...", # Alice(管理员) "age1qw4r...", # Bob(开发人员)

请勿包含外包人员或临时团队成员

]
undefined

Role-Based Secrets

基于角色的密钥管理

toml
undefined
toml
undefined

Backend secrets

后端密钥

[providers.backend] type = "aws-sm" region = "us-east-1"
[providers.backend] type = "aws-sm" region = "us-east-1"

Frontend secrets (different access level)

前端密钥(不同访问级别)

[providers.frontend] type = "aws-sm" region = "us-east-1"
[secrets] BACKEND_DB_PASSWORD = { provider = "backend", value = "backend/db-pass" } FRONTEND_API_ENDPOINT = { provider = "frontend", value = "frontend/api-url" }
undefined
[providers.frontend] type = "aws-sm" region = "us-east-1"
[secrets] BACKEND_DB_PASSWORD = { provider = "backend", value = "backend/db-pass" } FRONTEND_API_ENDPOINT = { provider = "frontend", value = "frontend/api-url" }
undefined

Git Security

Git安全

Never Commit Sensitive Data

切勿提交敏感数据

gitignore
undefined
gitignore
undefined

.gitignore

.gitignore

fnox.local.toml *.age-identity.txt *.key *.pem .env
undefined
fnox.local.toml *.age-identity.txt *.key *.pem .env
undefined

Audit Git History

审计Git历史

bash
undefined
bash
undefined

Check for accidentally committed secrets

检查是否意外提交了密钥

git log -p | grep -i "password|secret|key"
git log -p | grep -i "password|secret|key"

Remove secrets from git history (if found)

从Git历史中移除密钥(若发现)

git filter-branch --force --index-filter
'git rm --cached --ignore-unmatch fnox.local.toml'
--prune-empty --tag-name-filter cat -- --all
undefined
git filter-branch --force --index-filter
'git rm --cached --ignore-unmatch fnox.local.toml'
--prune-empty --tag-name-filter cat -- --all
undefined

Use Pre-Commit Hooks

使用提交前钩子

bash
undefined
bash
undefined

.git/hooks/pre-commit

.git/hooks/pre-commit

#!/bin/bash if git diff --cached --name-only | grep -q "fnox.local.toml"; then echo "Error: Attempting to commit fnox.local.toml" exit 1 fi
#!/bin/bash if git diff --cached --name-only | grep -q "fnox.local.toml"; then echo "错误:尝试提交fnox.local.toml" exit 1 fi

Check for plain text secrets

检查明文密钥

if git diff --cached | grep -q "password.=."[^a]"; then echo "Warning: Possible plain text password detected" exit 1 fi
undefined
if git diff --cached | grep -q "password.=."[^a]"; then echo "警告:检测到可能的明文密码" exit 1 fi
undefined

Environment Separation

环境分离

Separate Development and Production

分离开发与生产环境

toml
undefined
toml
undefined

fnox.toml (development)

fnox.toml(开发环境)

[secrets] DATABASE_URL = "postgresql://localhost/dev" DEBUG = "true"
[secrets] DATABASE_URL = "postgresql://localhost/dev" DEBUG = "true"

fnox.production.toml (production secrets)

fnox.production.toml(生产环境密钥)

[providers.prod] type = "aws-sm" region = "us-east-1"
[secrets] DATABASE_URL = { provider = "prod", value = "prod/db-url" } DEBUG = "false"
undefined
[providers.prod] type = "aws-sm" region = "us-east-1"
[secrets] DATABASE_URL = { provider = "prod", value = "prod/db-url" } DEBUG = "false"
undefined

Use Profiles for Environments

使用配置文件区分环境

bash
undefined
bash
undefined

Development

开发环境

fnox exec -- node app.js
fnox exec -- node app.js

Staging

预发布环境

FNOX_PROFILE=staging fnox exec -- node app.js
FNOX_PROFILE=staging fnox exec -- node app.js

Production

生产环境

FNOX_PROFILE=production fnox exec -- node app.js
undefined
FNOX_PROFILE=production fnox exec -- node app.js
undefined

Cloud Provider Security

云服务商安全

AWS Best Practices

AWS最佳实践

toml
undefined
toml
undefined

Use IAM roles instead of access keys

使用IAM角色而非访问密钥

[providers.aws-sm] type = "aws-sm" region = "us-east-1"
[providers.aws-sm] type = "aws-sm" region = "us-east-1"

No access_key_id or secret_access_key

无需配置access_key_id或secret_access_key

Uses IAM role or AWS credentials chain

使用IAM角色或AWS凭证链

Restrict by resource tags

按资源标签限制访问

[providers.aws-sm] type = "aws-sm" region = "us-east-1"
[providers.aws-sm] type = "aws-sm" region = "us-east-1"

Ensure IAM policy limits access to specific secrets

确保IAM策略仅允许访问特定密钥

undefined
undefined

Azure Best Practices

Azure最佳实践

toml
undefined
toml
undefined

Use managed identity

使用托管标识

[providers.azure] type = "azure-kv" vault_url = "https://my-vault.vault.azure.net"
[providers.azure] type = "azure-kv" vault_url = "https://my-vault.vault.azure.net"

Authentication via Azure managed identity

通过Azure托管标识进行身份验证

undefined
undefined

GCP Best Practices

GCP最佳实践

toml
undefined
toml
undefined

Use service account with minimal permissions

使用权限最小化的服务账号

[providers.gcp] type = "gcp-sm" project_id = "my-project"
[providers.gcp] type = "gcp-sm" project_id = "my-project"

Service account with only secretmanager.versions.access

仅授予secretmanager.versions.access权限的服务账号

undefined
undefined

Audit and Monitoring

审计与监控

Log Secret Access

记录密钥访问日志

bash
undefined
bash
undefined

Enable audit logging in cloud providers

在云服务商中启用审计日志

AWS CloudTrail for Secrets Manager

AWS CloudTrail(用于Secrets Manager)

Azure Monitor for Key Vault

Azure Monitor(用于Key Vault)

GCP Cloud Audit Logs for Secret Manager

GCP Cloud Audit Logs(用于Secret Manager)

undefined
undefined

Monitor for Anomalies

监控异常行为

bash
undefined
bash
undefined

Check which secrets are accessed

查看哪些密钥被访问

fnox list
fnox list

Verify provider configuration

验证服务商配置

fnox doctor
fnox doctor

Test provider connectivity

测试服务商连接性

fnox provider test aws-sm
undefined
fnox provider test aws-sm
undefined

Regular Security Audits

定期安全审计

bash
undefined
bash
undefined

List all secrets

列出所有密钥

fnox list
fnox list

Verify encryption status

验证加密状态

fnox doctor
fnox doctor

Check for plain text secrets

检查明文密钥

grep -r "password.=."[^a]" fnox.toml
undefined
grep -r "password.=."[^a]" fnox.toml
undefined

Secrets Lifecycle

密钥生命周期

Rotate Secrets Regularly

定期轮换密钥

bash
undefined
bash
undefined

Generate new secret

生成新密钥

NEW_PASSWORD=$(openssl rand -base64 32)
NEW_PASSWORD=$(openssl rand -base64 32)

Update in fnox

在Fnox中更新密钥

echo "$NEW_PASSWORD" | fnox set DATABASE_PASSWORD
echo "$NEW_PASSWORD" | fnox set DATABASE_PASSWORD

Update in actual service (database, API, etc.)

在实际服务中更新(数据库、API等)

Then verify application still works

然后验证应用是否仍能正常运行

undefined
undefined

Remove Obsolete Secrets

移除废弃密钥

bash
undefined
bash
undefined

Remove unused secret

移除未使用的密钥

fnox unset OLD_API_KEY
fnox unset OLD_API_KEY

Clean up from cloud provider

从云服务商中清理

aws secretsmanager delete-secret --secret-id old/api-key
undefined
aws secretsmanager delete-secret --secret-id old/api-key
undefined

Document Secret Purpose

记录密钥用途

toml
[secrets]
STRIPE_API_KEY = {
  provider = "age",
  value = "age[...]",
  description = "Stripe secret key for payment processing. Rotate quarterly."
}

DATABASE_PASSWORD = {
  provider = "aws-sm",
  value = "prod/db-password",
  description = "PostgreSQL master password. Last rotated: 2025-01-01"
}
toml
[secrets]
STRIPE_API_KEY = {
  provider = "age",
  value = "age[...]",
  description = "Stripe支付处理的密钥,每季度轮换一次。"
}

DATABASE_PASSWORD = {
  provider = "aws-sm",
  value = "prod/db-password",
  description = "PostgreSQL主密码,上次轮换时间:2025-01-01"
}

CI/CD Security

CI/CD安全

Use Dedicated CI Keys

使用专用CI密钥

toml
undefined
toml
undefined

Separate age key for CI/CD

为CI/CD设置独立的age密钥

[providers.age] type = "age" public_keys = [ "age1ql3z...", # Developer key "age1ci3d...", # CI/CD key (limited access) ]
undefined
[providers.age] type = "age" public_keys = [ "age1ql3z...", # 开发人员密钥 "age1ci3d...", # CI/CD密钥(权限受限) ]
undefined

Restrict CI Secret Access

限制CI密钥访问权限

yaml
undefined
yaml
undefined

.github/workflows/deploy.yml

.github/workflows/deploy.yml

env: FNOX_PROFILE: production

Use GitHub secrets for age identity

AGE_IDENTITY: ${{ secrets.AGE_IDENTITY }}
steps:
  • name: Load secrets run: | echo "$AGE_IDENTITY" > /tmp/identity.txt chmod 600 /tmp/identity.txt fnox exec -- ./deploy.sh rm /tmp/identity.txt
undefined
env: FNOX_PROFILE: production

使用GitHub Secrets存储age身份信息

AGE_IDENTITY: ${{ secrets.AGE_IDENTITY }}
steps:
  • name: 加载密钥 run: | echo "$AGE_IDENTITY" > /tmp/identity.txt chmod 600 /tmp/identity.txt fnox exec -- ./deploy.sh rm /tmp/identity.txt
undefined

Minimal CI Permissions

最小化CI权限

toml
undefined
toml
undefined

CI profile with minimal secrets

仅包含必要密钥的CI配置文件

[profiles.ci] [profiles.ci.secrets] DEPLOY_TOKEN = { provider = "age", value = "age[...]" }
[profiles.ci] [profiles.ci.secrets] DEPLOY_TOKEN = { provider = "age", value = "age[...]" }

Don't include database passwords or API keys

请勿包含数据库密码或API密钥

undefined
undefined

Best Practices Summary

最佳实践总结

DO

建议做法

✅ Always encrypt sensitive secrets ✅ Use strong encryption (age, KMS) ✅ Store private keys securely ✅ Separate dev and prod secrets ✅ Use .gitignore for local overrides ✅ Rotate keys and secrets regularly ✅ Use cloud provider managed identities ✅ Audit secret access ✅ Document secret purpose ✅ Use profiles for environments
✅ 始终加密敏感密钥 ✅ 使用强加密算法(age、KMS) ✅ 安全存储私钥 ✅ 分离开发与生产环境密钥 ✅ 使用.gitignore忽略本地配置文件 ✅ 定期轮换密钥与密钥对 ✅ 使用云服务商托管标识 ✅ 审计密钥访问记录 ✅ 记录密钥用途 ✅ 使用配置文件区分环境

DON'T

禁止做法

❌ Never commit private keys ❌ Never use plain text for sensitive data ❌ Don't share private keys between team members ❌ Don't hardcode credentials ❌ Don't mix dev and prod secrets ❌ Don't skip encryption in production ❌ Don't ignore security warnings ❌ Don't use weak passwords as secrets
❌ 切勿提交私钥 ❌ 切勿将敏感数据以明文形式存储 ❌ 切勿在团队成员间共享私钥 ❌ 切勿硬编码凭证 ❌ 切勿混合开发与生产环境密钥 ❌ 生产环境中切勿跳过加密步骤 ❌ 切勿忽略安全警告 ❌ 切勿使用弱密码作为密钥

Common Threats and Mitigations

常见威胁与缓解措施

Threat: Accidental Commit

威胁:意外提交

bash
undefined
bash
undefined

Mitigation: Pre-commit hooks

缓解措施:使用提交前钩子

cat > .git/hooks/pre-commit <<'EOF' #!/bin/bash if git diff --cached fnox.local.toml > /dev/null; then echo "Error: fnox.local.toml should not be committed" exit 1 fi EOF chmod +x .git/hooks/pre-commit
undefined
cat > .git/hooks/pre-commit <<'EOF' #!/bin/bash if git diff --cached fnox.local.toml > /dev/null; then echo "错误:fnox.local.toml不应被提交" exit 1 fi EOF chmod +x .git/hooks/pre-commit
undefined

Threat: Key Compromise

威胁:密钥泄露

bash
undefined
bash
undefined

Mitigation: Immediate rotation

缓解措施:立即轮换密钥

1. Generate new key

1. 生成新密钥

age-keygen -o ~/.config/fnox/keys/identity-new.txt
age-keygen -o ~/.config/fnox/keys/identity-new.txt

2. Re-encrypt all secrets

2. 重新加密所有密钥

fnox get --all | fnox set --provider age-new
fnox get --all | fnox set --provider age-new

3. Update public keys

3. 更新公钥

4. Revoke old key

4. 吊销旧密钥

undefined
undefined

Threat: Unauthorized Access

威胁:未授权访问

toml
undefined
toml
undefined

Mitigation: Use cloud provider IAM

缓解措施:使用云服务商IAM

[providers.aws-sm] type = "aws-sm" region = "us-east-1"
[providers.aws-sm] type = "aws-sm" region = "us-east-1"

Restrict with IAM policies:

通过IAM策略限制:

- Limit to specific secret ARNs

- 仅允许访问特定密钥ARN

- Require MFA

- 要求MFA验证

- Restrict by IP range

- 按IP范围限制访问

undefined
undefined

Related Skills

相关技能

  • configuration: Managing fnox.toml securely
  • providers: Choosing secure providers
  • configuration: 安全管理fnox.toml配置
  • providers: 选择安全的服务商