Kristoffer Qvists blogg om allt möjligt

Etikett: Skapa användare

Skapa användare med PowerShell

PowerShell är ett kraftfullt verktyg i Windowsmiljön. Med detta skriptspråk kan man göra mycket administrativt arbete, bland annat skapande av användare vilket detta inlägg kommer att gå igenom. Lösningen som kommer att visas här kanske inte passar alla, däremot skall den skapa unika användare i domänen och även skapa ett engångslösenord. Lösenordet sparas med användarinformationen i den aktuella administratörens dokument-mapp. Jag publicerar skriptet här med förhoppningen om att den skall vara intressant och ge en fingervisning i hur man kan skapa användare för de som behöver det.

Alla användare skapas så att deras användarnamn består av de två första tecknen i för- och efternamnet. Heter man Sven Svensson blir alltså användarnamnet svsv. Skulle flera användare få ett likadant användarnamn adderas ett nummer till slutet, så om två Sven Svensson finns blir en svsv och den andra svsv2, på samma sätt adderas en siffra om fler personer skulle heta likadant. Då protokollet LDAP – vilket Active Directory använder sig av – kräver en unik identifierare (Distinguished Name) kan detta skript generera 26 + 1 sådana.

För att skriptet skall fungera bör följande saker finnas;

  • Windows Server med Active Directory
  • En csv-fil innehållande användare

Csv-filen skall innehålla följande:

  • Förnamn
  • Efternamn
  • Stad i vilken användaren finns
  • Avdelning i vilken användaren jobbar

Sedan är det valfritt att ha roll som attribut för användaren. För att exemplifiera csv-filen med två användare, kan det se ut på följande sätt:

Firstname;Lastname;Department;City;Role
Sven;Svensson;IT;Göteborg;Manager
Rut;Johansson;HR;Göteborg

Vad gäller skriptet och csv-filen måste dessa sparas i utf-8 format för att åäö skall visas korrekt. I normala fall sparar program såsom exempelvis Notepad filer i ASCII, som inte innehåller vissa svenska tecken. Istället visas ett tecken som kan liknas vid en romb med ett frågetecken inuti.

Skriptet kommer att spara en användare i example.com/Example/Stad/Avdelning/. Här kan förstås ordet Example bytas ut till namnet på den organisation det gäller.

############## METADATA ############## 
# AUTHOR: KRISTOFFER QVIST
# LICENCE: Apache Licence, v.2
# GOALS:
# * Check that new users actually are
#   unique within domain,
# * Assign unique email-addresses
# * Check for duplicate names within
#   an OU to correct these.
#####################################
 
param([string]$csvfile= [Environment]::GetFolderPath('MyDocuments') + "\thisFile.csv")
 
Import-Module ActiveDirectory
 
while((Test-Path -Path $csvfile) -eq $false) {
    $csvfile = Read-Host "Please, fill in the correct path to the .csv file"
}
 
$users  = Import-Csv -Delimiter ";" -Path $csvfile
 
