Changing user properties in powershell - powershell

I have a script that creates a user and assigns the password and the user to a group but I need to get 2 check boxes ticked - 'User cannot change password' and 'Password never expires' but for the life of me I cannot find out how to do this.
My script so far is this:-
# Create User and add to IGNITEWEBUSERS Group
$user = $domain
# If more then 15 chars trim to just 15 chars
$user = $user.substring(0, 15)
$user = $user + "_web"
# Generate Random Complex Password
# Generate a password with 2 non-alphanumeric character.
$Length = 10
$Assembly = Add-Type -AssemblyName System.Web
$RandomComplexPassword = [System.Web.Security.Membership]::GeneratePassword($Length,2)
$password = $RandomComplexPassword
$group = 'IGNITEWEBUSERS'
$objOu = [ADSI]"WinNT://$computer"
$objUser = $objOU.Create("User", $user)
$objUser.setpassword($password)
$objUser.SetInfo()
$objUser.description = $domain + " IIS User"
$objUser.SetInfo()
$OBjOU = [ADSI]"WinNT://$computer/$group,group"
$OBjOU.Add("WinNT://$computer/$user")
That works and does what it should do but anyone know how I can set those 2 check boxes?
Various threads suggest something similar to Set-ADUser -CannotChangePassword:$true but am not using Active Directory and this doesn't work.
Your advice appreciated
Paul

Got it figured out this morning:-
$objUser.UserFlags = 64 + 65536 # ADS_UF_PASSWD_CANT_CHANGE + ADS_UF_DONT_EXPIRE_PASSWD

Set the useraccountcontrol property. You can find a list of useraccountcontrol flags here: http://support.microsoft.com/kb/305144
Add the values of the flags you want (NORMAL_ACCOUNT = 512, PASSWD_CANT_CHANGE = 64, DONT_EXPIRE_PASSWORD = 65536) for a total of 66112, and set the property to that number:
$obUser.useraccountcontrol = 66112
BTW, you only need to call the SetInfo() method once at the end, after setting all the properties you want to set.

Use WMI to get the user account:
# Use this filter so WMI doesn't spend forever talking to domain controllers.
$user = Get-WmiObject Win32_UserAccount -Filter ("Domain='{0}' and Name='{1}'" -f $env:ComputerName,$Username)
$user.PasswordChangeable = $false
$user.PasswordExpires = $false
$user.Put()

Related

Capture multiple variables

I currently have a powershell script that allows me to enter in the details for users one at a time which can then be used as variables later on. At present the script calls for each input and then saves for as a variable, this is then repeated 10 times.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$NameOne = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")
$firstname,$surname = $NameOne -split("\.")
$NameTwo = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")
$firstname,$surname = $NameTwo -split("\.")
Is there a way to shorten the script to both allow usernames to be input and stored but to also move on to the next part of the script when an InputBox has no data input?
Thanks
Tom
Use a while loop:
$Users = while(($Username = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")).Trim() -ne "")
{
$firstname,$surname = $Username -split '\.'
New-Object psobject -Property #{
Firstname = $firstname
Surname = $surname
Username = $Username
}
}
When the user inputs nothing or whitespace, the loop will exit, otherwise it'll create a new "User object" that will end up in the $Users array

Powershell list group membership of user (Novell eDirectory) NDS LDAP

Trying to figure out, how to map a network share based on group membership of Novell eDir.
I found a smart script in Technet for ActiveDirectory via ADSISEARCHER which is working pretty well in AD :)
# extract group names and removes unnecessary characters
$memberOf = ([ADSISEARCHER]"samaccountname=$($env:USERNAME)").Findone().$does.memberof -replace '^CN=([^,]+).+$','$1'
# check if user is member of group A
if($memberOf -contains "GroupA") {
# map network-drive
(New-Object -ComObject WScript.Network).MapNetworkDrive('X:','\\filer\sharename')
}
Is there any chance to use something similar for NDS?
As far as I researched I have to use LDAP to connect to NDS and list all groups of a user object, but haven't much luck yet.
Thx
I found a useful script out there which I just have to edit a littlebit...
URL to Script:
http://activedirectoryfaq.com/2014/01/searching-novell-nds-edirectory-with-powershell/
My final script in case somebody needs this crap:
<#
.SYNOPSIS
Mapping a network share based on a specific group membership in NDS
.DESCRIPTION
The script is mapping a network drive, based on a NDS group membership.
The first match wins!
#>
# --------<SET CORRESPONDING VALUES HERE >--------
# Hostname of eDir Server (e.g.: NDSSRV01):
$LDAPServer = "hostname"
# Name of BaseDN (e.g.: o=MyCompany):
$dn = "o=basedn"
# ------------------------------------------------
# set username of current logged on user
$filter = "(uid=$env:USERNAME)"
# Creating necessary objects
[reflection.assembly]::LoadWithPartialName("system.directoryservices.protocols") | out-null
$ldapIdentifier = new-object directoryservices.protocols.ldapdirectoryidentifier($LDAPServer)
$ldapConnection = new-object directoryservices.protocols.ldapconnection($ldapIdentifier,$null,0)
# Attributes to search for:
# To search for multiple use comma separated list (eg: "groupmembership","cn","emailAddress")
[string[]]$attr = "groupmembership"
# Establishing LDAP connection
$scope = $ADS_SCOPE_SUBTREE
$searchRequest = new-object directoryservices.protocols.searchrequest($dn,$filter,$ADS_SCOPE_SUBTREE,$attr)
$searchRequest.typesonly = $false
$searchRequest.sizelimit = 10
$result = [directoryservices.protocols.searchresponse]$ldapConnection.sendrequest($searchRequest)
$entry = $result.entries
# extract group names and removes unnecessary characters
$membership = $entry[0].Attributes["groupmembership"].getValues([string]) -replace '^CN=([^,]+).+$','$1'
# check if user is member of group A
if($membership -contains "GroupA") {
# map network-drive
(New-Object -ComObject WScript.Network).MapNetworkDrive('X:','\\filer\sharegroupa')
}
# check if user is member of group B
elseif($membership -contains "GroupB") {
# map network-drive
(New-Object -ComObject WScript.Network).MapNetworkDrive('X:','\\filer\sharegroupb')
}
# elseif() ... and so on
# if nothing matches, then:
else {
Write-Host 'current user is not a member of a specified group'
}

