Add proxyAddresses to Active Directory users when created in PowerShell - powershell

I am trying to add users in Active Directory. Those users need to have proxyAddresses. My problem is that those proxyAddresses are multiples and stored in an array.
I try :
$proxyAddresses = #("address1#test.com", "address2#test.com", "address3#test.com")
$userInstance = new-object Microsoft.ActiveDirectory.Management.ADUser
$userInstance.ProxyAddresses = $proxyAddresses
New-ADUser test -Instance $userInstance
And I get this error :
Invalid type 'System.Management.Automation.PSObject'. Parameter name: proxyAddresses
I would like to add this proxyAddresses array to the attribute proxyAddresses of my AD user but it don't seem to be possible.
Any idea how this could be done?

Anything wrong with using Set-ADUser?
$username = '...'
$proxyAddresses = 'address1#example.com', 'address2#example.com', 'address3#example.com'
New-ADUser -Name $username
Set-ADUser -Identity $username -Add #{
'proxyAddresses' = $proxyAddresses | % { "smtp:$_" }
}

I just had this same issue and I was pretty sure I was passing in a string array (that's how it was declared).
Problem was just before I sent my string array into AD I was passing it to "Sort-Object -Unique" - which unbeknownst to me was changing either the type or something that made the cmdlet unhappy.
Just FYI...Sort-Object can burn you in these circumstances.

So, in my testing of this. I made Get-ProxyAddresses at https://gist.github.com/PsychoData/dd475c27f7db5ce982cd6160c74ee1d0
function Get-ProxyAddresses
{
Param(
[Parameter(Mandatory=$true)]
[string[]]$username,
[string[]]$domains = 'domain.com'
)
#Strip off any leading # signs people may have provided. We'll add these later
$domains = $domains.Replace('#','')
$ProxyAddresses = New-Object System.Collections.ArrayList
foreach ($uname in $username) {
foreach ($domain in $domains ) {
if ($ProxyAddresses.Count -lt 1) {
$ProxyAddresses.Add( "SMTP:$uname#$domain" ) | Out-Null
} else {
$ProxyAddresses.Add( "smtp:$uname#$domain" ) | Out-Null
}
}
}
return $ProxyAddresses
}
It just returns as a collection. Pretty kludgy, but works for what I need. It also assumes the first username and first domain are the "primary"
I combined that with #ansgar's answer and tried just -OtherAttributes on New-Aduser
$proxyAddresses = Get-ProxyAddress -username 'john.smith', 'james.smith' -domains 'domain.com','domain.net'
New-ADUser -Name $username
-OtherAttributes #{
'proxyAddresses'= $proxyAddresses
}
Works perfectly and added the proxyAddresses for me right at creation, without having to have a separate set action afterwards.
If you are Going to do separate actions, I would recommend to use -Server, like below, so that you don't run into talking to two different DCs by accident (and you also know that the New-ADUser is finished and already there, you don't have to wait for replication)
#I like making it all in one command, above, but this should work fine too.
$ADServer = (Get-ADDomainController).name
New-ADUser -Server $ADServer -name $Username
Set-ADUSer -Server $ADServer -Identity $username -Add #{
'proxyAddresses' = $proxyAddresses | % { "smtp:$_" }
}

Related

Few questions regarding Powershell ForEach MFA script

