An early step in implementing countermeasures to potential threats in SQL Server is to ensure that you have a full understanding of the security model. SQL Server 2016 provides a rich security framework with overlapping layers of security that help database administrators (DBAs) counter risks and threats in a manageable way.
It is important for DBAs to understand the SQL Server security model so that they can implement the technologies in the way that best fits the needs of their organization and applications, while minimizing the amount of security administration that is required. This chapter discusses the implementation of the security hierarchy in SQL Server 2016.
Active security refers to the practice of limiting users’ access to data and structures through the use of permissions. When working with the SQL Server security model, the three entities to ensure that you understand are principals, securable, and permissions. The definition of each of these entities is found in Table 2-1.
Table 2-1. Security Model Definitions
Entity | Definition |
---|---|
Principal | A security principal is an entity, such as a user. |
Securable | A securable is data, an artifact, or metadata. |
Permission | Permissions are rights that are granted or denied to a security principal to define the principal’s permitted access to a securable. |
Tip
Passive security refers to auditing activity. SQL Server Audit is discussed in Chapter 3.
Security Principal Hierarchy
Security principals are organized into a hierarchy, which allows administrators to assign permissions to a group of users. This has obvious benefits, allowing you to implement a security based on a user’s role within an organization. For example, all salespersons can easily be assigned the same permissions if a preconfigured sales role that already has all required permissions assigned to it exists. Figure 2-1 defines the complete hierarchy of security principals that can access data or data structures within SQL Server. The hierarchy begins at the domain level and passes through to the local server layer, the SQL Server instance layer, and finally, the database layer.
Figure 2-1. Security hierarchy
The diagram in Figure 2-1 shows that a login, created within the SQL Server instance, can be mapped to a local Windows user or group or to a domain user or group. Usually, in an enterprise environment, this is a domain user or group. (A group is a collection of users that are granted permissions as a unit.) This eases the administration of security. Imagine (as described earlier), that a new starter joins the sales team. When he is added to the domain group called SalesTeam—which already has all of the required permissions to file system locations, SQL Server databases, and so on—he immediately inherits all required permissions to perform his role.
The diagram also illustrates how local server accounts or domain accounts and groups can be mapped to a user at the database level (a database user without login). This is part of the functionality of contained databases. This technology was introduced in SQL Server 2012 to support high availability with AlwaysOn Availability Groups. Contained database authentication is discussed later in this chapter.
SQL Server logins, which are mapped to local server or domain-level users or groups, are created at the SQL Server instance level. At the instance level, it is also possible to create SQL Server logins, which use second-tier authentication (if you are using mixed-mode authentication).
Both of these login types can be added to fixed server roles and user-defined server roles at the instance level. Doing this allows you to grant the principal a common set of permissions to instance-level objects, such as linked servers and endpoints. You can also map logins to database users, which in turn can be granted permissions to database level objects.
Database users reside at the database level of the hierarchy. You can grant them permissions directly to schemas and objects within the database, or you can add them to database roles. Database roles are similar to server roles, except they are used to grant a common set of permissions at the database layer instead of the instance layer. Database layer securables include schemas, tables, views, and stored procedures, and so forth.
Instance Level Security
Implementing instance level security involves creating and managing logins, credentials, and server roles. Securables at the instance level include databases, endpoints, and AlwaysOn Availability Groups. The following sections discuss logins, server roles, and credentials.
Tip
Cryptographic Providers and SQL Server Audits are also administered at the instance level. SQL Server Audit is discussed in Chapter 3 and Cryptographic Providers are discussed in Chapter 5.
Logins
Since SQL Server 2012, it has been possible for users to authenticate directly to a database as part of contained database functionality. Generally, however, database engine users need to authenticate at the instance level. SQL Server supports two authentication modes at the instance level: Windows authentication and mixed mode authentication.
When an instance is in Windows authentication mode, users must authenticate to either the local server or to the domain before they can access the SQL Server instance. A login is created within the SQL Server instance, which maps to either their Windows user or a Windows group that contains their Windows user. The SID (security identifier) of the Windows principal is stored in the Master database of the instance.
Tip
In addition to creating a login mapped to a Windows user or group, you can also map a login to a certificate or an asymmetric key. Doing so does not allow a user to authenticate to the instance by using a certificate, but it does allow code signing so that permissions to procedures can be abstracted, rather than granted directly to a login. This helps when you are using dynamic SQL, which breaks the ownership chain. In this scenario, when you run the procedure, SQL Server combines the permissions from the user who called the procedure and the user who maps to the certificate.
When an instance is configured to use mixed mode authentication , it is still possible to create a login that maps to a Windows user or Windows group, but it is also possible to create second-tier logins, known as SQL logins. These logins have their name, password, and SID stored in the Master database of the instance. These details are verified when a user connects to the instance. A user can then authenticate to the instance using this username and password, without the need for prior authentication to the server or domain.
Mixed mode authentication is less secure than authentication, because it is possible to attack the instance without first authenticating to the domain. Therefore, it is best practice us use Windows authentication. It is often necessary to use mixed mode authentication, however, for the following reasons:
Legacy applications that require a second-tier login
Access from outside of the domain (such as a Linux server)
Environments where security is implemented in the application tier and a single SQL login connects to the database engine
Creating a Login
A login can be created via T-SQL by using the CREATE LOGIN statement. When creating a login from a Windows user or group, the syntax is very straightforward, because there is no password management involved. Table 2-2 describes the WITH options that are valid when creating a login from a Windows security principal.
Table 2-2. CREATE LOGIN Options for Windows Security Principal
Option | Description |
---|---|
DEFAULT_DATABASE | Specifies a “landing” database for the login. This is the database to which their context is scoped when they initially authenticate to the instance. This scope can be overwritten in the connection string. |
DEFAULT_LANGUAGE | Specifies the default language that is assigned to the login. If omitted, then this is configured to be the default language of the instance. |
Listing 2-1 demonstrates how to create a login for the Windows user Pete in the CarterSecureSafe.com domain.
Listing 2-1. Create a Login from a Windows Security Principal
USE master
GO
CREATE LOGIN [cartersecuresafePete]
FROM WINDOWS
WITH DEFAULT_DATABASE=master, DEFAULT_LANGUAGE=British ;
GO
When creating a second tier, SQL login, however, there are many more WITH options that can be used. These options are described in Table 2-3.
Table 2-3. CREATE LOGIN Options for SQL Login
Option | Description |
---|---|
PASSWORD | Specifies the initial password used by the login; in clear text. |
PASSWORD HASHED | Specifies a hashed representation of the initial password used by the login.* |
SID | Specifies the SID of the login.* |
DEFAULT_DATABASE | Specifies a “landing” database for the login. This is the database to which their context id scoped when they initially authenticate to the instance. This scope can be overwritten in the connection string. |
DEFAULT_LANGUAGE | Specifies the default language assigned to the login. If omitted, then this is configured to be the default language of the instance. |
CHECK_POLICY | Specifies that the login’s password must meet the same requirements, such as length and complexity, as Windows users, as enforced by Group Policy or Local Security Policy. |
CHECK_EXPIRATION | Specifies that the login’s password will expire, in line with password expiration policy configured for Windows users, as enforced by Group Policy or Local Security Policy. This option is only valid if CHECK_POLICY is also specified. |
MUST_CHANGE | Specifies that the user must change their password the first time that they login to the instance. This option can only be used if CHECK_EXPIRATION is also specified. |
Listing 2-2 demonstrates how to create a SQL login called Danni. The password for the login must meet the complexity requirements specified by Group Policy, but the password will not expire. This means that it is not possible to force the password to be changed the first time that the user logs in.
Listing 2-2. Create a SQL Login
USE master
GO
CREATE LOGIN Danni
WITH PASSWORD='C0mplexPa$$w0rd',
DEFAULT_DATABASE=master, CHECK_EXPIRATION=OFF, CHECK_POLICY=ON ;
GO
Migrating Logins Between Instances
There will be occasions when you need the same login to exist on multiple servers. This may be because of a server migration, or it may be because you are implementing DR and you need users to be able to reconnect to the DR instance transparently.
For logins that are created from Windows security principals, this poses no problem what so ever. As discussed earlier in this chapter, the SID of the Windows security principal is stored in the Master database, but the principal itself, is managed by Windows. Therefore, you can simply create a login on the second instance and map it to the same Windows user or group.
If you are working with SQL logins, however, this scenario is more challenging to deal with, because the SQL Server instance hosts and manages the SID and the password of the login. This means that if you create a login with the same name and password on a different instance, then they will still be completely different, isolated principals. Once you move or failover your databases to the second instance, the database users become orphaned. This means that they no longer map to a login. This is because the login on the second instance has a different SID, despite having the same name and password.
You can manage this issue at point of failover by using an ALTER USER statement WITH LOGINoption.
Tip
The ALTER USER WITH LOGIN syntax replaces the functionality of the deprecated sp_change_users_logins system stored procedure.
Listing 2-3 demonstrates how to remap a database user called Danni in the AdventureWork2016 database to a login called Danni on a new instance.
Listing 2-3. Remap a Database User to a Login
USE AdventureWorks2016
GO
ALTER USER Danni WITH LOGIN = Danni ;
Tip
Database users are discussed in the “Database-Level Security” section of this chapter.
Naturally, it is more efficient if users are already mapped to their correct login at the point that the databases are moved or failed over. This can be achieved by creating the login and manually assigning it the correct SID.
This is where the WITH SID option mentioned in Table 2-1 comes into play. If you script out the SQL login on an instance and include the SID, then you can use the script to pre-create the login on the DR instance with the correct SID, meaning that the database users automatically map to the correct login without the need to alter them. Listing 2-4 demonstrates how this can be achieved using a SQLCMD script, which replicates a login called Danni from ProdInstance1 to DRInstance1.
Tip
The script must be running in SQLCMD mode ; otherwise, it will not execute.
Listing 2-4. Migrate a Login to a New Instance
:CONNECT CARTERSECURESAFEProdInstance1
DECLARE @SQL NVARCHAR(MAX) ;
SET @SQL = (SELECT 'CREATE LOGIN '
+ name
+ ' WITH PASSWORD = ''C0mplexPassw0rd'', SID = 0x'
+ CONVERT(NVARCHAR(64), SID, 2)
FROM sys.sql_logins
WHERE Name = 'Danni') ;
:CONNECT CARTERSECURESAFEDRInstance1
EXEC(@SQL) ;
Caution
The preceding method works perfectly well in a SQLCMD script. Although it is worthy to note that depending on your server and network configuration, you may be sending the password across the wire in plain text. If this is the case, then you should follow the approach discussed next to hash the password.
An issue arises with the approach that we have discussed; it’s a common scenario, in which you want to script out the logins for an environment and keep them under source control so that you can apply them to other environments, as required. In this scenario, you store passwords in plain text. This poses an obvious security risk and it should be avoided. Instead, you should script out the SQL logins, so that the passwords are stored in the same encrypted format that SQL Server stores them in.
This approach can be achieved by scripting the logins with passwords based on the password_hash column of the sys.sql_logins view. Instead of this, however, we script the logins using the HASHBYTES()()function to generate the password hash for the login. This technique is demonstrated in Listing 2-5 and gives you an insight into how SQL Server hashes the passwords. The script generates the DDL (Data Definition Language) statements required to script out all enabled SQL logins from an instance with hashed passwords. The script can subsequently be placed in source control and run on other environments as required.
Tip
In normal operations, you should take the approach of taking the password hash from the sys.sql_logins view. This is preferable because it does not require knowledge of the login’s plain text password.
The HASHBYTES()function returns a hash of its input. It accepts the parameters detailed in Table 2-4.
Table 2-4. HASHBYTES() Parameters
Parameter | Description |
---|---|
Algorithm | The algorithm that the function uses to hash the data. The following are acceptable values: • MD2 • MD4 • MD5 • SHA • SHA1 • SHA2_256 • SHA2_512 |
Input | The value hashed by the function. |
Notice that the script uses a function called CRYPT_GEN_RANDOM(). This function uses the Windows CAPI (Crypto API) to generate a cryptographic random number, which it returns as a hexadecimal number. The function accepts the parameters detailed in Table 2-5.
Table 2-5. CRYP_GEN_RANDOM Parameters
Parameter | Description |
---|---|
Length | The length of the number to be generated. |
Seed | An optional randomization seed. |
Listing 2-5. Script out Logins with Hashed Passwords
DECLARE @password NVARCHAR(MAX) = 'C0mplexPa$$w0rd' ;
DECLARE @salt VARBINARY(4) = CRYPT_GEN_RANDOM(4) ;
DECLARE @hash VARBINARY(1000) ;
DECLARE @SQL NVARCHAR(MAX) ;
SET @hash = (SELECT 0x0200 + @salt + HASHBYTES('SHA2_512', CAST(@password AS VARBINARY(MAX)) + @salt)) ;
SET @SQL = (SELECT 'CREATE LOGIN '
+ Name
+ ' WITH PASSWORD = '
+ CONVERT(NVARCHAR(1000), @hash, 1)
+ ' HASHED, SID = 0x'
+ CONVERT(NVARCHAR(64), SID, 2)
FROM sys.sql_logins
WHERE is_disabled = 0
FOR XML PATH('')) ;
SELECT @SQL ;
Server Roles
SQL Server provides a set of built-in server roles. These roles allow you to assign instance-level permissions to logins that have common requirements. They are called fixed server roles. It is not possible to change the permissions that are granted to them; you can only add and remove logins. Table 2-6 describes each fixed server role .
Table 2-6. Fixed Server Roles
Role | Description |
---|---|
sysadmin | The sysadmin role gives administrative permissions to the entire instance. A member of the sysadmin role can perform any action within the instance of the SQL Server relational engine. |
bulkadmin | In conjunction with the INSERT permission on the target table within a database, the bulkadmin role allows a user to import data from a file using the BULK INSERT statement. This role is normally given to service accounts that run ETL processes. |
dbcreator | The dbcreator role allows its members to create new databases within the instance. Once a login creates a database, that login is automatically the owner of that database and is able to perform any action inside it. |
diskadmin | The diskadmin role gives its members the permissions to manage backup devices within SQL Server. |
processadmin | Members of the processadmin role are able to stop the instance from T-SQL or SSMS (SQL Server Management Studio). They are also able to kill running processes. |
public | All logins are added to the public role. Although you can assign permissions to the public role, this does not fit with the principle of least privilege. This role is normally only used for internal SQL Server operations, such as authentication to TempDB. |
securityadmin | Members of the securityadmin role are able to manage logins at the instance level. For example, members may add a login to a server role (except sysadmin) or assign permissions to an instance-level resource, such as an endpoint. However, they cannot assign permissions within a database to database users. |
serveradmin | serveradmin combines the diskadmin and processadmin roles. In addition to starting or stopping the instance, however, members of this role can also shut down the instance using the SHUTDOWN T-SQL statement. The subtle difference here is that the SHUTDOWN command gives you the option of not running a CHECKPOINT in each database if you use it with the NOWAIT option. Additionally, members of this role can alter endpoints and view all instance metadata. |
setupadmin | Members of the setupadmin role are able to create and manage linked servers. |
You can also create custom server roles , which allow you to grant a custom set of permissions to a group of logins. For example, if you implemented AlwaysOn Availability Groups, then you may wish to create a server role called AvailabilityRoleand grant this group the following permissions:
Alter any availability group
Alter any endpoint
Create an availability group
Create endpoint
You can then add to this role the junior DBA s who are not authorized to be made members of the sysadmin fixed server role, but who need to manage the high availability and disaster recovery of the instance. The script in Listing 2-6 demonstrates how to create the server role and grant it the relevant permissions.
Notice that the script uses the GRANT statement to assign permissions to the role. When assigning permissions to a server role or login, the three following assignments can be made:
GRANT
DENY
REVOKE
GRANTprovides a principal with the permissions to access a securable. You can use the WITH option in a GRANT statement to additionally provide a principal with the ability to GRANT the same permission to other principals.
DENYspecifically denies a principal’s permissions to access a securable; DENY always overrules GRANT. Therefore, if a login is a member of a server role (or roles) that gives the login permissions to alter an endpoint, but the principal itself, has explicitly been denied permissions to alter the same endpoint, then the principal is not able to manage the endpoint.
REVOKEremoves a permission assignment to a securable. This includes DENY associations as well as GRANT associations. If a login has been assigned permissions through a server role, however, then revoking the permissions to that securable, directly against the login itself, has no effect. In order to have an effect, you need to either use the DENY permission assignment against the login or server role, or you need to REVOKE the permissions from the server role.
Listing 2-6. Create Server Role and Grant Permissions
CREATE SERVER ROLE AVAILABILITYROLE AUTHORIZATION [CarterSecureSafeSQLAdmin] ;
GO
GRANT ALTER ANY AVAILABILITYROLE GROUP TO AVAILABILITYROLE ;
GRANT ALTER ANY ENDPOINT TO AVAILABILITYROLE ;
GRANT CREATE AVAILABILITYROLE GROUP TO AVAILABILITYROLE ;
GRANT CREATE ENDPOINT TO AVAILABILITYROLE ;
GO
You could add the Danni login to this server role by using the code shown in Listing 2-7.
Listing 2-7. Add Login to Server Role
ALTER SERVER ROLE AvailabilityRole ADD MEMBER Danni ;
GO
Credentials
Credentials are used to provide the ability to access resources that are external to the SQL Server instance. SQL logins can use credentials to access operating system–level resources. SQL Server Agent Proxy Accounts use credentials to access SQL Server Agent Subsystems, such as PowerShell or CmdExec. Credentials are also used when taking backups to Azure.
When used to access operating system–level resources, a credential usually records the identity and password of a Windows security principal. If used for backups to Azure, however, then the credential records the name and private key of the Azure storage account. Listing 2-8 demonstrates how to create a credential to use for backups to Azure; the storage account is called CarterSecureSafeStorageAcc.
Listing 2-8. Create a Credential for Backups to Azure
CREATE CREDENTIAL URLBackupCredential
WITH IDENTITY = 'CarterSecureSafeStorageAcc'
,SECRET ='YdfgSGdTgJNpVFl992sBv7Bp1gyL61I33wNrTMHGBDdtVcx97F5f6SC5uDi59FeY2/IjxyqsuLU2xrkrNAGT==' ;
Database-Level Security
At the database level, security is implemented by assigning permissions to security principals; namely users and database roles. The following sections discuss both of these principal types.
Users
A database user is typically created from a login at the instance level. This means that the same instance level security principal can be granted permissions on resources in multiple databases. Since SQL Server 2012, however, it has also been possible to create a user without a login. The following sections discuss each of these database user types.
Users with a Login
Users can be created by using the CREATE USER T-SQL statement. Users that are created with an association to a login have a limited set of options that can be configured. These options are described in Table 2-7.
Table 2-7. Options When Creating a User from a Login
Option | Description |
---|---|
DEFAULT_SCHEMA | Specifies the default schema for a user. Schemas are discussed in Chapter 4 |
ALLOW_ENCRYPTED_VALUE_MODIFICATIONS | Specifies that users are allowed to bulk copy encrypted data, without first decrypting it. Encryption is discussed in Chapter 5. |
You can create a user in the AdventureWorks2016 database, which is associated with the login called Danni, by using the script in Listing 2-9.
Listing 2-9. Create a User from a Login
USE AdventureWorks2016
GO
CREATE USER Danni FOR LOGIN Danni
WITH DEFAULT_SCHEMA = Sales ;
The script creates a user that has the same name as the login. Whilst this is not mandatory, it is sensible, because it aids the administration of the security principals and makes the hierarchy of principals transparent to new DBA s joining your team. The script sets the user’s default schema to Sales. This means that the Danni user is able to reference objects in the Sales schema using one-part names. If no default schema is specified for a user, then their default schema is dbo.
Note
Schemas are discussed in further detail in Chapter 4.
Users Without a Login
When creating a user that is not associated with a login, the user can either be mapped to a Windows security principal or it can be created using SQL Server authentication.
Note
Users can only be created by using SQL Server authentication if the database is configured with a partial containment level. Contained databases are beyond the scope of this book, but you can learn more about them at https://msdn.microsoft.com/en-us/library/ff929071.aspx .
Table 2-8 details the properties that can be configured when creating a user without a login.
Table 2-8. Options When Creating a User Without a Login
Option | Description |
---|---|
DEFAULT_SCHEMA | Specifies the default schema for a user. Schemas are discussed in Chapter 4 |
ALLOW_ENCRYPTED_VALUE_MODIFICATIONS | Specifies that users are allowed to bulk copy encrypted data, without first decrypting it. Encryption is discussed in Chapter 5. |
DEFAULT_LANGUAGE | Specify the default language for the user. This options can be expressed as an lcid, a language name, or a language alias. |
SID | Specify the SID associated with the user (SQL Server authentication only). This creates users in multiple databases that share the same SID. It helps with high availability and disaster recovery techniques by using AlwaysOn Availability Groups. |
Listing 2-10 demonstrates how to create a user called Phil from a Windows security principal called Phil, which exists in the cartersecuresafe domain.
Listing 2-10. Create a User from a Windows Security Principal
USE AdventureWorks2016
GO
CREATE USER [cartersecuresafephil]
WITH DEFAULT_SCHEMA=dbo ;
As previously mentioned, creating users with SQL authentication—also known as users with a password—is only possible in contained databases. If you attempt to create a user with SQL authentication in a database that is not contained, you receive the error shown in Figure 2-2.
Figure 2-2. Error when attempting to create a user with password in a non-contained database
The script in Listing 2-11 configures the instance to allow contained database authentication before configuring the AdventureWorks2016 database to support partial containment. Finally, the script creates a user, named Pete, with a password.
Listing 2-11. Create a User with Password in a Contained Database
USE master
GO
EXEC sp_configure 'show advanced options', 1 ;
GO
RECONFIGURE ;
GO
EXEC sp_configure 'contained database authentication', '1' ;
GO
RECONFIGURE WITH OVERRIDE ;
ALTER DATABASE AdventureWorks2016
SET CONTAINMENT = PARTIAL
WITH NO_WAIT ;
GO
USE AdventureWorks2016
GO
CREATE USER Pete
WITH PASSWORD = 'Pa$$w0rd123' ;
GO
When you use contained database users, you need to take a number of additional security considerations into account. First, some applications may require a user have permissions to multiple databases. If the user is mapped to a Windows user or group, then this is straightforward because the SID that is being authenticated is that of the Windows object. If the database user is using second-tier authentication, however, then you need to duplicate the user’s SID from the first database. To do this, you need to adhere to the following steps:
Create a user with password in the first database .
Retrieve the user’s SID from sys.database_principals.
Create the user in additional databases, specifically supplying the SID that you have recovered from the metadata.
The sys.database_principals catalog view exposes the columns detailed in Table 2-9.
Table 2-9. sys.database_principals Columns
Column | Description |
---|---|
name | The name of the security principal. |
principal_id | The id of the security principal. This id is only unique within the database. |
type | A single-character abbreviation of the type description. |
type_desc | A description of the type of security principal. The following are possible values: • APPLICATION_ROLE • CERTIFICATE_MAPPED_USER • EXTERNAL_USER • WINDOWS_GROUP • ASYMMETRIC_KEY_MAPPED_USER • DATABASE_ROLE • SQL_USER • WINDOWS_USER • EXTERNAL_GROUPS |
default_schema_name | The name of the principals default schema. |
create_date | The date and time that the principal was created. |
modify_date | The date and time that the principal was last modified. |
owning_principal_id | The id of the security principal that is marked as the owner of the principal. This is 1, which is the dbo id for all principals except database roles. |
sid | The SID of the security principal. |
is_fixed_role | Indicates if the principal is a fixed database role. • 1 indicates that the principal is a fixed database role • 0 indicates that the principal is not a fixed database role |
authentication_type | Indicates how the principal authenticates to the database. The following are the possible values: • 0 indicates No authentication • 1 indicates Instance authentication • 2 indicates Database authentication • 3 indicates Windows authentication |
authentication_type_desc | A textual description of the authentication type. The following are the possible values: • NONE • INSTANCE • DATABASE • WINDOWS |
default_language_name | The name of the default language assigned to the principal |
default_language_lcid | The lcid of the default language assigned to the principal |
Listing 2-12 demonstrates how to generate a list of usernames and SID for users with a password in the AdventureWorks2016 database.
Listing 2-12. Retrieve SIDs for Users with a Password
USE AdventureWorks2016
GO
SELECT
name
,sid
FROM sys.database_principals
WHERE authentication_type = 2 ;
Database Roles
SQL Server provides a set of built-in database roles. These roles allow you to assign database-level permissions to users that have common requirements. They are called fixed database roles. It is not possible to change the permissions that are granted to them; you can only add and remove users to and from the roles. Table 2-10 describes each of these roles.
Table 2-10. Fixed Database Roles
Role | Description |
---|---|
db_accessadmin | Members of this role can add and remove database users from the database. |
db_backupoperator | The db_backupoperator role gives users the permissions they need to back up the database, natively. It may not work for third-party backup tools, such as CommVault or Backup Exec, since these tools often demand sysadmin rights. |
db_datareader | Members of the db_datareader role can run SELECT statements against any table in the database. It is possible to override this for specific tables by explicitly denying a user, the permissions to read those tables. DENY always overrides GRANT. |
db_datawriter | Members of the db_datawriter role can perform DML (data manipulation language) statements against any table in the database. It is possible to override this for specific tables by specifically denying a user the permissions to write to a table. DENY always overrides GRANT. |
db_denydatareader | The db_denydatareader role denies the SELECT permission against every table in the database. |
db_denydatawriter | The db_denydatawriter role denies its members the permissions to perform DLM statements against every table in the database. |
db_ddladmin | Members of this role are given the ability to run CREATE, ALTER, and DROP statements against any object in the database. This role is rarely used, but I have seen a couple of examples or poorly written applications that create database objects on the fly. If you are responsible for administering an application such as this, then the ddl_admin role may be useful. |
db_owner | Members of the db_owner role can perform any action within the database that has not been specifically denied. |
db_securityadmin | Members of this role can GRANT, DENY, and REVOKE a user’s permissions to securables. They can also modify role memberships, with the exception of the db_owner role. |
In addition to the fixed roles, it is also possible to create your own user-defined database roles. This simplifies administration by allowing DBA s to create roles that map to requirements of business teams that use a specific database. For example, an administrator of the AdventureWorks2016 database may create a role for salespeople, a role for the procurement department, and a role for the manufacturing department.
The script in Listing 2-13 demonstrates how to create the role for the sales team. The role is granted SELECT, INSERT, and UPDATE permissions on the Sales schema of the AdventureWorks2016 database. The Danni user is a member of the role. The role is called SalesRole and owned by dbo.
Listing 2-13. Create SalesRole
USE AdventureWorks2016
GO
--Create the role
CREATE ROLE SalesRole AUTHORIZATION dbo ;
GO
--Grant permissions to the role
GRANT DELETE ON SCHEMA::Sales TO SalesRole ;
GRANT INSERT ON SCHEMA::Sales TO SalesRole ;
GRANT SELECT ON SCHEMA::Sales TO SalesRole ;
GRANT UPDATE ON SCHEMA::Sales TO SalesRole ;
--Add user to the role
ALTER ROLE SalesRole ADD MEMBER Danni ;
Summary
SQL Server provides a flexible hierarchy to implement security. Role-based security is available out of the box. Database administrators should embrace this ability to simplify the administration of security.
The database engine supports two methods of authentication: Windows authentication and SQL Server authentication. The latter is SQL Server’s implementation of second-tier authentication. Windows authentication should be used—unless there is a good reason not to—because it is more secure.
Database engine users typically authenticate to the instance via a login. This login then maps to users within the databases that they require access to. It is also possible for users to authenticate directly to a database. This is known as a user without a login. When a user without a login is implemented, they can authenticate via Windows authentication, or if the database is contained, then SQL Server authentication can alternatively be used.