HashiCorp Vault

Bij het beheer van een applicatielandschap is het een uitdaging om gevoelige informatie achter slot en grendel te houden maar ook beschikbaar te maken binnen de infrastructuur. Het centraal beheren van deze informatie middels Vault biedt hierbij een uitkomst.

Wat is Vault?

Vault is ontwikkeld door HashiCorp en destijds (2015) ontworpen met een bepaalde filosofie. Namelijk het beschikbaar maken (distributie) van secrets op een veilige, makkelijke en cloud-native manier. Inmiddels is Vault uitgegroeid tot veel meer dan dit. Het bevat bijvoorbeeld ook een interne CA, biedt encryption-as-a-service en kan dynamic secrets genereren in bijv AWS, MySQL etc. Dynamic secrets worden aangemaakt wanneer ze nodig zijn en komen te vervallen zodra de lease is verlopen of wordt gerevoked. Het mooie van dynamic secrets is dat de credentials die vanuit Vault worden aangemaakt, gekoppeld kunnen worden aan de ACL’s binnen de applicatie (bijvoorbeeld AWS). Zo bepaal je in de applicatie welke rechten toegekend worden aan de credentials en heb je een centraal punt waar je dit beheert. Zo hoef je ook geen policies in-sync te houden tussen Vault en de applicatie.

Simpel gezegd bestaat Vault uit drie lagen. Namelijk de API laag, de barrier en de storage laag. De barrier is het belangrijkste onderdeel in Vault.

Storage

Vanuit Vault wordt de storage backend gezien als ‘untrusted’. Wanneer je Vault initialiseert zal de storage backend worden geconfigureerd en waar vervolgens de data versleuteld opgeslagen zal worden. Sinds Vault 1.4 (release 07 april 2020) kunnen we onderscheid maken tussen interne en externe storage backends. De interne storage oplossing is sinds versie 1.4 aanwezig en is volledig geintegreerd binnen Vault. Het biedt multi-cluster replicatie en failover toepassingen en levert qua performance ook meerdere voordelen op. Daarnaast wordt de data direct naar disk geschreven in tegenstelling tot bijvoorbeeld een externe oplossing met Consul waarbij je rekening moet houden dat deze memory-bound is. In geval van een Consul backend betekent dit dus regelmatig snapshots maken om data loss te voorkomen. Bij geintegreerde storage is dit niet nodig omdat de data direct naar disk wordt geschreven. Aangezien we minder resources aanspreken op het systeem, betekent dit minder beheertaken en een winstbehaling qua performance.

Interne storage maakt gebruik van het Raft protocol en zal in geval van een HA cluster, waarbij meerdere Vault servers opereren, gebruik maken van een raft-cluster waar een node de ‘leader’ is en de rest ‘follower’. Wie bekend is met Consul zal dit herkennen want hierbij wordt ook het raft protocol gebruikt. Consul biedt een KV store waar Vault zijn data in wegschrijft en is een logische keuze wanneer je een HA setup bouwt met externe storage.

Barrier

Zoals gezegd, is de barrier in Vault het belangrijkste onderdeel waar alle data in Vault doorheen gaat. Deze laag zorgt ervoor dat alle binnenkomende data gevalideerd en plaintext weggeschreven wordt en uitgaande data versleuteld eruit gaat is. Wanneer je iets met Vault wilt doen zul je ‘m eerst moeten unsealen. Nadat Vault is gestart bevindt die zich in een ‘sealed’ status. In deze status weet Vault waar de data zich bevindt, maar niet hoe de data gedecrypt kan worden.

[atcomputing@ ~]$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 0/3
Unseal Nonce n/a
Version 1.2.3
HA Enabled false

Bovenstaande toont een single server setup waarbij vault al geinitialiseerd is maar zich nog in een sealed status bevindt.

