mssql-django を使用した Microsoft Entra 認証

この記事では、mssql-django バックエンドを使用して Django アプリケーションのMicrosoft Entra認証を構成する方法について説明します。 Microsoft Entra認証を使用すると、アプリケーション構成にパスワードを格納する必要がなくなります。

前提条件

  • Microsoft ODBC Driver 18 for SQL Server(推奨)。 この記事のすべての認証モードは、Microsoft ODBC Driver 18 for SQL Serverでサポートされています。 ActiveDirectoryInteractiveは、ドライバーのバージョンに関係なくWindows専用です。 ODBC Driver 17 を使用する必要がある場合は、モードごとの最小 17.x バージョンの ODBC 認証リファレンス を参照してください。
  • アクセス トークン認証の場合: pip install azure-identity

認証方法

Django プロジェクトのDATABASES ファイルでsettings.py設定を追加または編集して、各メソッドを構成します。 この記事の例では、明確にするために完全な DATABASES["default"] ブロックを示します。関連するキーを既存の構成にコピーします。

mssql-djangoでは、次の 2 つの方法でMicrosoft Entra認証がサポートされます。

  • OPTIONS["extra_params"]による ODBC ドライバー認証。 バックエンドは、この文字列を変更せずに ODBC 接続文字列に追加するため、使用可能なAuthentication=の値は、mssql-django自体からではなく、インストールされている Microsoft ODBC Driver for SQL Serverから取得されます。
  • TOKEN設定を使用したプログラムによるアクセス トークン認証。 バックエンドは、ODBC TOKEN キーワードをバイパスするSQL_COPT_SS_ACCESS_TOKENとして、Authentication=を ODBC ドライバーに渡します。

認証方法の概要

Method を使用して構成する 最適な用途
アクセス トークン TOKEN 開発、有効期間の短いスクリプト、またはカスタム トークン更新を使用するアプリ
ActiveDirectoryMsi extra_params Azureホスト型運用アプリ (システム割り当てマネージド ID とユーザー割り当てマネージド ID)
ActiveDirectoryServicePrincipal USERPASSWORDextra_params マネージド ID を利用できない場合のアプリの登録
ActiveDirectoryIntegrated extra_params ドメイン参加済みユーザー コンテキスト
ActiveDirectoryInteractive USERextra_params 多要素認証を使用したユーザー サインイン (Windows)
ActiveDirectoryDefault extra_params ODBC ドライバーの既定の Microsoft Entra 資格情報チェーンを使用すべきローカル開発環境およびアプリ
ActiveDirectoryPassword USERPASSWORDextra_params 最終手段のレガシー シナリオ専用 (非推奨)

Note

mssql-django 1.7.3 以降では、インストールされている Microsoft ODBC Driver for SQL Server がそのモードをサポートしている場合、Authentication=ActiveDirectoryDefault から OPTIONS["extra_params"] までを受け入れます。 トークンの取得と更新の動作を明示的に制御する必要がある場合は、 クラスで azure.identity.DefaultAzureCredential パターンを使用します。

Azure SQLで ID アクセス権を付与する

マネージド ID またはサービス プリンシパル認証の場合は、データベース ユーザーを作成し、アプリケーションに必要なロールのみを付与します。

CREATE USER [<identity-name>] FOR EXTERNAL PROVIDER;

ALTER ROLE db_datareader ADD MEMBER [<identity-name>];
ALTER ROLE db_datawriter ADD MEMBER [<identity-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<identity-name>];

db_ddladmin固定データベース ロールは、アプリケーションが移行を実行する場合にのみ必要です。 読み取り専用ワークロードの場合は、 db_datareader で十分です。

Note

FROM EXTERNAL PROVIDERでは、SQL サーバーがプリンシパル名を解決するためにMicrosoft Graphを呼び出す必要があります。 サーバーがMicrosoft Entra専用認証用に構成されている場合、または Graph に到達できない場合、ステートメントは Msg 33130 (Principal '<name>' could not be found...) で失敗します。 明示的な SID を指定して、ユーザーを手動で作成します。

