
Conservi chiavi API, password, certificati e altri dati sensibili nei servizi cloud-native di gestione dei secrets e li utilizzi direttamente dai cluster K8s.
Introduzione
I secrets sono indispensabili per il funzionamento di molti sistemi in produzione. Un'esposizione accidentale rappresenta uno dei rischi più gravi e va affrontata con la massima attenzione. Gli sviluppatori devono fare il possibile per proteggere i secrets delle proprie applicazioni.
Il problema si fa ancora più complesso quando un'azienda adotta un'architettura a microservizi e diversi servizi devono accedere a secrets differenti per funzionare correttamente. Da qui nuove sfide: come distribuire, gestire, monitorare e ruotare i secrets delle applicazioni senza esporli involontariamente?
Nel post precedente ( Parte I) ho illustrato un metodo per integrare con Kubernetes i servizi di gestione dei secrets di AWS e Google Cloud ( AWS Secrets Manager, AWS SSM Parameter Store e Google Cloud Secret Manager), aggiungendo manualmente l'initContainer doitintl/secrets-init al Pod di destinazione.
In questo post presenterò invece un approccio Kubernetes-native per integrare i servizi di gestione dei secrets cloud sopra citati.
Iniezione automatica dei secrets cloud
Sebbene sia possibile modificare manualmente i file YAML di Deployment di Kubernetes per usare secret-init come sistema init del container, sarebbe molto più comodo se qualcuno se ne occupasse al posto nostro, e solo per i Pod che fanno effettivamente riferimento a secrets cloud. Per fortuna, Kubernetes mette a disposizione un meccanismo che consente di ispezionare e modificare un Pod prima della creazione del container: il mutating admission webhook.
Il progetto doitintl/kube-secrets-init è un progetto open-source di DoiT International che implementa un mutating admission webhook di Kubernetes per l'iniezione di secrets cloud, con supporto sia per i secrets gestiti da AWS sia per quelli di Google Cloud.
kube-secrets-init tiene sotto controllo i cluster Kubernetes per individuare i Pod appena creati o aggiornati e aggiunge un initContainer con l'utility doitintl/secrets-init ai Pod che fanno riferimento a secrets cloud direttamente (tramite variabili d'ambiente) e/o indirettamente (tramite Secret e ConfigMap di Kubernetes).

