How to get the value of a user's CHECK_EXPIRATION property? - sql-server

ALTER LOGIN allows one to change the CHECK_EXPIRATION property associated with an account, but how does one get the existing value of this property for an arbitrary user?

You can get this data through the LOGINPROPERTY() system function:
select loginproperty('your_login_name', 'daysuntilexpiration');
If you want to see if the SQL logins is subject to expiration, just check sys.sql_logins:
select name, is_expiration_checked
from sys.sql_logins;
Note: As per the documentation on CHECK_EXPIRATION, this only applies to SQL logins, not Windows logins. If you need to get this expiration for Windows accounts, then I recommend you create programmatic logic (outside of SQL Server) to grab the login(s) from SQL Server, and then make AD calls to get expiration date. To do this with PowerShell, this seems to be a good blog post on a quick methodology.

Related

Pass through Windows user for Datazen SQL Server data sources?

Is it possible to pass-through Windows User logins from Datazen through to SQL Server?
Scenario:
I created a Dashboard which uses a SQL Query as a data source.
The data source is of type "SQL Server" and the flag Integrated Security is set to YES.
I've also configured the data source to be "Real Time," to avoid any issues with caching.
I'm expecting the data view to execute on SQL Server with the credentials of the user which is browsing the final dashboard, unfortunately this is not the case.
Problem:
In this scenario the authentication against SQL Server is now done with the Windows user account, under which the Service "Datazen Server Data Acquisition Service" is running. I would expect that the "Acquisition Service" will delegate the effective user. Is this possible? Or will the authentication always be done with the service account?
I know about the "personalize for each member" setting, which passes-through the username to a data view query, but this is not the same as my requirement (leverage existing MSSQL-DB-Security for effective windows-users).
Your observations are correct that by default, the service account will be recognized as being logged into SQL Server.
There's no way to get around that with settings, but you can use some T-SQL magic to switch users at runtime. You have to lead your queries with an EXECUTE AS statement, like so:
EXECUTE AS USER = 'DomainName\' + '{{ username }}'
SELECT TOP 1 login_name -- This is just a nice quick test to echo the username.
FROM sys.dm_exec_sessions -- You can swap it out for your real query.
WHERE session_id = ##SPID
This, of course, also requires the "Personalize for each Member" setting to be turned on, so that the username is passed through.
It's pretty self-explanatory what's going on here, but basically you have to explicitly impersonate the request via your service account, as SQL Server will be connected to via the database using that account. Once you run this EXECUTE AS statement, it will use that user account for the remainder of the session.
Note that your service account will need permission the IMPERSONATE permission set, or else this will fail. It will also fail, of course, for any users that exist in your Datazen Server but do not have permissions against your SQL Server, and vice-versa. That's definitely the desirable behavior, but it's worth keeping in mind if you ever add users to one, you'll also have to add them to the other.
Disclaimer: I'm a Microsoft Support professional, paid to support Datazen.

SQL Server Execute As Requires Individual Logins

