分享

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

 jackeyqing 2024-05-24 发布于上海

什么是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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多