Vault, uygulama sırlarını yönetmek ve UI, CLI veya HTTP API kullanarak hassas bilgileri korumak için kullanılır - örneğin: tokenler, şifreler, sertifikalar, şifreleme anahtarları vs. Vault tüm sırları saklamak için merkezi bir yerdir. Bu örnekte yapacağımız şey, bir docker konteyner yaratacağız, bazı sırları içinde saklayacağız ve onlara Vault'un HTTP API'siyle dışarıdan erişeceğiz.


Kullanılan vault bileşenleri


Örneğimiz Vault'un aşağıda listelenen bileşenlerini kullanır.



Yapı


├── docker-compose.yml
└── vault
└── config
└── config.json

Dosyalar


docker-compose.yml


Prodüksiyon ortamında SKIP_SETCAP değişkeni false olmalı. SKIP_CHOWN=true değişkenini "config.json" dosyasını konteyner içine kopyalamadığımız için kullanıyoruz.


version: "3.4"

services:
vault:
image: vault:latest
environment:
- VAULT_ADDR=http://localhost:8200
- VAULT_API_ADDR=http://0.0.0.0:8200
- SKIP_SETCAP=true
- SKIP_CHOWN=true
ports:
- 8200:8200
cap_add:
- IPC_LOCK
command: server
volumes:
- ./vault/config:/vault/config

config.json


Prodüksiyon ortamında disable_mlock ve tls_disable girdileri false olmalı.


{
"storage": {
"file": {
"path": "vault/file"
}
},
"listener": {
"tcp": {
"address": "0.0.0.0:8200",
"tls_disable": true
}
},
"ui": true,
"max_lease_ttl": "8760h",
"default_lease_ttl": "8760h",
"disable_mlock": true
}

Kurulum


$ docker-compose up --build

Starting my-vault_vault_1 ... done
Attaching to my-vault_vault_1
vault_1 | ==> Vault server configuration:
vault_1 |
vault_1 | Api Address: http://0.0.0.0:8200
vault_1 | Cgo: disabled
vault_1 | Cluster Address: https://0.0.0.0:8201
vault_1 | Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
vault_1 | Log Level: info
vault_1 | Mlock: supported: true, enabled: false
vault_1 | Storage: file
vault_1 | Version: Vault v1.1.3
vault_1 | Version Sha: 9bc820f700f83a7c4bcab54c5323735a581b34eb
vault_1 |
vault_1 | ==> Vault server started! Log data will stream in below:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1859c17f18c3 vault:1.1.2 "docker-entrypoint.s…" 21 hours ago Up 27 minutes 0.0.0.0:8200->8200/tcp my-vault_vault_1

UI http://your-address-or-ip:8200/ui adresinden ulaşılabilir.



Kurulum


$ docker exec -it my-vault_vault_1 sh
/ # vault status
Key Value
--- -----
Seal Type shamir
Initialized false
Sealed true
Total Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version n/a
HA Enabled false

Başlatma


Vault sunucusu kapatıldıysa veya yeniden başlatıldıysa, aşağıdaki açma anahtarlardan üçünü kullanmanız gerekir. Ayrıca "root" kullanıcısı/poliçesi olarak giriş yapmak için aşağıdaki kodu kullanın.


/ # vault operator init
Unseal Key 1: 8+cqV1Kx23V+6Vk/Q5AcS44dUUt/9EOYOHYAgUW5Nr2x
Unseal Key 2: bB1TvY6HAHohDDnBkMUOtpwIjAqmuG1O3BO+PjPINJAU
Unseal Key 3: uptS2m4t26fTzWVfHbVa9ff6mYxyGLKAoooppVWcPNhP
Unseal Key 4: F/zN9VB0gN6PqiCJz26z0o+rKrYNSm/LVrPfpDZ7R+pr
Unseal Key 5: AIzECCC2OBFU8w1WyOoYmeM/HwnMVwisnsXwAa9uAs1N

Initial Root Token: s.wGVtc0rBJlBpsPQ8xNc84aNJ

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.

Kilidi açmak


Bu komutu, yukarıda belirtildiği gibi üç farklı "açılma anahtarı" ile üç kez çalıştırmanız gerekir. Sonuç aşağıdaki gibi görünmelidir.


/ # vault operator unseal
Unseal Key (will be hidden):

Key             Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 1.1.2
Cluster Name vault-cluster-6e925364
Cluster ID 57a932bc-bf5a-c358-a24a-5b716cee9e5b
HA Enabled false


