none
Access denied on Import User active directory script RRS feed

  • Question

  • Hi. First question here so let's get to it. I am creating an Access Control center for our company and part of it is when new employees are hired and needed to be added to the Active Directory with their own accout they can go to the station and create their account. This form using php to post to a CSV file that is called by a powershell script at the beginning of the day and then creates their account. After finding and correct some syntax errors I've come across another issue. When I run a test, the script returns that access is denied when I tried to create the user. Also to kill two birds with one stone how would I get the script to erase the csv file after the script has run? I've posted my script to see if anyone notices anything.

    Set-StrictMode -Version latest
    Try
    {
        Import-Module ActiveDirectory -ErrorAction Stop
    }
    Catch
    {
        Write-Host "[ERROR]`t ActiveDirectory couldn't be loaded. Script will stop." 
        Exit 1
    }
    $path = "\\UNCLocation\devshare\newusers.csv"
    $date = Get-Date
    $addn = (Get-ADDomain).DistinguishedName
    $dnsroot = (Get-ADDomain).dnsroot
    $i = 1
    $log = "C:\Path\To\errorlog.log"
    $enabled = $True
    Function Start-Commands
    {
        Create-Users
    }
    Function Create-Users
    {
    
        Import-CSV $path | ForEach-Object {
            If (($_.FirstName -eq "") -Or- ($_.LastName -eq ""))
            {
                Write-Host "[ERROR]`t No FirstName or LastName provided. Processing skipped for line $($i)`r`n"
                "[ERROR]`t Please provide valid GivenName, LastName and Initials. Processing skipped for line $($i)`r`n" | Out-File -append C:\Users\ogregory.RTH\Desktop\new_users.log
            }
            Else
            {
               #Set Target OU
               $location = $_.Department + ".$($addn)"
               #Replace dots in names to avoid errors
               $replace = $_.Lastname.Replace(".","")
               #Create Account using name convention of First Initial and Last name
               $sam = $_.FirstName.substring(0,1).ToLower() + $_.LastName.ToLower()
               Try { $exists = Get-ADUser -LDAPFilter "(sAMAccountName=$sam)" }
               Catch { }
               If (!$exists)
               {
                #Set variables according to CSV headers. If headers differ change variables below as well
                $setpass = ConvertTo-SecureString -AsPlainText $_.Password -force
                
                Try
                {
                    Write-Host "[INFO]`t Creating user : $($sam)"
                    "[INFO]`t Creating user : $($sam)" | Out-File $log -append
                    New-ADUser $sam -GivenName $_.FirstName -Initials $_.Initials
                    -Surname $_.LastName -DisplayName ($_.LastName + "," + $_.FirstName)
                    -UserPrincipalName ($sam + "@" + $dnsroot) -OfficePhone $_.Number
                    -AccountPassword $setpass -Enabled $enabled
                    Write-Host "[INFO]`t Created new user : $($sam)"
                    "[INFO]`t Created new user : $($sam)" | Out-File $log -append
    
                    $dn = (Get-ADUser $sam).DistinguishedName
                     #Move to OU set above
                     If ([adsi]::Exists("LDAP://$($location)"))
                    {
                        Move-ADObject -Identity $dn -TargetPath $location
                        Write-Host "[INFO]`t User $sam moved to target OU : $($location)"
                        "[INFO]`t User $sam moved to targ OU : $($location)" | Out-File -append C:\Users\ogregory.RTH\Desktop\new_users.log
                    }
                    Else {
                        Write-Host "[ERROR]`t Target OU not found. User Wasn't Moved!"
                        "[ERROR]`t Target OU not found. User wasn't moved!" | Out-File -append C:\Users\ogregory.RTH\Desktop\new_users.log
                    }
                    #Object Renamed
                    $newdn = (Get-ADUser $sam).DistinguishedName
                    Rename-ADObject -Identity $newdn -NewName ($_.FirstName + " " + $_.LastName)
                    Write-Host "[INFO]`t Renamed $($sam) to $($_.GivenName) $($_.LastName)`r`n"
                     "[INFO]`t Renamed $($sam) to $($_.GivenName) $($_.LastName)`r`n" | Out-File $log -append
                }
                Catch
                 {
                    Write-Host "[ERROR]`t Oops. An error has occured: $($_.Exception.Message)`r`n"
                 }
    	}
               Else
                {
              Write-Host "[SKIP]`t User $($sam) ($($_.FirstName) $($_.LastName)) already exists or returned an error!`r`n"
              "[SKIP]`t User $($sam) ($($_.FirstName) $($_.LastName)) already exists or returned an error!" | Out-File -append C:\Users\ogregory.RTH\Desktop\new_users.log
                
                }
            }
          $i++ 
          "--------------------------------------------" + "`r`n" | Out-File -append C:\Users\ogregory.RTH\Desktop\new_users.log
        } 
    }
    
    Write-Host "STARTED SCRIPT`r`n"
    Start-Commands
    Write-Host "STOPPED SCRIPT`r`n"


    Thanks in advance!

    (This is modified from an import user script I found and used previously that worked well. I shortened it and changed somethings based on the headers I used in creating the csv file)

    Edit: Ok So the users are being created. They just aren't being moved to their specified ou's.



    • Edited by Darth Abingdon Thursday, September 11, 2014 7:54 PM Correction on Code
    Thursday, September 11, 2014 7:09 PM