Evening,
I would like some practical confirmation in relation to an issue we are having.
We have a K2/SourceCode solution that turns upon the successful use of EXECUTE AS with Sql Server 2008 R2.
We have no direct control over how this solution is implemented, i.e. we cannot modify the queries that are submitted to the Sql Server engine. We can, of course, capture them using Profiler, and they tend to follow this pattern:
DECLARE #cookie VARBINARY(100);
EXECUTE AS LOGIN = 'DOMAIN\username' WITH COOKIE INTO #cookie;
SELECT #cookie;
exec [dbo].[SomeStoredProcedure] /* ... various params ...*/
exec sp_executesql N'REVERT WITH COOKIE = #cookie;',N'#cookie varbinary(100)',#cookie=/* some cookie value */
So what is happening is that [SomeStoredProcedure] is being executed in the security context of the user [Domain\username], with the service (application) account impersonating that user. Again, I emphasise that we have no control over this pattern. That's what the app does.
Outwardly this behaviour is perfectly-desirable, because we want things arranged in such a way that the stored procedure is effectively executed by whichever user is at the front-end of the application at the time.
However, these queries were consistently failing, and our investigation eventually led us to this, from the Sql Server documentation (my emphasis):
Specifying a User or Login Name
The user or login name specified in EXECUTE AS must exist as a principal in
sys.database_principals or sys.server_principals, respectively, or the
EXECUTE AS statement fails. Additionally, IMPERSONATE permissions
must be granted on the principal. Unless the caller is the database
owner, or is a member of the sysadmin fixed server role, the principal
must exist even when the user is accessing the database or instance of
SQL Server through a Windows group membership. For example, assume the
following conditions: CompanyDomain\SQLUsers group has access to the
Sales database. CompanyDomain\SqlUser1 is a member of SQLUsers and,
therefore, has implicit access to the Sales database. Although
CompanyDomain\SqlUser1 has access to the database through membership
in the SQLUsers group, the statement EXECUTE AS USER =
'CompanyDomain\SqlUser1' fails because CompanyDomain\SqlUser1 does not
exist as a principal in the database. If the user is orphaned (the
associated login no longer exists), and the user was not created with
WITHOUT LOGIN, EXECUTE AS will fail for the user.
We have a group of around 30 end users who need to be able to use this application, and the requirement is that the application security account must be able to impersonate any one of those users for the execution of these stored procedures. This requirement is fixed and non-negotiable.
The above documentation seems to preclude the possibility of meeting this requirement by adding all 30 users to an AD group, adding that group as a SQL Server login, and granting the group adequate permissions. And our practical testing results support this - EXECUTE AS fails.
Take one of those Users and give them their own, individual AD login on the Sql Server and the solution will work successfully for that user. EXECUTE AS succeeds, and the necessary permissions do not need to be assigned to the individual account because they have already been assigned by way of the AD group.
So, at this point, I am reasonably confident that I know what I am going to have to do. The requirement will be that every user has to have their AD account added as an individual Sql Server Windows login.
However, before I proceed with the rigmarole of implementing this, I wanted to ask the question publicly: is there something I am missing here?
It's instructive to imagine a similar scenario on an Enterprise-scale application - this model would somewhat fall apart, because of the need to add hundreds of individual, Windows-authenticated, Sql Server logins. Setting aside the possibility of automating this process, and the administrative burden that would ultimately result, I'm just finding it a bit of a stretch to imagine that this is the only way.
I would be grateful for confirmation and/or comments.
Thanks
Robert
As no-one has responded to the contrary (or indeed at all) we have assumed that BOL is accurate, and that there is no alternative resolution.

SQL Server: Checking role membership

In SQL Server I have a many to many relationship between items and active directory groups. I want to build a query, that based on a supplied active directory user, I would be able to query for all items associated to an active directory group if the user is a member of the group.
I went down the road of using IS_Member, but that only works for the currently connected user. The stored procedure will be called by an asp.net web app, which currently connects with a specific sql user account. I don't think I can connect using integrated authentication and impersonation in the web app, because I don't beleive our infrastructure configuration will allow delegation from the user machine, through the web server, then to the db server (3 hop issue).
What can I do here?
Write a C# or VB.NET .exe that queries AD and populates a table in the database with all the users/groups and call it from a SQL job that you execute daily. Then just use the synched up table data to do the comparisons. This way you can avoid all the other complexity of trying to do it on the fly. Group membership doesn't change that often. Even if something changed in AD you can just manually run your "sync job" and things would be ok. You can use Windows.Identity() or whatever it is from ASP.NET to check the username.
The issue you describe is a classic double-hop scenario, which can be (eventually) resolved through the painstaking process known as Kerberos configuration. A lazier workaround would involve passing the credentials from the asp.net application as a variable to a SQL query on your database.
If the SQL Server has the LDAP Server configured as a linked server, you could rewrite your stored procedures to accept the user as an input variable and check to see if the user is a member of an AD group before proceeding. Consider incorporating OPENQUERY into your stored procedures as shown below:
CREATE PROCEDURE CheckAccess
#CurrentUser varchar(max)
AS
IF #CurrentUser IN
(
SELECT CN
FROM OPENQUERY(ADSI,'<LDAP://DC=Your,DC=DomainComponent,DC=com>;(&(CN=*)
(memberOf=CN=YourADGroupName,OU=Your,OU=OrganizationalUnit,OU=Name,DC=Your,DC=DomainComponent,DC=com));CN')
)
THEN
SELECT 'Authorized User'
ELSE
SELECT 'Unauthorized User'
END
If you can, consult with your LDAP admins to make sure you get the group's correct domainComponents and organizationalUnits to tweak the OPENQUERY. One drawback to this is that it can take a while to query your AD group, obviously depending on the size of membership. It can be a pain, but as long as your app can pass the user as a variable, you can leverage OPENQUERY or even query sys.database_principals to check their access.

