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

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

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

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

🔧 Jenkins 注入环境变量的方式

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

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

Freestyle Job GUI 配置

  • 进入 Job → Configure → Build Environment

  • 勾选 Inject environment variables to the build process

  • 手动添加环境变量:

    ini 复制代码
    DB_HOST=127.0.0.1
    DB_USER=myuser
  • 在 Pipeline 脚本里可以直接用:

    groovy 复制代码
    echo "DB user is ${env.DB_USER}"

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

groovy 复制代码
pipeline {
	    agent any
	    environment {
	        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) 上传文件
    Certificate SSL 证书、PKCS#12 格式证书 上传证书文件、密码
  • 方式一:用 bash command 来加载这些 Credentials,以便 code 中通过环境变量来访问

    示例 GUI 上配置 credentia file 绑定,定义变量 API_KEY_FILE

    shell 脚本里导出 credentia,以便 app.py 通过环境变量来访问 credential 文件中配置的变量

    bash 复制代码
    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
      示例:数据库用户名/密码

      groovy 复制代码
      withCredentials([usernamePassword(credentialsId: 'db-creds', usernameVariable: 'DB_USER', passwordVariable: 'DB_PASS')]) {
      		    sh '''
      		        echo "Database user: $DB_USER"
      		        # echo "Password: $DB_PASS"  # 切勿打印密码!
      		    '''
      		}

      示例:Secret Text

      groovy 复制代码
      		withCredentials([string(credentialsId: 'api-key', variable: 'API_KEY')]) {
          sh 'curl -H "Authorization: Bearer $API_KEY" https://api.example.com'
      }

      示例:SSH Key

      groovy 复制代码
      		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
      groovy 复制代码
      	withCredentials([file(credentialsId: 'api_key_file', variable: 'SECRET_FILE')]) {
          sh '''
              set -o allexport
              . "$SECRET_FILE"
              set +o allexport
              echo "test DEV_API_KEY=$DEV_API_KEY"
          '''
      }

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

通过 withEnv 临时注入

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

groovy 复制代码
pipeline {
    agent any
    stages {
        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 格式):

      env 复制代码
      	DEV_API_KEY=abc123
      	DEV_API_USER=admin
      	DEV_DB_PASS=super-secret
  • 目标:

    • 在 Jenkinsfile 中安全加载 .env 文件
    • 在 Python 代码里通过 os.getenv 访问环境变量
    • 不在日志中泄露敏感信息

1️⃣ Jenkinsfile 示例

groovy 复制代码
pipeline {
    agent any

    stages {
        stage('Load Secret File') {
            steps {
                // 使用 Jenkins Credentials 拉取 secret file
                withCredentials([file(credentialsId: 'api_key_file', variable: 'SECRET_FILE')]) {
                    sh '''
                        #!/bin/sh
                        echo "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

python 复制代码
import os

api_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 中,也不会在日志中直接泄露,同时代码可以正常访问环境变量。
相关推荐
芥子沫7 小时前
Jenkins常见问题及解决方法
windows·https·jenkins
是小崔啊13 小时前
【Jenkins】01 - Jenkins安装
运维·jenkins
摘星编程2 天前
Docker容器定时任务时区Bug导致业务异常的环境变量配置解决方案
环境变量·定时任务·docker容器·时区配置·生产环境
maomao1713142 天前
Jenkins 环境部署
运维·jenkins
江湖人称小鱼哥3 天前
jenkins在windows配置sshpass
运维·jenkins
koboides3 天前
我的第一个开源项目-jenkins集成k8s项目
linux·运维·云原生·容器·kubernetes·jenkins
苦逼IT运维4 天前
Jenkins + SonarQube 从原理到实战三:SonarQube 打通 Windows AD(LDAP)认证与踩坑记录
运维·服务器·windows·docker·云计算·jenkins·devops
Hello.Reader5 天前
Elasticsearch Node.js 客户端连接指南(Connecting)
elasticsearch·node.js·jenkins
阑梦清川5 天前
派聪明RAG知识库----关于elasticsearch报错,重置密码的解决方案
大数据·elasticsearch·jenkins