Jenkins Pipeline用户权限管理新技巧:打造安全高效的流水线!

科技   2024-06-19 09:25   四川  

什么是RBAC

基于角色的访问控制(Role-based access control,简称 RBAC),指的是通过用户的角色(Role)授权其相关权限,这实现了更灵活的访问控制,相比直接授予用户权限,要更加简单、高效、可扩展。

image

当使用 RBAC 时,通过分析系统用户的实际情况,基于共同的职责和需求,授予他们不同角色。你可以授予给用户一个或多个角色,每个角色具有一个或多个权限,这种 用户-角色、角色-权限 间的关系,让我们可以不用再单独管理单个用户,用户从授予的角色里面继承所需的权限。

大家可以看一下的案例更容易理解:

用户角色分为管理员、开发、运维,各个角色并具备不同的权限。每个用户也具备单个与多个角色。

image

需求说明

本章节是通过一个企业案例进行讲解,需求如下:

image

接下来,我们根据上图的组织架构来创建用户与组。

Jenkins权限如何分配:

  • 开发组:只读权限

  • 运维组:管理员权限

  • 测试组:执行权限

配置权限

配置角色

image

分配权限

image

权限验证

张三(管理员),下图可以看到什么权限都有:

image

李四(只读),下图可以看到只有只读权限:

image

张三(执行权限),下图可以看到是有执行权限的:

image

配置Pipeline权限

需求说明

实际情况中,我们是通过Pipeline进行管理流水线的,接下来咱们针对Pipeline进行配置权限控制,详情如下图:

image

权限配置:

  • 运维组:管理员权限

  • 开发组:非生产环境只读权限

  • 测试组:非生产环境执行权限

权限配置

以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"
                           ]
                        ]
                    )}
                }
            }
        } 

验证

触发流水线,开发组李四用户登录:

image

触发流水线,测试组王五用户登录:

image

触发流水线,运维组张三用户登录:

image


运维开发故事
由一群志同道合的小伙伴共同维护,有运维也有开发,内容不限于Linux运维,devops工具链,k8s容器化技术,监控,日志收集,网络安全,Python或GO开发,团队成员有乔克、wanger、冬哥、素心、华仔、郑哥、夏老师
 最新文章