Powershell - Count X of something in String

Right so essentially I am storing a domain name into a variable - which then I need to split up later in my code into it's individual parts i.e.
$domainName = "testdomain.co.uk"
$domainNameSplit = $domainName.split(".")
echo $domainNameSplit[0]
echo $domainNameSplit[1]
echo $domainNameSplit[2]
In this instance it's fine as I know it's a .co.uk so will have 3 parts - however my code allows for input and therefore may take a testdomain.local format instead. How can I look through the $domainName variable and find the number of '.' in order to know what to do with it?
I also need to then use it in order to create a $ou variable to work with, so:
$ou = "DC=WhatWouldIPutHere?,DC=AndHere"
Thanks!
Just another suggestion:
$domainName = "testdomain.co.uk"
# Get Count
$PartCount = $domainName.Split(".").Count
# Make an OU
$ou = "DC=" + $domainName -replace "\.", ",DC="
Just count the array length isn't enougth?
$domainName = "testdomain.co.uk"
$domainNameSplit = $domainName.split(".")
$domainNameSplitCount = $domainNameSplit.count
or to create a DN:
$domainName = "testdomain.co.uk"
$domainNameSplit = $domainName.split(".")
$a = [string]::empty
$domainNameSplit | % { $a+="DC=$_," }
$a.trim(',')

Powershell add user to group

I am trying to read an XML file with user information and based on that information I want to add users to Active Directory groups. I have been looking up the error messages with no help so far. Here is the add user to group code:
$MyUsers = [xml] (Get-Content e:\sample.xml)
$a = 0
$b = 0
$c = 0
$OUServer = "servername.domain.domain.edu"
$AD3Server = "servername.domain.domain.edu"
$DSSPath = "cn=Atl-Users,OU=HR,DC=domain,DC=domain,DC=edu"
$AD3Path = "ou=Admin,DC=domain,DC=domain,DC=domain,DC=EDU"
$connection = "LDAP://$OUServer/$DSSPath"
LOOP LOGIC
{
$CurUser = $MyUsers.clusters.cluster[$a].departments.department[$b].people.person[$c].loginid
$Group = [adsi]"$connection"
$User = "LDAP://$AD3Server/$CurUser,$AD3Path"
$Group.Add($User)
}
Here is the error I get
Exception calling Add with 1 argument(s): "The server is unwilling to process the request. (Exception from HRESULT: 0x80072035)"
This do what you need:
$Connection = "LDAP://Server/CN=MyGoup,OU=MyOU,DC=MY,DC=CORP"
$Group = [adsi] $Connection
$User = "LDAP://Server/CN=MyUser,OU=MyOU,DC=MY,DC=CORP"
$Group.Add($User)
You have to check the contents of $CurUser AND $User variables.
Here is a working example, you perhaps can adapt it.
First you forget to call the setinfo(), which is a kind of commit.
Second be careful that the value of $CurUser is in the form of 'CN=XXXXX'.
Clear-Host
# Connecting without User/Password to Active Directory
#$dn = [adsi] "LDAP://192.168.30.200:389/dc=dom,dc=fr"
# Connecting with User/Password to Active Directory
$dn = New-Object System.DirectoryServices.DirectoryEntry ("LDAP://192.168.234.200:389/dc=dom,dc=fr","administrateur#dom.fr","admin")
# Creation of an OU
$Monou = $dn.create("OrganizationalUnit", "ou=Monou")
$Monou.put("Description", "Une description")
$Res = $Monou.Setinfo()
# Basic creation of a user
$objUtilisateur = $Monou.create("inetOrgPerson", "cn=Marc Assin")
$objUtilisateur.setinfo()
$objUtilisateur.samaccountname = "Massin"
$objUtilisateur.givenName = "Marc"
$objUtilisateur.sn = "Assin"
$objUtilisateur.userPrincipalName = "Massin#dom.fr"
# Set the state of the account
$objUtilisateur.pwdLastSet = 0
$objUtilisateur.userAccountControl = 544 #512
$objUtilisateur.SetInfo()
# Creation of a group
$MonGroupe = $Monou.Create("Group", "cn=MonGroupe")
$ADS_GROUP_TYPE_GLOBAL_GROUP = 0x00000002
$ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
$groupeType = $ADS_GROUP_TYPE_SECURITY_ENABLED -bor $ADS_GROUP_TYPE_GLOBAL_GROUP
$MonGroupe.put("groupType",$groupeType)
$MonGroupe.setinfo()
# Adding user to a group
$MonGroupe.add('LDAP://cn=Marc Assin,ou=Monou,dc=dom,dc=fr')
$MonGroupe.setinfo()

