{"id":64,"date":"2018-06-09T21:03:33","date_gmt":"2018-06-09T21:03:33","guid":{"rendered":"http:\/\/www.spktechfit.com\/?p=64"},"modified":"2018-06-09T21:03:33","modified_gmt":"2018-06-09T21:03:33","slug":"powershell-automating-exiting-users","status":"publish","type":"post","link":"https:\/\/www.spktechfit.com\/?p=64","title":{"rendered":"Powershell: Automating Exiting Users"},"content":{"rendered":"<h1>Introduction<\/h1>\n<p>I have being playing around with Powershell a lot more lately and trying to learn and utilise it as much as possible. One of the repetitive tasks we deal with is when a student exits the school. There are a number of steps in AD that have to be undertaken each time a student leaves. These include:<\/p>\n<ul>\n<li>Disable the account<\/li>\n<li>Move the account to a &#8216;Disabled&#8217; ou<\/li>\n<li>Remove the account from all Groups except &#8216;Domain Users&#8217;<\/li>\n<li>Hide the user in the Exchange Address List<\/li>\n<\/ul>\n<p>I knew it would be pretty easy to get a Powershell script to carry out these tasks, the tricky bit was going to be getting it automated so I have to do a as little as possible. I could enter the usernames that were to be disabled, but even better would be to get a scheduled task going that would check for users to be disabled and then carry out the tasks.<\/p>\n<p>Our school uses the SIMON system to manage students. When a student is leaving the administration staff update this in SIMON and IT get an email notifying us to disable the accounts. SIMON has an MS SQL back-end so I figured if I could pull the information on the students who were leaving, I could pass this to my Powershell script to process their accounts.<\/p>\n<h1>High Level Steps<\/h1>\n<ol>\n<li>Powershell script runs which queries the SQL database to see if any students are flagged to have exited in the last week. If there is, it outputs the details to a CSV.<\/li>\n<li>Powershell script imports this CSV, checks the usernames to see if the accounts are enabled<\/li>\n<li>If they are enabled it disables the account, moves it to a different OU etc&#8230;<\/li>\n<li>Script updates a log to say which accounts have been disabled and when<\/li>\n<li>Sends an email with the details of the accounts that have been disabled<\/li>\n<\/ol>\n<h1>Powershell Code<\/h1>\n<p>For ease of reading I have broken it up into a couple of sections<\/p>\n<h2>Querying the SQL Database<\/h2>\n<p>This section creates the connection to the SQL server, sends the query, then if there are results it outputs to a CSV file with that days date as the name.<\/p>\n<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/p>\n<p><em># Source SQL Server<\/em><br \/>\n<em> $SQLServerName =<\/em><\/p>\n<p><em># Source SQL Database<\/em><br \/>\n<em> $SQLDatabase =<\/em><\/p>\n<p><em># SQLQuery<\/em><br \/>\n<em> $SQLQuery1 = &#8220;SELECT blah blah'&#8221;<\/em><\/p>\n<p><em># Source SQL Username<\/em><br \/>\n<em> $SQLUsername =<\/em><\/p>\n<p><em># Source SQL Password<\/em><br \/>\n<em> $SQLPassword =<\/em><\/p>\n<p><em># SQL Server Connection Settigs<\/em><br \/>\n<em> $SQLConnectionString = \u201cServer=$SQLServer;uid=$SQLUsername; pwd=$SQLPassword;Database=$SQLDatabase;Integrated Security=False;\u201d<\/em><br \/>\n<em> $SQLConnection = New-Object System.Data.SqlClient.SqlConnection<\/em><br \/>\n<em> $SQLConnection.ConnectionString = $SQLConnectionString<\/em><\/p>\n<p><em># Issue SQL Connection Commands for Query1<\/em><br \/>\n<em> $SQLCommand = New-Object System.Data.SqlClient.SqlCommand<\/em><br \/>\n<em> $SQLCommand.CommandText = $SQLQuery1<\/em><br \/>\n<em> $SQLCommand.Connection = $SQLConnection<\/em><\/p>\n<p><em># Pull data<\/em><br \/>\n<em> $SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter<\/em><br \/>\n<em> $SQLAdapter.SelectCommand = $SQLCommand<\/em><br \/>\n<em> $SQLDataSet = New-Object System.Data.DataSet<\/em><br \/>\n<em> $SQLAdapter.Fill($SQLDataSet)<\/em><\/p>\n<p><em>$SQLQuery1DataSet = $SQLDataSet.Tables[0]<\/em><\/p>\n<div>\n<div><em># Export to CSV<\/em><\/div>\n<div><em>$SQLQuery1DataSet | Export-Csv $TargetStudentCSV -NoTypeInformation<\/em><\/div>\n<\/div>\n<div><em>\u00a0<\/em><\/div>\n<div>\u00a0&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/div>\n<h2>Process Exiting Students<\/h2>\n<p>This section:<\/p>\n<ul>\n<li>imports the CSV with todays date (if it exists)<\/li>\n<li>loops through the CSV and first checks if the account is enabled<\/li>\n<li>then hides it from the address list, removes it from groups, moves it to a &#8216;Disabled OU&#8217;, disables the account<\/li>\n<\/ul>\n<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p><em>#Set the variables to be used<\/em><\/p>\n<p><em>$CurrentYear = (Get-Date).ToString(&#8216;yyyy&#8217;)<\/em><br \/>\n<em> $TodaysDate = (Get-Date).ToString(&#8216;yyyy-MM-dd&#8217;)<\/em><br \/>\n<em> $DisabledOU =<\/em><\/p>\n<div>\n<div><em>$StudentCSV =<\/em><\/div>\n<div><em>\u00a0<\/em><\/div>\n<div><em># Exchange Mailbox Server UNC<\/em><\/div>\n<div><em>$ExchangeServerUNC = &#8220;\\\\$ExchangeServer\\&#8221;<\/em><\/div>\n<div><em># Exchange Mailbox Server Powershell Path<\/em><\/div>\n<div><em>$ExchangeServerPath = &#8220;http:\/\/&#8221; + $ExchangeServer + &#8220;\/powershell&#8221;<\/em><\/div>\n<div><em># Connect to Exchange Server<\/em><\/div>\n<div><em>$s=New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ExchangeServerPath -Authentication Kerberos<\/em><\/div>\n<div><em>Import-PSSession -Session $s -ErrorAction:SilentlyContinue<\/em><\/div>\n<div><em>\u00a0<\/em><\/div>\n<div><em># ======================================<\/em><\/div>\n<div><em># ******** Import list and PRocess users ********<\/em><\/div>\n<div><em># ======================================<\/em><\/div>\n<div><em># Import Exiting Students CSV<\/em><\/div>\n<div><em>$Students = Import-Csv -Path $StudentCSV<\/em><\/div>\n<div><em>ForEach ($User in $Students)<\/em><\/div>\n<div><em>{<\/em><\/div>\n<div><em>\u00a0<\/em><\/div>\n<div><em>$StudentCode = $User.UID<\/em><\/div>\n<div><em>#Check if the student has already been processed by check if the account is disabled<\/em><\/div>\n<div><em>$AlreadyProcessed = Get-ADUser $StudentCode | %{$_.enabled}<\/em><\/div>\n<div><em>if ( $AlreadyProcessed -eq $false)<\/em><\/div>\n<div><em>{<\/em><\/div>\n<div><em>$Output = &#8220;User &#8221; + $StudentCode + &#8221; is already disabled&#8221;<\/em><\/div>\n<div><em>Write-Output $Output<\/em><\/div>\n<div><em>}<\/em><\/div>\n<div><em>else<\/em><\/div>\n<div><em>{<\/em><\/div>\n<div><em># hide from Addrress List<\/em><\/div>\n<div><em>get-mailbox $StudentCode | set-mailbox -HiddenFromAddressListsEnabled $true<\/em><\/div>\n<div><em>#Remove all groups except &#8216;Domain USers&#8217;<\/em><\/div>\n<div><em>$RemoveGroups = Get-ADPrincipalGroupMembership -Identity $StudentCode | where {$_.Name -ne &#8220;Domain Users&#8221;}<\/em><\/div>\n<div><em>Remove-ADPrincipalGroupMembership -Identity $StudentCode -MemberOf $RemoveGroups -Confirm:$false<\/em><\/div>\n<div><em>#Move to diabled OU<\/em><\/div>\n<div><em>Get-ADUser $StudentCode | Move-ADObject -TargetPath $DisabledOU<\/em><\/div>\n<div><em>#Disable Account<\/em><\/div>\n<div><em>Disable-ADAccount $StudentCode<\/em><\/div>\n<div><\/div>\n<div>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/div>\n<h2>Update The Exiting Students Log file<\/h2>\n<div>This section exports the name of the account disabled and todays date to CSV log file.<\/div>\n<div>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/div>\n<div>\n<div><em>$LogFile =<\/em><\/div>\n<\/div>\n<div><em>$LogDetails = New-Object PSObject -Property @{ Details = $StudentCode + &#8221; has been disabled&#8221;; Date = $TodaysDate}<\/em><\/div>\n<div><em>Export-Csv -InputObject $LogDetails -Append -path $LogFile -NoTypeInformation<\/em><\/div>\n<div><em>\u00a0<\/em><\/div>\n<div><em>\u00a0&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/em><\/div>\n<h2>Send email of log<\/h2>\n<div>This section sends an email with the log of which accounts have been disabled that day.<\/div>\n<\/div>\n<div>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/div>\n<div>\n<div><em>#Email variables<\/em><\/div>\n<div><em>$To = @(&#8220;you@yourcompany.com&#8221;)<\/em><\/div>\n<div><em>$From = &#8220;no-repy@yourcompany.com&#8221;<\/em><\/div>\n<div><em>$SMTPServer =<\/em><\/div>\n<\/div>\n<div>\n<div><em>#Import details from log matching todays date<\/em><\/div>\n<div><em>$Body = Import-Csv -Path $LogFile | Where-Object {$_.Date -eq $TodaysDate}<\/em><\/div>\n<div><em>#If contains data, send the email<\/em><\/div>\n<div><em>If($Body)<\/em><\/div>\n<div><em>{<\/em><\/div>\n<div><em>$Body = Import-Csv -Path $LogFile | Where-Object {$_.Date -eq $TodaysDate} | ConvertTo-Html | Out-String<\/em><\/div>\n<div><em>Send-MailMessage -to $To -subject &#8220;Disabled Student Accounts Log&#8221; -Body $Body -BodyAsHtml -SmtpServer $smtpserver -From $from<\/em><\/div>\n<div><em>}<\/em><\/div>\n<\/div>\n<div>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/div>\n<div><\/div>\n<h1>Conclusion<\/h1>\n<div>This has worked quite well so far. I know my code could do with some cleaning up but I am refining it as I learn.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Introduction I have being playing around with Powershell a lot more lately and trying to learn and utilise it as much as possible. One of the repetitive tasks we deal with is when a student exits the school. There are a number of steps in AD that have to be undertaken each time a student [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":78,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[8,3],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/posts\/64"}],"collection":[{"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=64"}],"version-history":[{"count":13,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/posts\/64\/revisions"}],"predecessor-version":[{"id":77,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/posts\/64\/revisions\/77"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=\/wp\/v2\/media\/78"}],"wp:attachment":[{"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=64"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=64"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.spktechfit.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=64"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}