Get all logged in users / Check their AD groups

by maglor at 2013-01-08 18:45:59


Noob here trying to come up with a powershell solution for a server i look after. Ill give you a run down of the problem first and then what i think it is i want to do as a solution, but i am very open to a better way if anyone knows of one.

Situation is that the client thinks he knows what he is doing on the server, however, he keeps breaking things and i end up spending hours trying to figure out what he broke as he deny’s that he was even on the server (even though i can see his account in the logs). So what i am wanting is a script that either runs on every login (including RDP logins) or every 5minutes (for example) that checks for all current logged in user accounts to the server (including RDP logins), from that list of users it then checks that against AD to see if any of them are a member of the Domain Admins Group and if so create a file with login time, account name and any other useful snipets of information available and/or emails me.

The reason i cannot check for just a specific account, is that after telling him that i saw his account log in through the logs he is now making new admin accounts and also giving external people admin accounts also. The whole situation is very frustrating and he is doing all this to save a few dollars, by getting people from overseas to do "work" for him.

I already have a means of making the script run every 5 minutes and a way to read a file for specific keywords and then trigger an email if it exists however if there is a way to just make this happen from inside the script that would be great also.

I have dug around the interwebz and found individual scripts that seem to do each individual step but i cant seem to mash them together properly. I am also reading the Powershell 2 for dummy’s book however i think what im trying to do is a bit too advanced and isn’t really covered in the book.

Thanks in advance for any help.

by DonJ at 2013-01-09 07:03:56
Well, lets start with one piece that you don’t know how to do and go from there. Where would you like to start?
by maglor at 2013-01-11 16:04:26
Hi DonJ,

Thanks for your reply. Apologies for net getting back sooner but i have been in hospital with a pesky heart condition :frowning:

What i have found so far is this nice little function

function get-loggedonuser {
param (
[string]$computername = $env:COMPUTERNAME
Get-WmiObject -Class Win32_LogonSession -ComputerName $computername |
foreach {
$data = $_

$id = $data.__RELPATH -replace """", "'"
$q = "ASSOCIATORS OF {$id} WHERE ResultClass = Win32_Account"
Get-WmiObject -ComputerName $computername -Query $q |
select @{N="User";E={$($.Caption)}},

This seems to give a pretty good output i think and

$names = Import-CSV C:\Temp\contact2.csv
$numberof = $names.Length
Import-Module ActiveDirectory
write-host There are $numberof names in list
foreach ($username in $names) {
Get-ADUser -Identity $username.SamAccountName -Properties memberof | select -ExpandProperty memberof
# Get-Module -ListAvailable


which instead of the csv import i was going to try and use the function. Where i am stuck is passing just the account names part of the function to the $names variable, i would also like to be able to remove default accounts ie system / local service / network service etc to save time looking them up. And then do a search on the results returned from the second piece of code for domain admins. If it exists then send me an email, i have seen a script with this before but i cant seem to find it in amongst all the scripts I’ve been saving.

**note i haven’t been able to test the second script, but I’m fairly sure it does what I’m looking for.

by DonJ at 2013-01-11 16:32:19
Yeah, the problem with Win32_LogonSession is that it contains a lot of that. You’d have to make a manual list and filter them out. E.g.

Get-LoggedOnUser | Where { @("SYSTEM","NetworkService") -notcontains $
.Name }

That’ll filter out whatever names you add to that array.

I’ve no idea what you mean by "passing just the account names part of the function to the $names variable." Sorry.

Do you mean just extracting the names from the Get-LoggedOnUser function?

Get-LoggedOnUser | Where { @("SYSTEM","NetworkService") -notcontains $_.Name } | Select -Expand name

Will do that.

You put a bunch of other "I’d like to" stuff in there… again, it’s a lot easier if you ask just one question. How do I ____? I can help with one question, and then we can move on to the next. Trying to absorb all of your requirements and produce a complete answer for you is called "paid consulting" <grin>.

At the risk of a plug, you might look at Learn Windows PowerShell 3 in a Month of Lunches (my book). It covers a lot more of the techniques you’re asking about. Part of what I sense you’re struggling with is that you’re just grabbing stuff from the Intertubes without really knowing what they’re doing, and you need to solve that. I know it’s an investment, but I’m pretty sure you think it’s worth it, too.

Like, I’d rather you say, "hey, I’ve got this logged-on user function… can you explain what it’s doing?" So that you can then know enough about it to start tweaking it for your own nefarious purposes.

Good luck!
by DonJ at 2013-01-11 16:36:01
Oh, and Write-Host = bad. Like, going-to-Hell bad, in this context. You will want to move beyond Write-Host. The functional code you actually need is this:

foreach ($username in $names) {
Get-ADUser -Identity $username.SamAccountName -Properties memberof | select -ExpandProperty memberof

Which leads to…

Get-LoggedOnUser | Where { @("SYSTEM","NetworkService") -notcontains $
.Name } | Select -Expand name | ForEach { Get-ADUser -Identity $
-Properties MemberOf | Select -Expand MemberOf }

Now, if that one-liner works for you, awesome. If you can’t explain to yourself WHY it works for you… please, please, please ask. I’d rather teach you why that works than just hand you something.