CREATE USER [<identity-name>] WITH SID = 0x<sid-hex>, TYPE = E;

マネージド ID またはサービス プリンシパルの場合は、オブジェクト ID ではなく、ID の アプリケーション (クライアント) ID から SID を派生させます。 Azure SQLは、サービス プリンシパルとマネージド ID にアプリケーション ID を使用し、オブジェクト ID は通常の Entra ユーザーにのみ使用します。 ダッシュ区切りの最初の 3 つのグループをバイト単位で反転し、最後の 2 つはそのままにして GUID を変換します。 たとえば、アプリケーション ID 619a4449-b4aa-4383-a2a9-7c365106c5e7 は SID 0x49449A61AAB48343A2A97C365106C5E7になります。 PowerShell では次のとおりです。

$b = ([Guid]"<app-id>").ToByteArray()
"0x" + (($b | ForEach-Object { $_.ToString('X2') }) -join '')

オブジェクト ID を誤って使用すると、接続はトークンの取得に成功しますが、Azure SQLはトークンのLogin failed for user '<token-identified principal>'要求と一致するデータベース プリンシパルがないため、appidを返します。

VIEW ANY COLUMN MASTER KEY DEFINITION permission denied エラーが表示された場合は、Always Encrypted シナリオに対して ID に追加のアクセス権を付与します。

GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [<identity-name>];
GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [<identity-name>];

マネージド ID 認証 (ActiveDirectoryMsi)

Django アプリがAzure App Service、Azure Container Apps、Azure 仮想マシンなどのAzure サービスで実行されている場合は、マネージド ID を使用します。 ODBC ドライバーはトークンを自動的に取得して更新するため、運用環境ではこの方法をお勧めします。

システムによって割り当てられたマネージド ID

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryMsi",
        },
    },
}

ユーザー割り当て管理対象 ID

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": (
                "Authentication=ActiveDirectoryMsi;"
                "UID=<managed-identity-client-id-or-object-id>"
            ),
        },
    },
}

ActiveDirectoryMsi は、システム割り当てマネージド ID (SAMI) とユーザー割り当てマネージド ID (UAMI) の両方の ODBC モードです。 UAMI の場合、ODBC ドライバーでは、UIDがマネージド ID を識別することを想定しています。Azure App Serviceまたは Azure Container Instance の場合はクライアント ID を使用し、それ以外の場合はオブジェクト ID を使用します。 UIDは ODBC ドライバーに直接渡されるため、extra_params内にそのextra_paramsを配置します。

マネージド ID を使用する場合は、テスト データベースを手動で作成し、単体テストを実行する際に --keepdb を渡してください。

サービス プリンシパル認証 (ActiveDirectoryServicePrincipal)

ユーザー コンテキストなしでアプリが実行され、マネージド ID が使用できない場合は、Microsoft Entra アプリ登録 (サービス プリンシパル) を使用します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<application-client-id>",
        "PASSWORD": "<client-secret>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryServicePrincipal",
        },
    },
}

settings.pyでクライアント シークレットをハードコーディングしないでください。 Azure Key Vaultなどの環境変数またはシークレット マネージャーを使用して、実行時に資格情報を指定します。

統合認証 (ActiveDirectoryIntegrated)

ドメインに参加しているユーザー コンテキストで Django プロセスが実行され、ODBC ドライバーがそのWindowsまたは Kerberos ID をMicrosoft Entra認証に使用する場合は、統合認証を使用します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryIntegrated",
        },
    },
}

ODBC 認証リファレンスでは、Windows、および Linux または macOS と ODBC Driver 17.6 以降のバージョンのフェデレーション環境でのこのモードについて説明します。

対話型認証 (ActiveDirectoryInteractive)

ドライバーで資格情報の入力を求め、多要素認証を処理する場合は、ローカル ユーザーサインインに対話型認証を使用します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<user@email.com>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryInteractive",
        },
    },
}

主要な ODBC 認証のリファレンス ドキュメントでは、ActiveDirectoryInteractive を Windows 専用としています。 別のプラットフォームで使用する場合は、最初に正確なドライバー バージョンで動作を検証します。

