Bicep パラメーターを使用して、環境間の違いに対応する

完了

Bicep パラメーターについてはすでに学習しました。 パラメーターを使用することで、Bicep ファイルのデプロイごとに異なる値を指定することができます。

パラメーターは、環境ごとの違いをサポートするために一般的に使用されています。 たとえば、非運用環境では、Azure リソースの安価な SKU をデプロイしたいと思うことでしょう。 運用環境の場合は、パフォーマンスが優れた SKU をデプロイすることと思います。 また、各環境のリソースに対して異なる名前を使用する必要があるかもしれません。

Bicep ファイルをデプロイする際には、各パラメーターに値を指定します。 ワークフローから各パラメーターに値を指定する方法と、各環境に別個の値を指定する方法にはいくつかの選択肢があります。 このユニットでは、Bicep パラメーターの値をデプロイ ワークフローで指定する方法について学習します。

パラメーター ファイル

パラメーター ファイルは、各環境で使用するパラメーター値を一覧表示する JSON 形式のファイルです。 デプロイを送信する際に、パラメーター ファイルを Azure Resource Manager に送信します。

パラメーター ファイルの例を次に示します。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "reviewApiUrl": {
      "value": "https://sandbox.contoso.com/reviews"
    }
  }
}

パラメーター ファイルは、Bicep ファイルとともにお使いの Git リポジトリにコミットできます。 そうすれば、デプロイを実行するワークフロー テンプレート内でパラメーター ファイルを参照できます。

パラメーター ファイルのために、環境に基づく一貫した名前付けのルールを確立するのが理想的です。 たとえば、パラメーター ファイルに、parameters.ENVIRONMENT_NAME.json という名前を付けることができます (例: parameters.Production.json)。 次に、ワークフロー テンプレート入力を使用して、入力値に基づいて正しいパラメーター ファイルを自動的に選択できます。

on:
  workflow_call:
    inputs:
      environmentType:
        required: true
        type: string
      # ...

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    # ...
    - uses: azure/arm-deploy@v1
      with:
        failOnStdErr: false
        resourceGroupName: ${{ inputs.resourceGroupName }}
        template: ./deploy/main.bicep
        parameters: ./deploy/azuredeploy.parameters.${{ inputs.environmentType }}.json

パラメーター ファイルを使用するときは、ワークフロー YAML ファイルに、デプロイのステップに個別に渡す必要があるパラメーターの一覧を含める必要はありません。 これは特に、大量のパラメーターがある場合に役立ちます。

パラメーター ファイルは、パラメーター値を単一の JSON ファイル内でまとめて保持します。 パラメーター ファイルは Git リポジトリにあるので、他のコードと同様にバージョン管理できます。

重要

パラメーター ファイルは、セキュリティで保護された値に対して使用するべきではありません。 パラメーター ファイルのシークレットの値を保護する方法はないため、Git リポジトリには絶対にシークレットをコミットすべきではありません。

ワークフローの変数

GitHub Actions では "ワークフロー変数" を保存することができます。これは、環境ごとに異なる場合がある値に対して便利です。 また、一度だけ定義して、ワークフロー全体で再利用したい値にも便利です。

YAML ファイルで定義された変数

YAML ファイル内で、変数を定義して値を設定できます。 これは、同じ値を複数回再利用したい場合に便利です。 ワークフロー全体または 1 つのステップに対して変数を定義できます。

env:
  MyVariable1: value1

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      MyVariable2: value2
    steps:
    - run: echo Hello world!
      env:
        MyVariable3: value3

Web インターフェイスで定義されたシークレット

Bicep パラメーター ファイルと同様、YAML ファイルもシークレットには適していません。 代わりに、GitHub Web インターフェイスを使用してシークレットを定義できます。 変数の値はいつでも変更でき、ワークフローでは更新された値が次回の実行時に読み取られます。 GitHub Actions では、ワークフロー ログ内のシークレットの値を非表示にすることが試行されます。 つまり、Bicep ファイルが @secure() デコレーターとともにパラメーターとして受け取る値として保存できます。