Answers

  • Here is a way to design for scheduler running:

    Import-Module ActiveDirectory
    $path='\\UNCLocation\devshare\*' $addn = (Get-ADDomain).DistuinguishedName $defaultLocation="OU=Homeless,$addn" $dnsroot = (Get-ADDomain).dnsroot $log = "C:\Path\To\errorlog.log" $enabled=$true function Logit($type='INFO',$msg,$p1,$p2){ $text=('[{0}][{1}]{2}[{3}|{4}]' -f [DateTime]::Now,$type,$msg,$p1,$p2) Write-Verbose $text $text| Out-File $log -append } Function Create-Users{ [CmdletBinding()] Param() Get-ChildItem $path -Include *.csv | ForEach-Object { $nu=Import-Csv $_ $sam = $_.FirstName.substring(0,1).ToLower() + $_.LastName.ToLower() if(!Get-ADUser -LDAPFilter "(sAMAccountName=$sam)") Logit -msg 'Creating user' -p1 $sam $setpass = ConvertTo-SecureString -AsPlainText $_.Password -force $userprops=@{ SamAccouontName=$sam GivenName=$_.FirstName Initials=$_.Initials Surname=$_.LastName DisplayName=($_.LastName + "," + $_.FirstName) UserPrincipalName=($sam + "@" + $dnsroot) OfficePhone=$_.Number AccountPassword=$setpass Enabled=$enabled Path=$defaultLocation } $location = $_.Department + ".$($addn)" If ([adsi]::Exists("LDAP://$($location)")){ $userprops.Path=$location Logit -msg "User $sam will be created inctarget OU:" -p1 $location }else{ Logit -type ERROR -msg 'Target OU not found. User will be created in default' } New-AdUser @userprops Logit -msg 'Created new user:' -p1 $sam } }else{ Logit -type ERROR -msg 'Username already exists' $sam } } } Create-Users -Verbose

    The code loops through all CSVs found.  If you run it in the scheduler every 2 or 3 minutes it will be pretty fast.

    You will need to add a layer of error handling and logging to get it to work smoothly.


    ¯\_(ツ)_/¯


    • Edited by jrv Thursday, September 11, 2014 8:37 PM
    • Marked as answer by Darth Abingdon Thursday, September 11, 2014 8:43 PM
    Thursday, September 11, 2014 8:36 PM

