内容简介:写在前边这一篇文章是上一篇文章
写在前边
这一篇文章是 基于 Gitea+Drone CI+Vault 打造属于自己的CI/CD工作流 系列文章第二篇,让我们一起来完成 drone
与 vault
的搭配使用,这篇主要讲 vault
的部署和使用,以及怎么通过 drone
来使用 vault
上一篇文章 (一) Drone CI For Github —— 打造自己的CI/CD工作流 我们一起了解了, Drone
的部署和使用,一起感受了 Drone
的简单强大的功能带来的方便和快捷。在实际的应用中,我们会有很多的敏感数据, Drone
自身的 Secret
是以仓库为单位进行管理,而且也没有严格独立的权限控制,其实是不太方便的。
带着这样的疑惑,我再次向@Dee luo老哥寻求帮助,老哥掏了掏肚子上的口袋,取出一本武林秘籍,曰:“小伙子,我这里有一个色情网站记录在上面,你看看”。我打开只看到www.vaultproject.io 一行小字赫然记录在内,我迫不及待的打开,美滋滋的看了起来。
此处省略一万个字...
另外强烈推荐YUHAO的博客 私密信息管理利器 HashiCorp Vault系列文章
好了,现在我已经知道该做什么了。
说干就干,开始搞事。
了解Vault
Vault是一个管理Secrets并保护敏感数据的工具,来自HashiCorp,如果你对这个名字有点陌生,那么你一定知道Vagrant
Vault是一种安全访问 Secret
的工具。 Secret
就是您要严格控制访问的任何内容,例如API密钥,密码或证书。Vault为任何机密提供统一的界面,同时提供严格的访问控制并记录详细的审计日志。
现代系统需要访问大量 Secret
:数据库凭证,外部服务的API密钥,面向服务的体系结构通信的凭证等。了解谁正在访问哪些秘密已经非常困难且特定于平台。如果没有自定义解决方案,几乎不可能添加密钥滚动,安全存储和详细的审计日志。这是Vault介入的地方。
Vault的主要功能包括:
- 安全秘密存储 :任意密钥/值秘密可以存储在Vault中。Vault会在将这些机密写入持久存储之前加密这些机密,因此获取对原始存储的访问权限不足以访问您的机密。Vault可以写入磁盘,Consul等。
- 动态秘密 :Vault可以按需为某些系统生成机密,例如AWS或 SQL 数据库。例如,当应用程序需要访问S3存储桶时,它会要求Vault提供凭据,Vault将根据需要生成具有有效权限的AWS密钥对。创建这些动态机密后,Vault也会在租约到期后自动撤消它们。
- 数据加密 :Vault可以加密和解密数据而无需存储数据。这允许安全团队定义加密参数,并允许开发人员将加密数据存储在SQL等位置,而无需设计自己的加密方法。
- 租赁和续订 :Vault中的所有机密都有与之相关的 租约 。在租约结束时,Vault将自动撤销该秘密。客户可以通过内置续订API续订租约。
- 撤销 :Vault内置了对秘密撤销的支持。保险柜不仅可以撤销单个秘密,还可以撤销秘密树,例如特定用户读取的所有秘密,或特定类型的所有秘密。撤销有助于关键滚动以及在入侵情况下锁定系统。
上边都是废话,这里说一下我自己的体验。
首先我没有体验的很深,我现在只是体验了 key/value
结构和 database
,然后看了一下 ACL Policies
管理权限。
- 权限控制很严格,机制也很灵活和安全
- UI美观,操作简单,不过UI功能也简单
- CLI 操作容易理解,文档齐全。
- 安全确实很放心,token定时刷新,可以通过token来获取数据库的配置,UI的激活需要输入key,容器重启也需要重新输入key来激活。
部署 vault
这里并不是单独部署vault,而是参考上一篇文章来结合vault使用,在上一篇文章的 docker-compose.yml
基础上,加入 vault
的容器,并为 vault
提供 web
服务.
为了区分,以下代码块中,用 $
开头表示宿主机命令,用 / #
开头表示容器中的命令
编写模板文件
... vault: image: vault:latest container_name: vault restart: always networks: - dronenet volumes: - ./vault/file:/vault/file - ./vault/config:/vault/config - ./vault/logs:/vault/logs cap_add: - IPC_LOCK environment: - VAULT_ADDR=http://127.0.0.1:8200 command: vault server -config=/vault/config/local.json #这句非常重要,一定要替换原有的Dockerfile中的CMD,不然会自动初始化,生成的数据都在docker logs中,不说你肯定找不到。dog.jpg,所以我选择手动初始化 ... 复制代码
配置 vault
事先准备好一个数据库和对该数据库具有访问权限的数据库账号
参考
database name password
样例中的配置请事先阅读文档知晓含义
参考 Vault Configuration Vault
的配置文件是 HCL 或者 json
,这里我使用 json
HCL to json
请参考 HCL
- 初始化
vault
$ mkdir -p vault/config $ mkdir -p vault/file $ mkdir -p vault/logs $ vim vault/config/local.json { "ui": true, "storage": { "mysql": { "address": "mysql:3306", "username": "vault", "password": "vault123456" } }, "listener": { "tcp": { "address": "0.0.0.0:8200", "tls_disable": 1 } }, "backend": { "file": { "path": "/vault/file" } }, "log_level": "Debug", #调试阶段建议开启Debug "default_lease_ttl": "168h", "max_lease_ttl": "720h" } $ docker-compose up -d $ docker-compose exec vault ash / # vault operator init Unseal Key 1: cz/cSHqUep5IBQjtDWBgFnN+G02hLFh8s/19rPxKjxCe #记下来 Unseal Key 2: o+BRjfy64sUKLTWKV0jV+JjvKZWd0R3ibBR7IUbCn8sB #记下来 Unseal Key 3: xiJF+XI8gF1PWGMvOYhy0 go 16x2VgZdAVKw/xBIVGeo7 #记下来 Unseal Key 4: xd/H1hBdPGwm2qchkShgzGbVtWWHeeCv8S1RyYg34yKi #记下来 Unseal Key 5: 4OOHfxxwuX7Hz40E/bHJLbkwLLWeZkWnz7/pmdtgm7mn #记下来 Initial Root Token: s.RIeC53WBWizfl0OXVbDYuxbh #记下来 Vault initialized with 5 key shares and a key threshold of 3. Please securely distribute the key shares printed above. When the Vault is re-sealed, restarted, or stopped, you must supply at least 3 of these keys to unseal it before it can start servicing requests. Vault does not store the generated master key. Without at least 3 key to reconstruct the master key, Vault will remain permanently sealed! It is possible to generate new unseal keys, provided you have a quorum of existing unseal keys shares. See "vault operator rekey" for more information. 复制代码
初始化动作为我们生成了 5 个 Unseal key,此外还有默认的 Root Token。所以应该马上把这些信息记录到安全的地方,因为以后你是没有办法再看到它们的。
- 编辑nginx,为vault提供web服务
编辑完记得重启nginx服务
server { listen 80; server_name vault.yiranzai.top; location / { proxy_pass http://vault:8200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 复制代码
- 访问
vault.yiranzai.top
Vault 对于数据保护是非常重视的。服务器启动后,并不能够马上访问其数据,而必须经过一个解封(Unseal)的动作。
依次输入上边得到的五个 Unseal Key
中的三个来解封服务,然后使用 Root Token
登录,登录后如图,右侧会有教程,先跟着做一边熟悉熟悉。
- 创建一个
Secrets Engines
这个东西,怎么说呢,不太好理解。字面意思就是 秘密引擎
,是存储,生成或加密数据的一个组件,可以理解为一个数据集,也可以理解为一种数据渠道。只有 Secrets Engines
存在,数据才能被指定方式存储。
- Generic
- KV (这里只示范这种)
- PKI Certificates
- SSH
- Transit
- TOTP
- Cloud
- Active Directory
- AliCloud
- AWS
- Azure
- Google Cloud
- Google Cloud KMS
- Infra
- Consul
- Databases (支持多种驱动)
- Nomad
- RabbitMQ
- 创建一个
ACL Policy
创建一个 ACL Policy
,配置为仅对刚刚创建的 Secrets Engine
—— dronetest
有可读和列表权限。 ACL Policy
的配置格式为HCL, HCL 是 HashiCorp 创造的、专门用于配置文件的语言格式)
# Allow tokens to look up their own properties path "auth/token/lookup-self" { capabilities = ["read"] } # Allow tokens to renew themselves path "auth/token/renew-self" { capabilities = ["update"] } # Allow tokens to revoke themselves path "auth/token/revoke-self" { capabilities = ["update"] } # Allow a token to look up its own capabilities on a path path "sys/capabilities-self" { capabilities = ["update"] } path "dronetest" { capabilities = ["read", "list"] } path "dronetest/*" { capabilities = ["read", "list"] } 复制代码
至此,我们的 Vault
就配置好了,接下来让我们创建 secret
创建 Secret
上面我们简单配置了一下 Vault
,现在让我们创建 Secret
首先我们明白的是 dronetest(Policy)
对 dronetest(Secrets Engine)
只有可读和列表的权限。
- 登录
回到 vault
容器中,使用 Root token
登录
/ # vault login s.RIeC53WBWizfl0OXVbDYuxbh Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token s.RIeC53WBWizfl0OXVbDYuxbh token_accessor 5JoYSxx4CqR10mmeG7HusChz token_duration ∞ token_renewable false token_policies ["root"] identity_policies [] policies ["root"] 复制代码
- 创建一个用于验证的
token
这个token应当只对 dronetest(Secrets Engine)
可读,所以我们为他分配一个 dronetest(Policy)
/ # vault token create -policy=dronetest -no-default-policy Key Value --- ----- token s.mx4KQycrFAfiaHIuPnNLhFCy #记下来非常重要 token_accessor 8rzot4pDJvfX0JTi2ImYLvg4 token_duration 168h token_renewable true token_policies ["dronetest"] identity_policies [] policies ["dronetest"] 复制代码
- 写入
Secret
如图所示,这里我们为 web
创建了两对KV
接下来尝试用命令创建
/ # vault kv put dronetest/test v=k Key Value --- ----- created_time 2019-02-26T03:53:02.240676864Z deletion_time n/a destroyed false version 1 / # vault kv get dronetest/test ====== Metadata ====== Key Value --- ----- created_time 2019-02-26T03:53:02.240676864Z deletion_time n/a destroyed false version 1 == Data == Key Value --- ----- v k / # vault kv put dronetest/test a=b Key Value --- ----- created_time 2019-02-26T03:53:31.073689586Z deletion_time n/a destroyed false version 2 / # vault kv get dronetest/test ====== Metadata ====== Key Value --- ----- created_time 2019-02-26T03:53:31.073689586Z deletion_time n/a destroyed false version 2 == Data == Key Value --- ----- a b / # curl \ > --header "X-Vault-Token: s.RIeC53WBWizfl0OXVbDYuxbh" \ > http://127.0.0.1:8200/v1/dronetest/data/test {"request_id":"f5ce7d8f-cc60-ec79-20a5-5875c5e4362c","lease_id":"","renewable":false,"lease_duration":0,"data":{"data":{"a":"b"},"metadata":{"created_time":"2019-02-26T03:53:31.073689586Z","deletion_time":"","destroyed":false,"version":2}},"wrap_info":null,"warnings":null,"auth":null} 复制代码
可以看出后者覆盖了前者,注意 version
增加了 1
, vault
为每个 path
每次写入的数据都定义为了一个新的版本,这样就不难理解,这里为什么是后者覆盖了前者。
在 Drone
中使用 Vault
以上我们了解了 Vault
简单的部署和使用,现在我们一起了解怎么在 Drone
中使用 Vault
编辑Docker-compose.yml
结合上一篇文章 (一) Drone CI For Github —— 打造自己的CI/CD工作流 ,我们将 Vault
加入进来
然后我们还需要 drone-vault
这个插件来实现 Drone
和 Vault
之间的通信中转
参考
- Drone使用Vault存储Secret (仔细看,文档是有缺失的)
- Drone-vault源码分析 (之所以要分析,是因为官方文档中没有说明怎么和vault通信,观看源码一目了然)
version: "3.7" services: nginx: image: nginx:alpine container_name: dronetest_nginx ports: - "80:80" restart: always networks: - dronenet mysql: image: mysql:5.7 restart: always container_name: dronetest_mysql environment: - MYSQL_ROOT_PASSWORD=root_password - MYSQL_DATABASE=drone - MYSQL_USER=drone - MYSQL_PASSWORD=drone_password networks: - dronenet volumes: - /path/to/conf/my.cnf:/etc/mysql/my.cnf:rw - /path/to/data:/var/lib/mysql/:rw - /path/to/logs:/var/log/mysql/:rw vault: image: vault:latest container_name: vault restart: always networks: - dronenet volumes: - ./vault/file:/vault/file - ./vault/config:/vault/config - ./vault/logs:/vault/logs cap_add: - IPC_LOCK environment: - VAULT_ADDR=http://127.0.0.1:8200 command: vault server -config=/vault/config/local.json #这句非常重要,一定要替换原有的Dockerfile中的CMD,不然会自动初始化,生成的数据都在docker logs中,不说你肯定找不到。dog.jpg,所以我选择手动初始化 drone-server: image: drone/drone:1.0.0-rc.5 #不要用latest,latest并非稳定版本 container_name: dronetest_server networks: - dronenet volumes: - ${DRONE_DATA}:/var/lib/drone/:rw - /var/run/docker.sock:/var/run/docker.sock:rw restart: always environment: - DRONE_DEBUG=true - DRONE_DATABASE_DATASOURCE=drone:drone_password@tcp(dronetest_mysql:3306)/drone?parseTime=true #mysql配置,要与上边 mysql 容器中的配置一致 - DRONE_DATABASE_DRIVER=mysql - DRONE_GITHUB_SERVER=https://github.com - DRONE_GITHUB_CLIENT_ID=${Your-Github-Client-Id} #Github Client ID - DRONE_GITHUB_CLIENT_SECRET=${Your-Github-Client-Secret} #Github Client Secret - DRONE_RUNNER_CAPACITY=2 - DRONE_RPC_SECRET=YOU_KEY_ALQU2M0KdptXUdTPKcEw #RPC秘钥 - DRONE_SERVER_PROTO=http #这个配置决定了你激活时仓库中的webhook地址的proto - DRONE_SERVER_HOST=dronetest.yiranzai.top - DRONE_USER_CREATE=username:yiranzai,admin:true #管理员账号,一般是你github用户名 drone-vault: image: drone/vault container_name: dronetest_vault restart: always networks: - dronenet environment: - SECRET_KEY=7890bcce69bb685a9a424767fe9d1be1 #和drone-agent通信的加密 - DEBUG=true - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN_RENEWAL=84h - VAULT_TOKEN_TTL=168h - VAULT_TOKEN=s.mx4KQycrFAfiaHIuPnNLhFCy #这里不要用root token,用上边生成的只读token drone-agent: image: drone/agent:1.0.0-rc.5 container_name: dronetest_agent restart: always networks: - dronenet depends_on: - drone-server volumes: - /var/run/docker.sock:/var/run/docker.sock:rw environment: - DRONE_SECRET_SECRET=7890bcce69bb685a9a424767fe9d1be1 - DRONE_SECRET_ENDPOINT=http://dronetest_vault:3000 - DRONE_RPC_SERVER=http://dronetest_server - DRONE_RPC_SECRET=YOU_KEY_ALQU2M0KdptXUdTPKcEw - DRONE_DEBUG=true - DRONE_LOGS_DEBUG=true - DRONE_LOGS_PRETTY=true - DRONE_LOGS_NOCOLOR=false networks: dronenet: 复制代码
改写仓库中的 .drone.yml
- 为
dronetest
中的web
创建一个新版本
私钥中的换行符需要替换成\n粘贴进来
{ "port":"22", "name":"yiranzai", "host":"dronetest.yiranzai.top", "deploy_path":"/path/to/web", "rsa":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAu1uWokQH6tuExm1RcFTJj2F6b8TXUkAzpAywVFQuyIepQwVG\nfl+Y1iD8YrqB31ZDjJk3DbC6DYGsecJILpBKDJ6T1M4UPKF6m0DH+O4bb33rhBy/\nY/zeN2jOygKTfTWpxrs13ZLvsJzNsH7rs6P+K3c+2heAhrYlyzeXTO/VbqCAsjMp\nsDMRjCDEp7jxNeEOdGM/4gIxpatDkVSIbgCj1jkYJJ3C0ipS3KvI2A1Lic8Vjr4V\nxtRK82r4aa1qeWunUFJWaO1O/V11l63lixfrr12QDgRyAkC/GCVOso6+NRP+DfGj\nhGQ+XziBZRdaEkQwv4kI717l4ToFDvUj1G8K1QIDAQABAoIBADx0q/sIT0DYkpXb\nMPUw7W7361We6gBAXiPMTvot0pGeXeYSCiBpL/g40vwBvB47TzM8olcKDzqRAgKO\nn/IZXzNn2qLN4emT482p34b1O/AWtNFy7h4Le1SBernQULT1mQtIgt/rBMB2FzZ7\n//p4q0x3ZXKkRi+i/NTayi/pzW6DTxYreIek+FSIPPJ3Kc1tsooD8greiEYo3wef\nbzV17YIvEry3RRRKYcR/tjS/oWOKdG1YzxsiPVALrZtgHS3KcDCYRltQoALGfMjl\nL4iicfTe2Jlr36CvdH0yqFOsRPH0eh4dC1sFKBzHFqcccnNfnhOGgwCbj/zDEuX+\nDrUUnqECgYEA3NqvHSAg3ULF0Y+emRXDDLbLmBDsIX+7ygQeYcwC1EVVf7F2z+Tw\ntYTjTNu4HzXAHVQ3WcB4K0fXEAJuK0LtORpHPPxfMse6vURSOTubBqhp6+H33TTq\nJa0ph1vLvGp2G1sJHQ+QrwZw+SyJ2LtiSYlMTIf617DDYAc+iWoBc10CgYEA2XZ8\nfRy20YMb01znorEG7WQ/vErtasAJbN122M/e6a1FPMmDdiTuYvA4Q0xylDXBgwZ/\nXxBFc1fs6QI+Vks3J6lzAgJ+XbX3gtoPxTFRJu4yZjCmhxLOpr1zzR8eWWrJ3aA3\nIS2UmQhr8mGPPnQbc7OeLTUv+7ZokDElZmMpxekCgYB1ZPi4Lp/JfPjRz3mp3dt0\nIqZOCpC1rcAQPeg4a80FMGWmHprdHwCkPCLmc3SHIncgH+sMjjZSKzmyFNiivkyC\nkelUDYI813XnTS23pmtdOqAy3kmPD3V2eXkd0D6XxK3LEzTg8akin/XlPTt4rQIt\nvIGGHLHN/jOcE722JVboMQKBgQCFOyqaHHWFdyYdINZpvrvXxYum+ODsfitIH4co\n3nJcCGRbEbsRLx8+Tp6p3LR2SVj3xYVT4MwsFrp3J4C1re8R1ac4m/1/u3ShHqh6\nz/RAPb3zDGt6ZfNmBVk3WstlTR/e3QV+xkY8XASGw27XfJs1D37hI6z6Mo3tiC61\nxBdbwQKBgHMDXneApZOsByrm0fvrOdIeW247kkmO6jLrI6QI/mR70gjODKXApLbU\nAbyglSi/i6Ewp+Au3+2mMvHFGc8iRkh0pwEo+xMKqPUAZEnmCbo3mKSjnR/vE3Pa\nO1frNKNLFff6kMh0ufbO3YIixYHCNJO6j/k1GmkkECSTMMka1tig\n-----END RSA PRIVATE KEY-----" } 复制代码
- 编辑
.drone.yml
--- kind: pipeline name: drone workspace: base: /app path: git/drone steps: - name: build image: node:alpine volumes: - name: webroot path: /wwwroot commands: - /bin/sh bash.sh environment: host: from_secret: host port: from_secret: port abc: abctest - name: deploy image: appleboy/drone-scp when: status: - success settings: host: from_secret: host port: from_secret: port key: from_secret: rsa username: from_secret: username target: from_secret: deploy_path source: ./* volumes: - name: webroot host: path: /opt - name: cache host: path: /tmp/cache trigger: branch: - master event: - push --- kind: secret external_data: host: path: dronetest/data/web name: host username: path: dronetest/data/web name: name port: path: dronetest/data/web name: port deploy_path: path: dronetest/data/web name: deploy_path rsa: path: dronetest/data/web name: rsa 复制代码
- 提交修改
git add .;git commit -m 'init test 4'; git push origin master 复制代码
- 查看
Drone
的ACTIVITY FEED
如果成功就会如下图所示
-
去服务器检查一下
看到
bash.sh
和.drone.yml
都被上传到这里(只是测试,不是真的让你这么干)
$ pwd /home/www $ ll -a total 40 drwx------ 4 www www 4096 Feb 20 04:23 . drwxr-xr-x. 4 root root 4096 Feb 20 03:55 .. -rw------- 1 www www 61 Feb 19 03:00 .bash_history -rw-r--r-- 1 www www 18 Oct 30 13:07 .bash_logout -rw-r--r-- 1 www www 193 Oct 30 13:07 .bash_profile -rw-r--r-- 1 www www 231 Oct 30 13:07 .bashrc -rw-r--r-- 1 www www 35 Feb 20 04:23 bash.sh -rw-r--r-- 1 www www 812 Feb 20 04:23 .drone.yml drwxr-xr-x 8 www www 4096 Feb 20 04:23 .git drwxr-xr-x 2 www www 4096 Feb 19 02:40 .ssh 复制代码
总结和推荐
写到这里,就算是结束了。说实话,有了上一篇文章的的经验和踩坑,我已经对于 Drone
的文档相当失望了,没想到后边有更深的坑在等着我,当我了解到真相以后,气得差点砸键盘。
本次总结
- Vault 的文档其实还算清晰,在实际操作之间,建议至少把KV相关的部分熟读,而且第一次激活之后的手册一定要照着实践一遍。(如果你的英文不错,你可以看
vault
官方提供的高级教程) -
drone-vault
的官方样例中没有说明怎么与vault
通信,在我第一遍的操作中,我没有细想这个问题,跳过了,结果不用多说,自然是失败。后面发现问题一脸蒙蔽,这玩意他不说我怎么找呢?还是@Dee luo老哥提醒我,我才想起来去看看源码,在源码中找到了相关参数。(强烈吐槽!!!仓库还是只读的!!!) -
drone-vault
是用GO语言开发的,drone-vault
使用的http
包,不支持没写协议的url
,例如vault:8200
不能被识别,要写成http(s)://vault:8200
-
vault
中的Secret
存储路径是{Engine Name}/data/{Secret Name}
,这一点要牢记
如果你对 vault
想有更深层次的了解,可以看下YUHAO的博客 私密信息管理利器 HashiCorp Vault系列文章
以上所述就是小编给大家介绍的《[小团队自动化](二) Drone CI使用Vault作为凭据存储 —— 打造自己的CI/CD工作流》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 如何滥用LAPS窃取用户凭据
- 破坏攻击者利用域凭据
- 渗透测试中需要关注的本地凭据
- 通过 PAM 后门和 DNS 请求来泄漏用户凭据
- 攻击者如何借助授权插件,实现macOS持久化凭据窃取
- 挖洞经验 | 用绕过姿势形成SSRF获取印度最大股票经纪公司的AWS密码凭据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。