J'essaie de récupérer dynamiquement un secret GitHub à l'aide d'actions GitHub au moment de l'exécution:
Disons que j'ai deux secrets GitHub:
Dans mon action GitHub, j'ai une autre variable d'environnement qui différera entre les branches
name: Test env: CUSTOMER: CUSTOMER1 jobs: build: runs-on: ubuntu-latest env: AWS_ACCESS_KEY_ID: ${{ env.CUSTOMER }}_AWS_ACCESS_KEY_ID steps: - uses: actions/checkout@v2 - run: | AWS_ACCESS_KEY_ID=${{ secrets[env.AWS_ACCESS_KEY_ID] }} echo "AWS_ACCESS_KEY_ID = $AWS_ACCESS_KEY_ID"
Essentiellement, je veux trouver un moyen de faire une sorte de substitution de variable pour obtenir le bon secret. Donc, dans l'un de mes emplois pour enfants, je veux faire quelque chose comme:
{{ secrets.$FRUIT_NAME }}
J'ai essayé les approches suivantes sans succès:
secrets['$FRUIT_NAME'] }}
J'ai même essayé une approche plus simple sans concaténation juste pour essayer de la faire fonctionner
secrets['SECRET_$FRUIT_NAME'] }}
et
env: FRUIT_SECRET: {{ 'SECRET_' + env.FRUIT_NAME }}
Aucun de ces éléments n'a fonctionné.
Toutes mes excuses si je n'ai pas très bien expliqué cela. J'ai essayé de garder mon exemple aussi simple que possible.
Quelqu'un a-t-il une idée de la façon d'y parvenir?
Alternativement, ce que j'essaie de faire est de stocker des secrets sur une base par branche
Par exemple:
Dans customer1
branche de code SECRET_CREDENTIAL="abc123"
: SECRET_CREDENTIAL="abc123"
Dans customer2
branche de code SECRET_CREDENTIAL="def456"
: SECRET_CREDENTIAL="def456"
Ensuite, je peux accéder à la valeur correcte pour SECRET_CREDENTIAL
fonction de la branche dans laquelle je me trouve.
Merci!
Mise à jour: je me rapproche un peu plus de ce que j'essaie de réaliser:
env: FRUIT_NAME: APPLES
6 Réponses :
Suite à une expérience pratique avec ce projet terraform-monorepo , voici un exemple de la façon dont j'ai réussi à utiliser des noms secrets de manière dynamique
development
, staging
et production
$GITHUB_REF_SLUG
provient de l' action Slug GitHub qui récupère le nom de la brancheenv: SECRET_PREFIX: A SECRET_NAME: ${{ env.SECRET_PREFIX }}_FRUIT_NAME
SECRET_NAME = A_FRUIT_NAME SECRET_NAME = A_FRUIT_NAME SECRET_VALUE = ***
Après avoir lu ceci - Syntaxe de contexte et d'expression pour les actions GitHub , en me concentrant sur l' objet env , j'ai découvert que:
Dans le cadre d'une expression, vous pouvez accéder aux informations de contexte en utilisant l'une des deux syntaxes.
Syntaxe de l'index: github ['sha']
Syntaxe de déréférencement de propriété: github.sha
Donc, le même comportement s'applique aux secrets
, vous pouvez faire des secrets[secret_name]
, donc vous pouvez faire ce qui suit
- name: Run a multi-line script env: SECRET_NAME: A_FRUIT_NAME run: | echo "SECRET_NAME = $SECRET_NAME" echo "SECRET_NAME = ${{ env.SECRET_NAME }}" SECRET_VALUE=${{ secrets[env.SECRET_NAME] }} echo "SECRET_VALUE = $SECRET_VALUE"
Ce qui aboutit à
name: pipeline on: push: branches: [development, staging, production] paths-ignore: - "README.md" jobs: terraform: runs-on: ubuntu-latest env: ### ----------------------- ### Available in all steps, change app_name to your app_name TF_VAR_app_name: tfmonorepo ### ----------------------- steps: - uses: actions/checkout@v2 - name: Inject slug/short variables uses: rlespinasse/github-slug-action@v2.x - name: prepare-files-folders run: | mkdir -p ${GITHUB_REF_SLUG}/ cp live/*.${GITHUB_REF_SLUG} ${GITHUB_REF_SLUG}/ cp live/*.tf ${GITHUB_REF_SLUG}/ cp live/*.tpl ${GITHUB_REF_SLUG}/ 2>/dev/null || true mv ${GITHUB_REF_SLUG}/backend.tf.${GITHUB_REF_SLUG} ${GITHUB_REF_SLUG}/backend.tf - name: install-terraform uses: little-core-labs/install-terraform@v1 with: version: 0.12.28 - name: set-aws-credentials run: | echo "::set-env name=AWS_ACCESS_KEY_ID_SECRET_NAME::AWS_ACCESS_KEY_ID_${GITHUB_REF_SLUG}" echo "::set-env name=AWS_SECRET_ACCESS_KEY_SECRET_NAME::AWS_SECRET_ACCESS_KEY_${GITHUB_REF_SLUG}" - name: terraform-apply run: | export AWS_ACCESS_KEY_ID=${{ secrets[env.AWS_ACCESS_KEY_ID_SECRET_NAME] }} export AWS_SECRET_ACCESS_KEY=${{ secrets[env.AWS_SECRET_ACCESS_KEY_SECRET_NAME] }} cd ${GITHUB_REF_SLUG}/ terraform version rm -rf .terraform terraform init -input=false terraform get terraform validate terraform plan -out=plan.tfout -var environment=${GITHUB_REF_SLUG} terraform apply -auto-approve plan.tfout rm -rf .terraform
Puisque SECRET_VALUE est expurgé, nous pouvons supposer que le vrai secret a été récupéré.
Les choses que j'ai apprises -
Vous ne pouvez pas référencer env
partir d'un autre env
, donc cela ne fonctionnera pas
- name: set-aws-credentials run: | echo "::set-env name=AWS_ACCESS_KEY_ID_SECRET_NAME::AWS_ACCESS_KEY_ID_${GITHUB_REF_SLUG}" echo "::set-env name=AWS_SECRET_ACCESS_KEY_SECRET_NAME::AWS_SECRET_ACCESS_KEY_${GITHUB_REF_SLUG}" - name: terraform-apply run: | export AWS_ACCESS_KEY_ID=${{ secrets[env.AWS_ACCESS_KEY_ID_SECRET_NAME] }} export AWS_SECRET_ACCESS_KEY=${{ secrets[env.AWS_SECRET_ACCESS_KEY_SECRET_NAME] }}
Le résultat de SECRET_NAME est _FRUIT_NAME
, pas bon
Vous pouvez utiliser des expressions de contexte dans votre code, pas seulement dans env
, vous pouvez le voir dans SECRET_VALUE=${{ secrets[env.SECRET_NAME] }}
, ce qui est cool
Et bien sûr - voici le flux de travail que j'ai testé - https://github.com/unfor19/gha-play/runs/595345435?check_suite_focus=true - cochez l'action Run a multi-line script
Fantastique! C'est génial. Je joue avec ça depuis des heures et je n'ai nulle part. Merci beaucoup. Alors, comment cela fonctionnerait-il avec le nom du fruit si j'ai besoin d'une concaténation de chaînes: APPLE_SECRET1 APPLE_SECRET2 ORANGE_SECRET1 ORANGE_SECRET2 Alors je veux avoir A_FRUIT_NAME défini sur APPLE ou ORANGE, mais ensuite utiliser cet espace réservé ailleurs dans le script pour récupérer à la fois SECRET1 et SECRET2?
Ou si cela peut aider, je peux donner un exemple plus concret de ce que j'essaie de réaliser, basé sur les informations d'identification AWS ... J'ai deux branches (CUSTOMER1 et CUSTOMER2). Chaque branche que je souhaite définir une variable appelée "CUSTOMER" dans le fichier yml et elle sera définie sur CUSTOMER1 ou CUSTOMER2 Ensuite, dans Secrets, j'ai 2 ensembles d'informations d'identification AWS ... AWS_SECRET_ACCESS_KEY
à la valeur de CUSTOMER1_AWS_SECRET_ACCESS_KEY
Puisque vous avez mentionné que CUSTOMER est un nom de branche, je pense que vous pouvez utiliser github.ref , puis vous pouvez faire ceci: env: AWS_ACCESS_KEY_ID: ${{ github.ref }}_AWS_ACCESS_KEY_ID
puis utiliser ${{ secrets[env.AWS_ACCESS_KEY_ID] }}
sens?
De plus, au cas où vous auriez besoin d'une CLI pour ajouter / mettre à jour / supprimer / lister vos secrets, j'ai créé une CLI afin que je puisse éviter d'utiliser l'interface graphique - github.com/unfor19/githubsecrets
Excusez-moi, je trouble davantage les choses en essayant de garder les choses simples. J'ai des succursales distinctes pour le client 1 et le client 2, mais les noms des succursales ne correspondent pas directement. Les noms des succursales sont peut-être plus complexes (fonctionnalité / client / client1 / développer) etc. Existe-t-il un moyen de faire cela sans utiliser directement le nom de la succursale? En utilisant une seule variable env plus haut dans le fichier contenant le préfixe secret: par exemple CUSTOMER: Customer1
(même si le nom de la branche est totalement indépendant)
J'ai mis à jour ma question initiale avec ce que j'ai jusqu'à présent
Je pense que cela signifie que vous devrez définir un flux de travail différent par client (succursale). Je ne sais pas comment vous pouvez utiliser secrets[s_name]
sans utiliser env
ou coder en dur le nom du secret ... C'est là où je ne suis plus sûr d'être utile
OK super. Merci de votre aide. Je pense que votre réponse est assez proche de ce que j'essaie de réaliser. J'essayais d'éviter d'avoir des variables codées en dur dans mes fichiers YML et d'avoir à la place une seule variable à mettre à jour chaque fois que je créais une nouvelle succursale pour un client, mais je pense que ce que j'essaye est peut-être trop compliqué pour peu de gain. Je pense que je peux me contenter de coder en dur les changements dans chaque branche. Merci quand même pour votre aide!
Je pense que j'ai pu réaliser ce que je voulais en utilisant le nom du workflow! Je répondrai à ma propre question ci-dessous
Je pense que vous abusez de git, avoir une succursale par client dans le même dépôt semble être une mauvaise approche: / Je ne suis pas sûr de ce que vous essayez de réaliser, mais cela ne semble pas gérable ou évolutif
Je sais que cela sort du sujet de la question initiale, mais comment aborderiez-vous ce qui précède? J'ai un exemple d'application que je personnalise avec différentes saveurs (couleurs, mises à jour de texte, coordonnées) pour plusieurs clients. Je suis le seul à avoir accès au code (les clients eux-mêmes n'ont pas accès au code). Le modèle de branchement était pour que je puisse apporter des modifications à la copie principale du code, puis tirer les modifications / améliorations dans les branches spécifiques du client qui contiennent leurs modifications spécifiques. Comment feriez-vous cela?
On dirait que vous essayez d'obtenir une étiquette blanche pour votre application - une application de base qui comprend des fonctionnalités de base, puis l'application de chaque client est basée sur l'application de base, y compris certaines modifications de vars d'environnement et peut-être même plus d'applications. Peut-être utiliser Docker? Créez une image de base, puis chaque client aura son propre dépôt, mais son image sera basée sur votre image de base. Cela signifie que vous devrez définir un pipeline approprié, mais cela semble être une solution plus simple que d'avoir plusieurs clients en tant que succursales dans le même dépôt
Continuons cette discussion en chat .
J'ai pu y parvenir en utilisant le nom du workflow comme variable spécifique à la branche.
Pour chaque branche que je crée, je mets simplement à jour cette valeur unique en haut du fichier YML, puis j'ajoute GitHub Secrets pour correspondre au nom du workflow:
name: CUSTOMER1 jobs: build: runs-on: ubuntu-latest env: AWS_ACCESS_KEY_ID: ${{ github.workflow }}_AWS_ACCESS_KEY_ID steps: - uses: actions/checkout@v2 - run: echo "::set-env name=AWS_ACCESS_KEY_ID::${{ secrets[env.AWS_ACCESS_KEY_ID] }}" - run: echo $AWS_ACCESS_KEY_ID
Au cas où cela peut aider, après avoir lu les réponses ci-dessus qui ont vraiment aidé, la stratégie que j'ai décidé d'utiliser consiste à stocker mes secrets comme suit:
Où MASTER est la branche principale de l'environnement de production et TEST est la branche de test de l'environnement de test.
Ensuite, en utilisant les solutions suggérées dans ce thread, la clé est de générer dynamiquement les clés de la variable secrets
. Ces clés sont générées via une étape intermédiaire (appelée vars
dans l'exemple ci-dessous) à l'aide des outputs
:
name: Pulumi up on: push: branches: - master - test jobs: up: name: Update runs-on: ubuntu-latest steps: - name: Create variables id: vars run: | branch=${GITHUB_REF##*/} echo "::set-output name=DB_USER::DB_USER_${branch^^}" echo "::set-output name=DB_PASSWORD::DB_PASSWORD_${branch^^}" - uses: actions/checkout@v2 with: fetch-depth: 1 - uses: docker://pulumi/actions with: args: up -s ${GITHUB_REF##*/} -y env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} DB_USER: ${{ secrets[steps.vars.outputs.DB_USER] }} DB_PASSWORD: ${{ secrets[steps.vars.outputs.DB_PASSWORD] }}
Remarquez le hack pour obtenir la branche en majuscules:
${branch^^}
. Cela est nécessaire car GitHub force les secrets en majuscules.
Bon travail sur celui-ci! Je ne connais pas la référence de l'étape (vars), merci pour le partage
C'est bien! Merci!
Je suis tombé sur cette question en essayant d'implémenter la sélection secrète basée sur l'environnement pour une action Github.
Cette variable-mapper
l' action ( https://github.com/marketplace/actions/variable-mapper ) met en œuvre le concept souhaité de mapper une variable clé ou un nom d'environnement secrets ou d' autres valeurs prédéfinies.
L'exemple d'utilisation montre ceci:
on: [push] name: Export variables corresponding to regular expression-matched keys jobs: build: runs-on: ubuntu-latest steps: - uses: kanga333/variable-mapper@v1 with: key: ${{GITHUB_REF#refs/heads/}} map: | { "master": { "environment": "production", "AWS_ACCESS_KEY_ID": ${{ secrets.PROD_AWS_ACCESS_KEY_ID }}, "AWS_SECRET_ACCESS_KEY": ${{ secrets.PROD_AWS_ACCESS_KEY_ID }} }, "staging": { "environment": "staging", "AWS_ACCESS_KEY_ID": ${{ secrets.STG_AWS_ACCESS_KEY_ID }}, "AWS_SECRET_ACCESS_KEY": ${{ secrets.STG_AWS_ACCESS_KEY_ID }} }, ".*": { "environment": "development", "AWS_ACCESS_KEY_ID": ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}, "AWS_SECRET_ACCESS_KEY": ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} } } - name: Echo environment run: echo ${{ env.environment }}
Oh sympa! Cela semble être une excellente approche. Merci!
Il existe une option beaucoup plus propre pour y parvenir en utilisant la fonction de formatage .
Étant donné les secrets définis DEV_A et TEST_A, les deux travaux suivants utiliseront ces deux secrets:
name: Secrets on: workflow_dispatch: inputs: env: description: "Environment to deploy to" required: true jobs: secrets: name: secrets runs-on: ubuntu-18.04 steps: - run: echo ${{ secrets[format('{0}_A', github.event.inputs.env)] }}
Cela fonctionne également avec les entrées fournies via les workflows manuels (l'événement workflow_dispatch ):
name: Secrets on: [push] jobs: dev: name: dev runs-on: ubuntu-18.04 env: ENVIRONMENT: DEV steps: - run: echo ${{ secrets[format('{0}_A', env.ENVIRONMENT)] }} test: name: test runs-on: ubuntu-18.04 env: ENVIRONMENT: TEST steps: - run: echo ${{ secrets[format('{0}_A', env.ENVIRONMENT)] }}
Actions GitHub: abandon des commandes set-env et add-path
Voici la nouvelle méthode à compter du 1er octobre 2020
jobs: example-job: name: example runs-on: ubuntu-latest steps: - name: log untrusted output run: | # disable command workflow processing echo "::stop-commands::`echo -n ${{ github.token }} | sha256sum | head -c 64`" # log untrusted output echo "untrusted output" # enable workflow command processing echo "::`echo -n ${{ github.token }} | sha256sum | head -c 64`::"
En pensant à haute voix ici, puisque la syntaxe est
{{ secrets.SECRET_NAME }}
, vous pouvez peut-être essayer:{{ secrets['$FRUIT_NAME'] }}
, ou{{ secrets.$FRUIT_NAME }}
. Si les deux ne fonctionnent pas, je vous suggère de modifier votre question et de mentionner que vous avez déjà essayé les deuxMerci pour la suggestion, quand je fais ça et que je fais écho, c'est vide. Il semble qu'il n'analyse pas correctement $ FRUIT_NAME en tant que valeur du secret.
Et
{{ secrets[$FRUIT_NAME] }}
?Malheureusement non - j'ai juste essayé et obtenu le
Unexpected symbol: '$FRUIT_NAME'. Located at position 9 within expression: secrets[$FRUIT_NAME]
Apparemment, c'est faisable, a répondu avec une solution. J'ai été vraiment surpris de savoir que c'était possible, merci de m'avoir fait renforcer mes connaissances avec les expressions GitHub Actions :)