I'm working on a script to implement MFA deployment through Powershell. I'm connecting to an office365 and running the Get-MsolUser command to grab a list of users from AD (I believe). I'm putting it into an array which I'm then running through a ForEach loop. I'm not sure if this is even functional yet, but I'm trying to figure out how to exclude certain users from this loop as I don't want to activate MFA for domain admins.
Connect-MsolService
$array = #(Get-MsolUser | Select UserPrincipalName)
ForEach ($users in $array)
{
$st = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$st.RelyingParty = "*"
$st.State = "Enabled"
$sta = #($st)
Set-MsolUser -UserPrincipalName $users -StrongAuthenticationRequirements $sta
}
So I guess the 3 questions I have are:
How can I exclude users with names matching a certain string such as "Admin, Administrator" in the Array?
Is there anyway to take user input and apply it to the username/password fields for Connect-MsolService?
3)Is this code even functional as it stands or am I totally off the mark?
As commented, there are some enhancements to be made in your code.
Try:
Starting with your question 2)
Connect-MsolService has a -Credential parameter and the easiest way to obtain that is by using the Get-Credential cmdlet:
# ask for credentials to make the connection
$cred = Get-Credential -Message 'Please enter your credentials to connect to Azure Active Directory'
Connect-MsolService -Credential $cred
Next, you want to define a list of users to exclude from being affected.
$excludeTheseUsers = 'admin', 'user1', 'user2' # etc.
# for using the regex `-notmatch` operator later, you need to combine the entries with the regex OR sign ('|'),
# but you need to make sure to escape special characters some names may contain
$excludes = ($excludeTheseUsers | ForEach-Object { [regex]::Escape($_) }) -join '|'
# create the StrongAuthenticationRequirement object just once, to use on all users
$st = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$st.RelyingParty = "*"
$st.State = "Enabled"
$sta = #($st)
# get an array of UserPrincipalNames
$array = (Get-MsolUser | Where-Object { $_.DisplayName -notmatch $excludes }).UserPrincipalName
foreach ($user in $array) {
Set-MsolUser -UserPrincipalName $user -StrongAuthenticationRequirements $sta
}

Powershell: Create local administrators remotely

I'm looking at creating a local administrator on a handful of machines (>30). I don't really want to use GPO if I can get away with it. LAPS is a little overkill for what I need.
I found a nice script online but it only creates the user and doesn't add them to the administrators group. Can anyone see the error?
#Define variables
$computers = Get-Content C:\Computers.txt
#$computers = Import-CSV C:\Computers.txt | select Computer
$username = "Admin"
$password = "Password99"
$fullname = "Admin"
$local_security_group = "Administrators"
$description = "Description"
Foreach ($computer in $computers) {
$users = $null
$comp = [ADSI]"WinNT://$computer"
#Check if username exists
Try {
$users = $comp.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username already exists on $computer"
} else {
#Create the account
$user = $comp.Create("User", "$username")
$user.SetPassword("$password")
$user.Put("Description", "$description")
$user.Put("Fullname", "$fullname")
$user.SetInfo()
#Set password to never expire
#And set user cannot change password
$ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
$ADS_UF_PASSWD_CANT_CHANGE = 0x40
$user.userflags = $ADS_UF_DONT_EXPIRE_PASSWD + $ADS_UF_PASSWD_CANT_CHANGE
$user.SetInfo()
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$username = [ADSI]"WinNT://$Computer/$username,user"
#Validate whether user account has been created or not
$users = $comp.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username has been created on $computer"
} else {
Write-Host "$username has not been created on $computer"
}
}
}
Catch {
Write-Host "Error creating $username on $($computer.path): $($Error[0].Exception.Message)"
}
}
In your code you are not actually adding the user to the group.
Here you are actually retrieving a group object, but you are not doing anything with it.
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$username = [ADSI]"WinNT://$Computer/$username,user"
First you must remove the assignment to $username. Then you must invoke a method on the $group object to add the user:
#Add the account to the local admins group
$group = ([ADSI]"WinNT://$computer/$local_security_group,group")
$computerHostName = (Get-WmiObject -ComputerName $computer Win32_ComputerSystem).Name
$group.Add([ADSI]"WinNT://$computerHostName/$username,user")
There is a catch here. Notice I use Get-WmiObject to get the hostname from the computer. When using the Add() method, the computer name must be the unqualified hostname. For example server-01, and NOT server-01.domain.lan
If you want to retrieve the ADSI object for the user later, I recommend assigning it to a different variable name, like this:
$adsiUser = [ADSI]"WinNT://$Computer/$username,user"

Powershell setting up a new user with a specific attribute

