Aller au contenu

Comment déchiffrer les states Terraform stockés dans le backend GitLab

cover

En supposant que vous utilisez la fonctionnalité de stockage des states Terraform dans GitLab dans votre instance managée et que vous utilisez l'utilitaire intégré de sauvegarde fourni par GitLab.

Les fichiers de state Terraform sont chiffrés avant d'être stockés. Cela signifie que vous ne pouvez pas récupérer leur contenu à froid. À cette fin, GitLab utilise applications secrets (et dérive de nouveaux secrets à partir de ces clés si nécessaire) pour chiffrer le contenu sensible.

Vous souhaitez récupérer le contenu d'un fichier de state à partir d'une sauvegarde GitLab. Comme expliqué dans cette issue, il n'est pas possible de récupérer facilement un contenu déchiffré si l'instance est hors ligne.

Procédure de récupération

Récupération des secrets d'instance GitLab

En utilisant la documentation GitLab sur les secrets d'application, vous devez récupérer la valeur de db_key_base.

Récupération des informations du projet

Le stockage des states Terraform est lié à un projet GitLab. Si le projet existe toujours dans votre instance, enregistrez le project_id pour plus tard.

Si vous avez supprimé le projet, nous aurons besoin de la sauvegarde de la base de données (également stockée dans la sauvegarde GitLab).

Commencez par rechercher dans la table public.routes votre projet. Vous pouvez filtrer par source_type=Project et path=path/of/your/project. Notez la valeur dans la colonne namespace_id.

Regardez ensuite la table public.projects filtrant le namespace_id récupéré juste avant. Notez l'id du projet.

Calcul du chemin de stockage du state

Les states sont stockés avec un chemin haché.

La première partie est la somme hash256 du projet id. Vous pouvez utiliser la commande suivante pour le calculer :

echo -n "<id_projet>" | openssl dgst-sha256

La deuxième partie peut être récupérée de la base de données dans la table public.terraform_states. Filtrez par project_id et le name du state enregistrez le uuid.

Le chemin complet du dossier contenant le fichier de state est maintenant :

<part_1[0:1]>/<part_1[2:3]>/<part_1>/<part_2>

Si vous avez activé le versionning, le state est stocké avec le nom de fichier <serial_number>.tfstate

Récupération du contenu

C'est la partie la plus difficile et vous devez être un peu familier avec Ruby.

GitLab utilise un outil nommé Lockbox pour chiffrer le contenu du state de Terraform avant de le stocker. Nous allons utiliser le même outil pour déchiffrer nos fichiers.

Compléter et utilisez le script suivant :

#################
# Configuration #
#################

# Retreived from GitLab rails secrets
# https://docs.gitlab.com/ee/development/application_secrets.html
# This is a dummy key base. Don't bother using it
db_key_base = "<FILL_DB_KEY_BASE>"

# The project ID in GitLab
project_id = "<FILL_PROJECT_ID>"

# The file to decrypt
input_file = "<FILL_ENCRYPTED_STATE_FILE_PATH>"

# The file where to write the terraform state content
output_file = "<FILL_DECRYPTED_STATE_FILE_PATH>"

#############
# ALGORITHM #
#############

# Compute encryption key
key = OpenSSL::HMAC.digest('SHA256', db_key_base, project_id)

# Generate LockBox tool
# https://github.com/ankane/lockbox
lockbox = Lockbox.new(key: key)

encrypted_state_content = File.binread(input_file)
state_content = lockbox.decrypt_str(encrypted_state_content)
File.write(output_file, state_content)

Je ne suis pas un expert en Ruby mais voici un simple script bash pour configurer le bon environnement :

#!/bin/bash

rails new myapp
cd myapp/

echo 'gem "lockbox"' >> Gemfile
bundle install

bundle exec rails runner decode.rb

Resources