tech.guitarrapc.cóm

Technical updates

Azure SDK for .NET の認証を DefaultAzureCredential にそろえる

Azure SDK for .NETはなぜかAzureCredentialsDefaultAzureCredentialという2つの認証方法があります。

今回はAzureCredentialsしか受け付けないAzure SDKのクライアントに、DefaultAzureCredentialで得た認証を使いたいというメモです。

tl;dr;

  • DefaultAzureCredentialでとった認証はTokenを経由してAzureCredentialsで利用できる
  • Tokenは10分で切れるので長時間実行に使いまわすには再度認証をとるなり工夫が必要
  • 多少の手間があってもDefaultAzureCredentialのほうが認証の取り方が楽なので使っていきたい

AzureCredentials をなぜ使いたくないのか

AzureCredentialsは古いAzure SDK (あるいは移行されていないSDK) でのみ利用されている (?) 気配です。AzureCredentialsを使うには、個別サービスパッケージMicrosoft.Azure.Management.Xxxxx以外にMicrosoft.Azure.Management.ResourceManager.Fluentを参照します。

例えばこんな感じで使えます。

gist.github.com

AzureCredentialsは触ってみると使いにくい点がいくつかあります。

  • ローカルでの認証 (例: ServicePrincipal) やManaged Service Identity (System Assigned Identity / UserAssigned Identity) ごとにインスタンスの生成方法が異なる
  • NewtonSoft.Json 10.0.3に依存していて脆弱性が解消されていない。1
  • 生成方法がSdkContext.AzureCredentialsFactory.FromXxxnew AzureCredentials(new XxxInformationの2つがありAPIから推測する情報が多い

Newtonsoft.Json の脆弱性 https://github.com/advisories/GHSA-5crp-9r3c-p9vr
medium.com

次に示すDefaultAzureCredentialや他クラウドでの認証を考えると触りたくないです。

DefaultAzureCredential でどう変わるのか

DefaultAzureCredentialは新しいAzure SDK for .NETで利用が進んでいる気配で、新しいSDKやインタフェースではDefaultAzureCredentialが利用されています。(全部じゃない) DefaultAzureCredentialを使うには、Azure Identity SDKを参照します。

例えばこんな感じで使えます。

gist.github.com

DefaultAzureCredentialは、new DefaultAzureCredential()あるいはnew DefaultAzureCredential(new DefaultAzureCredentialOptions())とインスタンスを生成するだけで動作環境から自動的に認証を取得します。例えば、環境変数、Azure環境上でManaged Service Identity (System Assigned Identity / UserAssigned Identity) 、Visual Studio、Visual Studio Code、az loginなど一通りカバーされており便利です。

docs.microsoft.com

AzureCredentialsでの開発体験を振り返ると、DefaultAzureCredentialの「同じインスタンス生成で動作環境に応じた認証をいい感じに取れる」というのは、環境ごとの書き分けがいらずよい書き心地です。2

特にUserAssignedIdentityとSystem AssignedIdentityが環境変数AZURE_CLIENT_IDの有無で切り替わるのは、利用側で自由に調整できるので非常に都合がいいです。3

docs.microsoft.com

DefaultAzureCredential で得た認証を AzureCredentials で利用する

DefaultAzureCredentialAzureCredentialsと型レベルでは互換性がないため代わりに利用できません。 しかし、DefaultAzureCredential でとった認証のトークンは、Microsoft.Rest.TokenCredentialsを経由することでAzureCredentialsに差すことができます。

こうすることで、認証の取り方はDefaultAzureCredentialに任せつつ、AzureCredentialsを必要とするクライアントを利用できます。 例えば次のように書くことができます。

gist.github.com

TokenRequestContextは、2022年現在、https://management.azure.com/.default固定で問題ないはずです。(Azureはちょいちょい変わるので何も信用できない)

まとめ

ちょっとAzure Database forなんとかのSDKを使って操作しようとしたらAzureCredentialsで面食らったのでした。 DefaultAzureCredentialは普通な使い心地でいいのですが、AzureCredentials は厳しいものがあるので今後も避けていきたいところです。


  1. Newtonsoft.Jsonを明示的にパッケージ参照して解消しましょう
  2. 認証の取得の書き心地という意味では、AWS SDK for .NETはAWS IAMとの紐づけを含めてもっと洗練されていると感じます。なおAWS SSOの認証は全然ダメなのでよくなってほしい。
  3. 環境変数AZURE_CLIENT_IDがあればUser Assigned Identityが参照される。