Jenkins Pipeline用户权限管理新技巧:打造安全高效的流水线!
Jenkins Pipeline用户权限管理新技巧:打造安全高效的流水线!
什么是RBAC
基于角色的访问控制(Role-based access control,简称 RBAC),指的是通过用户的角色(Role)授权其相关权限,这实现了更灵活的访问控制,相比直接授予用户权限,要更加简单、高效、可扩展。
当使用 RBAC 时,通过分析系统用户的实际情况,基于共同的职责和需求,授予他们不同角色。你可以授予给用户一个或多个角色,每个角色具有一个或多个权限,这种 用户-角色、角色-权限 间的关系,让我们可以不用再单独管理单个用户,用户从授予的角色里面继承所需的权限。
大家可以看一下的案例更容易理解:
用户角色分为管理员、开发、运维,各个角色并具备不同的权限。每个用户也具备单个与多个角色。
需求说明
本章节是通过一个企业案例进行讲解,需求如下:
接下来,我们根据上图的组织架构来创建用户与组。
Jenkins权限如何分配:
-
开发组:只读权限
-
运维组:管理员权限
-
测试组:执行权限
配置权限
配置角色
分配权限
权限验证
张三(管理员),下图可以看到什么权限都有:
李四(只读),下图可以看到只有只读权限:
张三(执行权限),下图可以看到是有执行权限的:
配置Pipeline权限
需求说明
实际情况中,我们是通过Pipeline进行管理流水线的,接下来咱们针对Pipeline进行配置权限控制,详情如下图:
权限配置:
-
运维组:管理员权限
-
开发组:非生产环境只读权限
-
测试组:非生产环境执行权限
权限配置
以Ruoyi- Gateway为例,在Pipeline里配置权限:
DeployDev阶段(修改submitter配置):
...
stage('DeployDev'){
steps {
echo "部署开发环境"
script {
def userInput = input (
message: '确定要发布到DEV环境吗?',
parameters:[
choice(name: '操作', choices: ['发布', '跳过'])
],
ok: '确定',
submitter: 'ops,qa', // 配置ops,qa组即可
submitterParameter: 'APPROVER'
)
if (userInput['操作'] == '发布'){
echo "部署Dev环境开始"
....
DeployUat阶段(修改submitter配置):
....
stage('DeployUat'){
steps {
echo "部署测试环境"
script {
def userInput = input (
message: '确定要发布到UAT环境吗?',
parameters:[
choice(name: '操作', choices: ['发布', '跳过'])
],
ok: '确定',
submitter: 'ops,qa', // 配置ops,qa组即可
submitterParameter: 'APPROVER'
)
if (userInput['操作'] == '发布'){
echo "发布"
....
DeployGray阶段(修改submitter配置):
stage('DeployGray'){
steps {
echo "部署灰度环境"
script {
def GraysMode = input (
message: '确定要灰度验证吗?',
parameters:[
choice(name: 'operation', choices: ['基于权重灰度','基于请求头灰度','跳过'])
],
ok: '确定',
submitter: 'ops',
submitterParameter: 'APPROVER'
)
if (GraysMode['operation'] == '基于权重灰度'){
def WeightMode = input (
message: '请输入权重比例!',
parameters:[
string(name: 'workload_weight',defaultValue: '',description: ''),
string(name: 'grayload_weight',defaultValue: '',description: '')
],
ok: '确定',
submitter: 'ops',
submitterParameter: 'APPROVER'
)
sh """
echo $pipeline_dir
echo "打印编排文件详细信息"
if [ -e "$pipeline_dir/prod/$Project_Name/deployment-gray.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/deployment-gray.yml | sed "s/TAG/${Tag}/g"
cat $pipeline_dir/prod/$Project_Name/deployment-gray.yml | sed "s/TAG/${Tag}/g" | /usr/bin/kubectl apply -f -
fi
echo "配置权重"
echo ${WeightMode['grayload_weight']}
if [ -e "$pipeline_dir/prod/$Project_Name/ingress-gray-weight.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/ingress-gray-weight.yml | sed "s/WEIGHT-VALUE/${WeightMode['grayload_weight']}/g"
cat $pipeline_dir/prod/$Project_Name/ingress-gray-weight.yml | sed "s/WEIGHT-VALUE/${WeightMode['grayload_weight']}/g" | /usr/bin/kubectl apply -f -
fi
"""
}
if (GraysMode['operation'] == '基于请求头灰度'){
GrayHeaderMode = input (
message: '请输入请求头!',
parameters:[
string(name: 'header_key',defaultValue: '',description: ''),
string(name: 'header_value',defaultValue: '',description: '')
],
ok: '确定',
submitter: 'ops',
submitterParameter: 'APPROVER'
)
sh """
echo ${GrayHeaderMode['header_value']}
echo $pipeline_dir
echo "打印编排文件详细信息"
if [ -e "$pipeline_dir/prod/$Project_Name/deployment-gray.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/deployment-gray.yml | sed "s/TAG/${Tag}/g"
cat $pipeline_dir/prod/$Project_Name/deployment-gray.yml | sed "s/TAG/${Tag}/g" | /usr/bin/kubectl apply -f -
fi
echo "配置请求头"
echo ${GrayHeaderMode['header_key']}
echo ${GrayHeaderMode['header_value']}
if [ -e "$pipeline_dir/prod/$Project_Name/ingress-gray-header.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/ingress-gray-header.yml | sed "s/header-key/${GrayHeaderMode['header_key']}/g" | sed "s/header-value/${GrayHeaderMode['header_value']}/g"
cat $pipeline_dir/prod/$Project_Name/ingress-gray-header.yml | sed "s/header-value/${GrayHeaderMode['header_key']}/g" | sed "s/header-value/${GrayHeaderMode['header_value']}/g" | /usr/bin/kubectl apply -f -
fi
"""
}
// 默认模式为yes,如果跳过为no
if (GraysMode['operation'] == '跳过'){
GrayEnable='no'
}
}
}
DeployProd阶段(修改submitter配置):
stage('DeployProd'){
steps {
echo "部署生产环境"
script {
def userInput = input (
message: '确定要发布到生产环境吗?',
parameters:[
choice(name: '操作', choices: ['发布', '跳过'])
],
ok: '确定',
submitter: 'ops',
submitterParameter: 'APPROVER'
)
if (userInput['操作'] == '发布'){
echo "发布"
Namespace_Prod = sh(script: "cat $pipeline_dir/prod/$Project_Name/deployment.yml | grep namespace | awk -F ':' '{print \$2}'", returnStdout: true).trim()
DeploymentName = sh(script: "cat $pipeline_dir/prod/$Project_Name/deployment.yml | grep name: | head -n 1 | awk -F ':' '{print \$2}'", returnStdout: true).trim()
Revsion_Prod = sh(script: "kubectl get deployment $DeploymentName -n ${Namespace_Prod} -o=jsonpath='{.spec.template.spec.containers[*].image}' | awk -F ':' '{print \$NF}'", returnStdout: true).trim()
GrayDeploymentName = sh(script: "cat $pipeline_dir/prod/$Project_Name/deployment-gray.yml | grep name: | head -n 1 | awk -F ':' '{print \$2}'", returnStdout: true).trim()
GrayServiceName = sh(script: "cat $pipeline_dir/prod/$Project_Name/service-gray.yml | grep name: | head -n 1 | awk -F ':' '{print \$2}'", returnStdout: true).trim()
GrayIngressName = sh(script: "cat $pipeline_dir/prod/$Project_Name/ingress-gray-header.yml | grep name: | head -n 1 | awk -F ':' '{print \$2}'", returnStdout: true).trim()
sh '''
echo $pipeline_dir
echo "开始部署生产环境"
echo "打印编排文件详细信息"
if [ -e "$pipeline_dir/prod/$Project_Name/deployment.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/deployment.yml | sed "s/TAG/${Tag}/g"
cat $pipeline_dir/prod/$Project_Name/deployment.yml | sed "s/TAG/${Tag}/g" | /usr/bin/kubectl apply -f -
fi
if [ -e "$pipeline_dir/prod/$Project_Name/service.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/service.yml
cat $pipeline_dir/prod/$Project_Name/service.yml | /usr/bin/kubectl apply -f -
fi
if [ -e "$pipeline_dir/prod/$Project_Name/ingress.yml" ]; then
cat $pipeline_dir/prod/$Project_Name/ingress.yml
cat $pipeline_dir/prod/$Project_Name/ingress.yml | /usr/bin/kubectl apply -f -
fi
'''
if (GrayEnable == 'yes'){
sh """
kubectl delete deployment ${GrayDeploymentName} -n ${Namespace_Prod}
kubectl delete service ${GrayServiceName} -n ${Namespace_Prod}
kubectl delete ingress ${GrayIngressName} -n ${Namespace_Prod}
"""
}
} else {
echo "不发布"
}
}
}
post {
success {
wrap([$class: 'BuildUser']) {
lark (
robot: "2026ab67-7d07-46ec-a309-bebebaeaffbc",
type: "CARD",
title: "📢 Jenkins 应用发布成功",
text: [
"😋 **应用名称**:[${JOB_NAME}](${JOB_URL})",
"😜 **应用环境**:Prod",
"🤪 **任务编号**:[${BUILD_DISPLAY_NAME}](${BUILD_URL})",
"😘 **发布状态**: <font color='green'>成功</font>",
"🤩 **镜像版本**: $Tag",
"😎 **镜像仓库**: harbor.kubesre.com:8443/kubesre/$Project_Name",
"😝 **执 行 者**: ${env.BUILD_USER}",
"<at id=all></at>"
],
buttons: [
[
title: "更改记录",
url: "${BUILD_URL}changes"
],
[
title: "控制台",
type: "danger",
url: "${BUILD_URL}console"
]
]
)}
}
}
}
验证
触发流水线,开发组李四用户登录:
触发流水线,测试组王五用户登录:
触发流水线,运维组张三用户登录: