ASP.NET Core での開発におけるアプリ シークレットの安全な保存

Note

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の ASP.NET Core 8.0 バージョンを参照してください。

作成者: Rick Anderson および Kirk Larkin

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

このドキュメントでは、開発用コンピューターで ASP.NET Core アプリ用の機密データを管理する方法について説明します。 パスワードやその他の機密データを、ソース コードに格納しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 代わりに、運用環境のシークレットには、環境変数や Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure Key Vault 構成プロバイダーにより、Azure テストと運用のシークレットを格納し、保護することが可能です。

.NET コンソール アプリでユーザー シークレットを使うには、こちらの GitHub イシューをご覧ください。

環境変数

環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。

個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json ファイルに DefaultConnection というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。

警告

環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。

: の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 __(ダブルアンダースコア)は、

  • すべてのプラットフォームに対応しています。 たとえば、:: の区切り記号には対応していませんが、__ には対応しています。
  • 自動で : に置換されます。

シークレットマネージャー

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 が設定されます。

GenerateAssemblyInfofalse の場合

アセンブリ情報属性の生成が無効になっている場合は、手動で AssemblyInfo.csUserSecretsIdAttribute を追加します。 次に例を示します。

[assembly: UserSecretsId("your_user_secrets_id")]

UserSecretsId 属性を手動で AssemblyInfo.cs に追加する場合、UserSecretsId 値はプロジェクト ファイル内の値と一致する必要があります。

シークレットを設定する

キーとその値で構成されるアプリ シークレットを定義します。 シークレットは、プロジェクトの UserSecretsId の値に関連付けられます。 たとえば、プロジェクト ファイルが存在するディレクトリから次のコマンドを実行します。

dotnet user-secrets set "Movies:ServiceApiKey" "12345"

前の例のコロンは、ServiceApiKeyMovies プロパティを持つオブジェクト リテラルであることを示しています。

シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --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

シークレットにアクセスする

シークレットにアクセスするには、次の手順を実行します。

  1. ユーザー シークレットの構成ソースを登録します
  2. Configuration API を使用してシークレットを読み取ります

ユーザー シークレットの構成ソースを登録する

ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .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) によって、既定の構成が指定され、EnvironmentNameDevelopment の場合に 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:ConnectionStringMovies: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 でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。

Visual Studio showing Manage User Secrets

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"]);
    }
}

その他のリソース

作成者: Rick AndersonKirk LarkinDaniel RothScott Addie

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

このドキュメントでは、開発用コンピューターで ASP.NET Core アプリ用の機密データを管理する方法について説明します。 パスワードやその他の機密データを、ソース コードに格納しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 代わりに、運用環境のシークレットには、環境変数や Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure Key Vault 構成プロバイダーにより、Azure テストと運用のシークレットを格納し、保護することが可能です。

環境変数

環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。

個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json ファイルに DefaultConnection というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。

警告

環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。

: の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 __(ダブルアンダースコア)は、

  • すべてのプラットフォームに対応しています。 たとえば、:: の区切り記号には対応していませんが、__ には対応しています。
  • 自動で : に置換されます。

シークレットマネージャー

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"

前の例のコロンは、ServiceApiKeyMovies プロパティを持つオブジェクト リテラルであることを示しています。

シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --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

シークレットにアクセスする

シークレットにアクセスするには、次の手順を実行します。

  1. ユーザー シークレットの構成ソースを登録します
  2. Configuration API を使用してシークレットを読み取ります

ユーザー シークレットの構成ソースを登録する

ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .NET の Configuration API に登録されます。

プロジェクトで CreateDefaultBuilder が呼び出されると、ユーザー シークレットの構成ソースが開発モードで自動的に追加されます。 EnvironmentNameDevelopment のときは、CreateDefaultBuilder によって AddUserSecrets が呼び出されます。

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

CreateDefaultBuilder が呼び出されないときは、ConfigureAppConfigurationAddUserSecrets を呼び出して、ユーザー シークレットの構成ソースを明示的に追加します。 次の例で示すように、アプリが開発環境で実行されている場合にのみ、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:ConnectionStringMovies: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 でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。

Visual Studio showing Manage User Secrets

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"]);
    }
}

その他のリソース