Read Only Access for SQL Server

Read Only Access for SQL Server

·

2 min read

We recently had a snafu when the on-call developer ran an update statement on a production Azure SQL database when it should have been a select statement.

r/ProgrammerHumor - Don’t worry, we take backups regularly… I think.

Luckily we were able to restore the proper values based off other tables or worst-case scenario restore a backup.

Three takeaways:

  1. Review update statements with a peer.

  2. Limit the login to have read-only access by default.

  3. Comment out any update statements after running if logged in with write-access.

Read-Only Access

Create the AAD Group and add members.

az ad group create --display-name 'Developers' --mail-nickname 'developers@company.com'

az ad group member add --group 'Developers' --member-id 'some_dev@company.com'

Create the Login

CREATE login [some_dev@company.com]
FROM EXTERNAL PROVIDER

This the some_dev@company.com is an Azure Active Directory account (AAD).

Create the User

This user is expected to be an AAD Group which some_dev@company.com is a member.

CREATE USER [some_dev@company.com]
FROM EXTERNAL PROVIDER

Using Database Roles

EXEC sp_addrolemember 'db_datareader', [Developers]

--Prevent insert, update, and deletes.
EXEC sp_addrolemember 'db_denydatawriter', [Developers]

This will limit the Developers user from insert, update and delete rows on tables in the database. It will still allow the creation and dropping of tables.

Using Granular Permissions

We can limit the user from creating/dropping objects and stored-procedure/function execution:

-- Prevent object creation
DENY CREATE TABLE TO [Developers]
DENY CREATE PROCEDURE TO [Developers]
DENY CREATE FUNCTION TO [Developers]
DENY CREATE VIEW TO [Developers]

-- Prevent execution
DENY EXECUTE TO [Developers]

-- Prevent insert, update, delete and dropping of tables to schema for user.
DENY ALTER ON SCHEMA::[dbo] TO [Developers]

Or limit to whatever schema you want.

Testing

CREATE TABLE [dbo].Test (
    Id int,
    LastName varchar(255),
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255)
);

INSERT INTO [dbo].Test VALUES (1, 'Feyman', 'Richard', '123', 'Seattle')
SELECT * FROM [dbo].Test
UPDATE [dbo].Test SET FirstName = 'Test' WHERE Id = 1
SELECT * FROM [dbo].Test
DELETE FROM [dbo].Test

DROP TABLE [dbo].Test

Check levels of access by running all or individual lines.

You can drop the user and all related permissions.

DROP USER [Developers]

References