Na installatie en initialisatie van Vault wordt er een encryption key gegenereerd. Alle data in Vault is beveiligd met deze encryptie sleutel (encryption key) en toegang tot Vault (unsealen) betekent toegang tot de encryptie sleutel. De encryptie sleutel is om zijn beurt weer beveiligd met de hoofd sleutel (master key). Deze hoofd sleutel is opgeknipt in vijf gedeelde sleutels (shared keys) waarbij standaard 3 sleutels minimaal ingegeven moeten worden alvorens de hoofd sleutel te ontsleutelen, en dus toegang te krijgen tot de encryptie sleutel en Vault data. Voor het opknippen van de hoofd sleutel wordt Shamir’s secret sharing algoritme toegepast. Het idee achter gedeelde sleutels is dat meerdere medewerkers ieder een deelsleutel krijgen en uiteraard geen weet hebben van elkaars sleutel. In Vault terminologie worden deze medewerkers ‘unseal key holders’ genoemd.

Nadat drie geldige shared keys zijn ingevoerd is de encryption key beschikbaar en is Vault in staat om de data te decrypten. Vault bevindt zich nu in een unsealed status. Data in Vault is nu benaderbaar, maar de configuratie ook. Denk daarbij aan secret engines, authenticatie methodes (auth methods) en audit devices.

Het is ook mogelijk om Vault te unsealen middels ‘auto-unsealing’. Hierbij heb je een extra vault server nodig dat de rol overneemt van het handmatig invoeren van shared keys door de medewerkers.

De extra Vault server (Vault-1) zal hiervoor geconfigureerd worden met de Transit secrets engine. De Vault server (Vault-2) die gebruik maakt van Transit auto-unseal, schrijft de versleutelde master key naar zijn storage backend (buiten de barrier want je moet ‘m kunnen lezen in sealed status). Het bestand waar de versleutelde master key in wordt weggeschreven heet ‘barrier-unseal-keys’.

Authenticatie

Voordat je toegang hebt tot Vault zul je eerst moeten authenticeren. Authenticatie wordt afgehandeld in het component ‘auth method’ dat zich in de barrier laag bevindt. Authenticeren kan dus alleen als Vault in ‘unsealed’ status verkeerd.
Welke methode je gebruikt hangt af hoe de infrastructuur verder is ingericht en welke methode voor jou het prettigst werkt. Grofweg kun je kiezen uit een intern of extern authenticatie systeem. Bij externe authenticatie moet je denken aan bijvoorbeeld github, Azure, AWS maar ook LDAP infrastructuur. Voorbeelden van interne authenticatie zijn username/password of token authenticatie. De identities bevinden zich in dit geval in Vault.

Als voorbeeld authenticeren we hieronder via auth method ‘userpass’. Na een succesvolle authenticatie ontvang je een token dat toegang geeft tot Vault (en wat de policy toelaat). Het token verloopt uiteindelijk weer. Dit wordt getoond met ‘token_duration’. Voordat we kunnen authenticeren moeten wel eerst nog de auth method activeren in Vault.