Using Security Extension for certain reports only

My team has a service deployed internally, and part of this service is a list of client accounts stored in a sql table. SSRS is hosted on another server and we have integration jobs which [will eventually] pull these client accounts (along with additional info) from our 3 production environments to this SSRS database.
Also on this SSRS database, I’m creating a new table that will be a mapping of domain accounts and client accounts. I need this table so I can filter my report based on which client accounts the logged on user is allowed to see.
Pretty simple so far.
The next requirement of this is that I need to restrict access to the report itself. I understand I could normally use a security group to do this, but that would result in two separate locations to manage permissions for one resource and this is what I want to avoid.
The solution I’m looking into is to create a security extension to validate the logged in user against the database, allowing them access to the folder/report if they exist in the table. Once in, I can then use that same table again to filter their results.
What I’m not sure of is 1) if this is the best solution and 2) can I use a security extension for just MY portion of the site. There are many other users and reports on this site that I don’t deal with and don’t want to conflict with those.
Could you fill the DB table automatically from AD? Then you can use the standard windows security, but still only do the administration in Active Directory.
link text
You could set up an internal report parameter, called something like UserID, and set its default value to be the non-queried expression =User!UserID . (This user ID can be selected from the list of globals in the Edit Expression dialog.)
You could then add a cartesian/cross join to your users table in your query, with a selection condition based on your internal report parameter - eg. ...and UserTable.ID = #UserID . This would ensure that no records were returned if an unauthorised user was running the report.
Note that the User!UserID field will only return the user for interactively-run reports - in scheduled reports, this will be the account for the scheduling service.
Can't you restrict access to the report by using a security group (either in it's own folder or report level permissions). Use windows authentication in your datasource connection and filter you report retrieving your username using the sql function ORIGINAL_LOGIN?

SQL Server 2005/2008: Identify current user

I have a web application, which is using a SQL Server 2005 database.
My problem is, that the application has no role management. So the application always accesses the database with one default user. But now I have to save and access a value only for the current user.
Is there any way to do this? Maybe something like a session on the web server? The best way would be, if there is any possibility to access the current session id of the web server from T-SQL.
Do anyone understand my problem? :)
Allows a system-supplied value for the current login to be inserted into a table
DECLARE #sys_usr char(30);
SET #sys_usr = SYSTEM_USER;
SELECT 'The current user is: '+ #sys_usr;
GO
from MSDN
In my opinion, it's better don't do this. Another way: send to stored procedure current user from web sever:
command.CommandText = "EXEC mySP #user";
command.Parameters.Add("#user").Value = ((YourOwnUserClass)Session["user"]).Name;
// or System.Web.HttpContext.Current.User.Identity.Name; to use built-in
// from web page it becomes this.User.Identity.Name;
If you are using Windows integrated authentication instead of SQL accounts:
Give schema object permissions to a Windows group, not a user. Then add all of your application users to this group.
Use the built-in SUSER_NAME() function to retrieve the underlying Windows user name (in loginDomain\userName format.

Resources