Automatyczne zarządzanie Vault za pomocą OpenTofu
5 minute read
Są takie elementy infrastruktury, które na początku wyglądają niewinnie. Ot, postawisz Vaulta, wrzucisz kilka sekretów, wystawisz parę certyfikatów i lecisz dalej. A potem przychodzi życie: kolejna usługa, kolejny zespół, kolejny pipeline, ktoś prosi o dostęp „tylko do tego jednego patha”, a Ty orientujesz się, że Vault zaczyna przypominać szufladę z kablami — daj się w to wciągnąć na chwilę i nagle nie wiesz, co do czego prowadzi.
Właśnie w tym miejscu wjeżdża iac-vault: repozytorium, które robi z Vaulta coś, co da się normalnie utrzymać. Wszystko jest opisane w IaC, wersjonowane w Git, odtwarzalne i gotowe pod automatyzację. Bez ręcznego klikania, bez „a kto to zmieniał?”, bez tajemnej wiedzy w głowie jednej osoby.
To jest wpis o tym, jak ogarniam środowisko Vaulta przy pomocy OpenTofu — od PKI i KV, po polityki i uwierzytelnianie — i dlaczego to podejście jest po prostu… wygodne.
Dlaczego w ogóle chciałem to mieć jako IaC?
Bo Vault jest świetny, ale ręczne utrzymanie Vaulta w rosnącym środowisku to proszenie się o problemy:
- polityki „tymczasowe”, które zostają na zawsze,
- sekrety tworzone ad-hoc w różnych mountach,
- PKI, które żyje własnym życiem,
- brak jasnej odpowiedzi na pytanie: „jak to odtworzyć od zera?”
Z iac-vault mam jasny układ:
- Git jest źródłem prawdy,
- zmiany przechodzą przez Code Review,
- Rollout jest przewidywalny,
- a Vault przestaje być czarną skrzynką.
- jest rozliczalność i możliwości analizowania błędów na danych.
Co to właściwie jest iac-vault?
iac-vault to repozytorium, które pełni rolę orkiestratora konfiguracji Vault. Ono „składa” środowisko z czytelnych klocków:
pki– pełna warstwa certyfikatów (Root, Intermediate, leafy),secrets– przestrzenie KV na sekrety (KV v2),policies– polityki ACL (czytelne, modularne),auth– metody logowania i integracje (userpass + AppRole),- plus
providers.tf,variables.tfi reszta „kleju”.
W praktyce: repo mówi Vaultowi dokładnie, co ma istnieć — i możesz to odtworzyć na nowej instancji w identyczny sposób.
flowchart TB
subgraph s1["opentofu module"]
n2["vault-pki"]
end
A["iac-vault"] --> n3["auth"] & n4["pki"] & n5["secrets"] & n6["polices"]
n4 --> n2
Struktura katalogów jest prosta i „czyta się sama”:
.
├── auth # mechanizmy autoryzacji (userpass, AppRole)
├── main.tf # główny plik wykonawczy OpenTofu
├── pki # konfiguracja PKI oparta o moduł vault-pki
├── policies # polityki ACL Vault
├── providers.tf # definicje providerów
├── secrets # konfiguracja backendów KV
└── variables.tf # zmienne globalne
PKI: to tutaj robi się naprawdę fajnie
Jeżeli masz więcej niż kilka usług, to PKI potrafi być największym źródłem bólu. Wiele osób kończy z:
- jednym intermediate „do wszystkiego”,
- certyfikatami porozrzucanymi po systemach,
- rotacją robioną ręcznie,
- i tym cudownym uczuciem stresu, kiedy cert się kończy „jutro” 😉
W moim podejściu PKI jest robione przez moduł 👉 vault-pki opentofu
I to jest turbo wygodne, bo moduł automatyzuje cały, zdroworozsądkowy model:
- Root CA istnieje i jest używany wyłącznie do podpisywania intermediates,
- intermediates są podzielone logicznie (np.
infrastructureiapps), - leafy są generowane deklaratywnie z jednej mapy.
To na starcie wygląda jak „dodatkowa robota”, ale w praktyce daje ogromny spokój: PKI robi się przewidywalne i banalne do rozbudowy.
Jak wygląda hierarchia?
stateDiagram direction TB [*] --> s1 s1 --> s2 s1 --> s5 s1:Root CA s2:Infrastructure Intermediate CA s5:Apps Intermediate CA
Ja trzymam prosty mental model:
- infrastructure → Vault, Consul, GitLab, routery, load balancery, core infrastruktury,
- apps → aplikacje, serwisy, fronty, API.
W OpenTofu to jest po prostu czytelna mapa:
intermediates = {
infrastructure = {
path = "pki-infrastructure"
common_name = "rachuna-net.pl Infrastructure Intermediate CA"
role_name = "infrastructure-default"
}
apps = {
path = "pki-apps"
common_name = "rachuna-net.pl Apps Intermediate CA"
role_name = "apps-default"
}
}
Leaf: certyfikaty jako lista życzeń
Najlepsze jest to, że wystawianie certyfikatów końcowych robi się trochę jak „zamawianie” usług: wpisujesz co chcesz mieć, a reszta dzieje się sama.
leaf_requests = {
"infra-gitlab" = {
backend_key = "infrastructure"
common_name = "gitlab.rachuna-net.pl"
alt_names = ["registry.rachuna-net.pl"]
}
}
I nagle certyfikaty przestają być „operacją”, a stają się zwykłym elementem konfiguracji. Dodajesz wpis → commit → apply → gotowe.
To podejście jest genialne szczególnie wtedy, kiedy usług jest dużo i ciągle dochodzą nowe.
Certyfikaty: skąd je biorę?
W zależności od use-case:
- dla automatyzacji i narzędzi (Ansible/CI) — czytam z KV,
- dla prostych skryptów albo debugowania — biorę bezpośrednio z PKI.
Przykład pobrania bezpośrednio:
RESP=$(curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"common_name": "grafana.rachuna-net.pl"}' \
https://vault.rachuna-net.pl/v1/pki-apps/issue/apps-default)
ACME: czyli „Vault, ale jak Let’s Encrypt”
To jest ten fragment, który sprawia, że całość zaczyna błyszczeć: moduł wspiera ACME, więc możesz podpiąć np. certbota1 i robić odnowienia bardziej „cloud-native” niż „przypominajka w kalendarzu”.
acme = {
acme_enabled = true
acme_cluster_path = "https://vault.rachuna-net.pl"
allow_wildcard_certificates = true
max_ttl = "168h"
}
Efekt? Certyfikaty przestają być tematem. Po prostu się robią i odnawiają.
KV: sekrety w końcu mają swoje miejsce
KV v2 to klasyk, ale różnica robi się wtedy, gdy backendy i ich przeznaczenie masz uporządkowane, nazwane i utrzymywane w IaC.
resource "vault_mount" "kv_gitlab" {
path = "kv-gitlab"
type = "kv-v2"
description = "Storage for GitLab related secrets"
}
Dzięki temu:
- łatwiej delegować dostępy,
- łatwiej utrzymać porządek,
- łatwiej przenieść środowisko.
Polityki: bezpieczeństwo bez bólu
Polityki to miejsce, gdzie zwykle kończy się „porządek” — bo łatwo dorzucić wyjątek, trudniej go potem wyczyścić.
W iac-vault polityki są modularne: dla KV osobno, dla PKI osobno, dla admina osobno. Do tego klasyczny podział na read/write/admin.
To brzmi prosto, ale działa fenomenalnie przy rosnącej liczbie zespołów i integracji.
Auth: ludzie logują się prosto, automaty logują się bezpiecznie
Dwie metody, które pokrywają 95% potrzeb:
- userpass — dla ludzi (admin/dev),
- AppRole — dla CI/CD i automatyzacji.
AppRole jest idealny do GitLaba, bo daje kontrolę nad TTL, rolami, politykami i dostępami, bez zostawiania wszędzie tokenów „na wieczność”.
Podsumowanie: dlaczego to jest fajne?
Bo Vault przestaje być „ustawiony kiedyś” i staje się „zarządzany”.
Z iac-vault dostajesz:
- ✅ odtwarzalność środowiska,
- ✅ porządek w PKI (root -> intermediates -> leafy),
- ✅ certyfikaty jako deklaracja, nie jako operacja,
- ✅ opcję ACME i automatycznego odnawiania,
- ✅ przewidywalne, modularne polityki,
- ✅ przejrzysty model auth dla ludzi i automatyzacji,
- ✅ repozytorium, które jest dokumentacją samą w sobie.
I najważniejsze: zyskujesz spokój. A to w infrastrukturze jest walutą premium.