ASP.NET Core での開発におけるアプリ シークレットの安全な保存
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
作成者: Rick Anderson および Kirk Larkin
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
この記事では、開発用コンピューター上の ASP.NET Core アプリの機密データを管理する方法について説明します。 パスワードやその他の機密データをソース コードや構成ファイルに保存しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 運用シークレットには、Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure のテストシークレットと運用シークレットは、 Azure Key Vault 構成プロバイダーで格納および保護できます。
デプロイされたテスト アプリと運用アプリの認証の詳細については、「セキュリティで保護された認証フロー」をご覧ください。
.NET コンソール アプリでユーザー シークレットを使うには、こちらの GitHub イシューをご覧ください。
環境変数
環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。
個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json
ファイルに DefaultConnection
というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection
キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。
警告
環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。
:
の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 たとえば、:
の区切り記号は Bash では対応していません。 二重アンダースコア __
は、
- すべてのプラットフォームで対応しています。
- 自動でコロン
:
に置換されます。
シークレットマネージャー
Secret Manager ツールを使用すると、アプリケーションの開発中に機密データを保存できます。 このコンテキストでは、機密データはアプリのシークレットです。 アプリのシークレットは、プロジェクト ツリーとは別の場所に格納されます。 アプリのシークレットは、特定のプロジェクトに関連付けられるか、複数のプロジェクト間で共有されます。 アプリのシークレットは、ソース管理にはチェックインされません。
警告
シークレット マネージャー ツールでは保存されるシークレットは暗号化されないので、信頼されたストアとして扱わないでください。 それは開発のみを目的としたものです。 キーと値は、ユーザー プロファイルのディレクトリの JSON 構成ファイルに格納されます。
シークレット マネージャー ツールの動作
シークレット マネージャー ツールによって、値が格納される場所や方法などの実装の詳細が隠蔽されます。 これらの実装の詳細について知らなくても、このツールを使用できます。 値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。
ファイル システム パス:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
上のファイル パスで、<user_secrets_id>
はプロジェクト ファイルで指定されている UserSecretsId
の値に置き換えてください。
シークレット マネージャー ツールによって保存されるデータの場所または形式に依存するコードを記述しないでください。 これらの実装の詳細は変更される可能性があります。 たとえば、シークレットの値は暗号化されません。
シークレット ストレージを有効にする
シークレット マネージャー ツールは、ユーザー プロファイルに格納されているプロジェクト固有の構成設定に基づいて動作します。
CLI の使用
シークレット マネージャー ツールには、init
コマンドが含まれています。 ユーザー シークレットを使うには、プロジェクト ディレクトリで次のコマンドを実行します。
dotnet user-secrets init
上のコマンドによって、プロジェクト ファイルの PropertyGroup
内の UserSecretsId
要素が追加されます。 既定では、UserSecretsId
の内部テキストは GUID です。 内部テキストは任意ですが、プロジェクトに固有です。
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>
Visual Studio を使用する
Visual Studio のソリューション エクスプローラーでプロジェクトを右クリックし、コンテキスト メニューから [ユーザー シークレットの管理] を選びます。 これにより、UserSecretsId
要素がプロジェクト ファイルに追加されて、GUID が設定されます。
GenerateAssemblyInfo
が false
の場合
アセンブリ情報属性の生成が無効になっている場合は、手動で AssemblyInfo.cs
に UserSecretsIdAttribute を追加します。 次に例を示します。
[assembly: UserSecretsId("your_user_secrets_id")]
UserSecretsId
属性を手動で AssemblyInfo.cs
に追加する場合、UserSecretsId
値はプロジェクト ファイル内の値と一致する必要があります。
シークレットを設定する
キーとその値で構成されるアプリ シークレットを定義します。 シークレットは、プロジェクトの UserSecretsId
の値に関連付けられます。 たとえば、プロジェクト ファイルが存在するディレクトリから次のコマンドを実行します。
dotnet user-secrets set "Movies:ServiceApiKey" "12345"
前の例のコロンは、ServiceApiKey
が Movies
プロパティを持つオブジェクト リテラルであることを示しています。
シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --project
オプションを使用して、プロジェクト ファイルが存在するファイル システム パスを指定します。 次に例を示します。
dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"
Visual Studio での JSON 構造のフラット化
Visual Studioの [ユーザー シークレットの管理] を選ぶと、テキスト エディターで secrets.json
ファイルが開かれます。 secrets.json
の内容を、格納するキーと値のペアに置き換えます。 次に例を示します。
{
"Movies": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"ServiceApiKey": "12345"
}
}
JSON 構造体は、dotnet user-secrets remove
または dotnet user-secrets set
による変更後にフラット化されます。 たとえば、dotnet user-secrets remove "Movies:ConnectionString"
を実行すると、Movies
オブジェクト リテラルが折りたたまれます。 変更後のファイルは、次の JSON のようになります。
{
"Movies:ServiceApiKey": "12345"
}
複数のシークレットを設定する
JSON を set
コマンドにパイプすると、シークレットのバッチを設定できます。 次の例では、input.json
ファイルのコンテンツが set
コマンドにパイプされます。
コマンド シェルを開き、次のコマンドを実行します。
type .\input.json | dotnet user-secrets set
シークレットにアクセスする
シークレットにアクセスするには、次の手順を実行します。
ユーザー シークレットの構成ソースを登録する
ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .NET の Configuration API に登録されます。
dotnet new または Visual Studio で作成された ASP.NET Core の web アプリが、次のコードを生成します:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.CreateBuilder は、事前に構成された既定値を使用して WebApplicationBuilder クラスの新しいインスタンスを初期化します。 初期化された WebApplicationBuilder
(builder
) によって、既定の構成が指定され、EnvironmentName が Development の場合に AddUserSecrets が呼び出されます。
Configuration API を使用してシークレットを読み取る
Movies:ServiceApiKey
キーを読み取る次のような例を考えてみます。
Program.cs ファイル:
var builder = WebApplication.CreateBuilder(args);
var movieApiKey = builder.Configuration["Movies:ServiceApiKey"];
var app = builder.Build();
app.MapGet("/", () => movieApiKey);
app.Run();
Razor Pages ページ モデル:
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public void OnGet()
{
var moviesApiKey = _config["Movies:ServiceApiKey"];
// call Movies service with the API key
}
}
詳細については、「ASP.NET Core の構成」を参照してください。
シークレットを POCO にマップする
オブジェクト リテラル全体を POCO (プロパティを持つ単純な .NET クラス) にマップすると、関連するプロパティを集計するのに役立ちます。
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
前のシークレットを POCO にマップするには、.NET Configuration API のオブジェクト グラフ バインド機能を使います。 次のコードは、カスタム MovieSettings
POCO にバインドされていて、ServiceApiKey
プロパティ値にアクセスします。
var moviesConfig =
Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;
シークレット Movies:ConnectionString
と Movies:ServiceApiKey
は、MovieSettings
のそれぞれのプロパティにマップされます。
public class MovieSettings
{
public string ConnectionString { get; set; }
public string ServiceApiKey { get; set; }
}
シークレットでの文字列の置換
プレーンテキストでのパスワードの保存は安全ではありません。 たとえば、 appsettings.json
に格納されるデータベース接続文字列には、指定されたユーザーのパスワードが含まれる場合があります。
{
"ConnectionStrings": {
"Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
}
}
さらに安全な方法は、パスワードをシークレットとして保存することです。 次に例を示します。
dotnet user-secrets set "DbPassword" "pass123"
appsettings.json
内の接続文字列から、Password
のキーと値のペアを削除します。 次に例を示します。
{
"ConnectionStrings": {
"Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
}
}
SqlConnectionStringBuilder オブジェクトの Password プロパティでシークレットの値を設定して、接続文字列を完全なものにできます。
using System.Data.SqlClient;
var builder = WebApplication.CreateBuilder(args);
var conStrBuilder = new SqlConnectionStringBuilder(
builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;
var app = builder.Build();
app.MapGet("/", () => connection);
app.Run();
シークレットの一覧を表示する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets list
次のような出力が表示されます。
Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345
前の例のキー名のコロンは、secrets.json
内のオブジェクト階層を示します。
1 つのシークレットを削除する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets remove "Movies:ConnectionString"
アプリの secrets.json
ファイルが変更され、Movies:ConnectionString
キーに関連付けられているキーと値のペアが削除されました。
{
"Movies": {
"ServiceApiKey": "12345"
}
}
dotnet user-secrets list
では、次のメッセージが表示されます。
Movies:ServiceApiKey = 12345
すべてのシークレットを削除する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets clear
アプリのすべてのユーザー シークレットが、secrets.json
ファイルから削除されました。
{}
dotnet user-secrets list
を実行すると、次のメッセージが表示されます。
No secrets configured for this application.
Visual Studio でユーザー シークレットを管理する
Visual Studio でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。
ASP.NET Framework から ASP.NET Core へのユーザー シークレットの移行
こちらの GitHub のイシューを参照してください。
非 Web アプリケーションのユーザー シークレット
Microsoft.NET.Sdk.Web
をターゲットとするプロジェクトには、ユーザー シークレットのサポートが自動的に含まれます。 コンソール アプリケーションなど、Microsoft.NET.Sdk
をターゲットとするプロジェクトの場合は、構成拡張機能とユーザー シークレット NuGet パッケージを明示的にインストールします。
PowerShell を使用して、次の操作を実行します。
Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets
.NET CLI の使用
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
パッケージがインストールされたら、Web アプリの場合と同じ方法でプロジェクトを初期化し、シークレットを設定します。 次の例は、キー "AppSecret" で設定されたシークレットの値を取得するコンソール アプリケーションを示しています。
using Microsoft.Extensions.Configuration;
namespace ConsoleApp;
class Program
{
static void Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
Console.WriteLine(config["AppSecret"]);
}
}
その他のリソース
- IIS からのユーザー シークレットへのアクセスについては、この issue とこの issue を参照してください。
- ASP.NET Core での構成
- ASP.NET Core の Azure Key Vault 構成プロバイダー
作成者: Rick Anderson、Kirk Larkin、Daniel Roth、Scott Addie
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
この記事では、開発用コンピューター上の ASP.NET Core アプリの機密データを管理する方法について説明します。 パスワードやその他の機密データをソース コードや構成ファイルに保存しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 運用シークレットには、Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure のテストシークレットと運用シークレットは、 Azure Key Vault 構成プロバイダーで格納および保護できます。
テスト環境と運用環境の認証の詳細については、「 安全な認証フロー」を参照してください。
環境変数
環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。
個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json
ファイルに DefaultConnection
というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection
キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。
警告
環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。
:
の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 たとえば、:
の区切り記号は Bash では対応していません。 二重アンダースコア __
は、
- すべてのプラットフォームで対応しています。
- 自動でコロン
:
に置換されます。
シークレットマネージャー
Secret Manager ツールを使用すると、アプリケーションの開発中に機密データを保存できます。 このコンテキストでは、機密データはアプリのシークレットです。 アプリのシークレットは、プロジェクト ツリーとは別の場所に格納されます。 アプリのシークレットは、特定のプロジェクトに関連付けられるか、複数のプロジェクト間で共有されます。 アプリのシークレットは、ソース管理にはチェックインされません。
警告
シークレット マネージャー ツールでは保存されるシークレットは暗号化されないので、信頼されたストアとして扱わないでください。 それは開発のみを目的としたものです。 キーと値は、ユーザー プロファイルのディレクトリの JSON 構成ファイルに格納されます。
シークレット マネージャー ツールの動作
シークレット マネージャー ツールによって、値が格納される場所や方法などの実装の詳細が隠蔽されます。 これらの実装の詳細について知らなくても、このツールを使用できます。 値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。
ファイル システム パス:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
上のファイル パスで、<user_secrets_id>
はプロジェクト ファイルで指定されている UserSecretsId
の値に置き換えてください。
シークレット マネージャー ツールによって保存されるデータの場所または形式に依存するコードを記述しないでください。 これらの実装の詳細は変更される可能性があります。 たとえば、シークレットの値は暗号化されませんが、将来は暗号化される可能性があります。
シークレット ストレージを有効にする
シークレット マネージャー ツールは、ユーザー プロファイルに格納されているプロジェクト固有の構成設定に基づいて動作します。
シークレット マネージャー ツールには、.NET Core SDK 3.0.100 以降の init
コマンドが含まれています。 ユーザー シークレットを使うには、プロジェクト ディレクトリで次のコマンドを実行します。
dotnet user-secrets init
上のコマンドによって、プロジェクト ファイルの PropertyGroup
内の UserSecretsId
要素が追加されます。 既定では、UserSecretsId
の内部テキストは GUID です。 内部テキストは任意ですが、プロジェクトに固有です。
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>
Visual Studio のソリューション エクスプローラーでプロジェクトを右クリックし、コンテキスト メニューから [ユーザー シークレットの管理] を選びます。 これにより、UserSecretsId
要素がプロジェクト ファイルに追加されて、GUID が設定されます。
シークレットを設定する
キーとその値で構成されるアプリ シークレットを定義します。 シークレットは、プロジェクトの UserSecretsId
の値に関連付けられます。 たとえば、プロジェクト ファイルが存在するディレクトリから次のコマンドを実行します。
dotnet user-secrets set "Movies:ServiceApiKey" "12345"
前の例のコロンは、ServiceApiKey
が Movies
プロパティを持つオブジェクト リテラルであることを示しています。
シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --project
オプションを使用して、プロジェクト ファイルが存在するファイル システム パスを指定します。 次に例を示します。
dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"
Visual Studio での JSON 構造のフラット化
Visual Studioの [ユーザー シークレットの管理] を選ぶと、テキスト エディターで secrets.json
ファイルが開かれます。 secrets.json
の内容を、格納するキーと値のペアに置き換えます。 次に例を示します。
{
"Movies": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"ServiceApiKey": "12345"
}
}
JSON 構造体は、dotnet user-secrets remove
または dotnet user-secrets set
による変更後にフラット化されます。 たとえば、dotnet user-secrets remove "Movies:ConnectionString"
を実行すると、Movies
オブジェクト リテラルが折りたたまれます。 変更後のファイルは、次の JSON のようになります。
{
"Movies:ServiceApiKey": "12345"
}
複数のシークレットを設定する
JSON を set
コマンドにパイプすると、シークレットのバッチを設定できます。 次の例では、input.json
ファイルのコンテンツが set
コマンドにパイプされます。
コマンド シェルを開き、次のコマンドを実行します。
type .\input.json | dotnet user-secrets set
シークレットにアクセスする
シークレットにアクセスするには、次の手順を実行します。
ユーザー シークレットの構成ソースを登録する
ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .NET の Configuration API に登録されます。
プロジェクトで CreateDefaultBuilder が呼び出されると、ユーザー シークレットの構成ソースが開発モードで自動的に追加されます。 EnvironmentName が Development のときは、CreateDefaultBuilder
によって AddUserSecrets が呼び出されます。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
CreateDefaultBuilder
が呼び出されないときは、ConfigureAppConfiguration で AddUserSecrets を呼び出して、ユーザー シークレットの構成ソースを明示的に追加します。 次の例で示すように、アプリが開発環境で実行されている場合にのみ、AddUserSecrets
を呼び出します。
public class Program
{
public static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration((hostContext, builder) =>
{
// Add other providers for JSON, etc.
if (hostContext.HostingEnvironment.IsDevelopment())
{
builder.AddUserSecrets<Program>();
}
})
.Build();
host.Run();
}
}
Configuration API を使用してシークレットを読み取る
ユーザー シークレットの構成ソースが登録されている場合は、.NET Configuration API でシークレットを読み取ることができます。 コンストラクターの挿入を使って、.NET Configuration API にアクセスできます。 Movies:ServiceApiKey
キーを読み取る次のような例を考えてみます。
スタートアップ クラス:
public class Startup
{
private string _moviesApiKey = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
_moviesApiKey = Configuration["Movies:ServiceApiKey"];
}
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
await context.Response.WriteAsync($"Secret is {result}");
});
}
}
Razor Pages ページ モデル:
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public void OnGet()
{
var moviesApiKey = _config["Movies:ServiceApiKey"];
// call Movies service with the API key
}
}
詳しくは、「起動時の構成へのアクセス」および「Razor ページの構成にアクセスする」をご覧ください。
シークレットを POCO にマップする
オブジェクト リテラル全体を POCO (プロパティを持つ単純な .NET クラス) にマップすると、関連するプロパティを集計するのに役立ちます。
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
前のシークレットを POCO にマップするには、.NET Configuration API のオブジェクト グラフ バインド機能を使います。 次のコードは、カスタム MovieSettings
POCO にバインドされていて、ServiceApiKey
プロパティ値にアクセスします。
var moviesConfig =
Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;
シークレット Movies:ConnectionString
と Movies:ServiceApiKey
は、MovieSettings
のそれぞれのプロパティにマップされます。
public class MovieSettings
{
public string ConnectionString { get; set; }
public string ServiceApiKey { get; set; }
}
シークレットでの文字列の置換
プレーンテキストでのパスワードの保存は安全ではありません。 たとえば、 appsettings.json
に格納されるデータベース接続文字列には、指定されたユーザーのパスワードが含まれる場合があります。
{
"ConnectionStrings": {
"Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
}
}
さらに安全な方法は、パスワードをシークレットとして保存することです。 次に例を示します。
dotnet user-secrets set "DbPassword" "pass123"
appsettings.json
内の接続文字列から、Password
のキーと値のペアを削除します。 次に例を示します。
{
"ConnectionStrings": {
"Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
}
}
SqlConnectionStringBuilder オブジェクトの Password プロパティでシークレットの値を設定して、接続文字列を完全なものにできます。
public class Startup
{
private string _connection = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var builder = new SqlConnectionStringBuilder(
Configuration.GetConnectionString("Movies"));
builder.Password = Configuration["DbPassword"];
_connection = builder.ConnectionString;
// code omitted for brevity
}
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync($"DB Connection: {_connection}");
});
}
}
シークレットの一覧を表示する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets list
次のような出力が表示されます。
Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345
前の例のキー名のコロンは、secrets.json
内のオブジェクト階層を示します。
1 つのシークレットを削除する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets remove "Movies:ConnectionString"
アプリの secrets.json
ファイルが変更され、MoviesConnectionString
キーに関連付けられているキーと値のペアが削除されました。
{
"Movies": {
"ServiceApiKey": "12345"
}
}
dotnet user-secrets list
では、次のメッセージが表示されます。
Movies:ServiceApiKey = 12345
すべてのシークレットを削除する
アプリの secrets.json
ファイルに、次の 2 つのシークレットが含まれているとします。
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。
dotnet user-secrets clear
アプリのすべてのユーザー シークレットが、secrets.json
ファイルから削除されました。
{}
dotnet user-secrets list
を実行すると、次のメッセージが表示されます。
No secrets configured for this application.
Visual Studio でユーザー シークレットを管理する
Visual Studio でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。
ASP.NET Framework から ASP.NET Core へのユーザー シークレットの移行
こちらの GitHub のイシューを参照してください。
非 Web アプリケーションのユーザー シークレット
Microsoft.NET.Sdk.Web
をターゲットとするプロジェクトには、ユーザー シークレットのサポートが自動的に含まれます。 コンソール アプリケーションなど、Microsoft.NET.Sdk
をターゲットとするプロジェクトの場合は、構成拡張機能とユーザー シークレット NuGet パッケージを明示的にインストールします。
PowerShell を使用して、次の操作を実行します。
Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets
.NET CLI の使用
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
パッケージがインストールされたら、Web アプリの場合と同じ方法でプロジェクトを初期化し、シークレットを設定します。 次の例は、キー "AppSecret" で設定されたシークレットの値を取得するコンソール アプリケーションを示しています。
using Microsoft.Extensions.Configuration;
namespace ConsoleApp;
class Program
{
static void Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
Console.WriteLine(config["AppSecret"]);
}
}
その他のリソース
- IIS からのユーザー シークレットへのアクセスについては、この issue とこの issue を参照してください。
- ASP.NET Core での構成
- ASP.NET Core の Azure Key Vault 構成プロバイダー
ASP.NET Core