警告

GitHub Actions の既定では、ワークフロー ログでシークレット変数の値が難読化されますが、適切なプラクティスにも従う必要があります。 ワークフロー ステップから、シークレット値にアクセスすることができます。 シークレットを安全に処理しないステップがワークフローに含まれている場合は、シークレット値がワークフロー ログに表示される可能性があります。 シークレットが誤って処理されないように、ワークフロー定義ファイルへの変更を常に慎重に確認する必要があります。

シークレットを作成すると、GitHub で、Git リポジトリ全体と特定の環境のどちらにスコープを適用するかを選択できます。 環境スコープのシークレットでは、環境で構成した保護ルールが遵守されます。 つまり、必要なレビュー担当者ルールを構成した場合、指定した GitHub ユーザーがその環境へのパイプラインのデプロイを承認するまで、ワークフローはシークレットの値にアクセスできません。

環境スコープのシークレットは便利ですが、Azure Resource Manager のプレフライト検証や What-If 操作と簡単には連携しません。 これらの操作は Azure と通信する必要があるため、ワークロード ID が必要です。 通常は、プレフライト検証または What-If 操作が完了した "後" にデプロイの承認を提供します。これにより、デプロイする変更に対する信頼度が高くなります。 そのため、環境スコープのシークレットを使用すると、ワークフロー内の早すぎる段階で人によるレビュー プロセスが発生します。

したがって、このモジュールの演習では、環境スコープのシークレットは使用しません。 代わりに、環境名を含む予測可能な名前を持つリポジトリ スコープのシークレットを作成します。 これにより、ワークフローでは、各環境で使用する適切なシークレットを識別できます。 独自のワークフローでは、リポジトリ スコープのシークレット、環境スコープのシークレット、または両方の組み合わせを使用できます。

Note

GitHub 組織にシークレットのスコープを適用することもできます。 これについてはこのモジュールでは扱いませんが、概要セクションに詳細情報へのリンクを記載しています。

ワークフローで変数を使用する

ワークフロー内の変数の値にアクセスする方法は、変数の型によって異なります。

構文
同じファイル内で定義されている変数 ${{ env.VARIABLE_NAME }}
呼び出し対象のワークフローへの入力 ${{ inputs.INPUT_NAME }}
シークレット ${{ secrets.SECRET_NAME }}

たとえば、Bicep デプロイを実行するときに、シークレットを使用して、使用する Azure ワークロード ID を指定し、呼び出し対象のワークフロー入力を使用してリソース グループ名を指定し、変数を使用してパラメーターの値を指定することができます。

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      MyParameter: value-of-parameter
    steps:
    - uses: actions/checkout@v3
    - uses: azure/login@v1
      with:
        client-id: ${{ secrets.AZURE_CLIENT_ID }}
        tenant-id: ${{ secrets.AZURE_TENANT_ID }}
        subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    - uses: azure/arm-deploy@v1
      with:
        failOnStdErr: false
        resourceGroupName: ${{ inputs.resourceGroupName }}
        template: ./deploy/main.bicep
        parameters: myParameter=${{ env.MyParameter }}

最適な手法はどれか

デプロイで Bicep ファイルが必要とするパラメーターを扱ういくつかの方法について学習しました。 どの手法をいつ使うべきかを理解することは大切です。

不必要なパラメーターを避ける

パラメーターは、Bicep ファイルを再利用するのに役立ちますが、パラメーターを定義しすぎてしまうことがあります。 Bicep ファイルをデプロイする際には、各パラメーターに対して値を指定する必要があります。 複数の環境に対する複雑なデプロイでは、大量のパラメーター値を管理するのは難しくなります。

可能な場合にはパラメーターをオプションにして、ほとんどの環境に適用される既定値を使用してください。 そうすれば、ワークフローがパラメーターの値を渡す必要はなくなります。

