Windows Management and Scripting

A wealth of tutorials Windows Operating Systems SQL Server and Azure

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 721 other subscribers
  • SCCM Tools

  • Twitter Updates

  • Alin D

    Alin D

    I have over ten years experience of planning, implementation and support for large sized companies in multiple countries.

    View Full Profile →

Posts Tagged ‘Microsoft SQL Server’

How decrease SQL Server 2008 R2 With Sysprep Utility

Posted by Alin D on January 22, 2012

The release of SQL Server 2008 R2 brings us a feature unheard of in the SQL Server world – the ability to deploy an image of a server with SQL Server already installed. This is done using a feature that has been available through Windows for many years called Sysprep.

Sysprep allows the administrator to remove all the accounts, computer names and security identifiers (SID) from a computer and create an image. This image can then be deployed to physical or virtual machines. When the new machine boots up, it asks for various pieces of information such as the computer and Windows domain name and the networking settings – much of which can be configured as part of the Sysprep process.

If done correctly, after the image is deployed the only question that needs to be asked when the new machines boots up is, “What’s the computer’s name?” Every other setting can be preconfigured via the Sysprep process.

With SQL Server 2008 R2 we can now pre-configure the SQL Server components on the base image, allowing the SQL Server to be configured via Sysprep after the machine has been deployed. You’ll probably find this most useful when deploying virtual machines that have SQL Server on them, as this is where the bulk of Sysprep-oriented servers are being deployed.

Sysprep step-by-step

A SQL Server 2008 R2 installation is broken down into two separate processes: preparing the image and completing the image. During the first step the binaries are installed, while during the second step the computer, network and account-specific information are configured. When installing SQL Server normally, both of these steps are completed by the installer. On the other hand, when using Sysprep to deploy an image with SQL Server on it, only the prepare step is completed. The complete step is done by the Sysprep process after the image has been deployed to the new machine.

When deploying an image with Sysprep, not all of the SQL Server components can be installed. You can only install the SQL Server database engine and the Reporting Services components. The SQL Server Browser and SQL Server Writer services will be prepared automatically when the instance is completed.

After selecting the features you wish to install, you’ll be able to configure the instance name and instance path. You’ll then move through a couple more screens while you verify there is enough drive space and that you have set your installation options correctly. At this point, the installer will install the binaries to the server and exit.

Once the installer has exited, the machine can be configured with the Sysprep tool. While you can’t choose to install the Browser, Writer or SQL Native Client, they will be installed automatically once the instance is complete.

There are two ways to complete the installation once the image has been deployed. First, you can follow this path:

Start menu > Programs > Microsoft SQL Server 2008 R2 > Configuration Tools > “Complete SQL Server 2008 Installation”

The other option is to launch the installer from the SQL Server 2008 R2 DVD, navigate back to the Advanced tab and click the “Image completion of a prepared stand-alone instance of SQL Server” option on the right side. In either case you’ll effectively be walked through the rest of the installation wizard to complete the installation.

When you install using non-express SQL Server 2008 R2 media, the Evaluation Edition is used. This mandates a product key during the complete phase of the process. Note that if you select the Evaluation Edition, the timer will be set to expire 180 days after the wizard is completed.

The shortcomings of Sysprep

There are some specific limitations to using Sysprep to install SQL Server 2008 R2:

  • SQL Server cannot be installed on a failover cluster.
  • Tools cannot be installed via the Sysprep process.
  • Computers that use Itanium processors do not support the Sysprep process.
  • Repairing an instance that is prepared is not supported, so if the setup process fails the instance must be uninstalled and reinstalled.
  • If an instance is installed that is older than Microsoft SQL Server 2008 R2, you cannot prepare the instance via Sysprep. Install the older instances after the instances that have been installed are completed.
  • 32-bit editions cannot be installed on a 64-bit server using the Windows on Windows (WOW) 64 feature when preparing the server for deployment using Sysprep.
  • If you need to uninstall the instance either before or after the completion process has taken place, it can be completed through the Program and Features icon within the control panel.

That’s about it. As you can see though, using the Sysprep deployment feature can greatly increase the speed with which new SQL Server 2008 R2 servers can be deployed in either physical or virtual environments.

In order to install a SQL Server instance using Sysprep, launch the SQL Server 2008 R2 installer like normal, but instead of choosing the Installation menu option on the left, choose the Advanced option. Then select the “Image preparation of a stand-alone instance of SQL Server” option on the right. This will open a shortened wizard that will ask you which services to install and where to put them. You will notice that when you get to the feature selection page there are a few less options, as you can only select from the database engine, SQL Server replication, full-text search and Reporting Services. Any other features you wish to set up need to be installed once the image has been deployed.

Posted in SQL | Tagged: , , , , , , | Leave a Comment »

Password security in SQL Server part 2

Posted by Alin D on June 20, 2011

In our first part we have discussed about the SQL Server Password Security which is the first part of securing SQL Server 2008 R2.

Encrypting Client Connection Strings

 

While using Windows authentication is the best way to connect to the database server, this isn’t always possible because the client machine that is connecting to the database server may not be connected do the Windows Domain.

This is most often the case when the web server is located in a DMZ network and the database server is located within the internal network as shown in Figure below.


In a case like this, the application development team should take extra care to secure the web server’s connection string. Without this extra protection, someone could break into the web server and find the database server’s connection information sitting in the web.config file and simply log into the database using the username and password, which are stored in plain text in the configuration file. One great technique to do this is to have the web application on startup read the web.config file looking for an unencrypted connection string. Then read that string into memory, delete that node from the web.config file’s XML, and then add a new node labeled as being the encrypted string, encrypt the string, and place the encrypted string within the XML document, saving it when done. On subsequent loads of the XML file, the unencrypted connection string would not be found, and the application would then load the encrypted version, decrypting it in memory, thereby making it much, much harder for someone who has broken into the SQL Server to find any useful connecting string information. If you don’t want to give the web application access to write to the web.config file (as this would technically be a security hole unto itself), the application team could create a small standalone app that takes the normal connection string and outputs an encrypted value, which the SA could then put within the web.config file during deployment of the application by the SA team.

SQL Reporting Services

SQL Reporting Services does an excellent job of protecting the connection information to the repository databases, as well as the connection strings that the reports use to connect to the source databases. All database connection strings that are used by SQL Reporting Services are encrypted and stored within the web.config as the encrypted string. Within the SQL Server Reporting Services database, typically named ReportServer, all the connection information that the reports use to connect to the

source databases is also stored as an encrypted value. Both of these encrypted values together form a very secure platform that makes it very difficult for an attacker to exploit the SQL Server Reporting Services platform to get any useful information from the database holding the Reporting Server catalog database, or the source data; getting access to the source data via the data stored within the SQL Server Reporting Service repository would require decrypting two layers of information.

 

Application Roles

When using Windows Authentication, there is an unfortunate side effect that needs to be considered: The user can now log into the database using any Open Database Connectivity (ODBC) based application such as Microsoft Access, Microsoft Excel, and SQL Server Management Studio, and they have the same rights that they would have if they were logged in via the application. If the user logs into the database by supplying the SQL Login username and password, this name risk is there. However, if the application contains the username and password hard coded within the application, then the user won’t have this ability as they will not have the username and password. This is probably something that you don’t want to happen. Before you go and switch all your applications to using SQL Authentication and hard coding the password within the application, there’s another solution that gives you the best of both worlds. This solution is to use an application role.

The application role is not a very well-understood, and therefore not very frequently used, security feature of Microsoft SQL Server, which allows a user to authenticate against the Microsoft SQL Server Instance, but not have any specific rights

within the database. The rights to perform actions are granted to the application role, which would then need to be activated by the application before the user would be able to perform any actions.

Application roles are created by using the sp_addapprole system stored procedure in SQL Server 2000 and below or by using the CREATE APPLICATION ROLE statement in SQL Server 2005 and above. The application role has its own password that is used to ensure that only authorized applications are able to activate the application. The application role is activated by using the sp_setapprole system stored procedure, and then the application role is deactivated by using the sp_unsetapprole system stored procedure, or by simply closing the connection to the database engine.

Here is sample code using the sp_addapprole system stored procedure and CREATE APPLICATION ROLE statement to create an application role:

EXEC sp_addapprole @rolename=’MyAppRole’, @password=’MyPa$$word’

CREATE APPLICATION ROLE MyAppRole WITH PASSWORD=’MyPa$$word’

The sp_setapprole system stored procedure has four parameters that are of interest. The first and second parameters are the @rolename and @password parameters to which you supply the name and password that were specified when you created the

application role. The third parameter is the @fCreateCookie parameter, which is a bit parameter and tells the SQL Server if it should create a cookie when the application role is activated (I’ll explain the cookies in a moment). The fourth parameter is

the @cookie parameter, which is a varbinary(8000) and stores the cookie that was created if the @fCreateCookie parameter was set to 1.

The @cookie parameter stores a cookie much in the same way that your web browser stores cookies when you browse the web, so that it can correctly identify the session that was used to activate the application role. Thus, when the application role is

disabled, the SQL Server knows which session state to return the user’s session to. If you don’t plan to unset the application role and will simply close the connection to the SQL Server, then you don’t need to set a cookie and can simply set the @fCreate Cookie password to 0 telling the SQL Server to not create the cookie.

In the sample code shown in next example, I created a new database, and then we create an application role within that database. We then create a table within the database, as well as a user within the database. We next give the application role access to select data from the table. We then use the EXECUTE AS statement to change your execution context from that of our user to that of the user, which we just created and has no rights. Next we query the table, which returns an error message to us. After that we switch to using the application role and try and query the table again, this time receiving the output as a recordset. We then unset the application role using the cookie that was created by the sp_setapprole system stored procedure.

We then use the REVERT statement so that we are no longer executing code as our MyUser database use, after which we drop the sample database.

USE master

GO

IF EXISTS (SELECT * FROM sys.databases WHERE name =’AppRoleTest’)

DROP DATABASE AppRoleTest

GO

CREATE DATABASE AppRoleTest

GO

USE AppRoleTest

GO

CREATE APPLICATION ROLE MyAppRole WITH PASSWORD=’MyPa$$word’

GO

CREATE TABLE MyTable

(Col1 INT)

GO

CREATE USER MyUser WITHOUT LOGIN

GO

GRANT SELECT ON MyTable TO MyAppRole

GO

DECLARE @cookie varbinary(8000)

EXECUTE AS USER = ‘MyUser’

SELECT * FROM MyTable

EXEC sp_setapprole @rolename=MyAppRole, @password=’MyPa$$word’, @cookie=@cookie OUTPUT, @fCreateCookie=1

SELECT * FROM MyTable

EXEC sp_unsetapprole @cookie=@cookie

REVERT

GO

USE master

GO

DROP DATABASE AppRoleTest

GO

 

When we run this script as shown in text output mode from within SQL Server Management Studio, we see the output shown in next image. The first SELECT statement that we issued was rejected because the user didn’t have rights to the table dbo.MyTable in the AppRoleTest database. However, the second SELECT statement that we issued after we set the Application Role was accepted by the database, and the contents of the table were returned.

You can now see how use of the application role can enable the use of the very secure Windows authentication without requiring that the user’s Windows account actually have rights to access any objects within the database directly, but the application

can run once the application role has been activated.

 

Another technique that can be used along the same lines of the application role is to create a user with no attached login
and use the EXECUTE AS statement to run commands as that user. While this will allow you to run all your

