本文目录导读:

Shell脚本本身无法真正“加密”配置文件,因为脚本需要读取配置文件才能运行,加密后脚本就无法直接解析了,但针对“敏感配置”的保护,有以下几种实用方案:
文件权限控制(最基础)
# 配置文件权限设为仅当前用户可读写 chmod 600 /path/to/sensitive.conf chown user:user /path/to/sensitive.conf
使用 openssl 加密(实用方案)
加密配置文件
# 加密文件(需要输入密码) openssl enc -aes-256-cbc -salt -in config.txt -out config.enc # 或用密钥文件加密 openssl enc -aes-256-cbc -salt -in config.txt -out config.enc -pass file:./keyfile
在脚本中解密使用
#!/bin/bash # 解密配置文件到临时变量 CONFIG=$(openssl enc -aes-256-cbc -d -in config.enc -pass pass:your_password 2>/dev/null) # 加载配置 eval "$CONFIG" # 使用配置 echo "Database password is: $DB_PASSWORD" # 清理变量 unset DB_PASSWORD
使用 GPG 加密(推荐)
加密
# 使用接收者的公钥加密 gpg --encrypt --recipient user@example.com config.txt # 或使用对称加密 gpg --symmetric --cipher-algo AES256 config.txt
在脚本中使用
#!/bin/bash # 解密到变量(需要交互输入密码) DB_PASSWORD=$(gpg --decrypt config.gpg 2>/dev/null) # 或者在无交互环境使用 DB_PASSWORD=$(echo "your_passphrase" | gpg --batch --passphrase-fd 0 --decrypt config.gpg 2>/dev/null)
环境变量方式(最常用)
方法A:从加密文件读取
#!/bin/bash
# 从加密的配置文件中读取环境变量
while IFS='=' read -r key value; do
if [[ ! "$key" =~ ^# && -n "$key" ]]; then
export "$key=$value"
fi
done < <(gpg --decrypt config.gpg)
# 现在可以使用环境变量
echo "$DB_PASSWORD"
方法B:使用 .env 文件配合 docker/kubernetes
# .env 文件(不提交到版本控制) DB_PASSWORD=supersecret123 # shell 中加载 set -a source .env set +a
使用 ansible vault(企业级方案)
# 创建加密文件 ansible-vault create secrets.yml # 加密现有文件 ansible-vault encrypt config.yml # 在脚本中使用 ansible-vault decrypt --output - config.yml
防止命令行参数泄露
使用 read -s 读取密码,避免在命令行显示:
#!/bin/bash # 静默读取密码 read -s -p "Enter decryption password: " DECRYPT_PASS echo # 使用密码解密 source <(openssl enc -d -aes-256-cbc -in config.enc -pass pass:"$DECRYPT_PASS")
重要安全建议
- 不要硬编码密码:脚本中避免写死解密密码
- 临时文件清理:解密后立即清理临时文件或变量
- 使用密钥管理服务:生产环境考虑 HashiCorp Vault 等
- 审计日志:记录谁、何时使用了密钥
- 最小权限原则:仅给脚本必要的权限
完整示例脚本
#!/bin/bash
# 安全的配置加载脚本
CONFIG_ENCRYPTED="/etc/app/config.enc"
KEY_FILE="/etc/app/secret.key"
# 检查文件权限
if [[ $(stat -c %a "$CONFIG_ENCRYPTED") != "600" ]]; then
echo "错误:配置文件权限不安全"
exit 1
fi
# 检查密钥文件
if [[ ! -f "$KEY_FILE" ]]; then
# 从密钥管理服务获取
echo "使用密钥管理服务..."
# 实际代码会调用 API 获取密钥
fi
# 解密并加载配置
source <(
openssl enc -d -aes-256-cbc \
-in "$CONFIG_ENCRYPTED" \
-pass file:"$KEY_FILE" \
2>/dev/null
) || {
echo "配置解密失败"
exit 1
}
# 使用配置(环境变量已加载)
echo "连接到数据库..."
mysql -u "$DB_USER" -p"$DB_PASSWORD" -h "$DB_HOST"
没有绝对的安全,加密只是增加破解成本,如果脚本运行在不可信环境,加密也很难防护。