Drone CI 之凭证管理

warning: 这篇文章距离上次修改已过562天,其中的内容可能已经有所变动。

前言

在CICD或者说Devops领域实践的时候,避免不了会需要各种账号、密码、地址、密钥等等信息来帮助我们完成自动化的过程。比如自动构建的镜像需要推送到Registry时,需要Registry的账号密码进行登录授权才能推送。又比如自动部署时,需要目标机器的密钥或者是账号密码才可以SSH上去执行命令,等等。

领域解决方案

针对上述问题,简单的做法当然是直接在构建流程中将凭证明文编写,但是这样容易造成凭证泄露,且可见范围是不受控的(只要有查看脚本权限的人都可以看得到凭证)。
Jenkins中给出的解决方案是自带凭证管理,且支持插件进行扩展不同类型的凭证,比如SSH凭证就是通过插件获得的能力。而在Drone CI中,也有自带凭证管理功能,但是相对Jenkins而言是非常轻量化的功能模块,只能在激活的仓库或者所属组织内定义,无法在全局层面去定义。且和Jenkins一样,由于凭证管理集成,所以权限的控制就更加难以把握,稍不留神可能就会有用户得到凭证查看、管理的权限。

Drone CI的架构演进

在此基础上,Drone CI在架构层面将凭证管理进行了抽象,允许集成外部凭证管理服务,如Vault,来进行专门的凭证管理。得益于Drone CI的架构设计,RunnerServer是相对独立的 ,Server可以说是并不知道Runner的存在,而插件、扩展也只是存在于Runner侧。所以带来一个好处就是凭证管理除了Runner,没有任何人可以接触到(除了拥有Vault Token 和 访问地址的人)。

部署

建议基于Docker环境进行安装

安装Vault

Vault需要先定义一下配置文件,不然每次容器重启后都会重新初始化一个随机ID,也就造成一个假象(每次重启容器后数据都丢了,实际上并没有丢)
配置文件(放置在映射的配置目录中,文件名为local.json):

{
        "backend": {
                "file": {
                        "path":"/vault/file"
                }
        },
        "default_lease_ttl":"168h",
        "max_lease_ttl":"720h",
        "ui":true,
        "listener": {
                "tcp": {
                        "address":"0.0.0.0:8200",
                        "tls_disable":1
                }
        }
}

yml文件:

version: "3.9"
services:
  vault:
    image: hashicorp/vault:latest # 一定要用这个镜像,vault是老版本了
    container_name: vault
    command: vault server -config=/vault/config/local.json # 指定配置文件启动
    # environment:
      # - VAULT_API_ADDR=http://0.0.0.0:8201(这个在用了配置文件后也没啥用了)
      # - VAULT_DEV_ROOT_TOKEN_ID=随机生成一个ID用于标识,避免重启后重新生成(但是好像并没有啥用,会走一遍手动初始化的流程)
    volumes:
      - /docker/vault/data:/vault/file
      - /docker/vault/config:/vault/config
      - /docker/vault/logs:/vault/logs
    ports:
      - 8200:8200
    cap_add:
      - IPC_LOCK
    restart: always

填写内容即可(数量都填1,标识只生成一个token,以及解密密钥分为几个部分)。配置完成后会显示生成的token,请记录下来,因为后面也不会出现了,除非去容器日志里翻。

初始化 Vault

  1. 启动后访问地址,会进入到初始化配置的页面。
    2023-05-08T01:54:04.png2023-05-08T01:54:04.png
  2. 这里我都填写的是1,然后点击Initialize
    2023-05-08T01:54:55.png2023-05-08T01:54:55.png
  3. 初始化完成后,会显示生成的TokenKey,选择下载或者手动复制保存下来(后续不会显示了)
    2023-05-08T01:56:56.png2023-05-08T01:56:56.png
  4. 保存好信息后,点击Continue to Unseal,输入上一步生成的Key(注意不是Token),点击Unseal
    2023-05-08T01:58:53.png2023-05-08T01:58:53.png
  5. Unsealed之后就会到登录页面,使用之前生成的Token进行登录即可。
    2023-05-08T02:00:04.png2023-05-08T02:00:04.png
  6. 登录后就可以新建凭证了。
    2023-05-08T02:00:39.png2023-05-08T02:00:39.png

添加简单凭证(KV)

  1. 点击Enable new engine,创建一个新的存储引擎。
    2023-05-08T02:59:11.png2023-05-08T02:59:11.png
  2. 这里以KV(键值对)作为示例,选择KV类型,然后点击Next
    2023-05-08T03:00:02.png2023-05-08T03:00:02.png
  3. 输入path(凭证访问路径),再点击Enable Engine完成创建。
    2023-05-08T03:01:19.png2023-05-08T03:01:19.png
  4. 完成创建后,我们来创建一个凭证。点击Create secret
    2023-05-08T03:02:54.png2023-05-08T03:02:54.png
  5. 填写访问路径(也就是Key),并填写Value(记得点击Add才会添加进去),点击Save进行保存。
    2023-05-08T03:04:36.png2023-05-08T03:04:36.png

    如果更习惯Json方式,可以点击上方的JSON开关进行切换。
    2023-05-08T03:05:21.png2023-05-08T03:05:21.png
  6. 保存完成后就可以访问,此时setting的完整访问路径是:docker/setting,这就是settingKeyusername属于它的 Value

安装 Drone Vault扩展

Vault安装后, 此时还无法直接和Drone Runner进行通讯。需要一个扩展进行转发:Drone-Vault
yml文件:

version: "3.9"
services:
  drone-vault:
    image: drone/vault
    container_name: drone-vault
    environment:
      - DRONE_DEBUG=true
      - DRONE_SECRET=自定义一个随机密钥(这个密钥仅用于与Runner通讯,和Vault, Drone Server 都没有关系)
      - VAULT_ADDR=Vault Server的地址
      - VAULT_TOKEN=Vault生成的Token(开发环境可以直接用root token,方便快速验证)
    ports:
      - 3000:3000
    restart: always

启动后, 查看容器日志,检查下是否启动即可。

安装 Drone Cli 测试 Drone Vault

安装 Drone CLI,安装完成后,设置一下环境变量:

export DRONE_SECRET_PLUGIN_ENDPOINT= Drone Vault的访问地址
export DRONE_SECRET_PLUGIN_TOKEN=Drone Vault中定义的随机密钥 DRONE_SECRET

然后就可以使用命令进行测试,看是否可以取到设置的密钥:

drone plugins secret get docker/data/setting username --repo 仓库名(需要带上拥有者的完整仓库名,如:org/repo)

配置 Drone Runner

Drone Vault 部署好之后, 还需要修改Drone Runner的配置,让Drone Runner取凭证时使用Drone Vault进行代理,在Runner的环境变量中加入下面的两个变量,然后重启:

DRONE_SECRET_PLUGIN_ENDPOINT= Drone Vault的访问地址
DRONE_SECRET_PLUGIN_TOKEN=Drone Vault中定义的随机密钥 DRONE_SECRET

脚本中使用

脚本中的使用和正常没有任何区别,底层的凭证管理切换并不影响脚本语法:
声明secret:

kind: secret
name: username
get:
  # 这里注意,路径在vault是docker/setting, 
  # 但是在这里需要加一个data,来表示取setting的数据。因为还有元数据之类的
  path: docker/data/setting
  name: username
最后修改于:2023年05月08日 17:29

评论已关闭