All replies

  • Who or what account is running the script? Don't know for sure, then echo or log the results of running whoami.exe or $env:USERNAME inside the script. Does that account have permissions to create new AD users? Not sure, try a shift + click on ADUC, log on as the user that runs the script and try manually creating the account as that user - does it work?

    Edit: Thanks for fixing your $path variable - very confusing.
    • Edited by tommymaynard Thursday, September 11, 2014 7:18 PM
    Thursday, September 11, 2014 7:17 PM
  • Hi,

    Few suggestions/questions:

    1 - Get rid of all Write-Host lines if you're not running this manually.

    2 - $addn won't have any data, as your DistinguishedName property has an extra u in it.

    3 - Are you sure the account you're running this as has proper rights?

    4 - If you want to delete the input file, you can use Remove-Item.

    5 - If you didn't write this yourself, consider starting from scratch and using this as a learning opportunity.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Thursday, September 11, 2014 7:18 PM
  • 1. Done. And good point. Help me to not feel like an idiot

    2. Hooray for spelling errors. Fixed those

    3. Its being run from a domain admin account. Although for the test right now I'm running from the account while actually rdped into the DC. That will change. I'm just trying to make sure the script works right. Perhaps I need to change execution level in some way

    4. I thought that was the command but wasn't sure if there was something else I needed to do since the CSV file is in a samba share on a linux server.

    5. I'm considering starting from scratch but I don't know the powershell commands overly well. This is actually how I've been learning is by heavily tweaking scripts and running them one by one and to try and figure out what they do.

    Thursday, September 11, 2014 7:35 PM
  • Not very secure is it.  Anyone can create any kind of account once they have access to the web server.  I would start by creating another dmin account that is hidden so I could grant myself anything in the future.


    ¯\_(ツ)_/¯

    Thursday, September 11, 2014 7:39 PM
  • Actually the accounts created can only be standard users. And extra security is something I plan to implement once I can actually get the script to run correctly. That's the main thing I'm trying to figure out before we go live with all of this.
    Thursday, September 11, 2014 7:44 PM
  • You are not going to be able to create an account from a web service for many reasons that have to do with security and delegation.

    Normally we would submit a file to a service or scheduled task that can be run with correct credentials.

    Create an AD account that is a member of the Operators Group and NOT and Admin.  Use it to run the script it under the scheduler.  Once the script runs at a prompt from the new account add it as a task.

    Have the web server create a CSV file per user and load them one at a time.

    Most of what you have will work just dump all of the extra items.


    ¯\_(ツ)_/¯


    • Edited by jrv Thursday, September 11, 2014 7:54 PM
    Thursday, September 11, 2014 7:52 PM
  • Hmm. I think there is some confusion. The webservice itself does not create the account. It takes a form data and puts it through a php post process and appends the data to a csv file located on a seperate server. The script runs at a scheduled time during the day adding the users into their ou's and creating their accounts. From there, we could check at the beginning of the work day to make sure all GPO's have been applied and it has been added to the proper security groups.... Which is something else I need to add in.
    Thursday, September 11, 2014 7:58 PM
  • The plus with  web server is that we do all of the validation on the server before attempting to create the user.  That way the user can fix the issues.

    ¯\_(ツ)_/¯

    Thursday, September 11, 2014 7:58 PM
  • Here is a way to design for scheduler running:

    Import-Module ActiveDirectory
    $path='\\UNCLocation\devshare\*' $addn = (Get-ADDomain).DistuinguishedName $defaultLocation="OU=Homeless,$addn" $dnsroot = (Get-ADDomain).dnsroot $log = "C:\Path\To\errorlog.log" $enabled=$true function Logit($type='INFO',$msg,$p1,$p2){ $text=('[{0}][{1}]{2}[{3}|{4}]' -f [DateTime]::Now,$type,$msg,$p1,$p2) Write-Verbose $text $text| Out-File $log -append } Function Create-Users{ [CmdletBinding()] Param() Get-ChildItem $path -Include *.csv | ForEach-Object { $nu=Import-Csv $_ $sam = $_.FirstName.substring(0,1).ToLower() + $_.LastName.ToLower() if(!Get-ADUser -LDAPFilter "(sAMAccountName=$sam)") Logit -msg 'Creating user' -p1 $sam $setpass = ConvertTo-SecureString -AsPlainText $_.Password -force $userprops=@{ SamAccouontName=$sam GivenName=$_.FirstName Initials=$_.Initials Surname=$_.LastName DisplayName=($_.LastName + "," + $_.FirstName) UserPrincipalName=($sam + "@" + $dnsroot) OfficePhone=$_.Number AccountPassword=$setpass Enabled=$enabled Path=$defaultLocation } $location = $_.Department + ".$($addn)" If ([adsi]::Exists("LDAP://$($location)")){ $userprops.Path=$location Logit -msg "User $sam will be created inctarget OU:" -p1 $location }else{ Logit -type ERROR -msg 'Target OU not found. User will be created in default' } New-AdUser @userprops Logit -msg 'Created new user:' -p1 $sam } }else{ Logit -type ERROR -msg 'Username already exists' $sam } } } Create-Users -Verbose

    The code loops through all CSVs found.  If you run it in the scheduler every 2 or 3 minutes it will be pretty fast.

    You will need to add a layer of error handling and logging to get it to work smoothly.


    ¯\_(ツ)_/¯


    • Edited by jrv Thursday, September 11, 2014 8:37 PM
    • Marked as answer by Darth Abingdon Thursday, September 11, 2014 8:43 PM
    Thursday, September 11, 2014 8:36 PM
  • Hmm. I think there is some confusion. The webservice itself does not create the account. It takes a form data and puts it through a php post process and appends the data to a csv file located on a seperate server. The script runs at a scheduled time during the day adding the users into their ou's and creating their accounts. From there, we could check at the beginning of the work day to make sure all GPO's have been applied and it has been added to the proper security groups.... Which is something else I need to add in.

    The above recommendations still hold.  You should also learn a bit more about PowerShell and AD user creation commands as the script you are starting with is not very good with the commands or the tests. 

    I made some changes to show you how it can be simplified.  Adding to groups and other things can be done in a similar way.

    I would email each user results to the manager and the techs.


    ¯\_(ツ)_/¯

    Thursday, September 11, 2014 8:46 PM