また、リソースが他のリソースに接続する際に、Bicep でパラメーターが使用されることがよくあります。 たとえば、ストレージ アカウントに接続する必要がある Web サイトがある場合、ストレージ アカウント名とアクセス キーを指定する必要があります。 キーはセキュリティで保護された値です。 とはいえ、リソースのこの組み合わせをデプロイする際には、次のような他の手法についても検討してください。

  • Web サイトのマネージド ID を使用してストレージ アカウントにアクセスする。 マネージド ID を作成すると、Azure によってその資格情報が自動的に生成され、管理されます。 この手法により、接続設定が簡略化されます。 このことは、シークレットを扱う必要がまったくないことを意味しているため、最も安全なオプションです。
  • ストレージ アカウントと Web サイトを、同じ Bicep テンプレートでまとめてデプロイする。 Bicep モジュールを使用して、Web サイトとストレージ アカウントをまとめて保持する。 こうすると、ストレージ アカウント名とキーの値を、パラメーターとして渡すのではなく、Bicep コード内で自動的に探すことができます。
  • ストレージ アカウントの詳細を、シークレットとしてキー コンテナーに追加する。 こうすると、Web サイトのコードはアクセス キーを資格情報コンテナーから直接読み込みます。 この手法の場合、キーをワークフローで管理する必要はまったくなくなります。

少数のパラメーター セットにワークフロー変数を使用する

Bicep ファイルのパラメーターの数が少ない場合は、YAML ファイルで変数を定義することを検討してください。

大量のパラメーターに対してパラメーター ファイルを使用する

Bicep ファイルで大量のパラメーターを使用する場合、各環境に対してセキュリティで保護されていない値をまとめて保持するために、パラメーター ファイルを使用することを検討してください。 そうすれば、値を変更する必要がある場合、パラメーター ファイルを更新して変更をコミットできます。

この手法の場合、各パラメーターの値を明示的に設定する必要がないため、ワークフローのステップが簡潔になります。

シークレットを安全に保存する

シークレットは、適切な方法で保存し、扱う必要があります。 GitHub シークレットを使用して GitHub リポジトリにシークレットを格納するか、Key Vault を使用して Azure にシークレットを格納します。

セキュリティで保護されたパラメーターの場合、各パラメーターをデプロイ ステップに明示的に渡す必要があります。

GitHub では、誤ってコミットされたシークレットをリポジトリで自動的にスキャンして、通知を受け取り、シークレットを削除してローテーションすることができます。 この機能に関する詳細情報へのリンクを概要に示します。

手法を組み合わせる

複数の手法を組み合わせてパラメーターを扱うのは、一般的な方法です。 たとえば、ほとんどのパラメーター値をパラメーター ファイルに保存し、シークレットを使用して、セキュリティで保護された値を設定することができます。 次の例はこの組み合わせを示しています。

on:
  workflow_dispatch:
    inputs:
      environmentType:
        required: true
        type: string
      resourceGroupName:
        required: true
        type: string
    secrets:
      AZURE_CLIENT_ID:
        required: true
      AZURE_TENANT_ID:
        required: true
      AZURE_SUBSCRIPTION_ID:
        required: true
      MySecureParameter:
        required: true

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: azure/login@v1
      with:
        client-id: ${{ secrets.AZURE_CLIENT_ID }}
        tenant-id: ${{ secrets.AZURE_TENANT_ID }}
        subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    - uses: azure/arm-deploy@v1
      with:
        failOnStdErr: false
        resourceGroupName: ${{ inputs.resourceGroupName }}
        template: ./deploy/main.bicep
        parameters: >
          ./deploy/azuredeploy.parameters.${{ inputs.environmentType }}.json
          mySecureParameter=${{ secrets.MySecureParameter }}

ヒント

この例の最後にある parameters 値は、> 文字を使用して YAML 複数行文字列として指定されます。 これにより、YAML ファイルが読みやすくなります。 これは、値全体を 1 行に含めた場合と同じです。