statements without the user needing to have rights to the database objects, the problem with this technique is that any logging that is done via the username functions returns the dummy user that you created and not the login of the actual

user. This is shown along with sample code in next image As you can see in the sample code, we create a dummy user, then output my username using the SUSER_SNAME() system function, then switch to running under the context of the MyUser

database user, and then output the value of the SUSER_SNAME () function again with the output being the SID of the MyUser database user account. You can’t even query the dynamic management views to get the correct username of the user

logged in, because once the EXECUTE AS has been executed, the dynamic management views show the SID of the user instead of the name of the login that was originally connected to the database.

When using an application role, you don’t have the database username return problem when using the system functions or the dynamic management views.

 

How to use Windows Domain Policies to enforce password length

 

Starting with Microsoft SQL Server 2005, Microsoft introduced a new level of password security within the product, as this was the first version of Microsoft SQL Server that could use the domain policies to ensure that the passwords for the SQL

Authentication accounts were long enough and strong enough to meet the corporate standards as set forth by the SAs. By default, all SQL Authentication accounts created within the SQL Server instance must meet the domain password security policies. You can, if necessary, remove these restrictions by editing the SQL Authentication account. Within the Microsoft SQL Server, two settings can be applied to each SQL Authentication Login, which are shown in next screenshot.

  1. The “Enforce password policy” setting tells the SQL Server engine to ensure that the password meets the needed complexity requirements of the domain, and that the password hasn’t been used within a specific number of days, which is defined within the domain policy, and is explained later in this article.


  2. The “Enforce password expiration” setting tells the SQL Server that the password for the SQL Authentication Login should have expired based on the domain settings. The “User must change password at next login” option, shown disabled in the image above, will only become available when the logins password is manually reset and the “Enforce password policy” setting is enabled for the login. Allowing the SQL Server to ensure that your passwords meet your domain policies has some distinct advantages, especially when it comes to auditing. Without this ability you would need to physically check each SQL server password to ensure that It meets the corporate standards when the Auditor asks you if all your SQL Authentication passwords meet the corporate standards. In a worst case situation, this would require that you either keep a list of all the usernames and passwords somewhere (which would probably cause you to fail the audit) or you would need to contact each person that uses the SQL Authentication login and ask them how long the password is, and if it meets the company policies, and so on. Now with this feature built into the product, a quick and simple SQL query is all that it takes to verify the information.

Querying the sys.sql_logins catalog view will show you any logins that may not meet the domain password policies:

SELECT name, is_policy_checked FROM sys.sql_logins

 

While the T/SQL shown in next example works great for a single SQL Server, if there are dozens or hundreds of SQL Servers that need to be verified, a T/SQL script may not be the best way to check all those servers. In this case a Windows PowerShell script may be more effective. Within the Windows PowerShell script shown in next example, the SMO (Server Management Object) is used to get a list of all the available instances on the network.

After this list has been returned from the network, SMO is used to return the SQL Logins along with the value of the PasswordPolicyEnforced setting.

Example: “Using SMO to return the PasswordPolicyEnforced setting for all SQL Logins for all SQL Server Instances available on the network.”

[System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.SqlServer.Smo’) j out-null

foreach ($InstanceList in [Microsoft.SqlServer.Management.

Smo.SmoApplication]::EnumAvailableSqlServers())

{

$InstanceList;

$instanceName ¼ $InstanceList.Name;

$instanceName;

$SMOserver ¼ New-Object (‘Microsoft.SqlServer.Management.

Smo.Server’) $instanceName

$db ¼ $SMOserver.Logins j where-object {$_.loginType -eq

“sqllogin”} j select name, PasswordPolicyEnforced

$db;

}

 

By setting the is_policy_checked flag to true (shown as the number 1 when you run the sample query), this tells you that any password that is assigned to the SQL Authentication Login must meet the password requirements of the domain. Expanding on the query shown in Example “By setting the is_policy_checked flag, this tells you that any password that is assigned to the SQL Authentication Login must meet the password requirements of the domain. Expanding on the query shown in the example above SQL Server Reporting Services report could be configured that runs against each SQL Server in the environment, giving a simple report that can be run as needed for auditing purposes.

When you have the is_policy_checked flag set to true, there are several domainwide settings that will be evaulated each time the password is changed. These policies can be found by editing the Group Policy Object (GPO) on the domain that holds these, an SQL Server Reporting Services report could be configured that runs against each SQL Server in the environment, giving a simple report that can be run as needed for auditing purposes.

When you have the is_policy_checked flag set to true, there are several domainwide settings that will be evaulated each time the password is changed. These policies can be found by editing the Group Policy Object (GPO) on the domain that holds these

settings, or by editing the local security policies for the server in question if that server is not a member of a Windows domain. While you can set these settings on a server that is a member of the domain, doing so won’t have any effect as the domain policies but will overwrite any local settings you have set.

If all the SQL Server Instances that need to be polled are registered within SQL Server Management Studio, this select statement can be run against all the instances at once returning a single record with all the needed information. This can be done by opening the registered servers panel within SQL Server management studio by clicking on the View dropdown menu and then the “Registered Servers” menu item. Right click on the folder that contains the SQL Server Instances you want to execute the query against and select “New Query” from the context menu that opens. This opens a new query window which, when executed, will execute the query against all the servers that are within the registered servers folder with all the data from all the servers being returned as a single recordset.

SQL Server Management Studio will automatically add in a new column at the beginning of the recordset, which contains the name of the instance; this will allow you to use the same query shown in Example 3.4 against all the SQL Servers at once and

giving back a single recordset that can be reviewed or handed off as needed.

Windows Authentication Group Policies

There are a total of six policies that you can set within Windows that affect the domain or local password policy. However, Microsoft SQL Server only cares about five of them. The policy with which the SQL Server is not concerned is the “Store

passwords using reversible encryption” policy. This policy tells Windows if it should store the user’s password using a two-way encryption process, instead of a one-way hash. Enabling this policy presents a security vulnerability on your domain as an

attacker could download the list of all users and passwords, then break the encryption on the passwords and have full access to every user’s username and password. Due to the security issues with this setting, the setting is disabled by default and should

remain so unless there is a specific reason to enable it. The typical reasons to enable it include using Challenge Handshake Authentication Protocol (CHAP) through Remote Access or Internet Authentication Services (IAS). It is also required if one or

more Internet Information Service (IIS) servers within the Windows Domain are using Digest Authentication.

The five password policies that the SQL Server does recognize and follow are the following:

  1. Enforce password history;
  2. Maximum password age;
  3. Minimum password age;
  4. Minimum password length;
  5. Password must meet complexity requirements.

Each of these settings has a specific effect on what the passwords can be set to and should be fully understood before changing the password of an SQL Authentication Login. The “Enforce password history” setting on the domain (or local computer) is not a boolean, although the name sounds as though it would be. It is in fact the number of old passwords for the account that the SQL Server should track so that passwords cannot be reused. The setting has a valid range of 0 (or no passwords) to 24 passwords. The more passwords that are kept, the greater the chance that the user will forget their password, but the lesser the chance that someone will break into the system via an old password. The default on the domain is 24 passwords.

The “Maximum password age” setting tells the SQL Server howmany days a password is valid. After this number of days has passed since the last password change, the user will be prompted to change the password. If the password is not changed, the user will not be able to log into the database instance. This setting accepts a value from 0 (never expires) to 999 days, with a default value of 42 days. The “Minimum password age” setting tells the SQL Server how many days from the time a password has been changed until it can be changed again. This setting prevents the user from rapid-fire changing their passwords to eat up the number of passwords specified by the “Enforce password history” setting. Without this setting, or with this setting set to 0, when the user’s password expires, the user can simply change the password 24 times and then change it to the same password that it was before effectively breaking the password requirement feature. This setting accepts a value from 0 (allows immediate password changes) to 998 days, with a default value of 1; however, this setting has a practical upper limit of one day lower than the setting for the “Maximumpassword age.” If you were to set this setting to the same value or higher than

the “Maximumpassword age” setting, then the users wouldn’t ever be able to login until after their passwords had expired. The “Minimum password length” setting tells the SQL Server how many characters need to be in the password for the password

to be acceptable. This setting can be any value from 0 (allowing a blank password) to 14 characters, with a default value of 7 characters. It is typically recommended to increase this value from the default of 7 to a higher number such as 9 characters.

While this will make the password harder for the user to remember, it will also make it exponentially harder for an attacker to guess. The “Password must meet complexity requirements” setting tells the SQL Server that all passwords must be considered

“strong” passwords. There are several requirements to having a strong password beyond what one would normally consider. By default this setting is enabled.

1. The password cannot contain the username within it.

2. The password must be at least six characters in length.

3. The password must contain characters from at least three of these four categories:

a. Lower-case letters (a through z);

b. Upper-case letters (A through Z);

c. Numbers (0 through 9);