I have a script that creates new users that can be used for different operations.
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$GivenName, #=givenName
[Parameter(Mandatory=$True,Position=2)]
[string]$Name, # =sn
[Parameter(Mandatory=$True,Position=9)]
[string]$ADuser,
[Parameter(Mandatory=$True,Position=4)]
[string]$Description, #=title
[Parameter(Mandatory=$True,Position=4)]
[string]$AdministrationUser,
[Parameter(Mandatory=$True,Position=4)]
[string]$SamAccManager
)
after these parameters I have a new-user -name and so on, But I want to user the last Parameter SamAccManager to be added to the adminDisplayName, so I can search who is in charge of that AD user as there will be users that have no logon rights, will be used only for test purposes.
new-aduser -name $DisplayName -DisplayName $DisplayName -Description $Description -GivenName $GivenName -Surname $Name -SamAccountName $usr -UserPrincipalName $UserPrincipalName -Path $OU_AD
How Can I integrate to add that info into that specific adminDisplayName field? for example, I want to add in the last section code -admindisplayname $samaccmanager , but I can not do that as it is an invalid parameter. Any ideas?
First thing I noticed is that you add duplicate values for Position to the parameters. Also, there is a parameter you do not seem to use: $AdministrationUser and personally, I would change the param names for some of them so it becomes much clearer what they stand for.
The code below uses Splatting to feed the parameters to the New-ADUser cmdlet. This is a nice readable and maintainable way of calling on cmdlets with lots of properties.
Param(
[Parameter(Mandatory=$True,Position=0)]
[string]$GivenName, # =givenName
[Parameter(Mandatory=$True,Position=1)]
[string]$SurName, # =SurName
[Parameter(Mandatory=$True,Position=2)]
[string]$AccountName, # =SamAccountName
[Parameter(Mandatory=$True,Position=3)]
[string]$Description, # =title
[Parameter(Mandatory=$True,Position=4)]
[string]$OU, #= distinguishedName of the OU
[Parameter(Mandatory=$True,Position=5)]
[string]$SamAccManager #= AdminDisplayName
)
# create a hashtable for the New-ADUser parameters
$userParams = #{
Name = "$GivenName $SurName"
DisplayName = "$GivenName $SurName"
Description = $Description
GivenName = $GivenName
Surname = $SurName
SamAccountName = $AccountName
UserPrincipalName = "$AccountName#yourdomain.com"
Path = $OU
# add the AdminDisplayName attribute as hashtable
OtherAttributes = #{AdminDisplayName = $SamAccManager}
}
# create the user by splatting the parameters
New-ADUser #userParams
Of course, you can also set the AdminDisplayName property after creating the user by using
Set-ADuser -Identity $AccountName -Add #{AdminDisplayName = $SamAccManager}

Student Script for creating new users error :System.String' to the type 'System.Management.Automation.SwitchParameter

