For a SQL Server instance, to check if a windows user is present and has any access or not one can try various ways as detailed here.
I'm looking for something similar for SQL Server Analysis Services (SSAS) server.
I went into properties of SSAS Server from right-click context menu and on Security tab I can see that there are several windows users already configured:
Is there any way to check from a client application (written in C#) by making some sort of test connection or does SSAS also maintains some metadata database of its own like master
database in SQL Server instance (DB engine) which can be queried. I checked the Databases
node in SSAS server but I don't see any default databases there:
In the client application I'm working upon, I've windows user name and password as input. In my client application there is a simple winform with two text boxes to take AD user name and password which need to be connected to a SSAS Server. My gut feel is that password is of no relevance here as SSAS supports only Windows
integrated authentication mode. My client application would be running under an account which already has access to SSAS server I'm trying to connect.
Update: After getting help from @Vaishali, I'm able to figure out that it is possible to make a test connection to an SSAS server using ADOMD.Net.
Now, the problem here is that the connection string implicitly uses the AD account of the user with which I'm running the client application to connect to the SSAS server. I don't think it would be possible mention an windows AD account user name and password explicitly in the ADOMD.Net connection strings while using Windows Integrated authentication. Even connection strings of SQL Server don't allow mentioning the windows username and password explicitly in the connection string as mentioned here.
Update 2: I have got a lead from one of my friends that it is possible to fire some MDX query on SSAS to get user access details.
Update 3: SSAS server supports only Windows Integrated Security mode of authentication unlike SQL Server DB engine which also supports userid-password based SQL authentication. So, some form of impersonation would be required to fire MDX queries on behalf of other user for which I'm trying to check access on SSAS server through Windows Integrated Security only.
Hmphh...It was quite a journey to really be able to nail it through ADOMD.Net.
Core methodology: The core philosophy is the fact that connection to SSAS server supports only Windows Integrated Security based authentication. The SQL authentication like we do for sa
user in SQL Server isn't supported in SSAS.
So, the basic idea was to try to connect to the SSAS server using Windows Integrated Security based authentication and fire an MDX query in the context of the user we are trying to check. If the query gets executed successfully then the user has access. If the query execution returns an error/exception then the user doesn't have access.
Please note that just to be able to open a connection to the SSAS server is not an indicator of user-access due to reasons described here. You must fire a query to check access.
For ADOMD.Net until v12.x:
Now, we know that Windows Integrated Security based authentication always takes the user details from the user-context under which the application/process is running. You can not pass the user credentials in the connection string of ADOMD.Net connection. Here is the code I wrote to accomplish it. You need to refer to Microsoft.AnalysisServices.AdomdClient.dll
in your C# project.
using Microsoft.AnalysisServices.AdomdClient;
public static int IsSsasAccessibleToUser(string ssasServerName)
{
var hasAccess = 0;
try
{
using (var adomdConnection = new AdomdConnection($"provider=olap;datasource={ssasServerName};Catalog=myDatabaseName"))
using (var adomdCommand = new AdomdCommand())
{
adomdCommand.CommandText = "SELECT [CATALOG_NAME] AS [DATABASE],CUBE_CAPTION AS [CUBE/PERSPECTIVE],BASE_CUBE_NAME FROM $system.MDSchema_Cubes WHERE CUBE_SOURCE = 1";
adomdCommand.Connection = adomdConnection;
adomdConnection.Open();
adomdCommand.ExecuteNonQuery();
Log("ExecuteNonQuery call succeeded so the user has access");
hasAccess = 1;
}
}
catch (Exception ex)
{
Log("There was an error firing query on the database in SSAS server. so user doesn't have access");
}
return hasAccess;
}
Now, to leverage Windows Integrated Security based authentication we can run this code in two ways:
WindowsImpersonationContext
and WindowsIdentity
. Creator of this NuGet package had first posted a great answer here.Observation in SQL Server Profiler: After you've impersonated user Y
, you will clearly see the MDX query getting fired in the context of user Y
if you capture the session as shown below:
Caveats and concerns:
LogonUser
API (using LOGON32_LOGON_NEW_CREDENTIALS LogonType) which is called during impersonation calls by the NuGete package. You can try other logon types as detailed here which suites you need.For ADOMD.Net v13.x onwards
Then, I came across this ChangeEffectiveUser
API documentation on MSDN here. But, intellisense wasn't showing this API. Then I found out this API got added in ADOMD.Net with SQL Server 2016 release. There are various ways to get the latest release:
C:\Program Files\Microsoft.NET\ADOMD.NET\130\Microsoft.AnalysisServices.AdomdClient.dll
I'm not sure who dumps this file at this location. Is it part of Microsoft.Net extensions or SQL Server installation.C:\Program Files\Microsoft SQL Server\130\Setup Bootstrap\Update Cache\KB3182545\ServicePack\x64\Microsoft.AnalysisServices.AdomdClient.dll
Unofficial.Microsoft.AnalysisServices.AdomdClient
. Not sure why they introduced a separate NuGet package with Unofficial
prefix when this should have been simply the next version of the already existing NuGet package Microsoft.AnalysisServices.AdomdClient
present here.So the new API ChangeEffectiveUser
present in latest version on AdomdConnection
clas can be used easily to impersonate any user as below:
adomdConnection.Open();
//impersonate the user after opening the connection
adomdConnection.ChangeEffectiveUser("domainName\UserNameBeingImpersonated");
//now the query gets fired in the context of the impersonated user
adomdCommand.ExecuteNonQuery();
Observing Impersonation in SQL Server Profiler: Although one peculiar observation I had in the SQL Server Profiler is that the logs of query being fired still shows the name of the original user with which your application process is running.
So to check whether impersonation is happening or not I removed the access rights of the user domainName\UserNameBeingImpersonated
from SSAS server. After that, when I ran the above code again then it resulted in exception whose message clearly states that - the user domainName\UserNameBeingImpersonated doesn't have permission on the SSAS server or the database doesn't exist
. This error message clearly suggests that impersonation is working.
Advantages and Backward compatibility of this approach:
What to do if we simply want to check the access on the SSAS server without involving any database present on the SSAS server?
Catalog
key as following connection string - "provider=olap;datasource={ssasServerName};"SELECT * FROM $System.discover_locks
in the code snippet shown initially in the post.