プログラムでの秘密の文字列
業務系のプログラムでは、何かしらのデータベースやストレージのシステムにアクセスし、データの入出力を行います。データベースなどへの接続の際には、アカウント/パスワードといった機密の文字列を使用することが多いと思いますが、これを開発段階からリリース、運用フェーズまで安全に管理するのは意外と大変です。
プログラムから見た秘密の文字列の置き場所として、昔ながらの iniファイル、レジストリ、.NetFramework の場合は App.config に記述する方法などがありますが、基本的にプレーンテキストですので、扱いには気を使います。うっかりバージョン管理システムの管理対象にしてしまったり、デプロイ先で見つけられてしまうといったリスクがあります。ソースコードに直に埋め込んで、バイナリの中に隠すという方法も、実のところよく聞く話ですが、バイナリエディタで見れば、あっさりバレてしまいます。
独自のハッシュ化やエンコード関数を自作されている話も聞きますが、他社との共同開発になった時、ライセンシーや、その関数のソースコードを他社と共有する点で課題が発生することになります。
Microsoft の秘密文字ソリューション
秘密文字の管理のソリューションとして、Microsoft から2つの方法が提供されています。一つは、UserSecret を使う方法で、ローカルPC内の指定のディレクトリ内で管理します。管理場所が決まっていますので、うっかりバージョン管理システムにアップしてしまうこともありませんし、実装方法も簡単ですので、とっつきやすいと思います。ただ、暗号化などは行いませんので、Microsoft からは開発環境用としての位置づけとなっています。
もう一つは、Azure Key Vault を使う方法です。Azure Key Vault は、Microsoft のクラウド Azure のサービスの一つで、秘密の文字列をクラウドで管理します。Microsoft で厳重に管理されており、秘密文字へのアクセスには証明書が必要ですし、アクセスログも記録されます。エンタープライズ製品向けといえます。Microsoft では、UserSecret に比べ本番環境用として位置づけられています。
UserSecret を使った秘密文字の管理
UserSecret 及び Azure Key Vault での実装方法などを見ていきたいと思います。サンプルプログラムでは、.Net Core のコンソールで行いますが、ASP.NET などでも考え方などは変わりません。
サンプルで使うもの等
- Visual Studio Code
- dotnet code 3.1
- console プログラム
- Windows/MacOS/Linux
プログラムの準備
dotnet コマンドで新規プロジェクトを作成します。ターミナルから次のコマンドを実行し、コンソールプログラムとして作成しています。
# mkdir vaultsample
# cd vaultsample
# dotnet new console
パッケージの追加とシークレットマネージャーの初期化
UserSecrets に関連するパッケージをインストールします。.csproj ファイルがあるパスで次のコマンドを実行します。
# dotnet add package Microsoft.Extensions.Configuration
# dotnet add package Microsoft.Extensions.Configuration.UserSecrets
次に、シークレットマネージャーを初期化します。
# dotnet user-secrets init
インストールが完了すると、.csproj ファイルに Key Vault へのリファレンスが記述された ItemGroup と、追加されます。
ASP.NET Core の構成プロバイダーの Azure Key Vault
ASP.NET Core での開発におけるアプリシークレットの安全な保存
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>07f81c45-c201-4de5-b9ff-96510163b7d6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.5" />
</ItemGroup>
</Project>
秘密文字の登録
次のコマンドで秘密文字を登録します。秘密文字は、シークレット名と値の組み合わせで登録します。
dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"
なお、削除するときは次のようにコマンドを実行します。
dotnet user-secrets remove "SecretName" "secret_value_1_dev"
dotnet コマンドで作成しても構いませんが、格納先は下の通り、ユーザのホーム領域で、JSON 形式ですので、直接編集することもできます。
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
~/.microsoft/usersecrets/<user_secrets_id>/secrets.json
また、Visual Studio Core の拡張ツール .NET Core User Secrets を使えば、UI 上で操作できます。
プログラムから秘密文字を取得する
次に、登録した秘密文字列を、プログラムから取得する方法です。秘密文字などの管理には、ConfigurationBuilder を使用します。インスタンス化する際に、AddUserSecretsメソッドを呼び出すことで、UserSecret として登録した秘密文字を取得することができるようになります。
using System;
using Microsoft.Extensions.Configuration;
namespace vaultsample
{
class Program
{
static void Main(string[] args)
{
var cbr = new ConfigurationBuilder()
.AddUserSecrets<Program>().Build();
Console.WriteLine($" secret key is {cbr["SecretName"]}");
}
}
}
これにより、
- 秘密文字 -> ユーザのホームディレクトリ
- 開発ソースコード -> 開発用ディレクトリ
という運用が可能になりました。
次の投稿で、Azure Key Vault を使用した、さらに安全性の高い秘密文字の運用方法を記載します。
(つづく)
<参考>