Login


Yukarıdaki "Initial Root Token" kullanılmalı. Alternatif olarak, aynı token ile UI'den giriş yapabilirsiniz.


/ # vault login
Token (will be hidden):
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.wGVtc0rBJlBpsPQ8xNc84aNJ
token_accessor kLt2G7FFemIf9YaxvPrplCAp
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]

Prodüksiyon ortamında "root" politikasının kullanılması önerilmediğinden, daha sonra farklı bir poliçe tanımlayacağız.


Denetim


Denetlemeyi etkinleştirelim ve günlükleri bir dosyaya yazalım.


/ # ls -l vault/logs
total 0

/ # vault audit enable file file_path=/vault/logs/audit.log
Success! Enabled the file audit device at: file/

/ # ls -l vault/logs
total 4
-rw------- 1 vault vault 1131 May 5 22:15 audit.log

/ # vault audit list
Path Type Description
---- ---- -----------
file/ file n/a

Gizliler


"Statik" sırları kullanacağız. Ayrıca bunlar CLI, HTTP API veya UI üzerinden yönetilebilir.


/ # vault secrets list -detailed
Path Plugin Accessor Default TTL Max TTL Force No Cache Replication Seal Wrap Options Description
---- ------ -------- ----------- ------- -------------- ----------- --------- ------- -----------
cubbyhole/ cubbyhole cubbyhole_c051b82e n/a n/a false local false map[] per-token private secret storage
identity/ identity identity_f0455f33 system system false replicated false map[] identity store
sys/ system system_ef5abc18 n/a n/a false replicated false map[] system endpoints used for control, policy and debugging

Yukarıda gördüğünüz gibi kv (Anahtar/Değer) adında gizli bir motorumuz yok, bu yüzden önce onu etkinleştirmemiz gerekiyor.


/ # vault secrets enable -path=secret kv
Success! Enabled the kv secrets engine at: secret/

Doğrulayalım.


/ # vault secrets list -detailed
Path Plugin Accessor Default TTL Max TTL Force No Cache Replication Seal Wrap Options Description
---- ------ -------- ----------- ------- -------------- ----------- --------- ------- -----------
cubbyhole/ cubbyhole cubbyhole_c051b82e n/a n/a false local false map[] per-token private secret storage
identity/ identity identity_f0455f33 system system false replicated false map[] identity store
secret/ kv kv_f75b140b system system false replicated false map[] n/a
sys/ system system_ef5abc18 n/a n/a false replicated false map[] system endpoints used for control, policy and debugging

Gizlilerin oluşturulması


secret/my-vault/prod/DB_PASS yolu içinde 123123 değerine sahip olan DB_PASS anahtarını oluşturalım. Segmentleri açıklayacak olursak, şu şekilde yapardım (istediğiniz gibi yapılandırmakta özgürsünüz):


my-vault {application-name}
prod {application-environment-name}
DB_PASS {environment-variable-name}

Docker konteyneri silmediğiniz sürece, konteyneri yeniden başlattığınızda, sırlarınız hala orada olacak!


CLI versiyon


/ # vault kv put secret/my-vault/prod/DB_PASS DB_PASS=123123
Success! Data written to: secret/my-vault/prod/DB_PASS

/ # vault kv get secret/my-vault/prod/DB_PASS
===== Data =====
Key Value
--- -----
DB_PASS 123123


HTTP API versiyon


v1/ versiyonu mecburidir ama isterseniz başka bir versiyon aktifleştirip kullanabilirsiniz.


curl \
-H "X-Vault-Token: s.wGVtc0rBJlBpsPQ8xNc84aNJ" \
-H "Content-Type: application/json" \
-i -X POST \
-d '{"data":{"DB_USER":"inanzzz"}}' \
http://your-address-or-ip:8200/v1/secret/my-vault/prod/DB_USER

HTTP/1.1 204 No Content

curl \
-H "X-Vault-Token: s.wGVtc0rBJlBpsPQ8xNc84aNJ" \
-i -X GET \
http://your-address-or-ip:8200/v1/secret/my-vault/prod/DB_USER

HTTP/1.1 200 OK
{
"request_id": "f6d8e003-2b21-ee03-11f7-22bde3668120",
"lease_id": "",
"renewable": false,
"lease_duration": 31536000,
"data": {
"data": {
"DB_USER": "inanzzz"
}
},
"wrap_info": null,
"warnings": null,
"auth": null
}


