KEMBAR78
Secure Temporal Table History | PDF | Table (Database) | Data
0% found this document useful (0 votes)
57 views4 pages

Secure Temporal Table History

The document discusses securing the history of temporal tables in SQL Server. It describes how temporal tables keep a history of row changes with timestamps and recommends placing the history table in a separate schema to restrict access. The article demonstrates creating a minimally privileged user with access only to the application schema, preventing access to the history data. It concludes that the principle of least privilege is important for privacy by restricting access to only needed historical data.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views4 pages

Secure Temporal Table History

The document discusses securing the history of temporal tables in SQL Server. It describes how temporal tables keep a history of row changes with timestamps and recommends placing the history table in a separate schema to restrict access. The article demonstrates creating a minimally privileged user with access only to the application schema, preventing access to the history data. It concludes that the principle of least privilege is important for privacy by restricting access to only needed historical data.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Secure your temporal table history | sqlsunday.com https://sqlsunday.com/2023/01/19/secure-temporal-tab...

Secure your temporal


table history
2023-01-19 / DANIEL HUTMACHER
You may have already discovered a relatively new feature in SQL
Server called system-versioned temporal tables
(https://learn.microsoft.com/en-us/sql/relational-databases/tables
/temporal-tables). You can have SQL Server set up a history table
that keeps track of all the changes made to a table, a bit similar to
what business intelligence people would call a “slowly changing
dimension”.

1 CREATE SCHEMA App;


2  
3 CREATE TABLE App.Customers (
4 Company_ID int IDENTITY(1, 1) NOT NULL,
5 CompanyName nvarchar(250) NOT NULL,
6 Email varchar(250) NOT NULL,
7 Valid_From datetime2(7) GENERATED ALWAYS AS
8 Valid_To datetime2(7) GENERATED ALWAYS AS
9 CONSTRAINT PK_Customers PRIMARY KEY CLUSTERED (Company_ID),
10 PERIOD FOR SYSTEM_TIME (Valid_From, Valid_To)
11 ) WITH (SYSTEM_VERSIONING=ON);

What happens behind the scenes is that SQL Server creates a


separate table that keeps track of previous versions of row
changes, along with “from” and “to” timestamps. That way, you
can view the contents of the table as it was at any given point in
time.

But how to you version the contents of a table, while hiding things
like deleted records from prying eyes?

In the example above, we didn’t specify the name of the history


table, so SQL Server picked one for us,
App.MSSQL_TemporalHistoryFor_18099105, where the number
at the end is the object_id of our base table. If you’re like me, you
may want to pick a slightly more readable table name, but
specifying one in the CREATE TABLE statement:

9 ---
10 PERIOD FOR SYSTEM_TIME (Valid_From, Valid_To)
11 ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=App.Customers_history))

1 of 4 8/9/23, 08:39
Secure your temporal table history | sqlsunday.com https://sqlsunday.com/2023/01/19/secure-temporal-tab...

Put history tables in their own


schema

But you can even create the history table in a different schema:

1 CREATE SCHEMA History;


2  
3 CREATE TABLE App.Customers (
4 Company_ID int IDENTITY(1, 1) NOT NULL,
5 CompanyName nvarchar(250) NOT NULL,
6 Email varchar(250) NOT NULL,
7 Valid_From datetime2(7) GENERATED ALWAYS AS
8 Valid_To datetime2(7) GENERATED ALWAYS AS
9 CONSTRAINT PK_Customers PRIMARY KEY CLUSTERED (Company_ID),
10 PERIOD FOR SYSTEM_TIME (Valid_From, Valid_To)
11 ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=History.Customers));

I tend to use database schemas to assign permissions, rather


than messing with object-level permissions. With just a little
planning, you can build simple, yet very effective, access controls
using schemas. In our case, we could limit access to the History
schema to only a handful of principals, while allowing the
application to access the App schema as usual.

Testing the permissions

Let’s create a minimally privileged user and assign some schema


permissions on the App schema:

1 CREATE USER LowPrivilegeUser WITHOUT LOGIN;


2 GRANT SELECT, INSERT, UPDATE, DELETE ON App.Customers

Now, let’s impersonate this user to see what we can do.

1 EXECUTE AS USER='LowPrivilegeUser';
2  
3 --- Create a customer record
4 INSERT INTO App.Customers (CompanyName, Email) VALUES
5  
6 --- Update a customer record
7 UPDATE App.Customers SET Email='sales@contoso.com' WHERE
8  
9 --- Delete the customer record
10 DELETE FROM App.Customers WHERE CompanyName='Contoso'

But if we try to work with the history table as the low-privilege


user, we get a permission error:

1 --- Can we view the history?


2 SELECT * FROM History.Customers;

2 of 4 8/9/23, 08:39
Secure your temporal table history | sqlsunday.com https://sqlsunday.com/2023/01/19/secure-temporal-tab...

Msg 229, Level 14, State 5, Line 39


The SELECT permission was denied on the object
'Customers', database 'Test', schema 'History'.

Finally, we’ll revert back to the user we logged in as

1 REVERT;

Data retention vs. privacy

Let’s be honest. We all hang on to data more than we probably


need to. The new gold standard, whether you are subject to new
privacy laws or not, is to design software with “privacy by default”
in mind, meaning you only keep data you absolutely need in order
to meet your business objective. When you do need to keep old
data, for whatever reason (auditing, analysis, etc), you want to
reduce the surface area of this data as much as you can.

A data breach does not always mean somebody walking out of


the data center with all your backups or files – it could just be a
bug in the application API being exploited by a script kiddie, or
even a user with a grudge. This is why the principle of “least
required permissions” is so important.

The pattern we’ve looked at here is a low-effort pattern to


implement a principle of least permissions for historical data.

HISTORY ,
PERMISSIONS ,
TEMPORAL TABLE ,
VERSIONING

3 thoughts on “Secure your temporal


table history”

1. Wilfred van Dijk


2023-01-19 AT 11:27
I think this is solved in SQL2022 by implementing ledger
tables; even DBA’ers can’t delete data from this table type (but
it looks data will be forever in this audit table)

REPLY

3 of 4 8/9/23, 08:39
Secure your temporal table history | sqlsunday.com https://sqlsunday.com/2023/01/19/secure-temporal-tab...

◦ Daniel Hutmacher
2023-01-19 AT 11:32
I think ledger tables are pretty cool, but they solve for
slightly different requirements – plain history is not the
same as a proper ledger.

REPLY
2. Pingback: Securing Temporal Tables – Curated SQL

4 of 4 8/9/23, 08:39

You might also like