Un moyen rapide mais sécurisé d’extraire des champs à partir de secrets basés sur JSON
Plusieurs fournisseurs de cloud fournissent des informations d’identification en tant qu’objet JSON. Par exemple, Google Cloud permet la création d’un fichier JSON d’informations d’identification contenant entre autres l’identifiant du projet, la clé privée et l’e-mail client d’un compte de service. De même, Azure fournit un dictionnaire pour un principal de service qui inclut des informations sur l’application, le jeton d’authentification et les identifiants d’abonnement et de locataire.
Que se passe-t-il si vous souhaitez extraire ces informations de compte de service sans ajouter un deuxième secret d’action GitHub ?
Il en va de même lorsque vous exploitez le principal du service dans Azure, qui renvoie un dictionnaire contenant l’ID client/application et un secret. L’intégralité du JSON est nécessaire pour se connecter à Azure CLI (par exemple, en utilisant le azur/connexion action), mais seuls le nom d’utilisateur et le mot de passe sont nécessaires pour se connecter au registre de conteneurs et envoyer de nouvelles images Docker. Habituellement, votre action GitHub devrait avoir les trois secrets au lieu d’un seul.
Autre problème : le masquage des informations sensibles
Même si vous parvenez à extraire ces informations et à les définir comme variable d’environnement dans votre action ou flux de travail GitHub, vous devez vous assurer que ce champ est masqué afin que ces informations confidentielles ne soient pas enregistrées, ce qui pourrait être particulièrement dangereux dans un référentiel GitHub public.
Il y a deux choses que vous devez faire. Tout d’abord, définissez le secret en tant que variable d’environnement dans une étape du shell :
steps:
- shell: bash
env:
SUPER_SECRET: ${{ secrets.JSON_SECRET_TO_PARSE }}
run: |
command-to-parse "$JSON_SECRET_TO_PARSE"
Avant d’exporter l’élément analysé dans le run
section (par exemple, avec quelque chose comme jq
), assurez-vous d’envelopper cette variable d’environnement sensible dans ::add-mask::
annotation de sorte que lorsque vous la stockez en tant que variable d’environnement, elle ne soit pas enregistrée. Voici à quoi cela ressemble :
jobs:
secret-parsing-example:
runs-on: ubuntu-latest
steps:
- shell: bash
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
run: |
USERNAME=$(echo $AZURE_CREDENTIALS | jq -r '.["clientId"]')
PASSWORD=$(echo $AZURE_CREDENTIALS | jq -r '.["clientSecret"]')
echo "::add-mask::$USERNAME"
echo "::add-mask::$PASSWORD"
echo REGISTRY_USERNAME=$USERNAME >> $GITHUB_ENV
echo REGISTRY_PASSWORD=$PASSWORD >> $GITHUB_ENV
Générer des identifiants Azure
Tout d’abord, vous créez le principal du service sur Azure avec l’interface de ligne de commande. Voici le code pour le faire :
$groupId=$(az group show --name <resource-group> --query id --output tsv)az ad sp create-for-rbac --scope $groupId --role Contributor --sdk-auth
Les commandes CLI ci-dessus généreront un objet JSON semblable au suivant :
{
"clientId": "xxxx6ddc-xxxx-xxxx-xxx-ef78a99dxxxx",
"clientSecret": "xxxx79dc-xxxx-xxxx-xxxx-aaaaaec5xxxx",
"subscriptionId": "xxxx251c-xxxx-xxxx-xxxx-bf99a306xxxx",
"tenantId": "xxxx88bf-xxxx-xxxx-xxxx-2d7cd011xxxx",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
ou si vous utilisez la nouvelle syntaxe (c’est-à-dire en sautant --sdk-auth
):
{
"appId": "uuid",
"displayName": "azure-cli-timestamp",
"password": "uuid",
"tenant": "uuid"
}
Ajoutez cet objet JSON en tant que secret du référentiel GitHub
Vous pouvez maintenant ajouter cet objet JSON unique en tant que secret. Copiez simplement le contenu JSON et collez-le en tant que nouveau secret de référentiel, par exemple, AZURE_CREDENTIALS
:
Exécutez le flux de travail GitHub Action
Voici le flux de travail GitHub Action complet utilisant l’approche décrite ci-dessus :
name: Build a Docker image and push it to Azure ACR with a single secret
on:
workflow_dispatch:jobs:
masking:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to Azure CLI
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }} # Azure CLI needed for sth else
- shell: bash
env:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
run: |
REGISTRY_USERNAME=$(echo $AZURE_CREDENTIALS | jq -r '.["clientId"]')
REGISTRY_PASSWORD=$(echo $AZURE_CREDENTIALS | jq -r '.["clientSecret"]')
echo "::add-mask::$REGISTRY_USERNAME"
echo "::add-mask::$REGISTRY_PASSWORD"
echo REGISTRY_USERNAME=$REGISTRY_USERNAME >> $GITHUB_ENV
echo REGISTRY_PASSWORD=$REGISTRY_PASSWORD >> $GITHUB_ENV
- name: Build and push image
uses: azure/docker-login@v1
with:
login-server: prefectgha.azurecr.io
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ env.REGISTRY_PASSWORD }}
- run: |
docker build -q -t prefectgha.azurecr.io/prefect:${{ github.sha }} .
docker push prefectgha.azurecr.io/prefect:${{ github.sha }}
Une fois que vous l’exécutez, vous verrez que le nom d’utilisateur et le mot de passe sont extraits de manière à masquer les informations d’identification. Voici une image montrant que :
Si vous recherchez d’autres exemples d’utilisation des actions GitHub pour automatiser la création d’images et la configuration de l’infrastructure, consultez ce guide de démarrage Prefect et Google Cloud :