ASP.NET Coreを用いた開発で使う環境変数を1Passwordで管理するようにした
はじめに
作るアプリケーションによりますが、DBへの接続用の情報だったり、外部サービスと連携するためのAPIキーなど様々な、機密情報を扱う場面があると思います。
これらを、ローカルに保存した状態で扱うのは以下の点で危険です。
- ローカルでマルウェアを実行することによって機密情報を読み取られる可能性
- 間違って機密情報をgitにpushしてしまう可能性
さらに、危険だけではなく不便なこともあるかと思います。
- 開発環境で使う情報を他メンバーと共有ができない
- 機密情報に更新があったときに、関係する人たち全員に何らかの通知を行う必要がある
- いちいちコピペしないといけない
- コピペが横行することにより、機密情報があらゆる場所で管理された場合、関連する問題があったときに原因の特定が大変
上記の問題を踏まえ、機密情報をまとめて管理できて、安全かつ楽に呼び出せると良いですよね。
今回のゴール
ASP.NET Coreを用いた開発で機密情報を1Passwordから呼び出し、使用することができる
環境
- 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
アプローチ
- テンプレートを用いてアプリケーションを作成
- 環境変数から値を取得できるようにアプリケーションを修正
- 1Passwordに値を保存
- .envファイルを作成
- アプリケーションを実行する
- アプリケーションが環境変数を正しく読み取れているか確認する
1. テンプレートを用いてアプリケーションを作成
このページを参考に簡単なAPIを作成します。
検証しているマシン上でアプリケーションが実行でき、リクエストを送り、レスポンスが返されることを確認してください。2. 環境変数から値を取得できるようにアプリケーションを修正
環境変数を読み取り、IConfigurationを使うために以下の修正を行う必要があります。
// ここがPrograms.csの先頭行
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddConfiguration(configuration);
// ここで大体10行目ぐらい
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") ?? "環境変数の値を取得することに失敗しました。";
}
}
- WeatherForecastController.csに関してはコピペで問題ありません。
3. 1Passwordに値を保存
今回は以下の値を1Passwordに値を保存します。
保管庫などの保存する場所については、なんでも好きなようにしてください。
✅️環境変数から値を取得することに成功しました🎉
今回はTEST_VAULT
に以下のように保存しました。
4. .envファイルを作成
プロジェクトのルートディレクトリに.envファイルを作成してください。
KEY=op://TEST_VAULT/TEST_ITEM/TEST_FIELD
- KEYに指定する値は人によって異なります、具体的には以下のようになっています。環境によって調整をしてください。
op://{保管庫名}/{アイテム名}/{アイテムのフィールド名}
5. アプリケーションを実行する
プロジェクトのルートディレクトリで以下のコマンドを実行してください。
op run --env-file="./.env" -- dotnet run
6. アプリケーションが環境変数を正しく読み取れているか確認する
/WeatherForecastにGETを送り、以下の文字列が返されることが確認できましたら完了です。
✅️環境変数から値を取得することに成功しました🎉
まとめ
ステップは少し多いかもしれません。
ですが、1Passwordから環境変数を読み取ることができる環境を作れば、少なくとも1つ不安を滅ぼすことができます。
これだけの作業で1つでも、アプリケーションを開発するうえでの脅威を滅ぼすことができるのであれば、大したことではないかなと思いました。
今回記事を書いたことで、私が普段行っている作法が露呈しました、「なにかおかしい」や「ここ改善できるよ」等ありましたら教えて下さい。
この記事を書いた経緯自体は備忘録や個人的なトレーニングだったりしますが、誰かの役に立つことがあれば嬉しく思います。
ここまで読んでいただき、ありがとうございます。
検証したときに遭遇した不具合と解消方法
op run --env-file="./.env" --
を実行したときにparsing Dotenv file: error at line 1 column 1: expected '=' but found ''
が返される
解消方法はvscodeで.envファイルを作り直すことです。
私がこの現象を確認したのは、.envファイルをRiderで作成したときでした。
Riderで作成したファイルをコピーして別のディレクトリで実行しても発生したため、vscodeで作り直したところ、不具合は発生しなくなりました。
その他
<concealed by 1Password> について
op run
コマンドに--no-masking
を付与すると本来表示されるべき値が正しく表示されます。
公式にも以下のように書いてある。
Secrets printed to stdout or stderr are concealed by default. Include the --no-masking flag to turn off masking.
ネストした値を環境変数で表現する方法
例えば、もともとappsettings.Development.json
で実装をしていて、コードの変更を少なくして、対応したい場合は以下のように実装することで対応できます。
コード上でキーを指定するときの:
(コロン)を.envのキーに置き換えると__
になります。
{
"KEY": {
"NESTED_KEY": "VALUE"
}
}
KEY__NESTED_KEY=VALUE
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
configuration.GetValue<string>("KEY:NESTED_KEY"); // VALUE
Discussion