Powershell: How do you set the Read/Write Service Principal Name AD Permissions?

In Powershell, how do you set the Read/Write Service Principal Name AD user permissions?
Normally during my build process, I use ADSIedit to navigate to that object, and then go through all the security tabs to get down to put a checkmark next to:
Read Service Principal Name
Write Service Principal Name
But navigating through ADSIedit can take a long time so I'm trying to script the process. If I have a PowerShell LDAP bind with a new user created, how can I use PowerShell to set both of these properties for this user account?
The following is a hacked out code-snippet of the possible pertinent portions of my install script:
$strDomain = "dc=my,dc=com"
$objDomain = [ADSI] "LDAP://" + strDomain
$strSCCMSQLPW = Read-Host -assecurestring "Please enter a password for the " + $strSCCMSQL + " account: "
New-ADUser -SamAccountName $strSCCMSQL + -Name $strSCCMSQL -AccountPassword $strSCCMSQLPW -Enabled $true -Path $strUsersOU + "," + $strDomain -PasswordNeverExpires $true
You need to add an ActiveDirectoryAccessRule object to the ACL of the target object. For setting property specific rigths the trick is to pass in the schemaIDGUID to the attribute. So first we need to find the schemaIDGUID from the Service-Principal-Name schema entry. In the sample code i statically refer to the Service-Principal-Name, better yet would have been to search for the ldapDisplayname to find the entry but I'm sure you can sort that out. In any case this code should do the job:
Function Set-SpnPermission {
param(
[adsi]$TargetObject,
[Security.Principal.IdentityReference]$Identity,
[switch]$Write,
[switch]$Read
)
if(!$write -and !$read){
throw "Missing either -read or -write"
}
$rootDSE = [adsi]"LDAP://RootDSE"
$schemaDN = $rootDSE.psbase.properties["schemaNamingContext"][0]
$spnDN = "LDAP://CN=Service-Principal-Name,$schemaDN"
$spnEntry = [adsi]$spnDN
$guidArg=#("")
$guidArg[0]=$spnEntry.psbase.Properties["schemaIDGUID"][0]
$spnSecGuid = new-object GUID $guidArg
if($read ){$adRight=[DirectoryServices.ActiveDirectoryRights]"ReadProperty" }
if($write){$adRight=[DirectoryServices.ActiveDirectoryRights]"WriteProperty"}
if($write -and $read){$adRight=[DirectoryServices.ActiveDirectoryRights]"readproperty,writeproperty"}
$accessRuleArgs = $identity,$adRight,"Allow",$spnSecGuid,"None"
$spnAce = new-object DirectoryServices.ActiveDirectoryAccessRule $accessRuleArgs
$TargetObject.psbase.ObjectSecurity.AddAccessRule($spnAce)
$TargetObject.psbase.CommitChanges()
return $spnAce
}
Sample lines for calling the function...
$TargetObject = "LDAP://CN=User,OU=My User Org,DC=domain,DC=net"
$Identity = [security.principal.ntaccount]"domain\user"
Set-SpnPermission -TargetObject $TargetObject -Identity $Identity -write -read
Here is an example using Quest to set the permissions on the service principal name attributes.
First, add Quest:
Add-PSSnapin Quest.ActiveRoles.ADManagement;
Set the permission (using Add-QADPermission):
Get-QADUser UserName | Add-QADPermission -Account 'SELF' -Rights 'ReadProperty,WriteProperty' -Property 'servicePrincipalName' -ApplyTo 'ThisObjectOnly';
You can use Quest AD cmdlets. It makes AD permission stuff very easy in PowerShell.
Read this blog for some examples on how to add AD permissions or even copy the AD permissions.
Just lookup Add-QADPermission and it should do your job.