PKI
4 minute read
PKI (Public Key Infrastructure) to infrastruktura klucza publicznego – zestaw technologii, zasad i komponentów, które umożliwiają bezpieczną komunikację, uwierzytelnianie i szyfrowanie w systemach informatycznych.
Utworzenie drzewa certyfikatów Root CA i Intermediate CA
stateDiagram direction TB classDef Sky stroke-width:1px,stroke-dasharray:none,stroke:#374D7C,fill:#E2EBFF,color:#374D7C; classDef Peach stroke-width:1px,stroke-dasharray:none,stroke:#FBB35A,fill:#FFEFDB,color:#8F632D; [*] --> s1 s1 --> s2 s1 --> s5 s1:Root CA s1:*.rachuna-net.pl s2:Infrastructure Intermediate CA s2:Certyfikaty Infrastruktury [*] s5:Apps Intermediate CA s5:Certyfikaty Aplikacji class s5 Peach
module "vault_pki" {
source = "git@gitlab.rachuna-net.pl:pl.rachuna-net/infrastructure/opentofu/modules/vault-pki.git?ref=v1.0.0"
root_domain = "rachuna-net.pl"
root_common_name = "rachuna-net.pl ROOT CA"
pki_urls_base = "https://ct01101.rachuna-net.pl:8200/"
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"
}
}
}
Przykładowe rozwiązanie reprezentuje certyfikat główny ROOT CA oraz certyfikaty pośredniczące nfrastructure Intermediate CA dedykowany dla infrastruktury oraz Apps Intermediate CA
Wygenerowanie certyfikatu końcowego
-
Generowanie certyfikaty końcowe (leaf) dla konkretnych usług:
gitlab.rachuna-net.plconsul.rachuna-net.plvault.rachuna-net.pldocs.rachuna-net.pl
module "vault_pki" {
source = "git@gitlab.rachuna-net.pl:pl.rachuna-net/infrastructure/opentofu/modules/vault-pki.git?ref=v1.0.0"
root_domain = "rachuna-net.pl"
pki_urls_base = "https://ct01101.rachuna-net.pl:8200/"
intermediates = {
infrastructure = {
path = "pki-infrastructure"
common_name = "Infrastructure Intermediate CA"
role_name = "infrastructure-default"
}
apps = {
path = "pki-apps"
common_name = "Apps Intermediate CA"
role_name = "apps-default"
}
}
leaf_requests = {
"infra-gitlab" = {
backend_key = "infrastructure"
common_name = "gitlab.rachuna-net.pl"
alt_names = [
"registry.rachuna-net.pl"
]
}
"infra-consul" = {
backend_key = "infrastructure"
common_name = "consul.rachuna-net.pl"
alt_names = [
"ct01101.rachuna-net.pl",
"ct01102.rachuna-net.pl",
"ct01103.rachuna-net.pl",
]
}
"infra-vault" = {
backend_key = "infrastructure"
common_name = "vault.rachuna-net.pl"
alt_names = [
"ct01101.rachuna-net.pl",
"ct01102.rachuna-net.pl",
"ct01103.rachuna-net.pl",
]
}
"apps-docs" = {
backend_key = "apps"
common_name = "docs.rachuna-net.pl"
}
}
}
Kluczowe parametry:
-
root_domain = "rachuna-net.pl"Root CA będzie wystawiony dla tej domeny, np.Rachuna-Net Root CA. -
pki_urls_base = "https://ct01101.rachuna-net.pl:8200/"Baza do ustawienia:issuing_certificatescrl_distribution_pointsocsp_serversczyli gdzie klienci mają się zgłaszać po CRL / certyfikaty.
-
intermediates– definicja CA pośrednich (mapa):- klucz (
infrastructure,apps) to alias używany dalej w module, path– mount w Vault, np.pki-infrastructure,common_name– CN tego CA,role_name– domyślna rola w tym backendzie (do wystawiania leafów).
- klucz (
-
leaf_requests– lista certyfikatów końcowych do wygenerowania:- klucz mapy (
infra-gitlab,infra-consul…) to tylko nazwa logiczna w module, backend_key– mówi, z którego intermediate CA korzystać (infrastructure/apps),common_name– CN certyfikatu (zazwyczaj FQDN usługi),alt_names– Subject Alternative Names (SAN) – dodatkowe nazwy DNS w certyfikacie.
- klucz mapy (
Pobieranie certyfikatu
Zależy, jak moduł jest napisany, ale typowo:
- Zapisane są certyfikaty w
kv(np.kv-certificates/leaf/grafana),
{
"alt_names": [],
"backend_key": "apps",
"ca_chain": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
"certificate": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
"common_name": "test.rachuna-net.pl",
"issuing_ca": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
"private_key": "-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----",
"serial_number": "42:b5:19:73:cd:f9:70:0c:30:81:93:fb:b5:56:a1:7e:f9:25:6a:23"
}
- bezpośrednio do pobrania z pki
RESP=$(curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"common_name": "grafana.rachuna-net.pl"}' \
https://ct01005.rachuna-net.pl:8200/v1/pki-apps/issue/apps-default)
echo "$RESP" | jq -r '.data.certificate' > grafana.crt
echo "$RESP" | jq -r '.data.private_key' > grafana.key
echo "$RESP" | jq -r '.data.issuing_ca' > grafana.chain.crt
Proponowany podział PKI?
Z poziomu dev/DevOps masz bardzo prosty mentalny model:
-
Root CA – trzymasz w Vault, ale używasz tylko do podpisywania intermediates.
-
Intermediate CA – logiczny podział według typu systemów:
infrastructure: Proxmox, Consul, Vault, GitLab, routery, load balancery.apps: aplikacje biznesowe, frontend, API.- (opcjonalnie)
dmz,internal,storage,kubernetesitd.
-
Leaf certyfikaty – dla konkretnych hostów/usług.
I wszystko opisujesz w dwóch mapach: intermediates i leaf_requests.
Przykłady rozbudowania PKI
Kilka konkretnych trików:
-
Osobny intermediate dla Kubernetes:
intermediates = { # ... kubernetes = { path = "pki-k8s" common_name = "Kubernetes Intermediate CA" role_name = "k8s-default" } } -
Cert dla Ingress Controller:
leaf_requests = { "k8s-ingress" = { backend_key = "kubernetes" common_name = "ingress.rachuna-net.pl" alt_names = [ "*.apps.rachuna-net.pl", ] } }
Użycie ACME
Ten blok możesz podmienić w sekcji „Utworzenie drzewa certyfikatów Root CA i Intermediate CA” (stary przykład z ref=v1.0.0 → nowy z ref=v1.1.0 + ACME):
module "vault_pki" {
source = "git@gitlab.rachuna-net.pl:pl.rachuna-net/infrastructure/opentofu/modules/vault-pki.git?ref=v1.1.0"
root_domain = "rachuna-net.pl"
root_common_name = "rachuna-net.pl ROOT CA"
pki_urls_base = "https://ct01005.rachuna-net.pl:8200"
intermediates = {
infrastructure = {
path = "pki-infrastructure"
common_name = "rachuna-net.pl Infrastructure Intermediate CA"
role_name = "infrastructure-default"
# klasyczne parametry PKI
ttl = "26280h"
max_ttl = "26280h"
# konfiguracja ACME dla infrastruktury
acme = {
acme_enabled = true
acme_cluster_path = "https://ct01005.rachuna-net.pl"
allow_wildcard_certificates = true
max_ttl = "168h"
}
# (opcjonalnie) aliasy/parametry dla zachowania wstecznej kompatybilności modułu
acme_enabled = true
acme_cluster_path = "https://ct01005.rachuna-net.pl"
}
apps = {
path = "pki-apps"
common_name = "rachuna-net.pl Apps Intermediate CA"
role_name = "apps-default"
# zezwalamy na wildcardy z tego backendu
allow_wildcard_certificates = true
# klasyczne parametry PKI
ttl = "26h"
max_ttl = "26h"
# konfiguracja ACME dla aplikacji
acme = {
acme_enabled = true
acme_cluster_path = "https://ct01005.rachuna-net.pl"
max_ttl = "25h"
}
}
}
}