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()
Related
We want to generate an SR per row based on the criteria of a CSV file looking like:
SR templete
The additional criterion:
If the SLO countdown is less than 7 days then the due date is always 7 days for the ticket to be due. Otherwise then then countdown is number SLO _Countdown
The support group is always servicedesk
Unless the host_name does not contain "RES" then it is the support group is EITS_HW_Notes and it will be assigned to "custodian".
No matter what an SR is generated even if null.
My difficulty is my lack familiarity with smlets. I am happy to consider generating tickets via email as well. But would like help on how best to do that via powershell. But the code I came up with is below:
`#Prod
#$GLOBAL:smdefaultcomputer = "prodserver"
#Test
$GLOBAL:smdefaultcomputer = "testserver"
Import-Module SMlets
$path = "C:\Temp\Test.csv"
$csv = Import-csv -path $path
#Variable / Class Setup
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
$srprior = Get-SCSMEnumeration -Name ServiceRequestPriorityEnum.Medium
$srurg = Get-SCSMEnumeration -Name ServiceRequestUrgencyEnum.Medium
#$ararea = get-SCSMEnumeration -Name ServiceRequestAreaEnum.Other
$ararea = get-SCSMEnumeration -Name Enum.add3768303064ec18890170ba33cffda
$title = “Title Goes Here”
$descrip = "Description info goes here"
#Service Request Arguements
$srargs = #{
Title = $title;
Urgency = $srurg;
Priority = $srprior;
ID = “SR{0}”;
Area = $ararea;
SupportGroup = "ServiceDesk";
Description = $descrip
}
#Create Service Request
$newServiceRequest = New-SCSMOBject -Class $srClass -PropertyHashtable $srargs -PassThru
#get SR ID of the new object
$SRId = $newServiceRequest.id
#Get Projection & Object for Created Service Request
$srTypeProjection = Get-SCSMTypeProjection -name System.WorkItem.ServiceRequestProjection$
$SRProj = Get-scsmobjectprojection -ProjectionName $srTypeProjection.Name -filter “Id -eq $SRId”
#Set Afffected User
$userClass = Get-SCSMClass -Name Microsoft.AD.UserBase$
$cType = "Microsoft.EnterpriseManagement.Common.EnterpriseManagementObjectCriteria"
$cString = "UserName = 'itservicenotifications' and Domain = 'SHERMAN'"
$crit = new-object $cType $cString,$userClass
$user = Get-SCSMObject -criteria $crit
$AffectedUserRel = get-scsmrelationshipclass -name System.WorkItemAffectedUser$
New-SCSMRelationshipObject -RelationShip $AffectedUserRel -Source $newServiceRequest -Target $user -Bulk`
I tried the above code but am running into issues recognizing the column name in the CSV file and am unfamiliar with SMLETS + powershell if statements.
Columns are:
CSV Columns
CSV text with examples is: Columns with examples
Could you paste the CSV columns as text, please? Or, better, a sample CSV with one or two rows (redact any sensitive data).
I would expect a CSV to contain multiple rows - even if yours does not, it's good defensive programming to act as if it does. So the first modification I suggest is:
$path = "C:\Temp\Test.csv"
$csv = Import-csv -path $path
foreach ($Row in $csv)
{
# the rest of your code goes in here
}
I find it helpful while debugging to go step-by-step. If I understand your problem right, it's about building the right hashtable in $srargs to pass to New-SCSMOBject. So the next modification is:
foreach ($Row in $csv)
{
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
# etc
$srargs = #{
Title = $title
Urgency = $srurg
Priority = $srprior
ID = “SR{0}”
Area = $ararea
SupportGroup = "ServiceDesk"
Description = $descrip
}
$srargs # write the hashtable so you can inspect it
# skip the rest of the code for now
}
I understand your question as "how to express the logic of":
support group is always servicedesk
Unless the host_name does not contain "RES"
then the support group is contents of EITS_HW_Notes cell in CSV
and it will be assigned to "custodian"
I can't help you with setting the assignee. But we can rejig the rest of the statement:
if host_name contains "RES"
SupportGroup = servicedesk
else
SupportGroup = contents of EITS_HW_Notes cell
You can code that like this:
foreach ($Row in $csv)
{
$srClass = Get-SCSMClass -name System.WorkItem.ServiceRequest
# etc
if ($Row.host_name -like "*RES*")
{
$SupportGroup = "ServiceDesk"
}
else
{
$SupportGroup = $Row.EITS_HW_Notes
}
$srargs = #{
Title = $title
# etc
SupportGroup = $SupportGroup
Description = $descrip
}
}
Does that get you any closer to your solution?
I am very new to powershell script. i am trying to get SSAS Tabular model connection string details for multiple servers. i have code which will return only for single server. How to modify the code to pass multiple servers?
$servername = "servername1"
# Connect SSAS Server
$server = New-Object Microsoft.AnalysisServices.Server
$server.connect($servername)
$DSTable = #();
foreach ( $db in $server.databases)
{
$dbname = $db.Name
$Srver = $db.ParentServer
foreach ( $ds in $db.Model.DataSources)
{
$hash = #
{
"Server" = $Srver;
"Model_Name" = $dbname ;
"Datasource_Name" = $ds.Name ;
"ConnectionString" = $ds.ConnectionString ;
"ImpersonationMode" = $ds.ImpersonationMode;
"Impersonation_Account" = $ds.Account;
}
$row = New-Object psobject -Property $hash
$DSTable += $row
}
}
As commented, you can surround the code you have in another foreach loop.
Using array concatenation with += is a bad idea, because on each addition, the entire array needs to be recreated in memory, so that is both time and memory consuming.
Best thing is to let PowerShell do the heavy lifting of collecting the data:
$allServers = 'server01','server02','server03' # etc. an array of servernames
# loop through the servers array and collect the utput in variable $result
$result = foreach($servername in $allServers) {
# Connect SSAS Server
$server = New-Object Microsoft.AnalysisServices.Server
$server.Connect($servername)
foreach ( $db in $server.databases) {
foreach ( $ds in $db.Model.DataSources) {
# output an object with the desired properties
[PsCustomObject]#{
Server = $db.ParentServer
Model_Name = $db.Name
Datasource_Name = $ds.Name
ConnectionString = $ds.ConnectionString
ImpersonationMode = $ds.ImpersonationMode
Impersonation_Account = $ds.Account
}
}
}
}
# output on screen
$result | Out-GridView -Title 'SSAS connection string details'
# output to a CSV file (change the path and filename here of course..)
$result | Export-Csv -Path 'D:\Test\MySSAS_Connections.csv' -UseCulture -NoTypeInformation
The above uses parameter -UseCulture because then the delimiter used for the CSV file is the same as your machine expects when double-clicking and opening in Excel. Without that, the default comma is used
I am trying to create a script to add people to groups and i would like something like an IF statement that will automatically add our employees to their VLAN group if they are in a certain OU. Lets say our employees are in OU = test and they will be added to the group "Test VLAN"
I would like to add this to my script that checks which OU they're in and adds them to a specific VLAN group.
Thanks
Here you go, no activedirectory module needed.
You would need to adjust the LDAP filter to your liking. Currently it does it for all user objects with the Title field populated
$VerbosePreference = "Continue"
[void][System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement")
# LDAP search filter, this gets all users with the title field populated
$searchFilter = "(&(objectclass=user)(title=*))"
# Hash mapping between group name and OU
$mapping = #(
[PSCustomObject]#{ Name = "Test VLAN"; Value = "OU=Test,OU=Users,DC=contoso,DC=com"}
[PSCustomObject]#{ Name = "Test VLAN 2"; Value = "OU=Test2,OU=Users,DC=contoso,DC=com"}
[PSCustomObject]#{ Name = "Test VLAN 123123"; Value = "OU=Test123123,OU=Users,DC=contoso,DC=com"}
)
# Get all users in Active Directory
$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"")
$directorySearcher.Filter = $searchFilter
$directorySearcher.PropertiesToLoad.Add("samaccountname")
$directorySearcher.PropertiesToLoad.Add("distinguishedname")
$users = $directorySearcher.FindAll()
$domainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
$principalContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new("Domain",$domainName)
# Loop through users and add them to group
foreach ($user in $users) {
$userPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($principalContext, $user.Properties.samaccountname)
if ($userPrincipal) {
$vlanGroup = $mapping.Where({$user.Properties.distinguishedname.EndsWith($_.Value)})
if ($vlanGroup) {
$groupPrincipal = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($principalContext, $vlanGroup.Name)
if ($userPrincipal.IsMemberOf($groupPrincipal)) {
Write-Verbose "User '$($user.Properties.samaccountname)' is already memberof '$($vlanGroup)'"
}
else {
$groupPrincipal.Members.Add($userPrincipal)
$groupPrincipal.Save()
Write-Verbose "Added user '$($user.Properties.samaccountname)' to group '$($vlanGroup)'"
}
}
else {
Write-Verbose "No VLAN mapping found for user '$($user.Properties.samaccountname)'"
}
}
else {
Write-Verbose "Unable to find userprincipal for '$($user.Properties.samaccountname)'"
}
Clear-Variable 'userPrincipal', 'vlanGroup', 'groupPrincipal' -ErrorAction SilentlyContinue
}
I am looking for some powershell code that can add a user from one domain to another domain group. I can't seem to find the magic code that will work that uses System.DirectoryServices.
###############
# Query user
################
# Variables
$path="GC://ldap-server.company.com"
# To limit the information returned add properties. Use an empty string to
pull everything
$property="objectcategory,distinguishedname,cn,mailnickname,samaccountname"
$searchFilter="(&(objectClass=User)(samaccountname=joker))"
$rootEntry = New-Object System.DirectoryServices.DirectoryEntry $path
$search= New-Object System.DirectoryServices.DirectorySearcher $rootEntry;
if ($properties) {
foreach ($property in [regex]::split($properties, ", ?")) {
[void]$search.PropertiesToLoad.Add($property);
}
}
$search.Filter = $searchFilter;
$searchResults = $search.FindOne();
$user = $searchResults.GetDirectoryEntry()
$user_dn = $searchResults.GetDirectoryEntry().distinguishedName;
# to find the first or only result, use $searchResults = $search.FindOne();
################
#Query group
################
# Same as Query user, just change
$property="";
$searchFilter="(&(objectClass=Group)(samaccountname=mygroup))";
$search.Filter = $searchFilter;
$searchResults = $search.FindOne();
################
#Add user to group
################
# From your group query
$group_dn = $searchResults.GetDirectoryEntry().distinguishedName
I tried this, but it did not seem to add the user and is ADSI:
$Group = [ADSI]"LDAP://"+$group_dn
$User = [ADSI]"LDAP://"+$user_dn
If ($Group.IsMember($User.ADsPath) -eq $False)
{
$Group.Add($User.ADsPath)
}
I was unfortunate enough to have to do this the hard way once (a domain migration where the source domain was still on Windows Server 2008). What you need to do is add the user or group from the remote domain as a foreign security principal:
...
$group_dn = $searchResults.GetDirectoryEntry().distinguishedName
$fsp = New-Object Security.Principal.NTAccount('DOM1', 'username')
$sid = $fsp.Translate([Security.Principal.SecurityIdentifier]).Value
$group = New-Object DirectoryServices.DirectoryEntry("LDAP://$group_dn")
[void]$group.Member.Add("<SID=$sid>")
$group.CommitChanges()
$group.Close()
If possible you should use the ActiveDirectory module (requires at least Windows Server 2008 R2 and access to the AD Web Services).
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()