Integrazione con AWS Secrets Manager
Come valore di una variabile d'ambiente è possibile indicare un riferimento ARN a un secret di AWS. secrets-init risolverà il valore della variabile, utilizzando l'ARN specificato, restituendo il valore del secret a cui fa riferimento.
https://gist.github.com/930c9ea733557f9715f976df042bf361
Integrazione con AWS Systems Manager Parameter Store
È possibile sfruttare AWS Systems Manager Parameter Store per archiviare parametri e secrets delle applicazioni.
Come variabile d'ambiente si può indicare un riferimento ARN a un AWS Parameter Store. secrets-init risolverà il valore della variabile, utilizzando l'ARN specificato, restituendo il valore del parametro a cui fa riferimento.
https://gist.github.com/f7d9a81d5e239cdd734989a689d46f82
Integrazione con Google Secret Manager
Come valore di una variabile d'ambiente è possibile indicare il nome di un Google Secret (con il prefisso gcp:secretmanager:). secrets-init risolverà il valore della variabile, utilizzando il nome specificato, restituendo il valore del secret a cui fa riferimento. Il nome può includere anche la versione del secret, per puntare a una versione specifica.
https://gist.github.com/d121cce3a9d4664a876deb95f18493d7
Requisiti
AWS
Per risolvere i secrets di AWS provenienti da AWS Secrets Manager e Parameter Store, l'applicazione secrets-init deve essere eseguita con un AWS IAM Role a cui sia associata una delle seguenti policy IAM.
Per AWS Secrets Manager:
https://gist.github.com/7348301b4882a564cbd9644d6697c3eb
Per AWS Systems Manager Parameter Store:
https://gist.github.com/3f3dd3d015a4c000341491c18ac2c4b7
Quando si lavora in un cluster EKS, è consigliabile utilizzare gli AWS IAM Roles for Service Account. In alternativa è possibile assegnare un IAM Role direttamente all'istanza EC2 su cui gira il container, ma questa opzione è considerata meno sicura.
Google Cloud
Per risolvere i secrets di Google provenienti da Google Secret Manager, l'applicazione secrets-init deve essere eseguita con un IAM role dotato dei permessi necessari ad accedere ai secrets desiderati. A un Google Service Account si possono assegnare, ad esempio, i due ruoli IAM predefiniti di Google: Secret Manager Viewer e Secret Manager Secret Accessor.
In un cluster GKE è possibile assegnare un IAM Role a un Pod di Kubernetes tramite Workload Identity. In alternativa si può assegnare un IAM Role all'istanza GCE su cui gira il container, ma questa opzione è considerata meno sicura.
Decommentare il flag --provider=google nel file deployment.yaml.
Il deployment del webhook
- Per mettere in funzione il server webhook
kube-secrets-initdobbiamo creare un service webhook e un deployment nel nostro cluster Kubernetes. È un'operazione piuttosto lineare, con un'unica complicazione: la configurazione TLS del server. Aprendo il file deployment.yaml si nota che il certificato e la relativa chiave privata vengono letti dagli argomenti a riga di comando e che il percorso di questi file proviene da un volume mount che punta a un secret di Kubernetes:
https://gist.github.com/b861984a2be2f2f63596f089f417cefc
L'aspetto cruciale da non dimenticare è impostare in un secondo momento il certificato CA corrispondente nella configurazione del webhook, in modo che l'apiserver sappia di doverlo accettare. Per ora riutilizzeremo lo script scritto in origine dal team di Istio per generare una richiesta di firma del certificato. Invieremo poi la richiesta all'API di Kubernetes, recupereremo il certificato e creeremo a partire dal risultato il secret necessario.
Per prima cosa, eseguire lo script webhook-create-signed-cert.sh e verificare che il secret contenente certificato e chiave sia stato creato correttamente:
https://gist.github.com/43135c6af29328bcd74a37b0df5188f8
Una volta creato il secret, possiamo procedere con deployment e service. Si tratta di risorse standard di Kubernetes. Fino a questo punto abbiamo realizzato nient'altro che un server HTTP che accetta richieste tramite il service sulla porta 443:
https://gist.github.com/3971cf1f46f5a57d11d922ed84b0543f
Configurare il mutating admission webhook
Ora che il server webhook è in esecuzione, può ricevere richieste dall'apiserver. Prima però dobbiamo creare alcune risorse di configurazione in Kubernetes. Iniziamo dal validating webhook; configureremo il mutating webhook in un secondo momento. Esaminando la configurazione del webhook si nota un placeholder per CA_BUNDLE:
https://gist.github.com/fcafa7ed3b3c3b951b7fad3c0d5fbdb6
Esiste un piccolo script che sostituisce il placeholder CA_BUNDLE nella configurazione con questa CA. Eseguirlo prima di creare la configurazione del validating webhook:
https://gist.github.com/6d5bb7724cef04e9e6a2af12da917a21
Creare la configurazione del mutating webhook:
https://gist.github.com/f946d6046cc1a76a21526c346ca403c1
Configurare RBAC per secrets-init-webhook
Creare un Kubernetes Service Account da utilizzare con secrets-init-webhook:
https://gist.github.com/0cda887b586609cbdbb700f7412e70ad
Definire i permessi RBAC per il service account del webhook:
https://gist.github.com/1205f1a5d2f449cc3340a404ea474b77
In sintesi
Mi auguro che questo post Le sia stato utile. Attendo con piacere i Suoi commenti e le eventuali domande.
La invitiamo a contribuire al progetto GitHub doitintl/kube-secrets-init con Issues, Features e PR.
Vuole leggere altri articoli di Alexei? Visiti il nostro blog oppure segua Alexei su Twitter.