{"id":553,"date":"2018-07-25T10:39:55","date_gmt":"2018-07-25T09:39:55","guid":{"rendered":"https:\/\/sqldoubleg.live-website.com\/?p=553"},"modified":"2018-07-25T10:39:55","modified_gmt":"2018-07-25T09:39:55","slug":"managing-sql-logins-in-different-environments","status":"publish","type":"post","link":"https:\/\/www.sqldoubleg.com\/es\/2018\/07\/25\/managing-sql-logins-in-different-environments\/","title":{"rendered":"Administar Inicios de Sesi\u00f3n de SQL en entornos diferentes"},"content":{"rendered":"<p>En este post quiero mostrar como podemos administrar inicios de sesion en SQL Server para evitar un problema bastante comun&nbsp;En SQL Server tenemos la posibilidad de autenticarnos de dos maneras diferentes, una est\u00e1 basada en la Autenticaci\u00f3n de Windows y permite que los usuarios de Windows (locales o de dominio) se conecten al servidor usando sus credenciales y la otra est\u00e1 basada en inicios de sesi\u00f3n (logins) en el propio SQL Sever, los cuales se mantienen dentro de la instancia de SQL Server.<\/p>\n<p>La autenticaci\u00f3n de Windows siempre est\u00e1 habilitada y no se puede deshabilitar (en la version para Windows de SQL Server) y, por el contrario, la autenticaci\u00f3n de SQL Server debe habilitarse bien sea durante la instalaci\u00f3n proporcionando una contrase\u00f1a para [sa], o en cualquier otro momento en SSMS yendo a<\/p>\n<blockquote><p><strong>Server properties -> Security<\/strong><\/p><\/blockquote>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/01_server_authentication.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/01_server_authentication.png\" alt=\"\" width=\"448\" height=\"472\" class=\"aligncenter size-full wp-image-554\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/01_server_authentication.png 448w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/01_server_authentication-285x300.png 285w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/01_server_authentication-142x150.png 142w\" sizes=\"(max-width: 448px) 100vw, 448px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/02_server_authentication.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/02_server_authentication.png\" alt=\"\" width=\"692\" height=\"268\" class=\"aligncenter size-full wp-image-555\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/02_server_authentication.png 692w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/02_server_authentication-300x116.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/02_server_authentication-150x58.png 150w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\n<strong>Antecedentes<\/strong><\/p>\n<p>Es posible que la mayor\u00eda de nuestros servidores tengan ambos habilitados por lo que tarde o temprano nosotros, como DBAs, tendremos que lidiar con inicios de sesi\u00f3n de SQL, pero adem\u00e1s de proporcionar un nombre y una contrase\u00f1a (una fuerte, por supuesto) hay m\u00e1s cosas.<\/p>\n<p>Si aparte de eso, tenemos diferentes entornos, lo m\u00e1s probable es que queramos crear inicios de sesi\u00f3n diferentes para evitar que las aplicaciones o usuarios de DEV se conecten a LIVE o viceversa.<\/p>\n<p>Pero cuando tenemos inicios de sesi\u00f3n diferentes para cada entorno y, por defecto, usuarios de bases de datos, cuando necesitemos actualizar DEV (TEST, QA &#8230;) habr\u00e1 que volver a aplicar todos los permisos otorgados al usuario correcto porque ese inicio de sesi\u00f3n no existe en ese entorno. \u00bfOs suena familiar?<\/p>\n<p>En esta publicaci\u00f3n, os mostrar\u00e9 c\u00f3mo podemos manejar este problema de una manera muy simple.<\/p>\n<p>&nbsp;<br \/>\n<strong>Crear un inicio de sesi\u00f3n de SQL<\/strong><\/p>\n<p>Podemos crear un inicio de sesi\u00f3n en SQL Server Management Studio navegando a<\/p>\n<blockquote><p><strong>Server -> Security -> Logins -> New login<\/strong><\/p><\/blockquote>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/04_new_login.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/04_new_login.png\" alt=\"\" width=\"337\" height=\"298\" class=\"aligncenter size-full wp-image-558\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/04_new_login.png 337w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/04_new_login-300x265.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/04_new_login-150x133.png 150w\" sizes=\"(max-width: 337px) 100vw, 337px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/05_new_login_wizard.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/05_new_login_wizard.png\" alt=\"\" width=\"691\" height=\"626\" class=\"aligncenter size-full wp-image-559\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_new_login_wizard.png 691w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_new_login_wizard-300x272.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_new_login_wizard-150x136.png 150w\" sizes=\"(max-width: 691px) 100vw, 691px\" \/><\/a><\/p>\n<p>Como es habitual, debemos proporcionar la mayor cantidad de informaci\u00f3n posible, incluida la base de datos predeterminada y los usuarios de la base de datos asignados, no olvid\u00e9is anular la opci\u00f3n de db_owner para el nuevo usuario. Para ser sincero, no veo por qu\u00e9 est\u00e1 marcado por defecto.<\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/05_02_new_login_wizard.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/05_02_new_login_wizard.png\" alt=\"\" width=\"692\" height=\"627\" class=\"aligncenter size-full wp-image-560\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_02_new_login_wizard.png 692w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_02_new_login_wizard-300x272.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/05_02_new_login_wizard-150x136.png 150w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\nIndependientemente de si hacemos clic en \u00abAceptar\u00bb o \u00abScript\u00bb, hay algo que falta y es probablemente de lo m\u00e1s importante. Incluso una vez que el inicio de sesi\u00f3n existe y generamos el script de creaci\u00f3n, no se mostrar\u00e1.<\/p>\n<p>\u00bfYa sabes de lo que estoy hablando? Efectivamente&#8230; el SID.<\/p>\n<p>&nbsp;<br \/>\n<strong>El SID es todo<\/strong><\/p>\n<p>A diferencia de lo que la gente pueda pensar, SQL Server identifica de manera \u00fanica los inicios de sesi\u00f3n basandose \u200b\u200ben sus SID, no sus nombres.<\/p>\n<p>Los SID (identificadores de seguridad) pueden ser proporcionados por un dominio o una computadora que use Windows o por un servidor SQL Server. Esa es la clave de lo que estamos tratando de lograr. No existe un mecanismo de <strong><em>emparejamiento por nombre<\/em><\/strong>, por lo que todo se basa en el SID del inicio de sesi\u00f3n que intenta conectarse a nuestro servidor SQL.<\/p>\n<p>Los identificadores de seguridad son tambi\u00e9n el mecanismo para emparejar los inicios de sesi\u00f3n del servidor con los usuarios de las bases de datos.<\/p>\n<p>Como dije antes, no hay forma de que en SSMS generemos un script de un inicio de sesi\u00f3n de SQL Server que incluya el SID, pero por suerte hace alg\u00fan tiempo publiqu\u00e9 mi procedimiento almacenado <a href=\"https:\/\/sqldoubleg.live-website.com\/2017\/03\/14\/t-sql-tuesday-88-the-security-audit-wtf\/\" rel=\"noopener\" target=\"_blank\">[dbo].[sqlg_securityAuditServerLogins]<\/a> que hace el trabajo por m\u00ed (y por vosotros tambi\u00e9n)<\/p>\n<p>&nbsp;<br \/>\n<strong>C\u00f3mo ahorrarnos un problema<\/strong><\/p>\n<p>La mejor manera de solucionar un problema es no tener un problema, as\u00ed que veamos c\u00f3mo podemos abordar el hecho de tener diferentes inicios de sesi\u00f3n, uno por entorno que permita el acceso a la base de datos independientemente del entorno en el que nos encontremos.<\/p>\n<p>Necesitaremos:<\/p>\n<ul>\n<li>Un nombre de inicio de sesi\u00f3n por entorno, cada uno con una contrase\u00f1a diferente<\/li>\n<li>Un usuario de base de datos y <strong>solo uno<\/strong> para todos los entornos<\/li>\n<\/ul>\n<p>&nbsp;<br \/>\nEl primer inicio de sesi\u00f3n se puede hacer de cualquiera de las dos formas, usando TSQL o la interfaz de usuario, no importa. <\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [master]\r\nGO\r\nCREATE LOGIN [SalesApp_dev] WITH PASSWORD=N'StrongPassword.123!'\r\n\t, DEFAULT_DATABASE=[AdventureWorks2014]\r\n\t, CHECK_EXPIRATION=OFF\r\n\t, CHECK_POLICY=ON\r\nGO\r\nUSE [AdventureWorks2014]\r\nGO\r\nCREATE USER [SalesApp] FOR LOGIN [SalesApp_dev]\r\nGO\r\nGRANT SELECT ON [Person].[Address] TO [SalesApp]\r\n<\/pre>\n<p>Fijaos que el usuario de la base de datos no incluye _dev, porque personalmente odio encontrar cosas de _dev en mis servidores de producci\u00f3n, pero eso depende totalmente vosotros.<\/p>\n<p>Una vez que hayamos creado nuestro inicio de sesi\u00f3n, podemos ver el c\u00f3digo comandos, incluido el SID, con mi procedimiento almacenado. Simplemente despl\u00e1cese a la \u00faltima columna para encontrarlo.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nEXECUTE master.dbo.sqlg_securityAuditServerLogins @loginName = N'SalesApp_dev'\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc.png\" alt=\"\" width=\"1246\" height=\"101\" class=\"aligncenter size-full wp-image-561\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc.png 1246w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc-300x24.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc-768x62.png 768w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc-1024x83.png 1024w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2018\/07\/06_securityAudit_stored_proc-150x12.png 150w\" sizes=\"(max-width: 1246px) 100vw, 1246px\" \/><\/a><\/p>\n<p>El script generado es el siguiente<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [master]\r\nGO\r\nCREATE LOGIN [SalesApp_dev] WITH PASSWORD = 0x02001144A8F0BFE5A5C2C5E62656B13289912E02A1A483F77BD58D172F8779FBD495504D9F1196545B87983921D0629AB1DD4D0788DC1C1C813DBA66639F6FE0813010DC38DB HASHED\r\n, SID = 0xE27321DFC1DDFC4B83D0398823792E58\r\n, DEFAULT_DATABASE = [AdventureWorks2014]\r\n, CHECK_POLICY = ON, CHECK_EXPIRATION = OFF\r\nGO\r\nGRANT CONNECT SQL TO [SalesApp_dev]\r\nGO\r\n<\/pre>\n<p>Tened en cuenta que la contrase\u00f1a est\u00e1 cifrada y trae el SID. As\u00ed que lo que necesitamos cambiar para ejecutar esto en otros entornos es:<\/p>\n<ul>\n<li>nombre de inicio de sesi\u00f3n<\/li>\n<li>contrase\u00f1a<\/li>\n<\/ul>\n<p>&nbsp;<br \/>\ny eso seria todo. Ya podemos coger ese c\u00f3digo y crear el inicio de sesi\u00f3n en nuestro servidor de producci\u00f3n (si consideramos que este era nuestro entorno de desarrollo)<\/p>\n<p>Vamos a crear el inicio de sesi\u00f3n en nuestro servidor de \u00abproducci\u00f3n\u00bb, que es mi otra instancia MSSQL2016.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE [master]\r\nGO\r\nCREATE LOGIN [SalesApp] WITH PASSWORD = N'StrongPassword.456!'\r\n, SID = 0xE27321DFC1DDFC4B83D0398823792E58\r\n, DEFAULT_DATABASE = [AdventureWorks2014]\r\n, CHECK_POLICY = ON, CHECK_EXPIRATION = OFF\r\nGO\r\nGRANT CONNECT SQL TO [SalesApp]\r\nGO\r\n<\/pre>\n<p>Ahora estamos listos para ver el truco que hemos estado preparando.<\/p>\n<p>Por lo general, ser\u00eda al rev\u00e9s, pero en este caso vamos a tomar una copia de seguridad del servidor &#8216;Dev&#8217; y restaurarlo en &#8216;Prod&#8217; y luego podremos ver c\u00f3mo funciona de maravilla.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\n-- Run this in SQLDOUBLEG\\MSSQL2014 (aka dev)\r\n\r\nBACKUP DATABASE [AdventureWorks2014] TO DISK ='AdventureWorks2014_SalesApp.bkp'\r\n\r\n-- Copy the file to a location that can be accessed by the other instance\r\n\r\n-- Run this in SQLDOUBLEG\\MSSQL2016 (aka prod)\r\n\r\n\r\nRESTORE DATABASE AdventureWorks2014\r\nFROM DISK = 'AdventureWorks2014_SalesApp.bkp' \r\nWITH RECOVERY, REPLACE\r\n, MOVE 'AdventureWorks2014_Data'\tTO 'C:\\Program Files\\Microsoft SQL Server\\MSSQL13.MSSQL2016\\MSSQL\\DATA\\AdventureWorks2014_Data.mdf'\r\n, MOVE 'AdventureWorks2014_Log'\t\tTO 'C:\\Program Files\\Microsoft SQL Server\\MSSQL13.MSSQL2016\\MSSQL\\DATA\\AdventureWorks2014_Log.ldf'\r\n\r\nGO\r\n<\/pre>\n<p>&nbsp;<br \/>\nSi ahora verificamos los emparejamientos de los usuarios de la base de datos en los diferentes servidores, podemos ver que se corresponden con los inicios de sesi\u00f3n correctos<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\n-- Run in SQLCMD mode\r\n:CONNECT SQLDOUBLEG\\MSSQL2014\r\n\r\nUSE AdventureWorks2014\r\n\r\nSELECT @@SERVERNAME AS server_name\r\n\t\t, p.name AS dbuser_name\r\n\t\t, p.sid AS dbuser_sid\r\n\t\t, SUSER_SNAME(p.sid) AS login_name\r\n\tFROM sys.database_principals AS p\r\n\tWHERE name = 'SalesApp'\r\n\r\nGO\r\n\r\n:CONNECT SQLDOUBLEG\\MSSQL2016\r\n\r\nUSE AdventureWorks2014\r\n\r\nSELECT @@SERVERNAME AS server_name\r\n\t\t, p.name AS dbuser_name\r\n\t\t, p.sid AS dbuser_sid\r\n\t\t, SUSER_SNAME(p.sid) AS login_name\r\n\tFROM sys.database_principals AS p\r\n\tWHERE name = 'SalesApp'\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/07_db_users_mapping.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2018\/07\/07_db_users_mapping.png\" alt=\"\" width=\"1014\" height=\"192\" class=\"aligncenter size-full wp-image-562\" \/><\/a><\/p>\n<p>Y es como, mis queridos lectores, podemos atajar este problema tan com\u00fan sin tener que volver a correlacionar los inicios de sesi\u00f3n y los usuarios cada vez que restauran una base de datos de un entorno a otro.<\/p>\n<p>&nbsp;<br \/>\n<strong>Conclusi\u00f3n<\/strong><\/p>\n<p>Aunque es recomendable utilizar la autenticaci\u00f3n de Windows siempre que sea posible, existen motivos leg\u00edtimos para usar los inicios de sesi\u00f3n de SQL, para eso existen, pero con un poco de conocimiento de los mecanismos internos, podemos hacer que su mantenimiento sea un poco m\u00e1s f\u00e1cil.<\/p>\n<p>\u00a1Gracias por leer!<\/p>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>En este post quiero mostrar como podemos administrar inicios de sesion en SQL Server para evitar un problema bastante comun&nbsp;En SQL Server tenemos la posibilidad de autenticarnos de dos maneras diferentes, una&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,9],"tags":[22,59,12],"_links":{"self":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/553"}],"collection":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/comments?post=553"}],"version-history":[{"count":0,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/553\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/media?parent=553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/categories?post=553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/tags?post=553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}