A windows server has 20 users as usr01 - usr20. For particular application, each users should have user level environment variable such as LDTP_PORT but different values as 4001 for usr 1 and 4020 for usr20.
As manual process , I could log on as each user and update but not possible for 30 servers. I tried through codes but it needs explicit log in as specific user.
I look for powershell or some other way as one user (who is admin user) could set the user level variable for all other users. I do not want to work with -SID- at registry HKU as I am not sure how to map the user with SID)
I think, that there is one simple way, but not really elegant.
Since port number is not sensitive data (because in your case, you can easily predict other user's ports), I would just make 20 global variables, so everyone will have his own. For example:
User with username $env:userName, will have his port in $env:userNameLPTPort.
So code will be as simple as this:
$firstLPTPort = 4000
ForEach ($userName in $usersList) {
$newEnvVariableName = "env:" + $userName + "LPTPort"
#machine means that the scope is for whole machine and it wont disappear after closing the session
[System.Environment]::SetEnvironmentVariable($newEnvVariableName, $firstLPTPort, "Machine")
$firstLPTPort++
}
To confirm, that it works, use this:
echo ([System.Environment]::GetEnvironmentVariable($envName,"Machine"))
Remember that SetEnvironemtVariable function, will not throw exception, if there is already one variable with this name, but just simply overwrite the old one.
Edit:
You can also specify scope for specific user, just change this:
[System.Environment]::SetEnvironmentVariable($newEnvVariableName, $firstLPTPort, "Machine")
into this:
[System.Environment]::SetEnvironmentVariable($newEnvVariableName, $firstLPTPort, $userName)
But make sure, that $usersList contains correct user names.
Related
Huhu,
is it possible to disable the search for other Users in an AD? In this picture i am logged in as "normal" User.
Get-ADuser search
Here is a Picture of our AD structure.
AD Structure
So i don't want that a User can find another User in the Users OU by powershell (get-aduser)
is that possible?
I hope you have enough informations to understand my issue.
Regards
This is not really a thing in Windows proper. The default in AD is all users read. Secondly, anyone in AD is likely to have an email alias and thus search where they use PowerShell or not by their email alias/SMTP address, and should be for email lookups, so, IMHO, this is a futile use case.
One does not need Get-ADUser to find a user in AD. One has been able to do this since AD has been around and well before PowerShell was ever a thing using older scripting methods with .bat/.cmd/.vbs/WMI/ADSI or .Net directly and that is how it was done before PowerShell was ever a thing.
If you don't what a user using a specific cmdlet/cmdlets, then you need to implement restrictions via 'PowerShell just enough administration (JEA)'
Again, One does not need to use PowerShell to scan and get info from AD, a well documented and used thing, for folks who have PowerShell disabled (or tried to) in their environments.
Example:
How Can I Get a List of All the Users in an OU and Its Sub-OUs?
VBScript:
On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Set objConnection = CreateObject(“ADODB.Connection”)
Set objCommand = CreateObject(“ADODB.Command”)
objConnection.Provider = “ADsDSOObject”
objConnection.Open “Active Directory Provider”
Set objCommand.ActiveConnection = objConnection
objCommand.Properties(“Page Size”) = 1000
objCommand.Properties(“Searchscope”) = ADS_SCOPE_SUBTREE
objCommand.CommandText = _
“SELECT Name FROM ‘LDAP://ou=finance,dc=fabrikam,dc=com’ WHERE objectCategory=’user'”
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
Wscript.Echo objRecordSet.Fields(“Name”).Value
objRecordSet.MoveNext
Loop
Or
ADDS PowerShell (CMDLET, ADSI & .Net) to Expedite Your Tasks
ADSI:
<#
PowerShell ADSI(Active Directory Services Interface) commands
1. How to find the users property.
#>
$users1 = [ADSI]"LDAP://cn=copy,cn=users,dc=contoso,dc=com"
$users1 | select *
# 2. How to find the Group members for a Group.
$test = [ADSI]"LDAP://CN=test,CN=Users,DC=contoso,DC=com"
$test.Member |
ForEach-Object {[ADSI]"LDAP://$_"} |
select samccountname, samaccounttype
# 3. Listing an OU Contents
$ou=[ADSI]"LDAP://ou=tech,dc=contoso,dc=com"
$ou.PSBase.Children
$ou.PSBase.Children | Format-Table sAMAccountName
So this worked for me:
I just got it working by unchecking the "List Contents" from the "authenticated users" of the "Users" OU and I did not recognized any side effects so far.
Rights of Authenticated Users
And the "normal" User can't see the other users anymore by a query.
Tested with powershell: AD-GetUser and CMD "net user"
Query Result
So my problem is solved if there won't be any side effects in the future.
I will let you know.
Cheers
In preparation for a test, we need to load a Windows Server VM with up to 400,000 users and 100,000 groups, and various mappings between them.
A powershell script has been written to achieve this, running on a Server 2012 R2 VM (4 cores, 8GB RAM). However, at the rate the script is running, it's looking like it could take more than a month to complete.
We've tried the script using both the net command and the Add-AD commands to see if there's any speed increase. There doesn't seem to be. The script uses several For loops to iterate through creating users, creating groups, and adding certain users numbers to group numbers.
Command examples were:
#net users $userName mypassword /add
#New-ADUser -Name $userName -SamAccountName $userName -DisplayName $userName -AccountPassword mypassword -Enabled $true
and
net group $groupName $userName /add
#Add-ADGroupMember -Identity $groupName -Members $userName
Any suggestions on the fastest way to load an AD with a mass of new users/groups/mappings?
Thanks
The PowerShell cmdlets for AD are convenient, but they are not efficient.
Using ADSI directly will likely be faster because it gives you more control of what's going on. PowerShell has a shortcut notation of [ADSI]"LDAP://thepath" to create objects (they're technically DirectoryEntry object, but the examples here use the IADs methods).
There are instructions on creating users here, but I can summarize it:
[ADSI]$OU = "LDAP://OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local"
$new = $OU.Create("user","CN=Ginger Snaps")
$new.put("samaccountname","gsnaps")
$new.setinfo()
#Account is created disabled, so we need to enable and set a password
#(the password can't be set until it's created)
$new.put("userAccountControl",544)
$new.setpassword("P#ssw0rd")
$new.setinfo()
You use $new.put() for whatever other attributes you want to set. You can also create groups this way too, just use "group" instead of "user" in the Create() method.
This is still going to take a while. It's the network connections that will hurt you the most. So you have to:
Get as physically close to a DC as you can (run it on a DC if you can), and
Keep the number of network requests down
If you do run this on a DC, then (if the domain has more than one DC) make sure to target the DC that you're on. You can do that by injecting the DC name into the LDAP:// strings, like this:
"LDAP://dc1.domain.com/OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local"
Number 2 is limited by the fact that you have to do 2 requests per new user (one to create, one to set password). But you can do other things to keep the number down, like create all the users first and store the distinguishedName of each new user, which you can calculate yourself (rather than asking AD for it) because it's the CN=user that you pass to Create() plus the OU. So for the example above, the DN of the new user is:
CN=Ginger Snaps,OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local
Once you have all those, you can create the groups and add all the members in one go. For example:
[ADSI]$OU = "LDAP://OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local"
$new = $OU.Create("group","CN=group1")
$new.put("samaccountname","group1")
$members = #("CN=Ginger Snaps,OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local", `
"CN=Another User,OU=IT,OU=Departments,OU=Employees,DC=Globomantics,DC=Local")
$new.put("member", $members)
$new.setinfo()
Where $members is your array of the distinguishedName for each member.
This way you have one network request that creates the whole group with the members already set, rather than one network request for each member.
Working on a side project where I use a set of views to identify contention of records within an iSeries set of physical files.
What I would like to do once identified is pull the user profile locking the record, and then send a break message to their terminal as an informational break message.
What I have found is the QEZSNDMG API. Simple enough to use interactively, but I'm trying to put together a command that would be used in conjunction with QCMDEXC API to issue the call to QEZSNDMG and alert the user that they are locking a record.
Reviewing the IBM documentation of the QEZSNDMG API, I see that there are two sets of option parameters, but nothing as required (which seems odd to me, but another topic for another day). But I continue to receive the error "Parameters passed on CALL do not match those required."
Here are some examples that I have tried from the command line so far:
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS' '1' '1' '-4')
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS')
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS' '1')
Note: I would like to avoid using a CL or RPG program if possible but understand it may come to that using one of many examples I found before posting. Just want to exhaust this option before going down that road.
Update
While logged in, I used WRKMSGQ to see the message queues assigned to my station. There were two: QSYS/DOUGLAS and QUSRSYS/DOUGLAS. I then issued SNDBRKMSG with no affect on my workstation (IE, the message didn't break my session):
SNDBRKMSG MSG(TESTING) TOMSGQ(QSYS/DOUGLAS)
SNDBRKMSG MSG(TESTING) TOMSGQ(QUSRSYS/DOUGLAS)
I realized if I provide the workstation session name in the TOMSG parameter it worked:
SNDBRKMSG MSG(TESTING) TOMSGQ(*LIBL/QPADEV0003)
Using SNDBRKMSG was what I was looking for.
Some nudging in the right direction lead me to realize that the workstation session ID is located within QSYS2.RCD_LOCK in field JOB_NAME (job number/username/workstation).
Extracting the workstation ID allowed me to create a correctly formatted SNDBRKMSG command to QCMDEXC and alert the user that they are locking a record needed by another process.
I am a beginner in PowerShell, so I have been tinkering around it to learn more about its uses. Currently I have a task that requires me to remove a list of chosen groups from a user.
The user is in a different domain, hence I have used LDAP.
I am able to find that user and bind it to an object using the command below:
[ADSI]$user = "LDAP://CN=xxx,OU=xxx,DC=xxx"*
so I am able to display whatever information required from $user e.g. $user.sAMAccountName, $user.DisplayName it works. Except for the users groups...
I try the command to remove the groups listed in the user based on sAMAccountName; as all the users in that domain is identified easier by sAMAccountName, it doesnt work.
this command was used just to see if I can remove one group first; if $user can be found and read by the command; it doesnt work
remove-adgroupmember "GroupName" $user.sAMAccountName
or when I tried to display the groups instead to see if $user can be read, it also doesnt work,
Get-ADPrincipalGroupMembership [ADSI]$user = "LDAP://CN=xxx,OU=xxx,DC=xxx" |
select name
I have tried to search regarding this issue, but almost all the tips does not involve different domains or used ldap for other domains, it uses the primary domain instead, and I am not sure on how to edit that part.
If anyone can advice me I would be very grateful, thank you =)
My company, like everyone else's, requires password resets from time to time. This is all good and well for security's sake, but I'd like to explore the challenge of resetting it through a script (notably because we can't use our previous 25 passwords; Perl is much quicker about cycling through a list two-dozen deep than my fingers are).
I'm trying to use Perl and Win32::OLE's LDAP connectors to reset my password. I've followed a couple of examples online, and have, briefly:
use strict;
use Win32::OLE;
my $dn = 'cn=name,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://' . $dn,'username','password',1);
$ldap_user->SetPassword('mySw337NewPassword');
And all I get for my troubles is:
Win32::OLE(0.1707) error 0x80070005: "Access is denied"
in METHOD/PROPERTYGET "SetPassword" at pw.change.pl line 8
Is this something that can be worked around? I've located the Net::LDAP::Extension::SetPassword module, but no dice there.
Thanks!
Update for Leon (Max, you're next):
You're correct, I should have specified better. I tried Win32::OLE, failed, then separately tried Net::LDAP::Extension::SetPassword and failed even harder.
As for my server: I'm not certain, I'm not the LDAP guy :) By running ->root_dse->get_value('supportedExtension') I can see that the setPassword OID is not set, so maybe it's just not meant to be.
Final props to barneyton!
Final solution:
use strict;
use Win32::OLE;
my $orig_password = 'password123Test';
my $target_password = 'password321Test';
my $dn = 'cn=myname,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://'.$dn,'myname',$orig_password,1);
my $tmp_password = '';
for ( my $i = 0; $i < 30; ++$i )
{
$tmp_password = 'password' . $i . 'ABC';
print 'Changing to ' . $tmp_password . "\n";
$ldap_user->ChangePassword($orig_password,$tmp_password);
$orig_password = $tmp_password;
sleep 1;
}
$ldap_user->ChangePassword($tmp_password,$target_password);
When you said you were trying to "reset" your password, I think you really meant change password rather than set password. There is a difference between the two. "SetPassword" requires god/admin privilege since you are setting a user's password to a new value regardless of whether the old password is known, while "ChangePassword" requires the user to actually know the old password. I'm assuming your account does not have admin privilege, else you would not have gotten 0x80070005: "Access is denied"
So instead of:
$ldap_user->SetPassword('mySw337NewPassword');
try this:
$ldap_user->ChangePassword('password', 'mySw337NewPassword');
By the way, I've never done this stuff in perl, so I'm just guessing. Hope this helps you out.
Net::LDAP::Extension::SetPassword doesn't have anything to do with any OLE LDAP object. Either you use Net::LDAP, or you use Win32::OLE->GetObject('LDAP:').
You didn't mention what server you're using. Setting passwords requires an extension to LDAP, so that is relevant.
Another thing to keep in mind is Active Directory does not let you set passwords unless you bind to port 636 using LDAPS.
You could try to write the value to userPassword which would be a password reset, and you might not have rights to do that.
Otherwise you could try in one operation (LDIF would show it as separated by a single dash on a line) remove the value of the old password and then add the value of the new password. That would be a password change event.