Always Encrypted with mssql-django

この記事では、mssql-django バックエンドを介して SQL Server Always Encrypted と Django アプリケーションを使用する方法について説明します。 Always Encrypted では、保存時および転送中の機密データを保護する列レベルの暗号化が提供されます。

前提条件

  • SQL Server 用 Microsoft ODBC Driver 17 または 18
  • SQL Server 2016 以降、またはAzure SQL Database
  • SQL Server側で構成された列暗号化 (列マスター キーと列暗号化キー)

どのように機能するのか

Always Encrypted は、Django 自体ではなく、ODBC ドライバー レイヤーによって処理されます。 ColumnEncryption ODBC パラメーターを有効にすると、ドライバーは、アプリケーションとSQL Serverの間を通過するときに、データを自動的に暗号化および復号化します。 Django のモデルとクエリは、列が暗号化されているかどうかに関係なく、同じように動作します。

Windows 証明書ストア

列マスター キーがWindows証明書ストアに格納されている場合は、ColumnEncryption=Enabledextra_paramsを追加して Always Encrypted を有効にします。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "ColumnEncryption=Enabled",
        },
    },
}

このアプローチは、Windowsでのみ機能します。

クライアント ID とシークレットを使用したAzure Key Vault

列マスター キーがAzure Key Vaultに格納されている場合は、extra_paramsでアプリケーションの資格情報を指定します。

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": (
                "ColumnEncryption=Enabled;"
                "KeyStoreAuthentication=KeyVaultClientSecret;"
                "KeyStorePrincipalId=<application-client-id>;"
                "KeyStoreSecret=<client-secret>"
            ),
        },
    },
}

<application-client-id><client-secret>をアプリ登録のアプリケーション (クライアント) ID とクライアント シークレットの値に置き換えます。

Important

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

マネージド ID を使用したAzure Key Vault

Azureで実行する場合 (Azure 仮想マシンやAzure App Serviceなど)、マネージド ID を使用してAzure Key Vaultにアクセスします。

システムによって割り当てられた管理ID

KeyStoreAuthentication パラメーターを超える追加の構成は必要ありません。

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": (
                "ColumnEncryption=Enabled;"
                "KeyStoreAuthentication=KeyVaultManagedIdentity"
            ),
        },
    },
}

ユーザー指定のマネージド ID

マネージド ID のクライアント ID (アプリケーション 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": (
                "ColumnEncryption=Enabled;"
                "KeyStoreAuthentication=KeyVaultManagedIdentity;"
                "KeyStorePrincipalId=<managed-identity-client-id>"
            ),
        },
    },
}

マネージド ID のアクセス許可を付与する

  1. マネージド ID に Azure SQL データベースへのアクセス権を付与します。

    CREATE USER [<identity-name>] FOR EXTERNAL PROVIDER;
    
    ALTER ROLE db_datareader ADD MEMBER [<identity-name>];
    ALTER ROLE db_datawriter ADD MEMBER [<identity-name>];
    
    GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [<identity-name>];
    GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [<identity-name>];
    
  2. Always Encrypted Azure Key Vault ドキュメントに記載されているアクセス許可を使用して、列マスター キーを格納するAzure Key Vaultへのアクセス権をマネージド ID に付与します。

Django で暗号化されたテーブルを管理できるようにする

Django で Always Encrypted を使用する場合は、最初にSQL Serverに暗号化オブジェクトを構成してから、移行を実行します。

推奨される順序:

  1. SQL ServerまたはAzure SQLに列マスター キー (CMK) と列暗号化キー (CEK) を作成します。
  2. Django 接続設定で ColumnEncryption=Enabled を構成します。
  3. Django の移行を実行します。
  4. SQL Server Management Studioまたは T-SQL を使用してターゲット列を暗号化します。

移行を実行します。

python manage.py migrate

mssql-django は、Always Encrypted のキー メタデータを作成または管理しません。 キーの作成と列暗号化ポリシーは、引き続き SQL Server の管理タスクです。

サポートされていない認証方法

Always Encrypted キー ストアアクセスでは、ユーザー名/パスワードとAzure Key Vault対話型認証はサポートされていません。