d. Symbols ($, #, @, %, ^ for example).

When you enable the “Enforce password policy” setting for an SQL Authentication Login, this enforces the “Enforce password history,” “Minimumpassword length,” and “Password mustmeet complexity requirments” settings against that login. When you enable the “Enforce password expiration” setting for an SQL Authenticaiton Login, this enforces the “Maximum password age” and the “Minimum password age” settings against that login. In order to enable the “Enforce password expiration”

setting against an SQL Authenticaiton login, you must also enable the “Enforce password policy” setting. However, you do not need to enable the “Enforce password expiration” setting if you enable the “Enforce password policy” setting.

When working on an SQL Azure database, the login mustmeet the password complexity settings that Microsoft has defined. As of the summer of 2010, this means that the password must be 8 characters in length, and meet the complexity requirements

shown above. There is no way to configure a login to an SQL Azure instance to not meet these requirements, for the SQL Azure instances do not support using the check_policy parameter to disable the policy checking.

Summary

One of the biggest problems in today’s IT world is that once you have created your nice secure passwords, how do you track them? Those usernames and passwords are probably going to be documented somewhere, typically within an Excel sheet that is kept on a network share so that all the database administrators within the group have quick and easy access to them. However, by doing this you now have placed all the passwords that you have taken the time to ensure that are strong and secure within your web.config and app.config files are easily readable and usable by anyone who has access to the network share. Typically, not just the database administrators would have access to the network share. In addition to the database administrators, the SAs, backup software, and monitoring system would all have access to the network share. And this is in addition to whoever has found the lost backup tape for your file server. In other words, be sure to store that password list in a nice, safe place and not in the public arena available to everyone to read and network share.

 

Posted in SQL | Tagged: , , , , , , | Leave a Comment »

Password security in SQL Server part 1

Posted by Alin D on June 20, 2011

SQL Server Password Security

One of the key ways to protect your SQL Server is to use strong, secure passwords for your SQL Server login accounts. One of the biggest security holes in the SQL Server 2000 and olderversions of Microsoft SQL Server was that the server installed with a blank system administrator (SA) password by default and would allow you to use a blank password, thereby permitting anyone to connect without much work at all. Even with newer versions of Microsoft SQL Server, the SA account is still a potential weakness, as is any SQL Server Authentication based login. This is because SQL Accounts can be easily broken into by brute force password attacks. When using SQL Azure there is no SA account available to you the Microsoft customer work with. The SA account is reserved for the exclusive use of Microsoft.

When using SQL Azure as your database instance, only SQL Authentication is available. SQL Azure doesn’t support Windows Authentication for use by Microsoft’s customers as the SQL Azure database server doesn’t support being added to a company domain. The Azure database servers do support Windows Authentication buy only for use by the Azure administration team

within Microsoft. SQL Authentication Logins aremore susceptible to these login attacks than a Windows Authentication login because of the way that these logins are processed. With an SQL Authentication login, each connection to the SQL database passes the actual username and password from the client computer to the SQL Server Engine. Because of this, an attacker can simply sit there passing usernames and passwords to the server until a connection is successfully made.

With a Windows Authentication Login the process is much, much different from the SQL Authentication process. When the client requests a login using Windows Authentication, several

components within the Windows Active Directory network are needed to complete the request. This includes the Kerberos Key Distribution Center (KDC) for when Kerberos is used for

authentication, and the Windows Active Directory Domain Controller for when NTLM (NT LAN Manager) authentication is used. The Kerberos KDC runs on each domain controller within

an Active Directory domain that has the Active Directory Domain Services (AD DS) role installed.

The process that occurs when a Windows Authentication connection is established is fairly straightforward once you know the components that are involved. When the client requests

a connection, the SQL Server Native Client contacts the KDC and requests a Kerberos ticket for the Service Principal Name (SPN) of the Database Engine. If the request to the KDC fails, the SQL Server Native Client will then try the request for a ticket again using NTLM Authentication. This ticket will contain the Security Identifier (SID) of the Windows domain account, as well as the SIDs of the Windows groups that the domain account is a member of.

Once the SQL Server Native Client has received the ticket from the KDC, the ticket is passed to the SQL Server service. The SQL Server then verifies the ticket back against the Kerberos

or NTLM server service on the domain controller to verify that the SID exists and is active, and was generated by the requesting computer. Once the Windows ID is confirmed against the domain, the SIDs for the local server groups that the user is a member of are added to the Kerberos ticket and the process within the SQL Server is started. If any of these checks fail, then the connection is rejected. The first thing that the SQL Server will verify is if there is a Windows Authenticated login that matches the user. If there is no specific Windows login, the SQL Server then checks to see if there is a Windows Domain Group or Windows Local Group to which the user belongs. The next check is to see if the login or domain group that has the login as a member is enabled and has been granted the right to connect. The next check is to ensure that the login or domain group has the right to connect to the specific endpoint. At this point the Windows Login has successfully connected to the SQL Server Instance. The next step in the process is to assign the Login ID of the Windows Login as well as any authorized domain groups. These login

IDs are put together within an internal array within the SQL Server engine to be used by the last step of the authentication process as well as various processes as the user interacts with the objects within the SQL Server databases. The last step of the connection process takes the database name that was included within the connection string (or the login default database if no connection string database is specified) and checks if any of the login IDs contained with the internal array that was just created exist within the database as a user. If one of the login IDs exists within the database, then the login to the SQL Server is complete. If none of the login IDs exist within the database and the database has the guest user enabled, then the user will be connected with the permission of the guest user. If none of the login IDs exist within the database and the guest login is not enabled, then the connection is rejected with a default database specific error message.

Extended Protection

 

Expended Protection is a feature of the Windows operating system that was introduced with the release of Windows 2008 R2 and Windows 7. This new feature provides an additional

level of preauthentication protection for client-to-server communications when both the client and server software support it. As of the writing of this book, the only version of the

Microsoft SQL Server product that supports this new feature is Microsoft SQL Server 2008 R2. Patches are available from the website http://www.microsoft.com/technet/security/advisory/

973811.mspx for the older Operating Systems. This new feature enhances the protection that already exists when authenticating domain credentials using Integrated Windows

Authentication (IWA).

When Extended Protection is enabled, the authentication requests are both to the Service Principal Name (SPN) of the server which the client application is connecting to, as well as

to the outer Transport Layer Security (TLS) channel within which the IWA takes place. Extended Protection is not a global configuration; each application that wishes to use Extended

Protection must be updated to enable the use of Extended Protection.

If you are using Windows 7 and Windows Server 2008 R2 or later for both the client and server and if the SQL Server 2008 R2 Native Client or later are being used to connect to an SQL Server

2008 R2 SQL Server or later instance, and Extended Protection is enabled, then Extended Protection must also be negotiated before the Windows process can be completed. Extended Protection uses two techniquesdservice binding and channel bindingdin order to help prevent against an authentication relay attack.

Service Binding is used to protect against luring attacks by requiring that as part of the connection process, the client sends a signed Service Principal Name (SPN) of the SQL Server service

to which the client is attempting to connect. As part of the response, the server then validates that the SPN that was submitted by the client matches the one that the server actually

connected to. If the SPNs do not match, then the connection attempt is refused.

The service binding protection works against the luring attack as the luring attack works by having another service or application (such as Outlook, Windows Explorer, a .NET application, etc)

connect to a separate valid compromised connection (such as a file server or Microsoft Exchange server). The attacking code then takes the captured signed SPN and attempts to pass it to the

SQL server to authenticate. Because the SPNs do not match and the signed SPN is for another service, the connection to the SQL Server from the compromised server is rejected. Service binding requires a negligible one-time cost as the SPN signing happens only once when the connection is being made.

The channel binding protection works by creating a secure channel between the client and the SQL Server Instance. This is done by encrypting the connection using Transport Layer Security

(TLS) encryption for all of the traffic within the session. The protection comes by the SQL Server Service verifying the authenticity of the client by comparing the client’s channel binding token (CBT) with the CBT of the SQL Service. This channel binding protects the client from falling prey to both the luring and the spoofing attacks. However, the cost of this protection is much higher because of the TLS encryption, which must be maintained over the lifetime of the connection.

To enable Extended Protection, you first need to decide whether you wish to use service binding protection or channel binding protection. In order to use channel binding, you must force encryption for all SQL Server connections. With SQL Server encryption disabled, only service binding protection is possible.

Extended Protection is enabled from within the SQL Server 2008 R2 Configuration Manager for all editions of the Microsoft SQL Server 2008 R2 database engine. Within the SQL Server

Configuration Manager select “SQL Server Services” from the left hand pane and double click on the SQL Server Service you wish to enable Extended Protection for on the right, selecting the

Advanced tab from the window that pops up. The Extended Protection option has three values from which you can select. The setting of “Off” will disable Extended Protection and will allow

any connection whether or not the client supports Extended Protection. The setting of “Allowed” forces Extended Protection from Operating Systems which supported Extended Protection,

while allowing Operating Systems, which do not support Extended Protection to connect without error. The setting of “Required” will tell the SQL Server to accept from client computers only those connections that have an Operating System that supports Extended Protection. If your SQL Server has multiple Service Principal Names (SPNs) requested within the Windows domain, you will need to configure the Accepted NTLM SPNs setting. This setting supports up to 2048 characters and accepts a semicolonseparated list of the SPNs that the SQL Server will need to accept.

As an example, if the SQL Server needed to accept the SPNs MSSQLSvc/ server1.yourcompany.local and MSSQLSvc/ server2. yourcompany.local, then you would specify a value of “MSSQLSvc/server1.yourcompany.local;MSSQLSvc/server2.yourcompany.local” in the Accepted NTLM SPNs setting as shown in screenshot below.

After changing any of the Extended Protection properties, you will need to restart the SQL Server Instance for the settings change to take effect. As SQL Azure servers are not installed on Microsoft’s domain and not the company’s server, Extended Protection is not available when using SQL Azure.

Configuring the Accepted NTLM SPNs

Service Principal Names (SPNs) are unique service names within a Windows domain that uniquely identify an instance of a service regardless of the system that the service is running on, or

how many services are running on a single machine. While a single SPN can only reference a single instance of a service, a single instance of a service can havemultiple SPNs registered to

it. The most common reason for multiple SPNs for a service would be that a service needs to be accessed under multiple server names. Before an SPN can be used by Kerberos authentication, it must be registered within the Active Directory. The SPN when created is registered to a specific account within the domain. The account to which the SPN is registered must be the one under which the Windows service will be running. Because an SPN can only be registered to a single service, this means that an SPN can only be registered to a single Windows account. If the account will be running Windows service changes, then the SPN must be removed from the original account and assigned to the new account. When the client software attempts to connect using Kerberos authentication, the client locates the instance of the service and creates the SPN for that service. The client software then connects to the remote service and presents the created SPN for the service to authenticate. If the authentication fails, the client disconnects returning an error message to the end user. The client computer is able to create an SPN for the remote

service very easily as the format for an SPN is very simple. The format for an SPN is <service class>/ <host>: <port>/ <servicename>. The <service class> and <host> values are required

while the <port> and <service name> values are optional. In the case of Microsoft SQL Server the <service class> value will be MSSQLSvc, while the <host> value will be the name that the

client computers will use to connect to the SQL Server. As an example, for an SQL Server instance listening on the default TCP port 1433 on a server named DB1.contoso.local and a

Windows account named CONTOSOsqlserver would look like “MSSQLSvc/DB1.contoso.local:1433/CONTOSOsqlserver”.SPNs are created automatically when the SQL Service starts up, but

only for the default name under which the service will be running. Typically this would be the name of the SQL Server. Other SPNs can be manually registered as needed by a member of the

“Domain Administrators” group by using the setspn command line application with the -A switch followed by the SPN that should be created. If the DB1.contoso.local server needed to also support the name mydatabase.contoso.local, then the command as shown in Example bellow would be used.

setspn -A MSSQLSvc/mydatabase.contoso.local:1433/CONTOSOsqlserver

Once the SPN has been created and the SPN has replicated to all the domain controllers, the clients will be able to successfully authenticate against the new SPN. This replication can take

anywhere from a few seconds to several hours, depending on how the domain replication is configured and the speed of the network links between sites. SPNs do not need to be used with SQL Azure instances as you must use SQL Authentication with SQL Azure, and SPNs are used when using Windows Authentication with Kerberos.

Posted in SQL | Tagged: , , , , , , , , , , , , , , , , , , , | 1 Comment »

How to speedup SQL Server 2008 R2 with Sysprep

Posted by Alin D on June 15, 2011

SQL Server 2008 LogoThe release of SQL Server 2008 R2 brings us a feature unheard of in the SQL Server world – the ability to deploy an image of a server with SQL Server already installed. This is done using a feature that has been available through Windows for many years called Sysprep.

Sysprep allows the administrator to remove all the accounts, computer names and security identifiers (SID) from a computer and create an image. This image can then be deployed to physical or virtual machines. When the new machine boots up, it asks for various pieces of information such as the computer and Windows domain name and the networking settings – much of which can be configured as part of the Sysprep process.

If done correctly, after the image is deployed the only question that needs to be asked when the new machines boots up is, “What’s the computer’s name?” Every other setting can be preconfigured via the Sysprep process.

With SQL Server 2008 R2 we can now pre-configure the SQL Server components on the base image, allowing the SQL Server to be configured via Sysprep after the machine has been deployed. You’ll probably find this most useful when deploying virtual machines that have SQL Server on them, as this is where the bulk of Sysprep-oriented servers are being deployed.

Sysprep step-by-step

A SQL Server 2008 R2 installation is broken down into two separate processes: preparing the image and completing the image. During the first step the binaries are installed, while during the second step the computer, network and account-specific information are configured. When installing SQL Server normally, both of these steps are completed by the installer. On the other hand, when using Sysprep to deploy an image with SQL Server on it, only the prepare step is completed. The complete step is done by the Sysprep process after the image has been deployed to the new machine.

When deploying an image with Sysprep, not all of the SQL Server components can be installed. You can only install the SQL Server database engine and the Reporting Servicescomponents. The SQL Server Browser and SQL Server Writer services will be prepared automatically when the instance is completed.

In order to install a SQL Server instance using Sysprep, launch the SQL Server 2008 R2 installer like normal, but instead of choosing the Installation menu option on the left, choose the Advanced option. Then select the “Image preparation of a stand-alone instance of SQL Server” option on the right. This will open a shortened wizard that will ask you which services to install and where to put them. You will notice that when you get to the feature selection page there are a few less options, as you can only select from the database engine, SQL Server replication, full-text search and Reporting Services. Any other features you wish to set up need to be installed once the image has been deployed.

After selecting the features you wish to install, you’ll be able to configure the instance name and instance path. You’ll then move through a couple more screens while you verify there is enough drive space and that you have set your installation options correctly. At this point, the installer will install the binaries to the server and exit.

Once the installer has exited, the machine can be configured with the Sysprep tool. While you can’t choose to install the Browser, Writer or SQL Native Client, they will be installed automatically once the instance is complete.

There are two ways to complete the installation once the image has been deployed. First, you can follow this path:

Start menu > Programs > Microsoft SQL Server 2008 R2 > Configuration Tools > “Complete SQL Server 2008 Installation”

The other option is to launch the installer from the SQL Server 2008 R2 DVD, navigate back to the Advanced tab and click the “Image completion of a prepared stand-alone instance of SQL Server” option on the right side. In either case you’ll effectively be walked through the rest of the installation wizard to complete the installation.

When you install using non-express SQL Server 2008 R2 media, the Evaluation Edition is used. This mandates a product key during the complete phase of the process. Note that if you select the Evaluation Edition, the timer will be set to expire 180 days after the wizard is completed.

The shortcomings of Sysprep

There are some specific limitations to using Sysprep to install SQL Server 2008 R2:

  • SQL Server cannot be installed on a failover cluster.
  • Tools cannot be installed via the Sysprep process.
  • Computers that use Itanium processors do not support the Sysprep process.
  • Repairing an instance that is prepared is not supported, so if the setup process fails the instance must be uninstalled and reinstalled.
  • If an instance is installed that is older than Microsoft SQL Server 2008 R2, you cannot prepare the instance via Sysprep. Install the older instances after the instances that have been installed are completed.
  • 32-bit editions cannot be installed on a 64-bit server using the Windows on Windows (WOW) 64 feature when preparing the server for deployment using Sysprep.
  • If you need to uninstall the instance either before or after the completion process has taken place, it can be completed through the Program and Features icon within the control panel.

That’s about it. As you can see though, using the Sysprep deployment feature can greatly increase the speed with which new SQL Server 2008 R2 servers can be deployed in either physical or virtual environments.

Posted in SQL | Tagged: , , , , , , | Leave a Comment »

SQL Server stored procedures and parameters in examples

Posted by Alin D on May 19, 2011

Microsoft included several hundred stored procedures in the various versions of Microsoft SQL Server and it has documented a good percentage of them. But many stored procedures remain undocumented. Some are used within the Enterprise Manager GUI in SQL 2000 and were not intended to be used by other processes. Microsoft has slated some of these stored procedures to be removed (or they have been removed) from future versions of SQL Server. While these stored procedures can be very useful and save you lots of time, they can be changed at any time in their function or they can simply be removed.

The chart below shows that while many of the procedures have been carried through from one version of Microsoft SQL Server to another, new stored procedures have been introduced, and some have been removed from the install package. Most, if not all, of the procedures require the user to be a member of the sysadmin fixed server role in order to execute the procedures. The stored procedures that interact with the file system also require that the user executing the procedure (as well as SQL Server’s service account) have access to the file/folder. 

  

Procedure Name

SQL 2000

SQL 2005

SQL 2008

sp_executeresultset

X

  

  

sp_MSforeachdb

X

X

X

sp_MSforeachtable

X

X

X

sp_readerrorlog

X

X

X

xp_create_subdir

  

X

X

Xp_delete_file

  

X

X

xp_dirtree

X

X

X

xp_fileexist

X

X

X

xp_fixeddrives

X

X

X

xp_getfiledetails

X

  

  

xp_getnetname

X

X

X

xp_loginconfig

X

X

X

xp_makecab

X

  

  

xp_msver

X

X

X

xp_get_mapi_profiles

X

X

X

xp_subdirs

X

X

X

xp_test_mapi_profile

X

X

X

xp_unpackcab

X

  

  

sp_executeresultset

Microsoft removed this handy little procedure called sp_executeresultset from SQL Server in SQL Server 2005. It allows you to generate dynamic SQL code on the fly by using a SELECT query. Then, the resulting SQL commands will be executed against the database. It permits you to create a single piece of code that can, in a single step, find the number of records in every table in your database (as the example shows). This is an undocumented stored procedure and there is no way of knowing why it was removed. But, alas, this handy utility is gone.

exec sp_execresultset ‘SELECT ”SELECT ””” + name + ”””,
count(*) FROM ” + name
from sysobjects
where xtype = ”U”’

sp_MSforeachdb / sp_MSforeachtable

Two procedures, sp_MSforeachdb and sp_MSforeachtable, are wrappers around a cursor. They allow you to execute T-SQL code against each database on your SQL Server and each table within the current database, respectively. You cannot, however, use an sp_MSforeachtable command within an sp_MSforeachdb command in SQL 2000 and prior. The cursor name that was used within those procedures was the same (hCForEach) and would therefore return an error saying that the cursor name was already in use for each execution of the sp_MSforeachtable. In SQL Server 2005, Microsoft resolved this issue. In order to “next” the command, you must tell one of the procedures it will be using a different replacement character other than the default question mark. I change the replacement character in the database command because it’s easier.

Print each table name in the current database.

exec sp_MSforeachtable ‘print ”?”’

Print each database on the current server.

exec sp_MSforeachdb ‘print ”?”’

Print each table on the current server.

exec sp_MSforeachdb ‘use [@] exec sp_MSforeachtable ”print
””@.?”””’, ‘@’

sp_readerrorlog / xp_readerrorlog

The stored procedure sp_readerrorlog actually comes in two forms. Each works the same; one is simply a wrapper for the second. The wrapper stored procedure is sp_readerrorlog and it calls xp_readerrorlog. Both have four input parameters, but only the first two are useful to us. The first parameter establishes the file number that you wish to view. The second is the log to view (1 or null for ERRORLOG, 2 for SQL Agent Log). This allows you to view your error logs quickly and easily instead of having to look at the bloated log viewer that now comes with SQL Server 2005 and SQL 2008.

View the current SQL ERRORLOG file.

exec sp_readerrorlog

exec sp_readerrorlog 0, 1

View the Prior SQL Agent Log file.

exec sp_readerrorlog 1, 2

xp_create_subdir

Introduced in SQL Server 2005, the xp_create_subdir stored procedure is very handy because you can use it to create folders on SQL Server’s hard drive or on a network share from within T-SQL.

exec xp_create_subdir ‘c:MSSQLData’

xp_delete_file

Use the xp_delete_file stored procedure introduced in SQL Server 2005 to delete files from SQL Server’s hard drive or a network share from within T-SQL.

xp_dirtree

The xp_dirtree procedure allows you to view the folder tree and/or file list beneath a folder. This procedure has several parameters that control how deep the procedure searches and whether it returns files and folders or folders only. The first parameter establishes the folder to look in. (Recommendation: Do not run this procedure against the root of the drive that Windows is installed on because it will take some time to generate the tree and return the data.) The second parameter limits the number of recursive levels that the procedure will dig through. The default is zero or all levels. The third parameter tells the procedure to include files. The default is zero or folders only, a value of 1 includes files in the result set. Specifying a third value not equal to zero will add an additional column to the output called file which is a bit field showing the entry in a folder or file.

Get the full directory tree.

exec xp_dirtree ‘d:mssql’

Get the first two levels of the directory tree.

exec xp_dirtree ‘d:mssql’, 2

Get the first three levels of the directory tree, including files.

exec xp_dirtree ‘d:mssql’, 3, 1

xp_fileexist

This SQL Server stored procedure, xp_fileexist, is used to determine if a file exists on SQL Server’s hard drive or on a network share. It is extremely useful in stored procedures that load data from flat files. It allows you to check and see if the file exists before attempting to blindly load the file. The procedure has two parameters. Use the first parameter to determine if the file or folder you want exists. The second is an output parameter, which when specified, returns a 1 or 0 if the file exists or does not.

Without the parameter.

exec xp_fileexist ‘c:importfile.csv’

With the parameter.

DECLARE @file_exists int
exec xp_fileexist ‘c:importfile.csv’, @file_exists OUTPUT
SELECT @file_exists

xp_fixeddrives

The procedure xp_fixeddrives is one of the most useful procedures. It presents a list of all drive letters and the amount of free space each drive has. The parameter has a single optional input parameter that can filter the results by drive type. A value of 3 will return all mass storage devices (CD-ROM, DVD, etc.); a value of 4 will return the hard drives; while a value of 2 will return removable media (USB thumb drives, flash drives, etc.).

Return all drives.

exec xp_fixeddrives

Return hard drives only.

exec xp_fixeddrives 2

xp_getfiledetails

The procedure xp_getfiledetails is another extremely useful procedure, which was last available in SQL Server 2000. This procedure returns size, date and attribute information about the file specified, including date and times created, accessed and modified.

exec xp_getfiledetails ‘c:filetoload.csv’

xp_getnetname

The procedure xp_getnetname returns the name of the physical machine where Microsoft SQL Server is installed. You can have the machine name returned as a record set or as a variable.

Without the parameter.

exec xp_getnetname

Using the parameter.

DECLARE @machinename sysname
exec xp_getnetname @machinename OUTPUT
select @machinename

xp_loginconfig

This SQL Server stored procedure will tell you some basic authentication information about the user executing it. It tells you the authentication method (Windows versus SQL Login), the default domain of the server, the audit level, as well as some internal separator information.

exec xp_loginconfig

xp_makecab

Back in SQL Server 2000, Microsoft gave us the ability to compress OS files directly from T-SQL without having to shell out to DOS via xp_cmdshell and run third-party software, like pkzip or winzip. That command was xp_makecab. It allows you to specify a list of files you want to compress as well as the cab file you want to put them in. It even lets you select default compression, MSZIP compression (akin to the .zip file format) or no compression. The first parameter gives the path to the cab file in which you want to create or add files to. The second parameter is the compression level. The third parameter applies if you want to use verbose logging. Starting with the fourth parameter and on down are the names of the files you want to compress. In my testing, I was able to pass 45 file names to be compressed to the extended stored procedure, which means that it is a very flexible solution to your data compression requirements.

exec xp_makecab ‘c:test.cab’, ‘mszip’, 1, ‘c:test.txt’ , ‘c:test1.txt’

xp_msver

The procedure xp_msver is very useful when looking for system information. It returns a wealth of information about the host operating system — the SQL version number, language, CPU type, copyright and trademark information, Microsoft Windows version, CPU count and affinity settings, physical memory settings and your product key. This procedure has many input parameters that allow you to filter down the records that are returned. Each parameter is a sysname data type, which accepts the name of one of the records. If any parameters are specified, only the rows specified as a parameter are returned.

No filter specified.

exec xp_msver

Return only Platform and Comments records.

exec xp_msver ‘Platform’, ‘Comments’

xp_get_mapi_profiles

The xp_get_mapi_profiles procedure assists you in configuring SQL Mail. When executed, it will call to Windows via the SQL Mail component of SQL Server and display a list of available MAPI profiles that are configured in Outlook and it specifies which profile is the default profile. If it doesn’t display any records, then either Outlook is not configured correctly or SQL Server is not running under a domain account with Outlook profiles configured. In order to use this procedure in SQL Server 2005 or SQL Server 2008, you must enable the “SQL Mail XPs” option in the Surface Area Configuration tool or within the sp_configure procedure.

exec xp_get_mapi_profiles

xp_subdirs

The xp_subdirs procedure displays a subset of the information avaialble through xp_dirtree. Xp_subdirs will display all the subfolders in a given folder. It can be very handy when you are building a directory tree within a table dynamically and you do not want to worry about the extra parameters of the xp_dirtree procedure.

exec xp_subdirs ‘d:mssql’

xp_test_mapi_profiles

The procedure xp_test_mapi_profiles is another undocumented stored procedure that is very useful when you are setting up SQL Mail. It will start, then stop, a MAPI session to ensure that MAPI is configured correctly and working within the confines of Microsoft SQL Server. I should note that it does not verify the mail server configuration within the MAPI client (Outlook) nor does it send a test message.

The procedure accepts a single input parameter. That parameter is the name of the MAPI profile you wish to test. Like the xp_get_mapi_profiles procedure, for this stored procedure to function in SQL Server 2005 and SQL Server 2008, you must enable the “SQL Mail XPs” option in the Surface Area Configuration tool or within the sp_configure procedure.

When working with the SQL Mail stored procedures, be aware that SQL Mail is still slated for removal from the Microsoft SQL Server platform. That means the procedures sp_get_mapi_profiles and xp_test_mapi_profiles are slated for removal, as they are part of the SQL Mail subsystem. You should do all mail work on SQL Server 2005 and later using Database Mail instead of SQL Mail to ensure code portability with future versions of SQL Server. Microsoft initially slated SQL Mail for removal in SQL Server 2008, however, based on its inclusion in the current beta release, its future in SQL Server 2008 is unknown.

xp_unpackcab

Along with the xp_makecab procedure comes the xp_unpackcab extended stored procedure, and it does just what it says: It extracts files from cab files. The first paramater is the cab file, the second is the path you want to extract to and the third is verbose logging. A fourth paramater lets you specify the “extract to” file name.

exec xp_unpackcab ‘c:test.cab’, ‘c:temp’, 1

While this is not intended to be a complete list of the undocumented stored procedures in SQL Server, it does provide a reference point for many of these procedures with the hope of making the lives of the SQL Server administrators easier. Remember, you should never count on these procedures surviving from one SQL Server version to the next, nor should you expect their code base to remain the same between versions. 

 

 

 

 

Posted in SQL | Tagged: , , , , , , | Leave a Comment »

SQL Vulnerability Leaves Passwords In The Clear

Posted by Alin D on May 19, 2011

A vulnerability in Microsoft SQL Server could enable any user with administrative privileges to openly see the unencrypted passwords of all other users, researchers said today.

In SQL Server 2000 or 2005, administrators can view all of the passwords used since the server went online by reviewing its process memory. Under SQL Server 2008, the problem has been partially fixed, but an administrator with local access and a simple debugger could still view the passwords.

The vulnerability is most likely an insider threat because it requires administrative privileges. However, it is also possible for a hacker to take advantage of the flaw by exploiting SQL injection..

The flaw may not directly affect the data in the database, since an administrator would have access to that data already. But many people reuse their passwords for other applications, and it is possible that the vulnerability might lead to the compromise of other users’ work or personal accounts.

Many applications are deployed with administrative privileges.

Hackers using a simple SQL injection vulnerability can now access administrative passwords, which may be used to penetrate other systems on the network, escalating the breach. This is even worse in the case of SQL Server 2000 and 2005, where this can be done remotely.

One well-known security researcher, who requested anonymity, disagrees. “This seems like a nonissue,” the researcher says. “Anyone with the ability to read process memory would also have the ability to just hook the authentication code and capture passwords that way. For once, Microsoft is right to ignore it.”

There is a big difference between being able to reset a password to either a system-generated password which the administrator would not see (or to a password the administrator chooses) and actually seeing a user’s personal password.

he latter involves much greater risk, including access to additional systems the password may be used on, potentially enabling access to user’s private data, such as bank or brokerage accounts.

Posted in Security | Tagged: , , , , , , | Leave a Comment »

Oracle to SQL migration

Posted by Alin D on February 2, 2011

I started working on a simple migration of Oracle data to SQL Server and had a hard time finding a single document explaining the entire process. Having almost no experience with Oracle, any steps that involved Oracle took me a long time to complete. So here are the steps that I followed.

First, you need to run a script to create a Replication Administrative Schema User. There is a script that is provided when you install SQL Server 2008. It is located at :\Program FilesMicrosoft SQL Server\MSSQLInstalloracleadmin.sql. You need to copy this script to the Oracle server. In this example, I copied the script to the root of the C drive. Then you need to run the script using sqlplus. Here are the steps to run it using sqlplus on a Windows Server 2008 R2 server with Oracle installed.

Open a Command Prompt.Type sqlplus.Logon with an account with DBA privileges on the Oracle server.Run the script by typing @ and then the path to the script in quotes. For my example this would be @”c:oracleadmin.sql”.You will be prompted for a name and password for the new user. Also, you will be prompted for the default tablespace.

Next, you need to give the Replication Administrative Schema User you just created SELECT permissions on the tables you want to access in SQL Server.

You can grant the SELECT permissions in the Database Control console.

On the Oracle server, you need to login to the Database Control with a user that has DBA permissions.Click on the Server tab. Under Security, click Users.Select the user you created, and then click Edit.Click on the Object Privileges tab. In the Select Object Type list, select Table, and then click Add.Under Select Table Objects, click the flashlight icon.In the Schema list, select a schema.Click Go.Select the tables you want to be able to access in SQL Server.Under Available Privileges, click SELECT, and then click Move.Click OK, and then click Apply.

Next, you need to install the Oracle client networking software and the Oracle OLE DB provider on the SQL Server Distributor, so that the Distributor can make connections to the Oracle Publisher. You should install the most recent version of the Oracle client software. You may choose to install different options depending on your needs, but these are the steps that I followed when I installed the software.

I chose the Administrator option to ensure all the components I needed were installed. The Oracle Universal Installer will guide you through the rest of the steps to install the client software. I also installed the networking software which didn’t start automatically after I installed the client software. You can start this wizard by navigating to Start | All Programs | Oracle – OraClient11g_home1 | Configuration and Migration Tools | Net Configuration Assistant.

When I opened the Oracle Net Configuration Assistant, I chose the Local Net Service Name configuration option.

To access an Oracle database across the network you use a net service name. The net service name is usually the global database name. On the Net Service Name Configuration, Service Name page, you need to enter this name. I selected the option to use TCP to communicate with the database over the network. On the Net Service Configuration, TCP/IP Protocol page, you need to enter the name of your Oracle server, and you can change the port number if you want, but I kept the default.

On the Net Service Name Configuration, Test page, you should perform a test. When I performed this test, I got an error. To get around the error, I had to change the login to the Replication Administrative Schema user I created. Then, the test succeeded.

For the rest of the wizard, I accepted the defaults, and then restarted the computer.

Posted in TUTORIALS | Tagged: , , , , , , | Leave a Comment »

Re-generating SQL Server Logins

Posted by Alin D on January 28, 2011

Microsoft SQL Server stores all login permissions in security catalog system tables. By querying the system tables, database administrators can produce a comprehensive report for login permission including original password, the server and database roles assigned, down to granular level object permission.

It is a common task for a DBA to make sure user login permissions are properly assigned. Depending on the purpose of the logins, we grant an appropriate level of permission to ensure that the login can perform the tasks it needs to do and nothing more.

We replicate back-ends into multiple environments quite often. Each of them serves a different purpose, like development, testing, user acceptance testing, pilot and production environments. The very same login may have different levels of permission in each environment. Permissions are tightened up gradually from development to QA, then from QA to UAT, into Pilot and eventually completely secured in Production.

Other than maintaining multiple environments with completely different privilege settings, DBAs also often face tasks like Database/Server migration, breaking down one server into multiple environments but requiring exactly the same permission settings in all servers. The last thing a DBA wants to face when users from different systems calling in and complaining that their logins don’t perform the tasks that used to work before the segregation.

Last but certainly not the least is compliance auditing. More and more companies have gone under extensive scrutinization on the level of permission a login possesses in production systems. Auditors usually wanted to know what logins have elevated privileges and the justification for them. So it comes in handy if a DBA can quickly find the permission setup for all of the logins on monitored servers and take a step ahead to do some clean-up before reviewing login permissions with auditors.

In some cases, logins are required to have privileges downgraded or removed from the production systems. Reverse engineering the login comes in handy to analyze how login permission was configured for the server level, database level and object level before proceeding to any login permissions changes or login removal. With the presence of a reversing script, we can easily revert to its original setting in case the login changes impacted normal application or user operations.

MS SQL Server has stored all login permissions on security catalog system tables. By querying the system tables, we can re-generate a SQL statement to cover from the very beginning on how a login is generated along with the original password, getting server and database roles assigned, and down to granular level object permission. We can also produce a comprehensive report for login permission by combining information from system metadata.

We will start by creating a login along with the properties. There are four types of logins within MS SQL Server: SQL Server login, Windows logins, certificate-mapped logins, and asymmetric key-mapped logins. Here, we will focus on SQL Server login and Windows login since they are the most commonly used. Password generation will be covered in the script but not DROP LOGIN statement. This is to avoid any accidental login drop on the production system. We will utilize sp_hexadecimal from Microsoft support and extract some code from sp_help_revlogin to generate a hashed password and sid.

Starting with SQL 2005, you can enable password policy, password expiration and force user to change password at next login for SQL Server login, much like the password policy defined for our Windows logins. Password check policy is on by default, whereas password expiration policy is off by default. These two policies are only enforced on Windows 2003 or later. If you want user to change the password at the next login, then both policies will automatically set as ON. Since these policies are only for SQL Server logins, you will notice that for Windows logins, none of these properties will be included in the generated statement.

Before we look into how to generate a create statement for both SQL Server login and Windows login for MS SQL Server. You need to create stored the procedure sp_hexadecimal as a pre-requisite. Stored procedure sp_hexadecimal works on SQL 2005, 2008 and 2008 R2.

—————————————– Stored Procedure sp_hexadecimal————————————— USE masterGOIF OBJECT_ID (‘sp_hexadecimal’) IS NOT NULL DROP PROCEDURE sp_hexadecimalGOCREATE PROCEDURE sp_hexadecimal @binvalue varbinary(256), @hexvalue varchar (514) OUTPUTAS DECLARE @charvalue varchar (514) DECLARE @i int DECLARE @length int DECLARE @hexstring char(16) SELECT @charvalue = ‘0x’ SELECT @i = 1 SELECT @length = DATALENGTH (@binvalue) SELECT @hexstring = ‘0123456789ABCDEF’ WHILE (@i <= @length) BEGIN DECLARE @tempint int DECLARE @firstint int DECLARE @secondint int SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1)) SELECT @firstint = FLOOR(@tempint/16) SELECT @secondint = @tempint – (@firstint*16) SELECT @charvalue = @charvalue + SUBSTRING(@hexstring, @firstint+1, 1) + SUBSTRING(@hexstring, @secondint+1, 1) SELECT @i = @i + 1 END SELECT @hexvalue = @charvalueGO

