数据库验证

适用于: SQL Server 2022 (16.x) Azure SQL 数据库Azure SQL 托管实例

账本提供一种称为“前向完整性”的数据完整性,它提供对账本表中数据的数据篡改的证据。 数据库验证过程使用以前生成的一个或多个数据库摘要作为输入。 然后根据账本表的当前状态,该过程重新计算存储在数据库账本中的哈希值。 如果计算所得的哈希值与输入摘要不符,则验证将失败。 该失败指示数据已被篡改。 验证过程会报告它所检测到的所有不一致项。

数据库验证过程

验证过程会扫描所有账本和历史记录表。 该过程重新计算其行的 SHA-256 哈希,并将它们与传递到验证存储过程的数据库摘要文件进行比较。

由于账本验证会重新计算数据库中事务的所有哈希值,因此对于包含大量数据的数据库,此过程可能是一个资源密集型过程。 为了降低验证成本,该功能提供了用于验证单个账本表或者仅一部分账本表的选项。

数据库验证可通过两个存储过程来完成,具体取决于是使用自动摘要存储还是手动管理摘要

注意

必须首先在数据库上启用数据库选项 ALLOW_SNAPSHOT_ISOLATION ,然后才能运行 verifcation 存储过程。

使用自动摘要存储的数据库验证

使用自动摘要存储来生成和存储数据库摘要时,摘要存储的位置在系统目录视图 sys.database_ledger_digest_locations 中作为 JSON 对象。 运行数据库验证包括执行 sp_verify_database_ledger_from_digest_storage 系统存储过程。 在 sys.database_ledger_digest_locations 系统目录视图中指定 JSON 对象,数据库摘要在该视图中被配置为存储。

使用自动摘要存储时,可以在账本表的整个生命周期内更改存储位置。 例如,如果首先使用 Azure 不可变存储来存储摘要文件,但以后想要改为使用 Azure 机密账本,则可以这样做。 位置中的此更改存储在 sys.database_ledger_digest_locations

运行账本验证时,请检查 digest_locations 的位置,以确保从预期位置检索验证中使用的摘要。 你希望确保特权用户在没有配置和锁定的不可变策略的情况下未将摘要存储的位置更改为不受保护的存储位置,例如 Azure 存储。

为了简化使用多个摘要存储位置时运行的验证,以下脚本将提取摘要的位置,并使用这些位置执行验证。

DECLARE @digest_locations NVARCHAR(MAX) = (SELECT * FROM sys.database_ledger_digest_locations FOR JSON AUTO, INCLUDE_NULL_VALUES);
SELECT @digest_locations as digest_locations;
BEGIN TRY
    EXEC sys.sp_verify_database_ledger_from_digest_storage @digest_locations;
    SELECT 'Ledger verification succeeded.' AS Result;
END TRY
BEGIN CATCH
    THROW;
END CATCH

使用手动摘要存储的数据库验证

使用手动摘要存储生成和存储数据库摘要时,可采用存储过程 sp_verify_database_ledger 来验证账本数据库。 摘要的 JSON 内容被追加到存储过程中。 运行数据库验证时,可以选择验证数据库中的所有表或特定表。

下面的代码是传递两个摘要进行验证以运行 sp_verify_database_ledger 存储过程的示例:

EXECUTE sp_verify_database_ledger N'
[
    {
        "database_name":  "ledgerdb",
        "block_id":  0,
        "hash":  "0xDC160697D823C51377F97020796486A59047EBDBF77C3E8F94EEE0FFF7B38A6A",
        "last_transaction_commit_time":  "2020-11-12T18:01:56.6200000",
        "digest_time":  "2020-11-12T18:39:27.7385724"
    },
    {
        "database_name":  "ledgerdb",
        "block_id":  1,
        "hash":  "0xE5BE97FDFFA4A16ADF7301C8B2BEBC4BAE5895CD76785D699B815ED2653D9EF8",
        "last_transaction_commit_time":  "2020-11-12T18:39:35.6633333",
        "digest_time":  "2020-11-12T18:43:30.4701575"
    }
]';

sp_verify_database_ledgersp_verify_database_ledger_from_digest_storage 的返回代码是 0(成功)或 1(失败)。

建议

理想情况下,你想要最大程度地减少甚至消除攻击发生时间与检测到攻击时间之间的间隔。 Microsoft 建议定期计划账本验证,以避免在检测到篡改后还原几天或几个月前的数据库。 验证间隔应由客户决定,但请注意账本验证可能消耗资源。 建议在维护时段或非高峰时段运行此功能。

可以使用弹性作业或 Azure 自动化,来计划 Azure SQL 数据库中的数据库验证。 要计划 Azure SQL 托管实例和 SQL Server 中的数据库验证,可以使用 SQL Server 代理。

权限

数据库验证需要 VIEW LEDGER CONTENT 权限。 有关与账本表相关的权限的详细信息,请参阅权限