foreach ($user in $users) {
    $fname      = $user.Firstname
    $fname      = $fname.Trim()
    $sname      = $user.Lastname
    $sname      = $sname.Trim()
    $dplName    = $fname+" "+$sname
    $domain     = "@example.com"
    # Get first two letters of firstname
    $samf       = $fname.substring(0,2)
    # Get first two letters of lastname
    $saml       = $sname.substring(0,2)
    $sam        = $samf+$saml
    $sam        = $sam.ToLower()
    $department = $user.Department
    $city       = $user.City
    $role       = $user.Role
 
    # The user should be added here
    $OU = "OU=$department,OU=$city,OU=Example,DC=example,DC=com"
    $dn = "CN=" + $dplName + "," + $OU
 
    # Place to store groups in
    $GroupOU = "OU=Groups,DC=example,DC=com"
 
    # Check if the OU exists, otherwise create it
    $LDAPOU = "LDAP://" + $OU
    $OUexists = [adsi]::Exists($LDAPOU)
 
    if ($OUexists -eq $false) {
        dsadd ou $OU
    }
 
    # Generate random password 8-byte password
    $length   = 2 # length x 4 equals the password length 
    $password = ""
    $chars    = "ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrtuvxyz".ToCharArray()
    for($i=0; $i -lt $length; $i++) {
        $password += $chars | Get-Random
    }
 
    $chars2 = "0123456789!#%/()".ToCharArray()
    for($i=0; $i -lt $length; $i++) {
        $password += $chars2 | Get-Random
    }
 
    for($i=0; $i -lt $length; $i++) {
        $password += $chars | Get-Random
    }
 
    for($i=0; $i -lt $length; $i++) {
        $password += $chars2 | Get-Random
    }
 
    # Create a clean email address (e.g. from Åsa.Lindén to asa.linden)
    $eaddress    = $fname.ToLower() + "." + $sname.ToLower()
    $eaddress    = $eaddress -replace "é","e"
    $eaddress    = $eaddress -replace "å","a"
    $eaddress    = $eaddress -replace "ä","a"
    $eaddress    = $eaddress -replace "ö","o"
 
    $email = $eaddress + $domain
 
    $emailExists = Get-ADUser -Filter { EmailAddress -like $email }
    $emailBase   = $eaddress
    $i = 2
 
    while ($emailExists -ne $null) {
        $email = $emailBase + "." + $i + $domain
        $emailExists = Get-ADUser -Filter {EmailAddress -like $email }
        $i++
    }
 
    # Create clean login name
    $sam    = $sam -replace "é","e"
    $sam    = $sam -replace "å","a"
    $sam    = $sam -replace "ä","a"
    $sam    = $sam -replace "ö","o"
 
    # Check if the user sam exists in AD already
    $checkADUser = Get-ADUser -LDAPFilter "(SamAccountName=$sam)"
    $i = 2
    $baseSam = $sam
 
    # If user exist, add a number to the end
    while ($checkADUser -ne $null) {
        $sam = $baseSam+$i
        $checkADUser = Get-ADUser -LDAPFilter "(SamAccountName=$sam)"
        $i++
    }
 
    # Check that the user has a unique DN
    $DNExists = Get-ADUser -Filter {distinguishedName -eq $dn }
    $i = 0
    $letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
    while ($DNExists -ne $null) {
        $dplName = $fname + " " + $letters[$i] + " " + $sname
        $dn = "CN=" + $dplName + "," + $OU
        #Write-Host $dn
        $DNExists = Get-ADUser -Filter {distinguishedName -eq $dn }
        $i++
    }
 
    # And use it in user principal name
    $upn        = $sam+$domain
 
    # Check if the localisation group exists, otherwise create it
    try {
        Get-ADGroup -Identity $city | out-null
    } catch {
        New-ADGroup -Name $city -GroupScope Global -Path $GroupOU
        Write-Host "New group '$city' created"
    }
 
    # Check if the shadow group exists, otherwise create it
    $ADShadowGroup = "SG_" + $department
    try { 
        Get-ADGroup -Identity $ADShadowGroup | out-null
    } catch {
        New-ADGroup -Name $ADShadowGroup -GroupScope Global -Path $GroupOU
        Write-Host "New group '$ADShadowGroup' created"
    }
 
    # This file will hold the user login credentials
    $file = [Environment]::GetFolderPath('MyDocuments') + "\" + $sam + ".txt"
 
    # Add the user to AD
    New-ADUser -SamAccountName $sam -Name $dplName -GivenName $fname -Surname $sname -DisplayName $dplName -UserPrincipalName $upn -Department $department -City $city -EmailAddress $email -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) -AccountExpirationDate $null -ChangePasswordAtLogon $true -Enabled $true -Path $OU -ErrorAction SilentlyContinue
 
    # Add the role as title
    if ( $role -eq $false) {
        $role = $role.Trim()
        if ($role -ne $null) {
            Set-ADUser -Identity $sam -Title $role -ErrorAction SilentlyContinue
        }
    }
 
    # Add the user to an their repective shadow and localisation group
    Add-ADGroupMember $ADShadowGroup $sam
    Add-ADGroupMember $city $sam
 
    # Create file
    New-Item $file -type file -force -value "Login credentials for $dplName
    Domain: $domain
    Login name: $sam
    One time password: $password" | out-null
}
 
Remove-Module ActiveDirectory

Relaterat: Skapa användare med Perl.

Skapa användare med Perl

Uppdaterat: 2014.09.29

För ett tag sedan var jag tvungen att använda mig utav Perl för att generera användare och sedan ge dem ett tillfälligt lösenord som de kommer att få byta när de har loggat i. Systemet där skriptet användes är ett Linux-system (CentOS 6.5).