I'm pulling some user info from a .csv to create new users,
I've splatted the New User Params at the suggestion of someone here
but I'm getting this error
New-ADUser : Cannot convert 'System.String' to the type 'System.Management.Automation.SwitchParameter' required by parameter
'Confirm'.
At C:\Users\Administrator\Documents\GitHub\cyclone-internal-user-sync-1\Bamboo Attributes form a csv.ps1:68 char:28
+ New-ADUser #NewUserParms
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirectory.Management.Commands.NewADUser
I have no idea what this is haha, I've tried adding an erroraction stop to the new-aduser but that didn't have any effect
I have added trims and a section to remove spaces from usernames. to deal with multipart names such as Van der.... etc
#Bamboo Attributes from a .csv
#Enter a path to your import CSV file
$ADUsers = Import-csv 'path'
#Bamboo Attributes from a .csv
#Enter a path to your import CSV file
$ADUsers = Import-csv 'C:\Users\Administrator\Documents\GitHub\cyclone-internal-user-sync-1\documentation\SampleUserAttributes.csv'
#$apiRequest = Get-Content -Raw -Path C:\Users\alexh\Documents\GitHub\cyclone-internal-user-sync-1\cyclone-internal-user-sync-1\fake-api-query.json | ConvertFrom-Json
foreach ($User in $ADUsers) {
$firstName = $user.FirstName.Trim()
$surname = $user.Surname.Trim()
$vaildUsernameFormat = "[^a-zA-Z_.]" # identifies anything that's _not_ a-z or underscore or .
$username = "($firstName'.'$surname)" -replace $vaildUsernameFormat, '' #removes anything that isn't a-z
$DefaultPassword = 'Pa$$w0rd'
$NewUserParms = #{
'samAccountName' = $username;
'Name' = "$firstname $surname";
'DisplayName' = "$firstname $surname";
'UserPrincipalName' = "$username#domain.com";
'GivenName' = $firstname;
'Surname' = $surname;
'EmailAddress' = $User.Email;
'AccountPassword' = (ConvertTo-SecureString $DefaultPassword -AsPlainText -Force);
'Enabled' = $true;
'Path' = "OU=Users,DC=domain,DC=com";
'co' = $User.Country;
'company' = $User.CompanyName;
'countryCode' = $user.countryCode;
'department' = $user.OrgDepartmentName;
'Employeeid' = $user.EmployeeId;
'exstentionAttribute1' = $user.ExstentionNumber;
'ipPhone' = $user.ExstentionNumber;
'L' = $user.location;
'mail' = $user.Email;
'mobile' = $user.Mobile;
'Manager' = $user.Manager;
'physicalDeliveryOffice' = $user.Branch;
'postalCode' = $user.PostalCode;
'postOfficeBox' = $user.PostOfficeBox;
'proxyAddresses' = $user.ProxyEmail;
'scriptPath' = $user.scriptPath;
'st' = $user.StreetName;
'Title' = $user.Title
}
write-host "$username this is username value"
#Check if the user account already exists in AD
if (Get-ADUser -F {
sAMAccountName -eq $username
}) {
#If user does exist, output a warning message
Write-Warning "A user account $username has already exist in Active Directory."
}
else {
#If a user does not exist then create a new user account
New-ADUser #NewUserParms
}
}
I've removed some of the user attributes just to make this a bit smaller.
here is the.csv as well in case I've messed something up there
link to .csv file on git
A little known fact about PowerShell is that you don't need to use the whole parameter name. You can use the partial name and as long as it matches only one parameter name, that's what PowerShell assumes you mean.
The one it's choking on is this:
'co' = $User.Country;
If you look at the documentation for New-ADUser, it does not have a parameter called co. So PowerShell assumes it's a partial match to a known parameter, and the closest match is -Confirm. And the value in $User.Country doesn't make any sense for the -Confirm parameter, so it throws the error.
You will have to use the -OtherAttributes parameter to set all the other attributes that New-ADUser doesn't have a dedicated parameter for:
$NewUserParms = #{
...
'OtherAttributes = # {
'co' = $User.Country;
'exstentionAttribute1' = $user.ExstentionNumber;
...
}
...
}
As commented in this and previous questions, you are using New-ADUser $NewUserParms, where it should be New-ADUser #NewUserParms.
Also, to catch errors (you did add -ErrorAction Stop), you need to put that inside a try{..} catch{..} block.
I would also change the syntax you use for the -Filter parameter. Instead of using a scriptblock syntax {something -eq someotherthing}, you should create a string like "something -eq 'someotherthing'"
Try:
# define some 'constants'
$csvFile = 'X:\Folder\NewUsers.csv' # Enter a path to your import CSV file
$invalidCharacters = '[^a-z_.]' # identifies anything that's _not_ a-z or underscore or .
$DefaultPassword = 'Pa$$w0rd'
$securePassword = ConvertTo-SecureString -String $DefaultPassword -AsPlainText -Force
# read the input csv and loop through
Import-Csv -Path $csvFile | ForEach-Object {
$firstName = $_.FirstName.Trim()
$surname = $_.Surname.Trim()
$username = ('{0}.{1}' -f $firstName, $surname) -replace $invalidCharacters
# test if a user with that name already exists
$user = Get-ADUser -Filter "SamAccountName -eq '$username'" -ErrorAction SilentlyContinue
if ($user) {
Write-Warning "A user account $username already exist in Active Directory."
}
else {
Write-Host "Creating user $username"
$NewUserParms = #{
'SamAccountName' = $username
'Name' = "$firstname $surname"
'DisplayName' = "$firstname $surname"
'UserPrincipalName' = "$username#domain.com"
'GivenName' = $firstname
'Surname' = $surname
'EmailAddress' = $_.Email
'AccountPassword' = $securePassword
'Enabled' = $true
'Path' = "OU=Users,DC=domain,DC=com"
# add other properties to set from the CSV here.
# make sure you get the parameter data types correct and always check here:
# https://learn.microsoft.com/en-us/powershell/module/addsadministration/new-aduser?view=win10-ps#parameters
# switch parameters for the cmdlet can also be entered with a value $false or $true
}
try {
# '-ErrorAction Stop' ensures that also non-terminating errors get handled in the catch block
New-ADUser #NewUserParms -ErrorAction Stop
}
catch {
# something bad happened. Change 'Write-Warning' into 'throw' if you want your script to exit here
# inside a catch block, the '$_' automatic variable represents the actual exception object.
Write-Warning "Could not create account $username. $($_.Exception.Message)"
}
}
}