Poliçe


Vault ile etkileşimde bulunmak için tüm izinlere sahip "root" politikası kullanıyoruz. Bu varsayılan olarak Vault ile birlikte gelir, ancak ya tüm root tokenlerini iptal etmemiz yada Vault'u prodüksiyon ortamında çalıştırmadan önce sadece izinleri azaltmamız gerektiği önerilir. Poliçeyi kaldırırsanız, yeni poliçe oluşturamazsınız, bu nedenle ne yaptığınızı bildiğinizden emin olun. Daha fazla bilgi için Root Policy sayfasını okuyun.


Yeni poliçe


Aşağıdaki poliçe, secret/ ve secret/my-vault/ yolu altındaki tüm klasörlere ve değişken isimlerine (değerlere değil) sadece list iletişim hakkı veriyor (bu kısım sadece UI kullanacaksanız geçerlidir, CLI için değil yani isterseniz silebilirsiniz). Ama secret/my-vault/stag/ yolu altındaki tüm klasörler ve değişkenlere create|read|update|delete|list hakkı veriyor.


/ # vi vault/file/sys/policy/_my-vault-stag.json
{
"path": {
"secret/": {
"capabilities": [
"list"
]
}
},
"path": {
"secret/my-vault/": {
"capabilities": [
"list"
]
}
},
"path": {
"secret/my-vault/stag/*": {
"capabilities": [
"create",
"read",
"update",
"delete",
"list"
]
}
}
}

Yeni poliçeyi yaratalım.


/ # vault policy write my-vault-stag vault/file/sys/policy/_my-vault-stag.json
Success! Uploaded policy: my-vault-stag

Bu poliçe için kullanılabilecek yeni bir token oluşturun.


/ # vault token create -policy=my-vault-stag
Key Value
--- -----
token s.qjQxk6i7nBvq1yKx9ZK8Kkfp
token_accessor WZJHfz2GOpMvBFbIVUOtGRFF
token_duration 8760h
token_renewable true
token_policies ["default" "my-vault-stag"]
identity_policies []
policies ["default" "my-vault-stag"]

Test


İletişim hakkının olmadığı secret/my-vault/prod yoluna ulaşmayı deneyelim.


curl \
-H "X-Vault-Token: s.qjQxk6i7nBvq1yKx9ZK8Kkfp" \
-i -X GET \
http://your-address-or-ip:8200/v1/secret/my-vault/prod/DB_USER

HTTP/1.1 403 Forbidden
{"errors":["1 error occurred:\n\t* permission denied\n\n"]}

CLI ile test edelim. Öncelikle vault login komutu ile poliçeye login olmamız gerekli.


/ # vault login
Token (will be hidden):
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.qjQxk6i7nBvq1yKx9ZK8Kkfp
token_accessor WZJHfz2GOpMvBFbIVUOtGRFF
token_duration 8759h49m13s
token_renewable true
token_policies ["default" "my-vault-stag"]
identity_policies []
policies ["default" "my-vault-stag"]

İletişim hakkının olmadığı secret/my-vault/prod yoluna ulaşmayı deneyelim.


/ # vault kv get secret/my-vault/prod/DB_PASS
Error reading secret/my-vault/prod/DB_PASS: Error making API request.

URL: GET http://127.0.0.1:8200/v1/secret/my-vault/prod/DB_PASS
Code: 403. Errors:

* 1 error occurred:
* permission denied

İletişim hakkının olduğu secret/my-vault/stag yoluna ulaşmayı deneyelim.


/ # vault kv put secret/my-vault/stag/DB_PASS DB_PASS=666666
Success! Data written to: secret/my-vault/stag/DB_PASS

/ # vault kv get secret/my-vault/stag/DB_PASS
===== Data =====
Key Value
--- -----
DB_PASS 666666

curl \
-H "X-Vault-Token: s.qjQxk6i7nBvq1yKx9ZK8Kkfp" \
-i -X GET \
http://your-address-or-ip:8200/v1/secret/my-vault/stag/DB_PASS

HTTP/1.1 200 OK
{
"request_id": "e71bcdbf-1049-b635-1f47-91496e85e9c6",
"lease_id": "",
"renewable": false,
"lease_duration": 31536000,
"data": {
"DB_PASS": "666666"
},
"wrap_info": null,
"warnings": null,
"auth": null
}