当前位置: 首页 > ds >正文

Jenkins - CICD 注入环境变量避免明文密码暴露

Jenkins - CICD 注入环境变量避免明文密码暴露

  • 🔧 Jenkins 注入环境变量的方式
    • 在 Job 配置里直接写环境变量,代码中可通过环境变量访问
    • 使用 Jenkins Credentials 插件(推荐)
    • 通过 withEnv 临时注入
    • ✅ 对比总结
  • 示例:从 Jenkins Credentials 到 Pipeline 再到代码访问环境变量的全过程
    • 场景说明
    • 1️⃣ Jenkinsfile 示例
    • 2️⃣ Python 代码(app.py)
    • 3️⃣ 工作流程

上篇《 Pyhon - 环境变量本地开发方案避免明文密码暴露在代码里》介绍了本地开发方案将明文密码注入环境变量,但实际线上测试和生产环境,CICD 该如何注入明文密码,避免安全问题呢。

🔧 Jenkins 注入环境变量的方式

在 Jenkins 里,环境变量是最常用的方式来传递密码、API Key、数据库连接信息等敏感配置。

在 Job 配置里直接写环境变量,代码中可通过环境变量访问

Freestyle Job GUI 配置

  • 进入 Job → Configure → Build Environment

  • 勾选 Inject environment variables to the build process

  • 手动添加环境变量:

    DB_HOST=127.0.0.1
    DB_USER=myuser
    

    在这里插入图片描述

  • 在 Pipeline 脚本里可以直接用:

    echo "DB user is ${env.DB_USER}"
    

Pipeline Job 里是没有 GUI 勾选的,所有环境变量都要在 Jenkinsfile 里配置

pipeline {agent anyenvironment {DB_USER = 'myuser'}stages {stage('Show env') {steps {sh 'echo "Key: $DB_USER"'}}}}

⚠️ 缺点:敏感信息容易暴露,不推荐存密码。

使用 Jenkins Credentials 插件(推荐)

👉 如果将敏感信息直接写在代码或 Jenkinsfile 里会有安全隐患,因此推荐通过 Credentials 插件来管理。这是安全管理敏感信息(密码、API Key)的最佳方式。
步骤:

  • 添加 Credentials 的位置, 在 Jenkins 界面:

    • 进入 Dashboard → Manage Jenkins → Credentials
    • 选择 系统(System) → 全局凭据(Global credentials)
    • 点击 Add Credentials 添加新的凭据
  • 尝见的凭据类型

    类型用途配置项
    Username with password需要用户名 + 密码的场景(DB、Git、FTP、Docker Registry)用户名、密码
    Secret text单个敏感值(API Key、Token、Password)Secret
    SSH Username with private key通过 SSH 连接服务器、Git 仓库用户名、私钥
    Secret file整个敏感文件(如 kubeconfig、JSON Key)上传文件
    CertificateSSL 证书、PKCS#12 格式证书上传证书文件、密码
  • 方式一:用 bash command 来加载这些 Credentials,以便 code 中通过环境变量来访问
    示例 GUI 上配置 credentia file 绑定,定义变量 API_KEY_FILE
    在这里插入图片描述
    shell 脚本里导出 credentia,以便 app.py 通过环境变量来访问 credential 文件中配置的变量

    echo "Credential temp file path is: $API_KEY_FILE"
    export $(grep -v '^#' "$API_KEY_FILE" | xargs)
    python3 -c "import os; print(os.getenv('DEV_CAAS_DL_API_KEY'))"
    echo "export credential end"
    python3 app.py
    

    ⚠️ 注意:这种方式注入只在当前会话时有效,也就是说在其他 bash 会话中是无效,需要访问到这些环境变量就加载

  • 方式二:在 jenkinsfile 中加载这些 Credentials, 以便 code 中通过环境变量来访问:

    • 使用 withCredentials
      示例:数据库用户名/密码
      withCredentials([usernamePassword(credentialsId: 'db-creds', usernameVariable: 'DB_USER', passwordVariable: 'DB_PASS')]) {sh '''echo "Database user: $DB_USER"# echo "Password: $DB_PASS"  # 切勿打印密码!'''}
      
      示例:Secret Text
      		withCredentials([string(credentialsId: 'api-key', variable: 'API_KEY')]) {sh 'curl -H "Authorization: Bearer $API_KEY" https://api.example.com'
      }
      
      示例:SSH Key
      		withCredentials([sshUserPrivateKey(credentialsId: 'ssh-key', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'SSH_USER')]) {sh 'ssh -i $SSH_KEY_FILE $SSH_USER@server.example.com'
      }
      
      示例:Secret file,创建了一个上传了 .env 文件的 credential id 为 api_key_file
      工作机制
      • withCredentials([file(…)]) → Jenkins 把 .env Secret file 下载到一个临时路径,并写到 $SECRET_FILE 变量里。
      • source $SECRET_FILE → 加载 .env 内容到 shell。
      • 用 set -o allexport / set +o allexport 确保 .env 文件里的 KEY=value 都会自动 export。
      • 这样 .env 配置 DEV_CAAS_DL_API_KEY 就能被后续的 shell、Python 程序读取。
        ⚠️ 注意:
      • 如果 jenkins 执行 shell 时默认用的是 /bin/sh,就用 . “$SECRET_FILE”
      • 如果 jenkins 执行 shell 时默认用的是 /bin/bash, 就用 source $SECRET_FILE
      	withCredentials([file(credentialsId: 'api_key_file', variable: 'SECRET_FILE')]) {sh '''set -o allexport. "$SECRET_FILE"set +o allexportecho "test DEV_API_KEY=$DEV_API_KEY"'''
      }
      

    这样,密码不会出现在 Job 配置和日志里,安全性高。

