onsdag 22 augusti 2018

ERROR NT AUTHORITY\ANONYMOUS LOGON när du autentiserar mot SQL server

Något som jag ser ofta hos kunder är detta problem som har med autentisering att göra när man missat att konfigurera kerberos och trusted for delegation i sin miljö. Tänker varje gång att jag skall dokumentera ner det och nu gör jag slag i saken.

Lite bakgrund
När du sätter upp en SQL miljö och använder en vanlig domänanvändare som service konto så måste man skapa SPN-s manuellt för att kunna använda kerberos autentisering, om inte så är det NTML. (En annan fråga är ju om man skall använda domänkonton som servicekonto numera men det är vanligt att man gör då det tidigare varit rekommenderat.) Använder man sedan andra SQL produkter som Reporting services, Analysis services och kör dessa på egna servrar, vilket man bör göra om det skall vara bets practices, så kommer du troligtvis få autentiserings problem.

Exempel
Låt oss säga att en klient kör Explorer mot en rapport på en Reporting services server som i sin tur har en datasource som autentisera sig mot en SQL server med windows autentisering (”As the user viewing the report” heter det i rapport konfigureringen) där databasen ligger. Du har nu en autentiserings kedja eller en så kallad dubbel hopp. Detta är inte möjligt att göra med vanlig NTML utan det måste vara kerberos.
















Konfigurering
Så hur skall detta konfigureras för att fungera? Först av allt så skall SPN sättas på respektive servicekonto för både SQL servern och Reporting services servern. I mitt fall så har jag två servrar, SQLServer och SQLRSServer med respektive servicekonto SQLService, SQLRSservice. Domainname och domain är domänen som servrarna ligger i.
Följande SPN-er skall då sättas:

SETSPN -s MSSQLSvc/SQLServer.domainname.com:1433 domain\SQLService
SETSPN -s MSSQLSvc/SQLServer.domainname.com domain\SQLService
SETSPN -s http/SQLRSServer.domain.com domain\SQLRSService

Nu är tjänsterna ok för att använda kerberos autentisering. Starta om och verifiera anslutningarna med tex denna query i SQL:

select c.auth_scheme, c.client_net_address, s.program_name from sys.dm_exec_connections c
inner join sys.dm_exec_sessions s
on c.session_id = s.session_id
where c.session_id >50

Men vi måste också konfigurera så Rapportservern kan skicka autentiserings frågan vidare till SQL servern från klienten. Detta görs med det som heter ”trusted for delegation” i Active Directory verktyget. På kontot för Reporting services väljer man enklast “Trust this user to any service”. Eller om man är en säkerhetsnörd så kan man peka ut exakt vilken service som skall får autentisera sig via kontot. Bläddra upp de tidigare SPN registreringarna på kontot för SQL och lägg till dessa. Se den nedre bilden.

















































Mer information från Microsoft kring hur du gör detta för Reporting services. Det är ytterligare justering i configurationsfilen för reporting som måste ändras. Dock nämns inget om trusted for delegation vilket är konstigt.
https://docs.microsoft.com/en-us/sql/reporting-services/report-server/register-a-service-principal-name-spn-for-a-report-server?view=sql-server-2017

torsdag 29 mars 2018

Hämta information från flera servrar med SSIS

Tänkte dela med mig om ett bra användningsområde som man som DBA kan nytta av när det gäller SSIS. Allt som oftast vill vi hämta information från våra servrar. Har vi inget system för detta så få vi användar det som finns att tillgå i SQL. Antingen Centralmanagement Server eller SSIS ser jag som det som fungera bäst. I detta fallet så kommer jag visa hur man använder SSIS och en sk Foreach Loop för att hämta det datat vi vill har. Själva listan på alla servrar får jag med en query mot en Centralmanagement Server.

Tanken är att Connection Managern som skall koppla upp sig mot respektive server för informations inhämtningen skall vara dynamisk. I detta fall behöver Server Name samt Initial Catalog vara dynamiska.

Låt oss starta med att lägga till en Execute SQL Task i paketet. Samt de nödvändiga variablerna. Det är viktigt att dessa variabler är av rätt datatyp.













Execute SQL Task konfigureras enligt följande med en Connection Manager som pekar på listan med servrar.


































Variabeln för att spara datat från queryn med serverlistan sätts under ResultSet. Detta är allt som behöver göras på Execute SQL Task.


































Nästa steg är att lägga till en Foreach Loop kontainer. Denna konfigureras enligt följande. Tanken är att den använder datat som vi hämtar i Execute SQL Task. I Foreach Loop kontainern lägger vi också till en Data Flow Task.





















För att använda oss av serverlistan vi generera från Execute SQL Task skall Enumeration vara en Foreach ADO Enumerator. Mappa sedan variabeln objServerList vi skapat tidigare enligt nedan.


































Under Variable Mappings mappar vi de andra variablerna också. Det vi behöver för att använda en dynamisk connection manager är ServerName och DBName.



































I Data Flow Task konfigurera vi sedan en vanlig OLEDB Source och en OLEDB Destination och knyter dessa till varsin Connection Manager.


















Om vi nu markera vår "source" Connection Manager, i mitt fall SourceQuery så väljer vi att göra den dynamisk. Under properties skall det se ut så här. Knyt variablerna till ServerName och InitialCatalog i Expression Editorn genom att klicka på den lilla fyrkanten i höger överkant.














Gå sedan in på respektive property och knyt variabeln till den.




























































Nu är hela lösningen klar och redo att användas.