既定の資格情報チェーンによる認証 (ActiveDirectoryDefault)

ODBC ドライバーで既定のMicrosoft Entra資格情報チェーンを適用する場合は、このモードを使用します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryDefault",
        },
    },
}

mssql-django 1.7.3 以降のバージョンでは、このモードが ODBC ドライバーに渡されます。 資格情報ソースまたはトークン更新の動作を明示的に制御する必要がある場合は、 アクセス トークン認証を使用します。

アクセス トークン認証 (TOKEN)

Python コードでMicrosoft Entra トークン自体を取得する場合は、TOKENを使用します。

from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://database.windows.net/.default").token

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "TOKEN": token,
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

このパスは、DefaultAzureCredentialManagedIdentityCredentialClientSecretCredentialなど、任意のPython資格情報クラスで動作します。

settings.pyでフェッチされたアクセス トークンは、プロセスの起動時に 1 回評価され、通常は 60 分から 90 分後に期限切れになります。 Django プロセスがトークンの有効期間より長く存続する場合は、アプリケーション コードでトークンを更新する必要があります。 実行時間の長いほとんどの運用アプリでは、 ActiveDirectoryMsiActiveDirectoryServicePrincipalなど、トークンを自動的に更新する ODBC ドライバー モードを使用します。

パスワード認証 (ActiveDirectoryPassword、非推奨)

Important

Microsoft SQL ドライバーでは、ActiveDirectoryPassword 認証オプション (Microsoft Entra ID パスワード認証) は非推奨です。 このリスクの高い認証フローは、必須のMicrosoft Entra多要素認証 (MFA) と互換性がありません。MFA が適用されているテナントでは機能しない可能性があります。 別のMicrosoft Entra認証方法への移行を計画します。

Microsoft Entra IDパスワード認証は、OAuth 2.0 リソース所有者パスワード資格情報 (ROPC) の付与に基づいています。これにより、アプリケーションは自分のパスワードを直接処理してユーザーにサインインできます。

MICROSOFTでは、MFA と互換性がないため、ROPC フローを使用しないことをお勧めします。 ほとんどのシナリオでは、より安全な代替手段が利用でき、推奨されます。 このフローには、アプリケーションに対する高度な信頼が必要であり、他のフローに存在しないリスクが伴います。 このフローは、より安全なフローが実行できない場合にのみ使用します。 Microsoft は、悪意のある攻撃からユーザーを保護するために、この危険度の高い認証フローから離れています。 詳細については、「 Azure の必須多要素認証の計画」を参照してください。

ユーザーがサインイン時に存在する場合は、ActiveDirectoryInteractive 認証または ActiveDirectoryIntegrated 認証を使用して、サインインしているユーザーポリシーと条件付きアクセス ポリシーに監査証跡属性が適用されるようにします。

サービス間の無人シナリオの場合は、Microsoft Entra サービス アカウントのガイダンスに従ってください。

  • アプリケーションがAzureインフラストラクチャで実行されている場合は、ActiveDirectoryMSI (または一部のドライバーでは ActiveDirectoryManagedIdentity) を使用します。 マネージド ID により、シークレットと証明書の保守とローテーションのオーバーヘッドが排除されます。
  • マネージド ID が使用できない場合 (たとえば、アプリケーションはAzure外で実行されます)、ActiveDirectoryServicePrincipal を使用します。 ドライバーでサポートされている場合は、クライアント シークレットよりもクライアント証明書を優先します。 証明書を使用すると、秘密キーはクライアント上にとどまり、署名されたアサーションのみがクライアントを認証するためにMicrosoft Entraに送信されます。 キーがハードウェア (TPM や HSM など) に格納されている場合、または非エクスポートとしてマークされている場合、クライアント シークレットのように文字列としてコピーすることはできません。
  • Microsoft Entra ユーザー アカウントをサービス アカウントとして使用しないでください。

レガシ シナリオで使用する必要がある場合は、明示的に構成します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<user@email.com>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryPassword",
        },
    },
}