通过 withEnv 临时注入

如果需要在某个阶段设置环境变量,可以用 withEnv:

pipeline {agent anystages {stage('Deploy') {steps {withEnv(["APP_ENV=production", "DB_HOST=10.0.0.1"]) {sh 'echo "Environment: $APP_ENV, Host: $DB_HOST"'}}}}
}

好处:只在这个 stage 有效,不会污染全局。

✅ 对比总结

方式适用场景优点缺点
Job 配置里写变量非敏感配置简单密码不安全
Credentials 插件敏感信息(推荐)安全、审计J需要额外配置
withEnv临时变量控制作用域只适合少量变量

示例:从 Jenkins Credentials 到 Pipeline 再到代码访问环境变量的全过程

场景说明

  • 创建 Jenkins Credentials:
    • 类型:Secret file
    • ID:api_key_file
    • 文件内容(.env 格式):
      	DEV_API_KEY=abc123DEV_API_USER=adminDEV_DB_PASS=super-secret
      
  • 目标:
    • 在 Jenkinsfile 中安全加载 .env 文件
    • 在 Python 代码里通过 os.getenv 访问环境变量
    • 不在日志中泄露敏感信息

1️⃣ Jenkinsfile 示例

pipeline {agent anystages {stage('Load Secret File') {steps {// 使用 Jenkins Credentials 拉取 secret filewithCredentials([file(credentialsId: 'api_key_file', variable: 'SECRET_FILE')]) {sh '''#!/bin/shecho "Loading secret file from $SECRET_FILE"# 把 .env 文件里的变量导入当前 shell 环境set -o allexport. "$SECRET_FILE"set +o allexport# 验证(生产环境不要打印敏感信息)echo "DB_USER=$DEV_DB_USER"# 运行 Python 程序python3 app.py'''}}}}
}

⚠️ 注意:

  • 在 /bin/sh 中没有 source 命令,所以用 . 替代
  • set -o allexport 可以确保 .env 文件里的 KEY=value 全部被 export

2️⃣ Python 代码(app.py)

import osapi_key = os.getenv("DEV_CAAS_DL_API_KEY")
db_user = os.getenv("DEV_CAAS_DL_DB_USER")
db_pass = os.getenv("DEV_CAAS_DL_DB_PASS")print("API Key:", api_key)
print("DB User:", db_user)
# 千万不要打印 db_pass

3️⃣ 工作流程

  • Jenkins Pipeline 执行 withCredentials([file(…)]),把 .env secret file 下载到临时路径 $SECRET_FILE
  • Shell 脚本用 . 和 set -o allexport 把 .env 变量导入环境
  • Python 里直接通过 os.getenv 访问环境变量
  • Pipeline 结束后,Jenkins 会自动删除临时文件,保证安全
  • 这样,你的 敏感信息不会硬编码在代码或 Jenkinsfile 中,也不会在日志中直接泄露,同时代码可以正常访问环境变量。
http://www.xdnf.cn/news/18229.html

相关文章:

  • Python中f - 字符串(f-string)
  • Hadoop入门
  • 前端基础知识版本控制系列 - 05( Git 中 HEAD、工作树和索引之间的区别)
  • 图论水题4
  • 写作路上的迷茫与突破
  • java_spring boot 中使用 log4j2 及 自定义layout设置示例
  • NestJS 手动集成TypeORM
  • 关于第一次接触Linux TCP/IP网络相关项目
  • Docker入门:容器化技术的第一堂课
  • python---装饰器
  • 在线编程题目之小试牛刀
  • [每周一更]-(第155期):Go 1.25 发布:新特性、技术思考与 Go vs Rust 竞争格局分析
  • 回溯剪枝的 “减法艺术”:化解超时危机的 “救命稻草”(一)
  • 机器学习算法篇(十三)------词向量转化的算法思想详解与基于词向量转换的文本数据处理的好评差评分类实战(NPL基础实战)
  • 微服务之间的调用需要走网关么?
  • Linux Shell定时检查日期执行Python脚本
  • Python数据类型转换详解:从基础到实践
  • uniappx 安卓端本地打包的一些总结
  • 【typenum】 16 非零标记及改进建议
  • 【Linux系统】动静态库的制作
  • java之 junit4单元测试Mockito的使用
  • Pycharm Debug详解
  • 深度学习之优化器
  • 数据与模型融合波士顿房价回归建模预测
  • 数据结构(排序篇)——七大排序算法奇幻之旅:从扑克牌到百亿数据的魔法整理术
  • LeetCode 1323: 6和9组成的最大数字
  • 内网后渗透攻击--隐藏通信隧道技术(应用层隧道技术)
  • 一键管理 StarRocks:简化集群的启动、停止与状态查看
  • JAVA后端开发——Token自动续期机制的必要性
  • 库制作与原理(下)