Skriptet matchar följande krav:

  • Ha stöd för utf-8
  • Läsa in för- och efternamn från en textfil
  • Skapa unika användare från textfilen
  • Skriva ut användarinformation till en ny textfil per användare, i en särskild mapp

För att kunna köra skriptet krävs modulen Text::Iconv, vilket kan testas genom att skriva perl -e 'use Text::Iconv;' i kommandotolken. Om du inte får ett svar, är modulen installerad. Om du får många felmeddelanden som svar, är modulen inte installerad. Hur man installerar moduler kan jag skriva om i ett annat inlägg, annars kan ni använda det ”gamla” sättet (vad gäller mitt skript) där icke-ASCII-tecken blir bytta till ett x. Eventuellt kan du kika på denna hemsida som förklarar hur man installerar ett verktyg som kan vara till stor hjälp i en CentOS-maskin, på engelska. Vidare står här hur man sedan använder verktyget för att installera modulerna.

Om du undrar över något, går det att skicka in ett mail till mig, så ska jag försöka svara så fort jag kan. Eventuellt, om det är flera som frågar, kan jag publicera svaren här i detta inlägg eller någon annanstans på hemsidan. Dock kommer skriptet inte att kontrollera om användaren lägger till mer input än vad som behövs.

För att få denna kod att vara såpass internationell som möjligt, används engelska kommentarer och variabelnamn.

#!/bin/usr/perl
#############METADATA############
# Author:	Kristoffer Qvist
# Version:	2
# Last
# Modified:	Sep 29th, 2014
# History:	Made utf-8 to
# 		ASCII converting
#		better.
#################################
use warnings;
use strict;
use Text::Iconv;
binmode STDOUT, 'utf8';
# Get file that contains users
my ($file, $userDir) = @ARGV;
while(not -e $file) {
print("Please, add a valid file containing your users.\n");
chomp($file = <STDIN>);
}
while(not -e $userDir) {
print("Please, add a valid folder to store the user password files\n");
chomp($userDir = <STDIN>);
}
# A basic check for script injection attempt
if($file =~ /;/ or $userDir =~ /;/) {
die("Script injection attempt found!\n");
}
# Put all new users in array
open(USERS, "<", $file) or die("The file $file could not be opened: $!");
chomp(my @new_users=<USERS>);
while (<USERS>) {
push (@new_users, $_);
}
close USERS or die($!);
# Get passwd content
my $passwd_file     = "/etc/passwd";
my $passwd_contents = open(PASSWD, "<", "/etc/passwd") or die("$!");
my @passwd;
while (<PASSWD>) {
push (@passwd, $_);
}
close PASSWD or die("$!");
# Set all existing users in hash
my %existing_users = ();
for(my $i=0;$i<scalar(@passwd);$i++) {
my @passwd_entry = split /:/,$passwd[$i];
$existing_users{$passwd_entry[0]} = $i;
}
# Add users to the system and create a random one-time password
foreach my $new_user(@new_users) {
my @names = split(/ /, $new_user); 
my $fn = substr($names[0],0,3);
my $ln = substr($names[1],0,2);
my $username = $fn.$ln;
# Converts non-ascii to x (old; latter converting is better)
# $username =~ s/[^[:ascii:]+]/x/g; 
# Encode usernames to ascii (new)
my $convert_this = Text::Iconv->new("UTF-8", "ASCII//TRANSLIT");
$username = $convert_this->convert($username);
$username = lc($username);
# Check for duplicate users, if found add number 
my $i = 1;
while(exists $existing_users{$username}) {
$username =~ s/[0-9]//g;
$username = $username.$i++;
}
$existing_users{$username} = $i;
my $password = join'', map +(0..9,'a'..'z','A'..'Z','!?()""')[rand(10+26*2)], 1..8;
`useradd $username -c "$new_user" &> /dev/null`;
`echo -e "$password\n$password" | passwd $username &> /dev/null`;
`chage -d 0 $username`;
open (USERFILE, ">", "$userDir/$username.txt") or die("The file $userDir/$username.txt could not be opened: $!\n");
print USERFILE "$new_user\n--------------------\n$username: $password";
close USERFILE or die("The file $userDir/$username.txt could not be closed: $!\n");
}
print("\nBatch completed!\n");

© 2024 qvi.st

Tema av Anders NorenUpp ↑