🙌

Azure サービスプリンシパルの条件付きアクセスを試してみる

2021/12/09に公開

はじめに

先日、「サービスプリンシパルに条件付きアクセスを適用できる」という機能がプレビューで公開されました。
https://jpazureid.github.io/blog/azure-active-directory/introducing-ca-for-workload-id/
これ、地味にすごいアップデートですので、解説しつつ試してみたいと思います。

タイトルの用語

わざわざこの記事を開いた方に説明は不要だろうとは思いますが…

サービスプリンシパルとは

人の資料で説明してしまいますが、とても分かりやすくまとまっていますので紹介します。
https://www.slideshare.net/ToruMakabe/3azure-service-principal

サービスプリンシパルは、Azureを操作するために使うアプリケーション専用のIDのことです。いわゆる「ユーザーアカウント」(Azure用語でいうユーザープリンシパル)を使って操作することも可能なのですが、ユーザー(人)は異動したり退職したりするので権限セットが変わってしまうことがあり得ます。
「IT推進部の鈴木さんが、総務部に移動したらこのアプリ使えなくなったんですけど!」
なんてことが起きると悲劇ですので、アプリケーションにユーザーのアイデンティティを使うのはとても危険です。
そういう場合のために、アプリケーション専用でIDを払い出す仕組みが「サービスプリンシパル」です。

条件付きアクセスとは

条件付きアクセスは、以前解説や基本的な使い方を書いたことがありますので、こちらをご覧ください。
https://zenn.dev/tomot/articles/8fc9a5799ef1e2

セルフ引用すると、下記のような機能です。

条件付きアクセスポリシーという、If-Thenのルールを書くことで実現する、AzureADによるアクセス制御の仕組みです。
組織の持つアプリケーションに対して、誰が・どこから・何を使って…などを条件にして、アクセスの許可/不許可を制御することができます。

課題とアップデート

さてこれまで、条件付きアクセスはサービスプリンシパルを制御できず、専らユーザープリンシパルの制御に用いられてきました。すると何が起こるのか。

条件付きアクセスの代表的な使い方として「接続元のIPアドレス制限」があります。
「会社の拠点のIPアドレスからのみアクセスできる」ようにして、自宅の個人PCやスマホからはアクセスできないようにする仕組みです。
BLOBストレージやSQLDatabaseにアクセスし、業務データを抜き取ってしまえると大変なことになりますので、接続元を絞ろうという思想ですね。

ところがこれまで、条件付きアクセスはサービスプリンシパルの制御に使えなかったので、
「サービスプリンシパルのID/PWを持ち出せば、どこからでもアクセスすることができる」という抜け道がありました。

この抜け道が無くなります!というのが今回のアップデートです。スバラシイ!

試してみる

早速、制御の有無でどう挙動が変わるか試してみます。

準備

サービスプリンシパルの作成

AzureADの「アプリの登録」からサービスプリンシパルを作成します。
今回はここは主眼では無いので、こちらのドキュメントを参考にイイカンジに進めます。
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal

また、サービスプリンシパルは認証に証明書を使うことが推奨されていますが、今回はテストですのでパスワード(クライアントシークレット)を作成し、使用します。
GUIで作成する場合は、注意点が2点あります。

条件付きアクセスポリシーの作成

次に条件付きアクセスポリシーを作成します。


最初の「このポリシーは何に適用されますか?」が今回新しく追加された設定値です。
元々暗黙的にユーザープリンシパルしか選べなかったのですが、アップデートにより「ワークロードID」が選択できるようになりました。ワークロードIDとはシングルテナントのサービスプリンシパルのことのようで、最初に貼ったブログ記事の中に解説が書いてありますので詳細はそちらへ。

続けて、対象のサービスプリンシパルを指定します。

この環境で動いているほかのアプリケーションも有りますので、テスト用に作成したサービスプリンシパルのみが制御対象になるように指定しました。

最後に、条件を指定します。

「全ての場所」を選択してアクセスがブロックされるようにし、「対象外」のところに指定のIPアドレスセットを登録します。
この書き方で「特定のIPアドレスからしか接続できない」が実現できます。

もう一点、「クラウド アプリまたは操作」で「すべてのクラウドアプリ」を選択しないと意図した挙動になりませんでした。
ユーザープリンシパルを対象とした条件付きアクセスだと、なにも設定しないと「未構成」=Anyの条件になっていると思うのですが、この辺りはちょっと要確認です。

最終的にこのように登録しています。

検証

それでは、制御のOnOffを変えながらサインインを試してみます。

制御Off

「対象外の場所」に登録されたところからサインインを試します。
1行目を入力すると、プロンプトが立ち上がり、ID/PWを入力する画面になりますので、
サービスプリンシパルの「アプリケーションID」と「シークレット」を入力します。

$pscredential = Get-Credential
$tenantId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId

-------                              ---------------- --------                             -----------
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx                  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AzureCloud

サインインに使用した、サービスプリンシパルのアプリケーション(クライアントID
ID)と、AzureADのテナントIDが表示され、サインイン成功していることが確認できます。

一旦、切断します。

Disconnect-AzAccount

Id                    : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Tenants               : {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
Credential            :
TenantMap             : {}
CertificateThumbprint :
ExtendedProperties    : [Tenants, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]

制御on

続けて、条件付きアクセスポリシーから、場所の「対象外」を削除します。
これで全ての場所からのサービスプリンシパルでのサインインに失敗するようになります。

試してみます。

$pscredential = Get-Credential
$tenantId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId

Connect-AzAccount : ClientSecretCredential authentication failed: AADSTS53003: Access has been blocked by Conditio 
nal Access policies. The access policy does not allow token issuance.
Trace ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Correlation ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Timestamp: 2021-12-09 09:38:39Z
発生場所 行:1 文字:1
+ Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Connect-AzAccount]、AuthenticationFailedException

と、期待した通りに「条件付きアクセス(Conditional Access)にブロックされたので、認証失敗」とエラーになりました。

おわりに

条件付きアクセスでサービスプリンシパルの接続元を制御できることを確認しました。
プレビューということですが期待通り動作しますので、これはいろんな環境で標準的な設計になり得るものかと思います。しっかり設定して、安全にクラウドを使いましょう!

Discussion