[atcomputing@ ~]$  vault auth enable userpass
[atcomputing@ ~]$  vault write auth/userpass/users/atcomputing password=secret
[atcomputing@ ~]$  vault login -method=userpass username=atcomputing 
Password (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.grW1VtiRbmuNmTPbqIugjqkd
token_accessor         TqpeTgrm96aqdj7h9QracdkE
token_duration         768h
token_renewable        true
token_policies         ["default"]
identity_policies      []
policies               ["default"]
token_meta_username    atcomputing

Het component ‘Auth method’ is uiteindelijk verantwoordelijk voor het toewijzen van identiteit en policies. Een succesvolle authenticatie levert zoals hierboven te zien, een token op waar bepaalde rechten aan gekoppeld zijn. De rechten worden beschreven in een policy in Vault. Hierboven zijn geen policies opgegeven bij het aanmaken van de user ‘atcomputing’ waardoor alleen de policy ‘default’ wordt toegekend. Deze policy is standaard onderdeel van Vault en geeft minimale rechten voor bijvoorbeeld management van dit token. Denk aan renewal, revoke of capabilities opvragen. Je moet tenslotte wel je eigen token kunnen beheren.
De policy ‘default’ wordt overigens altijd aan een token toegekend, naast de eventuele extra policies die zijn geconfigureerd.

Tokens

Toegang tot Vault verloopt via token authenticatie. Dit kan op twee manieren:

  • Direct inloggen met een eerder gecreeerd token:
[atcomputing@ ~]$  vault login
Token (will be hidden): 
  • Indirect via een auth method:
[atcomputing@ ~]$  vault login -method=userpass username=atcomputing 
Password (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.

Indirect inloggen via een auth method genereert een token dat meteen in dezelfde sessie wordt gebruikt voor authenticatie. Dit gebeurt op de achtergrond maar het resultaat is hetzelfde als bij directe token authenticatie.

Token authenticatie (token auth method) is standaard geactiveerd in Vault en kan niet uitgezet worden. Zoals we hierboven zagen kan authenticatie ook via andere auth methods verlopen maar dit resulteert dus altijd in een token dat uiteindelijk wordt gebruikt om daadwerkelijk toegang te krijgen via ‘token auth method’.
Zoals eerder aangegeven zijn de rechten in Vault (policies) gekoppeld aan het token. De policies die van toepassing zijn op een bepaald token worden bij het aanmaken van het token opgegeven. Indien je inlogt via bijvoorbeeld ‘userpass auth method’ zijn de policies in een eerder stadium al gekoppeld aan de identiteit van de gebruiker. Bijvoorbeeld:

[atcomputing@ ~]$ vault write auth/userpass/users/atcomputing policies=<policy>

De eigenschappen van een token worden bepaald wanneer het token wordt aangemaakt. Ze kunnen vervolgens opgevraagd worden middels ‘vault token lookup’. Hieronder een voorbeeldje van een token dat via ‘userpass auth method’ is aangemaakt. We gebruiken hier ‘accessor’ als optie. De ‘accessor’ is de referentie naar een token.

[atcomputing@ ~]$  vault token lookup -accessor TqpeTgrm96aqdj7h9QracdkE
Key                 Value
---                 -----
accessor            TqpeTgrm96aqdj7h9QracdkE
creation_time       1590340672
creation_ttl        768h
display_name        userpass-atcomputing
entity_id           70270f86-6ae3-507f-2cdc-cc07c667ec88
expire_time         2020-06-25T19:17:52.379196097+02:00
explicit_max_ttl    0s
id                  n/a
issue_time          2020-05-24T19:17:52.379195905+02:00
meta                map[username:atcomputing]
num_uses            0
orphan              true
path                auth/userpass/login/atcomputing
policies            [default]
renewable           true
ttl                 767h58m38s
type                service

We zien hier o.a. wanneer dit token verloopt (expire_time) en hoe vaak het is gebruikt (num_uses). Daarnaast zien we ook het ‘path’ dat van toepassing is op dit token. Dit zegt iets over het path dat gebruikt werd bij het aanmaken van het token en kan handig gebruikt worden bij ‘source based revocation’. Stel dat je alle tokens die aangemaakt zijn via ‘auth/userpass/login wilt intrekken, dan kun je dit via de ‘auth/userpass’ prefix heel snel uitvoeren:

[atcomputing@ ~]$  vault lease revoke -prefix auth/userpass

Bovenstaande commando heeft betrekking op alle leases die gekoppeld zijn aan tokens die aangemaakt zijn via ‘auth/userpass/login. Je zou misschien ‘vault token revoke’ verwachten maar aangezien dat betrekking heeft op één token zul je daarmee niet alle tokens in 1 keer kunnen intrekken.

Root token

Bij initialisatie van Vault zal er een root token gemaakt worden. Dit token geeft je super admin rechten op Vault en beschikt een aantal afwijkende eigenschappen ten opzichte van een standaard (service) token. Een root token verloopt nooit en heeft als enige de policy ‘root’ gekoppeld. Zoals je hieronder ziet is deze policy zelfs voor gebruiker root niet in te zien.

[atcomputing@ ~]$  vault policy list
default
root
[atcomputing@ ~]$  vault policy read root
No policy named: root

Omdat een root token nooit verloopt en daarnaast super admin rechten in Vault heeft, is het van belang dat je de root token ook verwijderd zodra hij niet meer nodig is. Opnieuw genereren van een root token kan op elk willekeurig moment wanneer Vault operationeel is. De procedure vereist dat Vault ‘unsealed’ is. Extra rechten in Vault is ook niet noodzakelijk aangezien deze procedure min of meer gelijk staat aan het unsealen van Vault. Dit kan ook door elke medewerker gestart worden zolang er uiteindelijk maar drie geldige unseal keys worden opgevoerd.
Voor het genereren van een nieuw root token is dus van belang dat de unseal keys (gedeelde sleutels) beschikbaar zijn, danwel in eigen beheer of via de ‘unseal key holders’.

In Vault kunnen we onderscheid maken tussen twee type token. Namelijk service en batch tokens.

Service tokens

Service tokens zijn in tegenstelling tot batch tokens persistent. Bij service tokens is er sprake van een token administratie die door de Vault server wordt bijgehouden (Metadata). Service tokens hebben bepaalde eigenschappen waarvoor fysieke storage noodzakelijk is. Denk aan:

  • Bepaalde policies die bij een token horen
  • Metadata behorende bij een token (TTL, creation time, last renewal time etc).

Er is dus nog meer informatie waar Vault van af moet weten om het token te kunnen beheren en daarnaast clients de juiste toegangsrechten uit te geven. Dit is specifieke informatie dat op de server moet worden weggeschreven.

Elke service token dat wordt aangemaakt heeft een TTL (Time-To-Live) en zal automatisch worden revoked nadat max-TTL is verlopen (standaard 32 dagen).
Dit heeft ook effect op eventuele child tokens die aangemaakt zijn onder een bepaalde token. Wanneer je bijvoorbeeld inlogt met het root token en vervolgens ‘vault token create’ uitvoert zul je een nieuwe token krijgen met dezelfde rechten als het root token. Niet aan te raden, maar dit illustreert wel het principe. Standaard zal Vault het child token dezelfde rechten geven als het parent token. Tenzij je specifieke opties meegeeft waarbij je dus bepaalde settings overruled (policy, ttl, use-limit etc).
Wanneer het parent token verloopt of wordt gerevoked, zullen child tokens automatisch ook opgeruimd worden. Ook wanneer een child token een langere max-ttl heeft dan het parent token. Dit geldt niet voor een orphan token. Deze service tokens zijn aanmaakt als orphan (‘vault create token -orphan true’). Om dit te kunnen heb je wel root of sudo rechten nodig in Vault.

Periodic service tokens

Service tokens die onbeperkt verlengt moeten worden kun je aanmaken met de ‘period’ optie. Hiervoor zijn wel root of sudo rechten in Vault nodig. In geval van een ‘auth method’ zal deze dit moeten ondersteunen (zoals bijvoorbeeld Approle auth method).
Periodic service tokens hebben standaard wel een TTL maar geen max TTL. Zolang ze binnen de time-to-live worden verlengt zal het token onbeperkt geldig blijven. De max TTL is overigens wel in te stellen met explicit-max-ttl mocht je dit toch willen.

De noodzaak van periodic service tokens is bijvoorbeeld toegang vanaf applicaties die niet om kunnen gaan met gegenereerde tokens. Dit is bijvoorbeeld het geval wanneer je een vault server ((laten we die even Vault-2 noemen) met behulp van Auto-unsealing wilt unsealen. Zoals eerder beschreven maak je gebruik van de Transit Secrets Engine (Vault-1) waarvoor je uiteraard toegang moet hebben. Er is in een eerdere stadium een token aangemaakt met rechten op Transit Secrets engine. Het token wordt door Vault-2 gebruikt om te mogen de/encrypten op Vault-1. Als dit token na 32 dagen verloopt (standaard max-TTL in Vault) zal Auto-unsealing dus logischerwijs niet meer werken, en dat is niet wenselijk. Een periodic service token biedt hierbij uitkomst. Het token moet uiteraard wel met enige regelmaat (lees binnen de time-to-live) worden vernieuwd. Dit is iets dat Vault -2 automatisch doet zolang deze actief is.

Batch tokens

Het gebruik van service tokens kan zoals al aangegeven ook een negatief effect hebben op de performance van een Vault server. Dit zal zich pas uiten wanneer er veel tokens tegelijkertijd aanmaakt worden. Batch tokens zijn dan ook ontworpen met het oog op grote workloads. Het processen van bijvoorbeeld Big Data kan tot gevolg hebben dat van het ene op het andere moment heel veel machines worden opgestart die allemaal toegang tot Vault vragen. Hiervoor zal Vault tokens moeten genereren en bijhouden. Service tokens vragen in dat opzicht server performance waar bij batch tokens geen sprake is.

Batch tokens zijn zo ontworpen dat de relevante Metadata versleuteld in het token worden meegestuurd. Dit zie je meteen terug in de lengte van het token.

[atcomputing@ ~]$  vault token create  -policy=default -type=batch -ttl=5m
Key                  Value
---                  -----
token                b.AAAAAQIdWeJoB2oL5E0Y_sfIBleDz2ebOETs0GS6F3cCno2d9xaGw82fftHQUpDlpK7FC7vCRUcnOW6usWiakBx09zAr-eaFSQolz5wM9xR2fbAz9k_yYO0ZBEyhFGnMWKKs08yHf39BI2b-3646AclCBrKmFlU
token_accessor       n/a
token_duration       5m
token_renewable      false
token_policies       ["default"]
identity_policies    []
policies             ["default"]

[atcomputing@ ~]$  vault token lookup 
b.AAAAAQIdWeJoB2oL5E0Y_sfIBleDz2ebOETs0GS6F3cCno2d9xaGw82fftHQUpDlpK7FC7vCRUcnOW6usWiakBx09zAr-eaFSQolz5wM9xR2fbAz9k_yYO0ZBEyhFGnMWKKs08yHf39BI2b-3646AclCBrKmFlU

Key                 Value
---                 -----
accessor            n/a
creation_time       1590326295
creation_ttl        5m
display_name        token
entity_id           n/a
expire_time         2020-05-24T15:23:15+02:00
explicit_max_ttl    0s
id                  b.AAAAAQIdWeJoB2oL5E0Y_sfIBleDz2ebOETs0GS6F3cCno2d9xaGw82fftHQUpDlpK7FC7vCRUcnOW6usWiakBx09zAr-eaFSQolz5wM9xR2fbAz9k_yYO0ZBEyhFGnMWKKs08yHf39BI2b-3646AclCBrKmFlU
issue_time          2020-05-24T15:18:15+02:00
meta                <nil>
num_uses            0
orphan              false
path                auth/token/create
policies            [default]
renewable           false
ttl                 4m49s
type                batch

Voor de client is deze metadata niet te lezen, maar de Vault server zal bij interactie deze metadata decrypten en het token verwerken zonder dat er data bijgehouden dient te worden op de server.

In het volgende artikel ga ik ‘userpass auth method’ verder configureren met ‘ssh secrets engine’. Hiermee is het mogelijk met OTP (One-Time Passwords) te authenticeren op ssh servers.

Vincent Lamers

Vincent Lamers, Linux-consultant @ AT Computing

Onderwerpen
Actieve filters: Wis alle filters
Loading...