Hi forum,
first a big picture: I've got a csv-file with app. 500 Servers.
The task is to: connect to every server, collect all user-accounts having anything to do with SQL-Server services.
Then loop the user-accounts list - only if it's a domain user - and using Get-ADUser get the information about the account as: PasswortLastSet, Expiration etc. Then write all the informations to a sql server table.
I've got the first (working) draft. What I don't like is: in the time I'm collecting the data the connection to the sql server is whole the time open (it takes about 25 min. to accomplish the task..). I suppose I could: put the information termporarily in a csv-file and after complition read it back and then make insert in the table and delete the file. But it's not that cute. Maybe to create a DataTable, an ArrayList or something?
Thanks for your help.
Purclot
the code:
first a big picture: I've got a csv-file with app. 500 Servers.
The task is to: connect to every server, collect all user-accounts having anything to do with SQL-Server services.
Then loop the user-accounts list - only if it's a domain user - and using Get-ADUser get the information about the account as: PasswortLastSet, Expiration etc. Then write all the informations to a sql server table.
I've got the first (working) draft. What I don't like is: in the time I'm collecting the data the connection to the sql server is whole the time open (it takes about 25 min. to accomplish the task..). I suppose I could: put the information termporarily in a csv-file and after complition read it back and then make insert in the table and delete the file. But it's not that cute. Maybe to create a DataTable, an ArrayList or something?
Thanks for your help.
Purclot
the code:
If(-not(Get-Module -Name ActiveDirectory))
{
Import-Module -Name ActiveDirectory
}
# Open SQL connection (you have to change these variables)
$DBServer = "mySQLServer\SQL01"
$DBName = "Central_Management"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server=$DBServer;Database=$DBName;Integrated Security=True;"
$sqlConnection.Open()
# Quit if the SQL connection didn't open properly.
if ($sqlConnection.State -ne [Data.ConnectionState]::Open) {"Connection to DB is not open."
Exit
}
$sqlCommand = New-Object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$servers = Import-Csv -Path C:\Users\XXX\Desktop\Get-ExpirationDates\Liste.csv -Delimiter ","
foreach($server in $servers)
{
try
{
$accounts = gwmi win32_service -ComputerName $server.server_ip | select name ,
@{N="Startup Type";E={$_.StartMode}},
@{N="Service Account";E={$_.StartName}},
@{N="System Name";E={$_.Systemname}} | where-object{$_.Name -like '*sql*'} | Sort-Object "Name"
}
catch [System.Exception]
{
("win32_service error, Server: " + $server.server_name + " " + $_.Exception.Message) | out-File -FilePath C:\Users\W9A01RG9\Desktop\Get-ExpirationDates\Errors.txt -Append
}
foreach($account in $accounts)
{
$dbviewID = [int]$server.dbview_id
$serverName = [string]$server.server_name
if($server.instance_name -eq "")
{
$serverInstance = "DEFAULT"
}
else
{
$serverInstance = $server.instance_name
}
$sqlService = $account.Name
$accountName = $account."Service Account"
$splitter = $account."Service Account".Split("\")
if($splitter[0] -like 'ww*')
{
$output = ADPasswordExpiration -SamAccountName $splitter[1] -dns $splitter[0]
$isDomainAccount = 1 #isDomainAccount
$passNeverExpires = $output[2].PasswordNeverExpires
$passLastSet = $output[2].PasswordLastSet
$passExpired = $output[1]
$expDate = $output[0]
$accountCreated = $output[2].Created
$accountDescription = $output[2].Description
$displayName = $output[2].DisplayName
$accountSN = $output[2].sn
$trustedForDelegation = $output[2].TrustedForDelegation
$trustedToAuthForDelegation = $output[2].TrustedToAuthForDelegation
$sqlCommand.CommandText =
@"
SET NOCOUNT ON;
INSERT INTO dbo.AccountsInventory
(DBViewID, SQLServerName, InstanceName, SQLService, AccountName, isDomainAccount, PasswordNeverExpires, PasswordLastSet, PasswordExpired, ExpirationDate,
AccountCreated, AccountDescription, DisplayName, Account_SN, isTrustedForDelegation, isTrustedToAuthForDelegation)
VALUES ('$dbviewID', '$serverName', '$serverInstance', '$sqlService', '$accountName', '$isDomainAccount', '$passNeverExpires', '$passLastSet', '$passExpired', '$expDate',
'$accountCreated', '$accountDescription', '$displayName', '$accountSN', '$trustedForDelegation', '$trustedToAuthForDelegation')"@
$sqlCommand.CommandText
}
else
{
$isDomainAccount = 0 #isDomainAccount
$sqlCommand.CommandText =
@"
SET NOCOUNT ON;
INSERT INTO dbo.AccountsInventory(DBViewID, SQLServerName, InstanceName, SQLService, AccountName)
VALUES ('$dbviewID', '$serverName', '$serverInstance', '$sqlService', '$accountName') "@
$sqlCommand.CommandText
}
try
{
$sqlCommand.ExecuteNonQuery()
}
catch [Exception]
{
("sqlCommand.Execute error, Server: " + $server.server_name + " " + $_.Exception.Message) | out-File -FilePath C:\Users\W9A01RG9\Desktop\Get-ExpirationDates\Errors.txt -Append
}
}
}
if ($sqlConnection.State -eq [Data.ConnectionState]::Open)
{
$sqlConnection.Close()
}
Function ADPasswordExpiration([String]$SamAccountName, [string]$dns)
{
#Password never expires? It'll be changed anyway once per year, so we take 365 days, add it to create date and get Expiratin date!
$wholeYear = 365
if($(Get-ADUser $SamAccountName -server $dns -Properties PasswordNeverExpires).PasswordNeverExpires)
{
$MaxPasswordAge = $wholeYear
}
else
{
$MaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy -server $dns).MaxPasswordAge.TotalDays
}
$PasswordBeginDate = (Get-ADuser $SamAccountName -server $dns -properties *).PasswordLastSet
$PasswordExpriyDate = ($PasswordBeginDate).AddDays($MaxPasswordAge)
$PasswordExpired = $((Get-Date).AddDays(0) -gt $PasswordExpriyDate)
$ADPasswordInfo = Get-ADUser -Filter {Enabled -eq $true -and SamAccountName -eq $SamAccountName} -server $dns -Properties *
return [array]$a = $PasswordExpriyDate, $PasswordExpired, $ADPasswordInfo
}