Now we can proceed with generating a create login statement for both SQL Server login and Windows login. Replace ‘YourLoginName’ with the login you would like to generate. This script works on SQL 2005, SQL 2008 and SQL 2008 R2. Assuming you have adequate permission on the instance to run all subsequent scripts, execute the following code.

————————————————Login Pre-requisites ———————————————- USE mastergoSET NOCOUNT ON DECLARE @login_name varchar(100)SET @login_name = ‘YourLoginName’ IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @login_name AND type IN (‘G’,’U’,’S’))BEGIN PRINT ‘Please input valid login name’ RETURNEND DECLARE @login_sid varbinary(85)SELECT @login_sid = sid FROM sys.server_principals WHERE name = @login_name DECLARE @maxid intIF OBJECT_ID(‘tempdb..#db_users’) is not nullDROP TABLE #db_users SELECT id = identity(int,1,1), sql_cmd = ‘SELECT ”’+name+”’, * FROM ‘+name+’.sys.database_principals’ INTO #db_users FROM sys.sysdatabases SELECT @maxid = @@ROWCOUNT ———————————————–Retrieve hashed password and hashed sid ———————————————IF EXISTS (SELECT * FROM sys.server_principals WHERE type = ‘S’ and name = @login_name )BEGIN DECLARE @PWD_varbinary varbinary (256) SET @PWD_varbinary = CAST( LOGINPROPERTY( @login_name, ‘PasswordHash’ ) AS varbinary (256) ) DECLARE @SID_string varchar (514) DECLARE @PWD_string varchar (514) EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT EXEC sp_hexadecimal @login_sid, @SID_string OUTEND–select @SID_string–select @PWD_string ————————————————Login Properties———————————————-PRINT ‘———————————————-‘PRINT ‘–SET Login Properties’PRINT ‘———————————————-‘ DECLARE @login_sqlcmd varchar(1000)SET @login_sqlcmd = ”SELECT @login_sqlcmd = ‘– LOGIN [‘+@login_name+’] IS ‘+case is_disabled WHEN 1 THEN ‘DISABLED’ ELSE ‘ENABLED’ END FROM sys.server_principals WHERE name = @login_name IF EXISTS (SELECT * FROM sys.sql_logins WHERE name = @login_name)BEGIN SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’CREATE LOGIN ‘+ QUOTENAME(@login_name)+’ WITH PASSWORD = ‘ + @PWD_string + ‘ HASHED, SID = ‘ + @SID_string + ‘, DEFAULT_DATABASE = [‘+default_database_name+’], DEFAULT_LANGUAGE = [‘+default_language_name+’]’ FROM sys.server_principals WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd + ‘, CHECK_POLICY’ + CASE is_policy_checked WHEN 0 THEN ‘=OFF’ ELSE ‘=ON’ END FROM sys.sql_logins WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd + ‘, CHECK_EXPIRATION’ + CASE is_expiration_checked WHEN 0 THEN ‘=OFF’ ELSE ‘=ON’ END FROM sys.sql_logins WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’ALTER LOGIN [‘+@login_name+’] WITH DEFAULT_DATABASE = [‘+default_database_name+’], DEFAULT_LANGUAGE = [‘+default_language_name+’]’ FROM sys.server_principals WHERE name = @login_nameENDELSEBEGIN SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’CREATE LOGIN ‘ + QUOTENAME( @login_name ) + ‘ FROM WINDOWS WITH DEFAULT_DATABASE = [‘ + default_database_name + ‘]’ FROM sys.server_principals WHERE name = @login_nameEND PRINT @login_sqlcmd

By executing the above script, you will see a result similar to the snapshot below in the SSMS result pane. [Refer Fig 1.0 and Fig 1.1]

ch-regenerate-logins-image001
Fig 1.0

For Windows login, the result looks like this. There will be no hashed password, sid and password policy defined for Windows login.

ch-regenerate-logins-image002
Fig 1.1

Now we have the script used to recover login create, but a login without any permission doesn’t serve any purpose. So next we will see how to recover sever level permission for a login by running the statement below on SSMS.

————————————————Login Pre-requisites ———————————————- USE mastergoSET NOCOUNT ON DECLARE @login_name varchar(100)SET @login_name = ‘YourLoginName’ IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @login_name AND type IN (‘G’,’U’,’S’))BEGIN PRINT ‘Please input valid login name’ RETURNEND DECLARE @login_sid varbinary(85)SELECT @login_sid = sid FROM sys.server_principals WHERE name = @login_name DECLARE @maxid intIF OBJECT_ID(‘tempdb..#db_users’) is not nullDROP TABLE #db_users SELECT id = identity(int,1,1), sql_cmd = ‘SELECT ”’+name+”’, * FROM ‘+name+’.sys.database_principals’ INTO #db_users FROM sys.sysdatabases SELECT @maxid = @@ROWCOUNT ————————————————Grant Server Role to login ———————————————-PRINT ”PRINT ‘———————————————-‘PRINT ‘–Grant Server Role to login ‘PRINT ‘———————————————-‘ IF OBJECT_ID(‘tempdb..#srvrole’) IS NOT NULLDROP TABLE #srvrole CREATE TABLE #srvrole(ServerRole sysname, MemberName sysname, MemberSID varbinary(85)) INSERT INTO [#srvrole] EXEC sp_helpsrvrolemember DECLARE @login_srvrole varchar(1000)SET @login_srvrole = ”IF EXISTS (SELECT 1 FROM #srvrole WHERE[MemberName] = @login_name) BEGIN SELECT @login_srvrole = @login_srvrole + ‘EXEC sp_addsrvrolemember ”’+MemberName+”’,”’+ServerRole+”” FROM #srvrole WHERE [MemberName] = @login_name PRINT @login_srvrole ENDELSEBEGIN PRINT ‘–Login [‘+@login_name+’] is not a member of any server level role’END

You can see a result similar to the snapshot below on the result pane. [Refer Fig 1.2]

ch-regenerate-logins-image003
Fig 1.2

If the login you inquired doesn’t have any server level permission, then the result pane will display as below. [Refer Fig 1.3]

ch-regenerate-logins-image004
Fig 1.3

Database level role permission for a login

Now, a login may be a member of a specific database role. It’s important we don’t miss out restoring database role permission setting for a login.

————————————————Login Pre-requisites ———————————————- USE mastergoSET NOCOUNT ON DECLARE @login_name varchar(100)SET @login_name = ‘YourLoginName’ IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @login_name AND type IN (‘G’,’U’,’S’))BEGIN PRINT ‘Please input valid login name’ RETURNEND DECLARE @login_sid varbinary(85)SELECT @login_sid = sid FROM sys.server_principals WHERE name = @login_name DECLARE @maxid intIF OBJECT_ID(‘tempdb..#db_users’) is not nullDROP TABLE #db_users SELECT id = identity(int,1,1), sql_cmd = ‘SELECT ”’+name+”’, * FROM ‘+name+’.sys.database_principals’ INTO #db_users FROM sys.sysdatabases SELECT @maxid = @@ROWCOUNT —————————————————–Find out list of db that the login has access to ————————————————— IF OBJECT_ID(‘tempdb..#alldb_users’) is not nullDROP TABLE #alldb_users CREATE TABLE #alldb_users( [dbname] [sysname] NOT NULL, [name] [sysname] NOT NULL, [principal_id] [int] NOT NULL, [type] [char](1) NOT NULL, [type_desc] [nvarchar](60) NULL, [default_schema_name] [sysname] NULL, [create_date] [datetime] NOT NULL, [modify_date] [datetime] NOT NULL, [owning_principal_id] [int] NULL, [sid] [varbinary](85) NULL, [is_fixed_role] [bit] NOT NULL) DECLARE @id int, @sqlcmd varchar(500)SET @id = 1 WHILE @id <=@maxidBEGIN SELECT @sqlcmd = sql_cmd FROM #db_users WHERE id = @id INSERT INTO #alldb_users EXEC (@sqlcmd) SET @id = @id + 1 END DELETE FROM #alldb_users WHERE sid is null DELETE FROM #alldb_users WHERE sid <> @login_sid –SELECT * FROM #alldb_users————————————————granting database role to login ———————————————-PRINT ”PRINT ‘———————————————-‘PRINT ‘–Grant database role to login ‘PRINT ‘———————————————-‘ IF OBJECT_ID(‘tempdb..#dbrole’) is not nullDROP TABLE #dbrole create table #dbrole (dbname varchar(100), dbrole varchar (100), dbrole_member varchar(100), sid varbinary(85), default_schema_name varchar(100), login_name varchar(100), db_principal_id int)DECLARE @dbrole_sqlcmd varchar(max)SET @dbrole_sqlcmd = ”SELECT @dbrole_sqlcmd = @dbrole_sqlcmd + ‘SELECT ”’+dbname+”’, c.name, b.name, b.sid, b.default_schema_name, d.name, b.principal_id as login_name from [‘+dbname+’].sys.database_role_members a inner join [‘+dbname+’].sys.database_principals b on a.member_principal_id = b.principal_idinner join [‘+dbname+’].sys.database_principals c on a.role_principal_id = c.principal_idleft join sys.server_principals d on b.sid = d.sid’from #alldb_users –SELECT @dbrole_sqlcmd–PRINT @dbrole_sqlcmdINSERT INTO #dbrole exec(@dbrole_sqlcmd)–SELECT * FROM #dbrole DELETE FROM #dbrole WHERE sid <> @login_sid ALTER TABLE #dbrole ADD ID INT identity(1,1) DECLARE @counter int, @maxid2 int, @login_dbrole varchar(max) SELECT @maxid2 = MAX(ID) FROM #dbroleSET @counter = 1 –SELECT * FROM #dbrole IF NOT EXISTS (SELECT * FROM #dbrole )BEGIN PRINT ‘–Login [‘+@login_name+’] is not a member of any database level role’ return END WHILE @counter <= @maxid2BEGIN SELECT @login_dbrole = ‘USE [‘+dbname+’]IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ”’+dbrole_member+”’)BEGIN CREATE USER [‘+dbrole_member+’] FOR LOGIN [‘+login_name+’]’+isnull(‘ WITH DEFAULT_SCHEMA=[‘+default_schema_name+’]’,”)+’ENDALTER USER [‘+dbrole_member+’] WITH LOGIN = [‘+login_name+’]EXEC sp_addrolemember ”’+dbrole+”’,”’+dbrole_member+”’ ‘ FROM #dbrole WHERE ID = @counter SELECT @counter = @counter + 1 PRINT @login_dbrole END

If the login does not belong to any database role, then a result similar to the below snapshot will show up in the result pane. [Refer Fig 1.4 and Fig 1.5]

ch-regenerate-logins-image005
Fig 1.4

Otherwise, here is the sample result that denotes what database role the login is a member of.

ch-regenerate-logins-image006
Fig 1.5

We need to make sure that a database user is created for the login we are trying to recover on the database. If the login already has a database user defined for it, then we just need to make sure that a user is re-mapped to match the login’s SID. sp_change_users_login will be removed in a future version of Microsoft SQL Server. It is good to start avoiding using it and replace it with ALTER USER WITH LOGIN to perform sid remap.

By combing all three scripts, you can generate a script that does the following:

1.    Create login with original password, original sid, default database setting along with password policy setting

2.    Server level role permission

3.    Database level role permission

The script below demonstrates how to combine all three scripts into one. It is assumed you have created stored procedure sp_hexadecimal by running previous scripts.

————————————————Login Pre-requisites ———————————————- USE mastergoSET NOCOUNT ON DECLARE @login_name varchar(100)SET @login_name = ‘YourLoginName’ IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = @login_name AND type IN (‘G’,’U’,’S’))BEGIN PRINT ‘Please input valid login name’ RETURNEND DECLARE @login_sid varbinary(85)SELECT @login_sid = sid FROM sys.server_principals WHERE name = @login_name DECLARE @maxid intIF OBJECT_ID(‘tempdb..#db_users’) is not nullDROP TABLE #db_users SELECT id = identity(int,1,1), sql_cmd = ‘SELECT ”’+name+”’, * FROM ‘+name+’.sys.database_principals’ INTO #db_users FROM sys.sysdatabases SELECT @maxid = @@ROWCOUNT ———————————————–Retrieve hashed password and hashed sid ———————————————IF EXISTS (SELECT * FROM sys.server_principals WHERE type = ‘S’ and name = @login_name )BEGIN DECLARE @PWD_varbinary varbinary (256) SET @PWD_varbinary = CAST( LOGINPROPERTY( @login_name, ‘PasswordHash’ ) AS varbinary (256) ) DECLARE @SID_string varchar (514) DECLARE @PWD_string varchar (514) EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT EXEC sp_hexadecimal @login_sid, @SID_string OUTEND–select @SID_string–select @PWD_string————————————————Login Properties———————————————-PRINT ‘———————————————-‘PRINT ‘–SET Login Properties’PRINT ‘———————————————-‘ DECLARE @login_sqlcmd varchar(1000)SET @login_sqlcmd = ”SELECT @login_sqlcmd = ‘– LOGIN [‘+@login_name+’] IS ‘+case is_disabled WHEN 1 THEN ‘DISABLED’ ELSE ‘ENABLED’ END FROM sys.server_principals WHERE name = @login_name IF EXISTS (SELECT * FROM sys.sql_logins WHERE name = @login_name)BEGIN SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’CREATE LOGIN ‘+ QUOTENAME(@login_name)+’ WITH PASSWORD = ‘ + @PWD_string + ‘ HASHED, SID = ‘ + @SID_string + ‘, DEFAULT_DATABASE = [‘+default_database_name+’]’ FROM sys.server_principals WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd + ‘, CHECK_POLICY’ + CASE is_policy_checked WHEN 0 THEN ‘=OFF’ ELSE ‘=ON’ END FROM sys.sql_logins WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd + ‘, CHECK_EXPIRATION’ + CASE is_expiration_checked WHEN 0 THEN ‘=OFF’ ELSE ‘=ON’ END FROM sys.sql_logins WHERE name = @login_name SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’ALTER LOGIN [‘+@login_name+’] WITH DEFAULT_DATABASE = [‘+default_database_name+’]’ FROM sys.server_principals WHERE name = @login_nameENDELSEBEGIN SELECT @login_sqlcmd = @login_sqlcmd+ char(10)+’CREATE LOGIN ‘ + QUOTENAME( @login_name ) + ‘ FROM WINDOWS WITH DEFAULT_DATABASE = [‘ + default_database_name + ‘]’ FROM sys.server_principals WHERE name = @login_nameEND PRINT @login_sqlcmd ————————————————Grant Server Role to login ———————————————-PRINT ”PRINT ‘———————————————-‘PRINT ‘–Grant Server Role to login ‘PRINT ‘———————————————-‘ IF OBJECT_ID(‘tempdb..#srvrole’) IS NOT NULLDROP TABLE #srvrole CREATE TABLE #srvrole(ServerRole sysname, MemberName sysname, MemberSID varbinary(85)) INSERT INTO [#srvrole] EXEC sp_helpsrvrolemember DECLARE @login_srvrole varchar(1000)SET @login_srvrole = ”IF EXISTS (SELECT 1 FROM #srvrole WHERE[MemberName] = @login_name) BEGIN SELECT @login_srvrole = @login_srvrole + ‘EXEC sp_addsrvrolemember ”’+MemberName+”’,”’+ServerRole+””+CHAR(10) FROM #srvrole WHERE [MemberName] = @login_name PRINT @login_srvrole ENDELSEBEGIN PRINT ‘Login [‘+@login_name+’] is not a member of any server level role’END —————————————————–Find out list of db that the login has access to ————————————————— IF OBJECT_ID(‘tempdb..#alldb_users’) is not nullDROP TABLE #alldb_users CREATE TABLE #alldb_users( [dbname] [sysname] NOT NULL, [name] [sysname] NOT NULL, [principal_id] [int] NOT NULL, [type] [char](1) NOT NULL, [type_desc] [nvarchar](60) NULL, [default_schema_name] [sysname] NULL, [create_date] [datetime] NOT NULL, [modify_date] [datetime] NOT NULL, [owning_principal_id] [int] NULL, [sid] [varbinary](85) NULL, [is_fixed_role] [bit] NOT NULL) DECLARE @id int, @sqlcmd varchar(500)SET @id = 1 WHILE @id <=@maxidBEGIN SELECT @sqlcmd = sql_cmd FROM #db_users WHERE id = @id INSERT INTO #alldb_users EXEC (@sqlcmd) SET @id = @id + 1 END DELETE FROM #alldb_users WHERE sid is null DELETE FROM #alldb_users WHERE sid <> @login_sid –SELECT * FROM #alldb_users————————————————granting database role to login ———————————————-PRINT ”PRINT ‘———————————————-‘PRINT ‘–Grant database role to login ‘PRINT ‘———————————————-‘ IF OBJECT_ID(‘tempdb..#dbrole’) is not nullDROP TABLE #dbrole create table #dbrole (dbname varchar(100), dbrole varchar (100), dbrole_member varchar(100), sid varbinary(85), default_schema_name varchar(100), login_name varchar(100), db_principal_id int)DECLARE @dbrole_sqlcmd varchar(max)SET @dbrole_sqlcmd = ”SELECT @dbrole_sqlcmd = @dbrole_sqlcmd + ‘SELECT ”’+dbname+”’, c.name, b.name, b.sid, b.default_schema_name, d.name, b.principal_id as login_name from [‘+dbname+’].sys.database_role_members a inner join [‘+dbname+’].sys.database_principals b on a.member_principal_id = b.principal_idinner join [‘+dbname+’].sys.database_principals c on a.role_principal_id = c.principal_idleft join sys.server_principals d on b.sid = d.sid’from #alldb_users –SELECT @dbrole_sqlcmd–PRINT @dbrole_sqlcmdINSERT INTO #dbrole exec(@dbrole_sqlcmd)–SELECT * FROM #dbrole DELETE FROM #dbrole WHERE sid <> @login_sid ALTER TABLE #dbrole ADD ID INT identity(1,1) DECLARE @counter int, @maxid2 int, @login_dbrole varchar(max) SELECT @maxid2 = MAX(ID) FROM #dbroleSET @counter = 1 –SELECT * FROM #dbrole IF NOT EXISTS (SELECT * FROM #dbrole )BEGIN PRINT ‘–Login [‘+@login_name+’] is not a member of any database level role’ return END WHILE @counter <= @maxid2BEGIN SELECT @login_dbrole = ‘USE [‘+dbname+’]IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ”’+dbrole_member+”’)BEGIN CREATE USER [‘+dbrole_member+’] FOR LOGIN [‘+login_name+’]’+isnull(‘ WITH DEFAULT_SCHEMA=[‘+default_schema_name+’]’,”)+’ENDALTER USER [‘+dbrole_member+’] WITH LOGIN = [‘+login_name+’]EXEC sp_addrolemember ”’+dbrole+”’,”’+dbrole_member+”’ ‘ FROM #dbrole WHERE ID = @counter SELECT @counter = @counter + 1 PRINT @login_dbrole END

Posted in SQL | Tagged: , , , , , | Leave a Comment »

Transparent data encryption in SQL Server 2008

Posted by Alin D on January 11, 2011

Transparent Data Encryption (TDE) is a new feature in SQL Server 2008 designed to encrypt your database files, database backups and temporary database (tempdb). As you request data from your database, it will be decrypted in real time, and TDE will not prevent any user authorized to enter your database from accessing and reading your tabular data.

Transparent data encryption – why use it?

The PCI DSS (Payment Card Industry Data Security Standard) requires that each of your databases and backups are secured, and TDE is intended primarily to help companies running SQL Server 2008 meet the terms of those compliance guidelines.

Keep in mind that TDE won’t satisfy all of your security or compliance requirements on its own. It is instead part of a suite of features provided by SQL Server 2008 to help DBAs achieve compliance. The DBA will still need to ensure that sensitive data is encrypted by the encryption algorithms, and network and system administrators must ensure that the Windows servers, network and link between the Web and application servers are secure. Developers are still responsible for making sure that communication from the client to the Web server is secure or encrypted.

Considerations before using TDE

Before you implement transparent data encryption on your SQL Server you should consider several factors.

For example, any company using TDE in SQL Server may notice a slight performance degradation as data is encrypted while being written to disk, and decrypted when being read from the disk. This hit is mainly due to increased CPU requirements. The data file, transaction log and backups will be the same size as with a database that does not have TDE enabled.

Database compression ratios for encrypted database backups are far more cost-effective for unencrypted backups. This may require increased storage requirements for your backups, and an added fee may be incurredif you are transferring those encrypted backup files offsite.

Database compression ratios for encrypted database backups are much less when compared to those of unencrypted backups. This may require increased storage requirements for your backups, and added costs if you are transferring those encrypted backup files offsite.

While securing backups can also be done natively in SQL Server via a password, this is considered a weak option. Most tape backup solutions now include encryption on the fly while writing to tape devices. While in the past this technology was slow, there have been considerable advances in tape encryption over the past few years. Still, these developments will not prevent a hacker from accessing your SQL Server, nor will they hinder their efforts to detach your database files, copy them to another SQL Server, attach them and read your database contents. Database file encryption is required by most compliance regulations.

Below are some other important factor to take into account before implementing transparent data encryption:

  • Using TDE requires a database encryption key (DEK) and any certificate that you may have used for the DEK. You will need this key when restoring your backups.
  • If you are using TDE, instant file initialization is disabled. Instant file initialization is a feature of Windows Server 2003 that SQL Server 2005 can take advantage of where database growth times are extremely fast, as the underlying space in the file system does not need to be zeroed out. If you are log shipping or database mirroring a transparent data encryption database, TDE will need to be enabled on the secondary, ormirror server.
  • FILESTREAM data will not be encrypted. FILESTREAM is a feature of SQL Server 2008 where varbinary columns can be stored in the file system and asynchronously streamed to the client.
  • Read-only file groups in your database will have to be made writable to enable TDE to encrypt the database contents. They can then be made read-only again.
  • Enabling a database for transparent data encryption may take some time, and some database operations will not be enabled during this conversion period. Consult Microsoft’s page on understanding TDE for more information on what these limitations are.
  • Replication is “TDE unaware”, and replicated data will not be encrypted. In other words, replication network traffic will be plain text as always, as will the replication snapshot files. The DBA will need to account for this in the compliance effort.
  • Full-text indexing will extract textual data from varbinary and image columns into the file system momentarily during the index process. This data will be plain text and not encrypted. Microsoft recommends that you do not full-text index data stored in the varbinary/image columns.

Enabling transparent data encryption in SQL Server 2008

To enable TDE you will fist need to create a Service Master Key (SMK). To do this, use the following statement in your master database:

Create Master Key Encryption By Password = 'MyPassword'

You will then need to protect the DEK with a certificate which you will be able to transfer to another server should you need to restore the TDE protected database there. You can achieve this by using the following statement:

CREATE CERTIFICATE MyCertificate WITH SUBJECT = 'My Certificate'

You will then need to backup the certificate into the file system, along with the private key. Ensure that you keep both of these files in a secure, known location. If you loose these files you will be unable to restore your database and read its contents.

BACKUP CERTIFICATE MyCertificate TO FILE = 'c:tempMyCertificateBackup.bck'
WITH PRIVATE KEY (
FILE = 'c:TempMyPrivateKey.key',
ENCRYPTION BY PASSWORD = 'MyPassword');

You will now need to create a database encryption key encrypted with the above certificate.

CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE MyCertificate

Now you can enable transparent data encryption on your database by using the following command:

ALTER DATABASE myDatabase SET ENCRYPTION ON

Finally, you can monitor the progress or state of the encryption conversion by querying the following DMV:

Select db_name(database_id), encryption_state fromsys.dm_database_encryption_keys

The important thing to remember about transparent data encryption for SQL Server is that it’s not a one stop encryption solution. It also does not encrypt sensitive data in your database, but rather the data files and backups. You will still need to protect sensitive data by encrypting individual columns to only allow authorized people to view them.

Posted in SQL | Tagged: , , , | Leave a Comment »

SQLCMD – SQL Server command-line utilitie

Posted by Alin D on January 4, 2011

This article explores various command-line utilities that ship with SQL Server. These utilities give administrators a different way to access the database engine and its related components. In some cases, they provide functionality that is also available with SQL Server’s graphical user interface (GUI). Other command-line utilities provide functionality that is available only from the command prompt.

For each utility, this article provides the command syntax along with the most commonly used options. For the full syntax and options available for the utility, see SQL Server Books Online.Below table lists the command-line utilities discussed in this chapter. This table lists the physical location of each utility’s executable. The location is needed to execute the utility in most cases, unless the associated path has been added to the Path environmental variable.

Utility Install Location
sqlcmd c:Program FilesMicrosoft SQL Server100ToolsBinn
dta c:Program FilesMicrosoft SQL Server100ToolsBinn
tablediff c:Program FilesMicrosoft SQL Server100COM
bcp c:Program FilesMicrosoft SQL Server100ToolsBinn
sqldiag c:Program FilesMicrosoft SQL Server100ToolsBinn
sqlserver c:Program FilesMicrosoft SQL ServerMSSQL10.MSSQLSERVERMSSQLBinn

When you are testing many of these utilities, it is often easiest to set up a batch file (.BAT) that contains a command to change the directory to the location shown in above Table. After you make this directory change, you can enter the command-line utility with the relevant parameters. Finally, you should enter a PAUSE command so that you can view the output of the utility in the command prompt window. Following is an example you can use to test the sqlcmd utility (which is discussed in more detail later in this chapter):

CD “C:Program FilesMicrosoft SQL Server100ToolsBinn”

SQLCMD -S(local) -E -Q “select @@servername”

pause

After you save the commands in a file with a .BAT extension, you can simply double-click the file to execute it. This approach is much easier than retyping the commands many times during the testing process.

What’s New in SQL Server Command-Line Utilities

The SQL Server command-line utilities available in SQL Server 2008 are basically the same as those offered with SQL Server 2005. This has some key benefits for those who are familiar with the 2005 utilities. Very little has changed in the syntax, and batch files or scripts you have used with these utilities in the past should continue to work unchanged.

A few command-line utilities have been added in SQL Server 2008, however, and some have been removed. The sqlps utility is new to SQL Server 2008. This utility can be used to run PowerShell commands and scripts. The sqlps utility and the PowerShell Windows–based command-line management tool will be discussed in article,“Administering SQL Server 2008 with PowerShell.”

Utilities removed from SQL Server 2008 include sac. The sac utility can be used in SQL Server 2005 to import or export settings available in the graphical Surface Area Configuration (SAC) tool. Both the sac command-line utility and SAC graphical tool have been removed. Similar functionality is now available via policy-based management and the Configuration Manager tool.

The sqlcmd Command-Line Utility

The sqlcmd command-line utility is the next generation of the isql and osql utilities that you may have used in prior versions of SQL Server. It provides the same type of functionality as isql and osql, including the capability to connect to SQL Server from the command prompt and execute T-SQL commands. The T-SQL commands can be stored in a script file, entered interactively, or specified as command-line arguments to sqlcmd.

The syntax for sqlcmd follows:

sqlcmd

[{ { -U login_id [ -P password ] } | –E trusted connection }]

[ -z new password ] [ -Z new password and exit]

[ -S server_name [  instance_name ] ] [ -H wksta_name ] [ -d db_name ]

[ -l login time_out ] [ -A dedicated admin connection ]

[ -i input_file ] [ -o output_file ]

[ -f < codepage > | i: < codepage > [ < , o: < codepage > ] ]

[ -u unicode output ] [ -r [ 0 | 1 ] msgs to stderr ]

[ -R use client regional settings ]

[ -q “cmdline query” ] [ -Q “cmdline query” and exit ]

[ -e echo input ] [ -t query time_out ]

[ -I enable Quoted Identifiers ]

[ -v var = “value”…] [ -x disable variable substitution ]

[ -h headers ][ -s col_separator ] [ -w column_width ]

[ -W remove trailing spaces ]

[ -k [ 1 | 2 ] remove[replace] control characters ]

[ -y display_width ] [-Y display_width ]

[ -b on error batch abort ] [ -V severitylevel ] [ -m error_level ]

[ -a packet_size ][ -c cmd_end ]

[ -L [ c ] list servers[clean output] ]

[ -p [ 1 ] print statistics[colon format]]

[ -X [ 1 ] ] disable commands, startup script, environment variables [and exit]

[ -? show syntax summary ]

The number of options available for sqlcmd is extensive, but many of the options are not necessary for basic operations. To demonstrate the usefulness of this tool, we look at several different examples of the sqlcmd utility, from fairly simple (using few options) to more extensive.

Executing the sqlcmd Utility

Before we get into the examples, it is important to remember that sqlcmd can be run in several different ways. It can be run interactively from the command prompt, from a batch file, or from a Query Editor window in SSMS. When run interactively, the sqlcmd program name is entered at the command prompt with the required options to connect to the database server. When the connection is established, a numbered row is made available to enter the T-SQL commands. Multiple rows of T-SQL can be entered in a batch; they are executed only after the GO command has been entered. Figure 1 shows an example with two simple SELECT statements that were executed interactively with sqlcmd. The connection in this example was established by typing sqlcmd at the command prompt to establish a trusted connection to the default instance of SQL Server running on the machine on which the command prompt window is opened.

 Executing sqlcmd interactively

Figure1- Executing sqlcmd interactively

The capability to edit and execute sqlcmd scripts was added to SSMS with SQL Server 2005. A sqlcmd script can be opened or created in a Query Editor window within SSMS. To edit these scripts, you must place the editor in SQLCMD Mode. You do so by selecting Query, SQLCMD Mode or by clicking the related toolbar button. When the editor is put in SQLCMD Mode, it provides color coding and the capability to parse and execute the commands within the script. Figure 2 shows a sample sqlcmd script opened in SSMS in a Query Editor window set to SQLCMD Mode. The shaded lines are sqlcmd commands.

 Executing and editing sqlcmd scripts in SSMS

Figure2 - Executing and editing sqlcmd scripts in SSMS

The most common means for executing sqlcmd utility is via a batch file. This method can provide a great deal of automation because it allows you to execute a script or many scripts by launching a single file. The examples shown in this section are geared toward the execution of sqlcmd in this manner. The following simple example illustrates the execution of sqlcmd, using a trusted connection to connect to the local database, and the execution of a simple query that is set using the –Q option:

sqlcmd -S (local) -E -Q”select getdate()”

You can expand this example by adding an output file to store the results of the query and add the –e option, which echoes the query that was run in the output results:

sqlcmd -S (local) -E -Q”select getdate()” -o c:TestOutput.txt –e

The contents of the c:TestOutput.txt file should look similar to this:

select getdate()

– – – – – – – – – – – –

2008-09-10 20:29:05.645

(1 rows affected)

Using a trusted connection is not the only way to use sqlcmd to connect to a SQL Server instance. You can use the –U and –P command-line options to specify the SQL Server user and password. sqlcmd also provides an option to specify the password in an environmental variable named sqlcmdPASSWORD, which can be assigned prior to the sqlcmd execution and eliminates the need to hard-code the password in a batch file.

sqlcmd also provides a means for establishing a dedicated administrator connection (DAC) to the server. The DAC is typically used for troubleshooting on a server that is having problems. It allows an administrator to get onto the server when others may not be able to. If the DAC is enabled on the server, a connection can be established with the –A option and a query can be run, as shown in the following example:

sqlcmd -S (local) -A -Q”select getdate()”

If you need to manage more complex T-SQL execution, it is typically easier to store the TSQL in a separate input file. The input file can then be referenced as a sqlcmd parameter. For example, say that you have the following T-SQL stored in a file named

C:TestsqlcmdInput.sql:

BACKUP DATABASE Master

TO DISK = ‘c:master.bak’

BACKUP DATABASE Model

TO DISK = ‘c:model.bak’

BACKUP DATABASE MSDB

TO DISK = ‘c:msdb.bak’

The sqlcmd execution, which accepts the C:TestsqlcmdInput.sql file as input and executes the commands within the file, looks like this:

sqlcmd -S (local) -E -i”C:TestsqlcmdInput.sql” -o c:TestOutput.txt –e

The execution of the preceding example backs up three of the system databases and writes the results to the output file specified.

Using Scripting Variables with sqlcmd

sqlcmd provides a means for utilizing variables within sqlcmd input files or scripts. These scripting variables can be assigned as sqlcmd parameters or set within the sqlcmd script. To illustrate the use of scripting variables, let’s change our previous backup example so that the database that will be backed up is a variable. A new input file named c:BackupDatabase.sql should be created, and it should contain the following command:

BACKUP DATABASE $(DatabaseToBackup)

TO DISK = ‘c:$(DatabaseToBackup).bak’

The variable in the preceding example is named DatabaseToBackup. Scripting variables are referenced using the $( ) designators. These variables are resolved at the time of execution, and a simple replacement is performed. This allows variables to be specified within quotation marks, if necessary. The –v option is used to assign a value to a variable at the command prompt, as shown in the following example, which backs up the model database:

sqlcmd -S (local) -E -i”C:BackupDatabase.sql” -v DatabaseToBackup = model

If multiple variables exist in the script, they can all be assigned after the –v parameter.These variables should not be separated by a delimiter, such as a comma or semicolon. Scripting variables can also be assigned within the script, using the :SETVAR command. The input file from the previous backup would be modified as follows to assign the DatabaseToBackup variable within the script:

:SETVAR DatabaseToBackup Model

BACKUP DATABASE $(DatabaseToBackup)

TO DISK = ‘c:$(DatabaseToBackup).bak’

Scripts that utilize variables, sqlcmd commands, and the many available options can be very sophisticated and can make your administrative life easier. The examples in this section illustrate some of the basic features of sqlcmd, including some of the features that go beyond what is available with osql.

Pages: 1 2 3

Posted in SQL | Tagged: , , , , , , , | Leave a Comment »