ASP.NET Coreを用いた開発で使う環境変数を1Passwordで管理するようにした

DB の接続情報や外部サービスの API キーをローカルの .envappsettings.Development.json にべた書きすると、2 種類の問題を抱える。

危険

  • ローカルにマルウェアが入れば読み取られる
  • 誤って git に push すれば公開される

不便

  • チームメンバーと共有できない
  • 更新のたびに関係者へ周知が要る
  • 使うたびにコピペが発生する
  • コピペが増えると、事故が起きたときに出所が追えない

1Password に集約して op run 経由で環境変数として渡せば、両方まとめて片付く。この記事では ASP.NET Core での組み方を残す。

検証環境

  • Windows 10
  • .NET 8 (8.0.204)
  • JetBrains Rider 2024.1.2 RD-241.15989.179
  • 1Password for Windows 8.10.45 (81045002)
  • 1password-cli 2.29.0

手順

  1. テンプレートからアプリを作る
  2. 環境変数から値を取れるようにコードを直す
  3. 1Password に値を保存する
  4. .env を書く
  5. op run でアプリを起動する
  6. 環境変数が読めているか確認する

1. テンプレートからアプリを作る

Microsoft の Web API チュートリアルに沿って、ローカルで動くところまで持っていく。 チュートリアル: ASP.NET Core を使用してコントローラー ベースの Web API を作成するASP.NET Core を使用してコントローラー ベースの Web API を構築する方法について説明します。learn.microsoft.com

2. 環境変数を読む

Program.csWeatherForecastController.cs に手を入れて、環境変数を IConfiguration 経由で取れるようにする。

Programs.cs
// ここがPrograms.csの先頭行
var configuration = new ConfigurationBuilder()
    .AddEnvironmentVariables()
    .Build();

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddConfiguration(configuration);

// ここで大体10行目ぐらい
WeatherForecastController.cs
using Microsoft.AspNetCore.Mvc;

namespace TodoApi.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController (
    IConfiguration configuration
    ) : ControllerBase
{

    [HttpGet(Name = "GetWeatherForecast")]
    public string Get()
    {
        return configuration.GetValue<string>("KEY") ?? "環境変数の値を取得することに失敗しました。";
    }
}

3. 1Password に値を保存

保管庫はどこでもいい。ここでは TEST_VAULT に次の値を置いた。

✅️環境変数から値を取得することに成功しました🎉

4. .env を書く

プロジェクトルートに .env を置き、値の実体ではなく 1Password への参照を書く。

.env
KEY=op://TEST_VAULT/TEST_ITEM/TEST_FIELD

参照の形式は次の通り。

op://{保管庫名}/{アイテム名}/{アイテムのフィールド名}

5. アプリを実行

op run --env-file="./.env" -- dotnet run

6. 確認

/WeatherForecast に GET を投げて次が返れば、環境変数が経路を通っている。

✅️環境変数から値を取得することに成功しました🎉

不具合メモ

op run --env-file="./.env" --parsing Dotenv file: error at line 1 column 1: expected '=' but found ''

Rider で作った .env だと踏んだ。VSCode で作り直したら消えた。BOM か改行コードあたりが疑わしい。

<concealed by 1Password> と出るとき

stdout / stderr に出た値は既定でマスクされる。デバッグ時に本物を見たいときは --no-masking を付ける。

Secrets printed to stdout or stderr are concealed by default. Include the --no-masking flag to turn off masking.

run - 1Password DeveloperLearn about the 1Password CLI 'run' command.developer.1password.com

ネストした値の書き方

もともと appsettings.Development.json でネストされていた設定を、コード側を変えずに移したいとき。キーの :(コロン)を __ に置換すれば同じキーで引ける。

appsettings.Development.json
{
    "KEY": {
        "NESTED_KEY": "VALUE"
    }
}
.env
KEY__NESTED_KEY=VALUE
main.cs
var configuration = new ConfigurationBuilder()
    .AddEnvironmentVariables()
    .Build();
configuration.GetValue<string>("KEY:NESTED_KEY"); // VALUE

参考