Jenkins CI/CD (一) 基于角色的授权策略
最近开始客串运维做CI/CD的规划设计, 主要是基于’Pipeline as Code in Jenkins’. 整理了下思路和技术点, 慢慢的写.
这一篇是关于基于角色的授权策略, 用的是Role-Based Authorization Strategy Plugin
.
授权在CI/CD流程中比较常见, 比如我们只让某些特定用户才可以构建Pre-Release的Job. 而更高级的Release发布, 又会需要某些用户的审批才可以进行. 需要授权时, 可能还需要发邮件提醒用户.
UI上如何使用就不提了, 这里只说Pipeline as Code. 后面的几篇也会是这个背景.
参考的这篇文章, 文章里的代码运行失败, 做了修复.
配置
安装完插件, 需要开始基于角色的授权策略
. 同时添加角色和为用户分配角色.
使用Role-Based Strategy
作为验证方式
Manage Jenkins / Configure Global Security / Configure Global Security
添加角色
Manage Jenkins / Manage and Assign Roles / Manage Roles / Global roles
输入要添加的角色名
为新加的角色配置权限
为用户指定角色
`Manage Jenkins / Manage and Assign Roles / Assign Roles / Global roles'
输入已有的用户名
分配角色
编码
授权会在很多job里使用, 所以我们使用shared library
来定义.
timeout(time: 5, unit: 'MINUTES') {
notifyAwaitApproval approvers: getApprovers('pre-release'),
emailPrompt: 'Build is ready to prepare release'
}
给用户发送待审批邮件, 使用input
等待用户的交互, 同时使用milestone
阻塞后续的构建请求.
notifyAwaitApproval.groovy
def call(options) {
def jobName = env.JOB_NAME
if(options.message == null) {
options.message = "Action Required For Build $jobName"
}
def csvApproverUsernames = {
switch (options.approvers) {
case String:
// already csv
return options.approvers
case Map:
// keys are usernames and values are names
return options.approvers.keySet().join(',')
case ArrayList:
case HashSet:
return options.approvers.join(',')
default:
throw new Exception("Unexpeced approver type ${options.approvers.class}!")
}
}()
echo "Notify approvers: $csvApproverUsernames for approval"
// emailext needs to be inside a node block but don't want to take up a node while waiting for approval
emailext body: "Action Required For Build \${jobName} (#\${env.BUILD_NUMBER})",
to: csvApproverUsernames,
subject: "Action Required For Build \${jobName} (#\${env.BUILD_NUMBER})"
milestone()
input id: 'Approval',
message: options.message,
submitter: csvApproverUsernames,
submitterParameter: 'submitter'
milestone()
}
检查并获取Jenkins当前配置的授权策略, 如果是Role-Based Authorization
, 返回拥有指定角色的用户列表.
getApprovers.groovy
import com.cloudbees.groovy.cps.NonCPS
import com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
@NonCPS
def call(role) {
echo "Retrieving users for $role"
def strategy = RoleBasedAuthorizationStrategy.instance;
if (strategy != null) {
return strategy.getGrantedRoles(RoleBasedAuthorizationStrategy.GLOBAL)
.entrySet()
.find { entry -> entry.key.getName().equals(role) }.getValue()
} else {
throw new Exception("Role Strategy Plugin not in use. Please enable to retrieve users for a role")
}
}