How to add user to local admin group in Powershell?

I am trying to create user on remote machine using Powershell. Once account created I want to add that in local admin group.
Account is getting created but it is not getting added in admin group. Below is the code that I am using.
cls
$username = "test_user"
$password = "password"
$computer1 = hostname
$users = $null
$computer = [ADSI]“WinNT://$computer1”
Try {
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username already exists"
} Else {
$user_obj = $computer.Create(“user”, “$username”)
$user_obj.SetPassword($password)
$user_obj.SetInfo()
$user_obj.Put(“description”, “$username”)
$user_obj.SetInfo()
$user_obj.psbase.invokeset(“AccountDisabled”, “False”)
$user_obj.SetInfo()
$users = $computer.psbase.children | select -expand name
if ($users -like $username) {
Write-Host "$username has been created on $($computer.name)"
$group = [ADSI]("WinNT://"+$env:COMPUTERNAME+"/administrators,group")
$group.add("WinNT://$env:localhost/$username,user")
} Else {
Write-Host "$username has not been created on $($computer.name)"
}
}
} Catch {
Write-Host "Error creating $username on $($computer.path): $($Error[0].Exception.Message)"
}
What am I doing wrong?
$env:computername is your local computer. $env:localhost doesn't exist. $computer1 is the variable you defined of the computer to you are adding the user to earlier.
$group = [ADSI]("WinNT://$computer1/administrators,group")
$group.add("WinNT://$computer1/$username,user")
I use this
$computername = "computername" # place computername here for remote access
$username = 'user'
$password = 'P#ssw0rd1' #password
$desc = 'Local admin account'
$computer = [ADSI]"WinNT://$computername,computer"
$user = $computer.Create("user", $username)
$user.SetPassword($password)
$user.Setinfo()
$user.description = $desc
$user.setinfo()
$user.UserFlags = 65536
$user.SetInfo()
$group = [ADSI]("WinNT://$computername/administrators,group")
$group.add("WinNT://$username,user")
That is a whole lot of code, just to do this.
Invoke-Command -ComputerName SomeRemoteComputerName -ScriptBlock {
net user SomeNewUserName SomePassword
net localgroup administrators SomeNewUserName /add
}
Yeppers, I know, it's not all pure PoSH. Sure, you can do this with via more code in PoSH (way more in ), but sometimes you just need to get stuff done.
But vs doing this from scratch (well, unless you are just trying to learn stuff). There is a whole set of pre-built scripts and module for you to leverage. See:
'gallery.technet.microsoft.com/scriptcenter/site/search?f%5B0%5D.Type=RootCategory&f%5B0%5D.Value=localaccount'
Of course if all machines were on PoSH v5+, then you just use the built-in cmdlets for local user / group management.
'learn.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/?view=powershell-5.1'
As for the other question:
'check service account exist or not'
Assuming you are asking if this is for a remote computer, then it's the same approach.
Invoke-Command -ComputerName SomeRemoteComputerName -ScriptBlock {
Get-Service -Name SomeServiceName
Get-Service -DisplayName SomeServiceDisplayName
}