公众号:yunops

直入正题:我们在落地 Zadig 的过程中,发现项目初始化时有很多重复性配置工作,比如说同一类 java 服务构建部署中构建过程 90%都是重复的,要一个个手动创建过去;通过 Zadig 里的“项目”区分一个业务线的多个环境的话,每个环境中的服务也要一个个创建,哪怕是通过模板导入,也是一个不小的工作量。这里我们分享一下我们通过自动化脚本来降低这部分工作量的做法,抛砖引玉,仅用于为大家提供一个参考思路~


一、思路

Zadig 自身有丰富的 API 接口用于外部调用,通过 API Token 实现认证; 在此基础上,我们可以通过浏览器调试模式获取相关功能接口地址和请求参数,要实现批量操作,只需要自己拼装 HTTP 请求,循环调用相关接口即可。我们以通过脚本批量为用户授权这个场景为例说明整个过程。

以下实现过程还存在较大优化空间,比如说手动创建用户列表配置文件仍较难维护且容易出错,使用 shell 开发不利于后期功能扩展等。

二、场景说明


三、前期准备

  1. 浏览器登录 Zadig,导航到:demo-qa 项目 » 配置 » 权限 页面,打开浏览器调试模式(Chrome 快捷键为 F12),点击“添加成员”按钮;
  2. 点击调试调试工具中的 Clear 按钮清空控制台,点击 Fetch/XHR 过滤指定类型请求(去除干扰项),如图 1:curl-001
  3. 在弹出的选择框中下拉选择用户名称和角色名称,点击“确定”按钮,观察调试工具窗口里的输出,如图 2:curl-002可以看到,我们页面执行为一个用户分配权限的动作,Zadig 控制台和服务端两个接口发生了交互,简单分辨一下可以看出来,第一个是我们需要的功能接口,第二个其实是操作完成后页面刷新加载新的页面内容用的(有个简单的判断办法,根据调试工具右侧的 Response 来判断,这是接口响应的具体内容,一般来讲内容为:{"message":"success"}的就是我们需要用的接口),鼠标右键点击这个接口,如图以此展开 Copy » Copy as cURL(bash),将复制到的内容粘贴到文本编辑器里,得到如下内容:
# 将ldap账户绑定角色
curl 'http://<Your Zadig Address>/api/v1/rolebindings?projectName=<Your Project Name>&bulk=true' \
  -H 'Connection: keep-alive' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'DNT: 1' \
  -H 'Authorization: Bearer <Your Bearer>' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36' \
  -H 'Content-Type: application/json;charset=UTF-8' \
  -H 'Origin: http://<Your Zadig Address>' \
  -H 'Referer: http://<Your Zadig Address>/v1/projects/detail/<Your Project Name>/rbac' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \
  --data-raw '[{"uid":"e3521a93-a123-11ec-123a-86c0dc7647f5","role":"developer","preset":false,"type":"custom"}]' \
  --compressed \
  --insecure

其中的 http://<Your Zadig Address>/api/v1/rolebindings?projectName=<Your Project Name>&bulk=true 就是为用户绑定角色的接口地址, --data-raw 就是调用这个接口需要传递的表单参数,我们简单分析一下参数内容就能发现,其中有两个关键的属性:uidrole,一个是用户 id,一个是角色名,那接下来我们就需要获取需要授权的用户的 id,因为当前页面就会加载用户列表,所以我们直接刷新当前页面,在调试工具中找一找,可以发现,search 接口就返回了所有的用户信息,如图 3:curl-003,我们拷贝 Response 里的响应内容到文件编辑器中备用,样例:

{
  "users": [
    {
      "lastLoginTime": 1646994537,
      "uid": "786f514f-8b0a-11ec-ba40-bea187f93886",
      "name": "",
      "identity_type": "ldap",
      "email": "",
      "phone": "",
      "account": "",
      "token": ""
    },
    {
      "lastLoginTime": 1646993873,
      "uid": "e3949fd2-a123-22ec-837a-86c0dc7647f5",
      "name": "小明",
      "identity_type": "ldap",
      "email": "xiaoming@demo.com",
      "phone": "",
      "account": "xiaoming",
      "token": ""
    },
    {
      "lastLoginTime": 1646993873,
      "uid": "dafea9fd2-a123-11ec-837a-86c0dc7647f5",
      "name": "小亮",
      "identity_type": "ldap",
      "email": "xiaolaing@demo.com",
      "phone": "",
      "account": "xiaoming",
      "token": ""
    }
  ],
  "totalCount": 2
}

结合场景简单分析一下,对我们有用的属性有俩:一个是 uid,就是上文中提到的用户 id;另外一个是 name,这个和 uid 是一一对应的,我么那后续接口调用的时候用不到,仅用做我们手写配置文件的时候肉眼区分用户;

四、脚本开发

需求很小,shell 最方便,如果考虑维护性和规范性,建议使用 Python 或者 Golang。

这里我们使用 shell 开发,原理就是通过:配置 + 模板组装 HTTP 请求,通过 curl 执行;根据上面已经掌握的信息,先写一个 http 请求模板,命名为 curl_rbac_bind.tpl,内容(注意替换为你的 zadig 地址)为:

curl 'http://<Your Zadig Address>/api/v1/rolebindings?projectName=${project_name}&bulk=true' \
  -H 'Connection: keep-alive' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'DNT: 1' \
  -H 'Authorization: Bearer ${auth_bearer}' \
  -H 'Content-Type: application/json;charset=UTF-8' \
  -H 'Origin: http://zadig.demo.com' \
  -H 'Referer: http://<Your Zadig Address>/v1/projects/detail/${project_name}/rbac' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' \
  --data '[{"uid":"${user_uuid}","role":"${user_role}","preset":false,"type":"custom"}]' \
  --compressed \
  --insecure

然后写一个配置文件,分三列,依次为 uid、用户名、角色名,命名为:ldap-user-list.txt,内容为:

9414a55a-a22d-11ec-837a-86c0dc7647f5 小明 developer
9414a55a-a22d-11ec-837a-86c0dc7647f5 小亮 developer
e32dd191-a321-11ec-837a-86c0dc7647f5 小红 tester
e3d6c003-a321-11ec-837a-86c0dc7647f5 小黄 tester

最后写一个主程序,名为 do_bind.bash,这里项目名和 Token 是写死的,没有参数化,注意替换,内容为:

#!/bin/bash

export project_name="demo-qa"

export auth_bearer="aaabbbcccddd"

mkdir -p create_bind

cat ldap-user-list.txt | while read line
do
    export user_uuid=`echo $line | awk -F ' ' '{print $1}'`
    user_name=`echo $line | awk -F ' ' '{print $2}'`
    export user_role=`echo $line | awk -F ' ' '{print $3}'`
    echo "do with ${user_name}..."
    envsubst < curl_rbac_bind.tpl > create_bind/${user_uuid}.bash
    cat create_bind/${user_uuid}.bash | bash
    sleep 1
done

整体文件结构(假设执行目录为 script):

---script
    |---ldap-user-list.txt
    |---curl_rbac_bind.tpl
    |---do_bind.bash

五、使用

确认配置和脚本语法无误后在 bash 会话中执行命令:sh do_bind.bash,顺利执行完后刷新项目权力管理页面查看效果。 其他批量操作的需求也可以通过类似思路实现,实现服务、构建等的批量创建删除等,我们也有类似的脚本,但是目前处在能用的阶段,并没有很完善,后续改进下再跟大家分享。