Статья размещена автором Бетке Сергей Сергеевич

PowerShell: формируем samAccountName сотрудника транслитерацией из его ФИО

Ранее уже приводил сценарии, позволяющие изменить атрибуты учётных записей в AD по данным csv файла. Сегодня реализую простейшую задачу: по Фамилии, Имени и Отчеству в csv файле сгенерирую samAccountName, lname (для почты). Генерировать буду по одним и тем же правилам, но при они могут различаться – на samAccountName достаточно жёсткие ограничения по длине накладывает ОС (по сути – 14 символов, если всё ещё стремиться к поддержке WINS, хотя кому это сейчас уже надо?).

Приведу пример сценария, который загружает данные из .csv файла, формирует транслитерацией дополнительные атрибуты и выгружает результат обратно в csv файл.

<#
    .Synopsis
        Загружает данные сотрудников из .csv файла, добавляет необходимые атрибуты 
    .Description
    .Parameter csvFile
        Полный путь к файлу, из которого будем импортировать
    .Parameter outputFile
        Полный путь к файлу, в котором будут сохранены данные
    .Example
        Импортируем 

        .\UpdateUsersAttributes.ps1 -csvFile 'users.csv'
#> 

param (
    [Parameter(
        Mandatory=$false,
        Position=0,
        ValueFromPipeline=$false,
        HelpMessage="Полный путь к файлу, из которого будем импортировать."
    )]
    [System.IO.FileInfo]
    $csvFile = `
        (join-path `
            -path ( ( [System.IO.FileInfo] ( $myinvocation.mycommand.path ) ).directory ) `
            -childPath 'users.csv' `
        )
    , [Parameter(
        Mandatory=$false,
        Position=1,
        ValueFromPipeline=$false,
        HelpMessage="Полный путь к файлу, в который будет осуществлена запись результата."
    )]
    [string]
    $outputCsvFile = $csvFile `
) 

Import-Module `
    (join-path `
        -path ( ( [System.IO.FileInfo] ( $myinvocation.mycommand.path ) ).directory ) `
        -childPath 'ITG.Translit\ITG.Translit' `
    ) `
    -force `
;

function Add-Attribute {
    param (
        [Parameter(
            Mandatory=$true,
            Position=0,
            ValueFromPipeline=$false,
            ValueFromPipelineByPropertyName=$false
        )]
        [string]
        $Name
        , [Parameter(
            Mandatory=$false,
            Position=1,
            ValueFromPipeline=$false,
            ValueFromPipelineByPropertyName=$false
        )]
        [scriptBlock]
        $Value = {$null}
        , [Parameter(
            Mandatory=$true,
            Position=2,
            ValueFromPipeline=$true
        )]
        [PSObject]
        $InputObject
    ) 
    
    Add-Member `
        -PassThru `
        -InputObject $InputObject `
        -MemberType noteProperty `
        -ErrorAction SilentlyContinue `
        -Name $Name `
        -Value ( $InputObject | % { & $Value } ) `
        -Force `
    ;
}
$users = ( `
get-content `
    -path $csvFile `
| convertFrom-csv `
    -UseCulture `
| ? { $_.sn } `
| % { 
    $_ `
    | Add-Attribute sn { $_.sn.Trim() | ?{$_} | %{ $_.Substring(0,1).ToUpper() + $_.Substring(1).ToLower() } } `
    | Add-Attribute givenName { $_.givenName.Trim() | ?{$_} | %{ $_.Substring(0,1).ToUpper() + $_.Substring(1).ToLower() } } `
    | Add-Attribute middleName { $_.middleName.Trim() | ?{$_} | %{ $_.Substring(0,1).ToUpper() + $_.Substring(1).ToLower() } } `
    | Add-Attribute extensionName `
    | Add-Attribute personalTitle `
    | Add-Attribute generationQualifier `
    | Add-Attribute initials { ( $_.givenName, $_.middleName | ? { $_ } | % { $_[0] + '.' } ) -join ' ' } `
    `
    | Add-Attribute cn { ( $_.sn, $_.givenName, $_.middleName | ? { $_ } ) -join ' ' } `
    | Add-Attribute name { $_.cn } `
    | Add-Attribute displayName { $_.cn } `
    `
    | Add-Attribute mailNickname { ( $_.givenName, $_.middleName[0], $_.sn | ? { $_ } | ConvertTo-Translit ) -join '.' } `
    | Add-Attribute mail { $_.mailNickname + '@csm.nov.ru' } `
    | Add-Attribute wWWHomePage { 'www.csm.nov.ru' } `
    `
    | Add-Attribute sAMAccountName { if ($_.length -gt 20) {$_.mailNickname.Substring(0, 20)} else {$_.mailNickname} } `
    | Add-Attribute userPrincipalName { $_.mail } `
    `
    | Add-Attribute company { 'Новгородский филиал ФБУ "Тест-С.-Петербург"' } `
    | Add-Attribute employeeID `
    | Add-Attribute employeeType `
    | Add-Attribute department {
        switch ( $_.department.Trim() ) {
            'АУП' { 'Дирекция' }
            'Старорусское подраз-е' { 'Старорусский филиал' }
            'Боровическое подраз-е' { 'Боровический филиал' }
            'СОФФ' { 'Технический отдел' }
            default { $_ }
        }
    } `
    | Add-Attribute departmentNumber `
    | Add-Attribute division {
        switch ( $_.department ) {
            'Старорусский филиал' { 'Старорусский филиал' }
            'Боровический филиал' { 'Боровический филиал' }
            default { 'Новгородский филиал' }
        }
    } `
    | Add-Attribute title `
    | Add-Attribute businessCategory `
    | Add-Attribute businessRoles `
    | Add-Attribute description `
    `
    | Add-Attribute telephoneNumber {
        if ( $_.telephoneNumber -match '(?:[+](?<КодСтраны>\d{1,3}))?\s*(?:[(](?<КодГорода>\d{3}[\s-]*\d{1,2})[)])?[\s-]*(?<Телефон>[\d\s-]{5,10})' ) {
            $countryCode = if ( $matches['КодСтраны'] ) { $matches['КодСтраны'] } else { '7' };
            $cityCode = if ( $matches['КодГорода'] ) {
                $matches['КодГорода'] -replace '[\s-]', '' 
            } else {
                switch ( $_.division ) {
                    'Старорусский филиал' { '81652' }
                    'Боровический филиал' { '81664' }
                    default { '8162' }
                }
            };
            $phone = $matches['Телефон'] -replace '[\s-]', '-';
            "+$countryCode ($cityCode) $phone";
        };
    } `
    | Add-Attribute facsimileTelephoneNumber {
        if ( $_.facsimileTelephoneNumber -match '(?:[+](?<КодСтраны>\d{1,3}))?\s*(?:[(](?<КодГорода>\d{3}[\s-]*\d{1,2})[)])?[\s-]*(?<Телефон>[\d\s-]{5,10})' ) {
            $countryCode = if ( $matches['КодСтраны'] ) { $matches['КодСтраны'] } else { '7' };
            $cityCode = if ( $matches['КодГорода'] ) {
                $matches['КодГорода'] -replace '[\s-]', '' 
            } else {
                switch ( $_.division ) {
                    'Старорусский филиал' { '81652' }
                    'Боровический филиал' { '81664' }
                    default { '8162' }
                }
            };
            $phone = $matches['Телефон'] -replace '[\s-]', '-';
            "+$countryCode ($cityCode) $phone";
        };
    } `
    | Add-Attribute mobile {
        if ( $_.mobile -match '(?:[+]?(?<КодСтраны>\d{1,3}))?[-\s]*(?:[(]?(?<КодОператора>\d{3})[)]?)[\s-]*(?<Телефон>[\d\s-]{7,10})' ) {
            $countryCode = if ( $matches['КодСтраны'] ) { $matches['КодСтраны'] } else { '7' };
            $provCode = if ( $matches['КодОператора'] ) {
                $matches['КодОператора']; 
            } else {
                '911';
            };
            $phone = $matches['Телефон'] -replace '[\s-]', '-';
            "+$countryCode ($provCode) $phone";
        };
    } `
    | Add-Attribute otherTelephone {
        if ( $_.otherTelephone -match '(?<Телефон>\d{2})' ) {
            $matches['Телефон'];
        };
    } `
    `
    | Add-Attribute c { 'RU' } `
    | Add-Attribute co { 'RUSSIAN FEDERATION' } `
    | Add-Attribute countryCode { '643' } `
    | Add-Attribute o { 'Новгородская область' } `
    | Add-Attribute l { 
        switch ( $_.division ) {
            'Старорусский филиал' { 'г. Старая Русса' }
            'Боровический филиал' { 'г. Боровичи' }
            default { 'Великий Новгород' }
        }
    } `
    | Add-Attribute st `
    | Add-Attribute postalCode { 
        switch ( $_.division ) {
            'Старорусский филиал' { '175200' }
            'Боровический филиал' { '174400' }
            default { '173021' }
        }
    } `
    | Add-Attribute street {
        switch ( $_.division ) {
            'Старорусский филиал' { 'ул. Володарского' }
            'Боровический филиал' { 'ул. Сушанская' }
            default { 'ул. Нехинская' }
        }
    } `
    | Add-Attribute streetAddress {
        switch ( $_.division ) {
            'Старорусский филиал' { 'ул. Володарского, д.43' }
            'Боровический филиал' { 'ул. Сушанская, д.6' }
            default { 'ул. Нехинская, д.57' }
        }
    } `
    | Add-Attribute houseIdentifier {
        switch ( $_.division ) {
            'Старорусский филиал' { '43' }
            'Боровический филиал' { '6' }
            default { '57' }
        }
    } `
    | Add-Attribute postalAddress {
        switch ( $_.division ) {
            'Старорусский филиал' { 'ул. Володарского, д.43' }
            'Боровический филиал' { 'ул. Сушанская, д.6' }
            default { 'ул. Нехинская, д.57' }
        }
    } `
    | Add-Attribute roomNumber `
} `
);

$users `
| % {
    $_ `
    | Add-Attribute managerCn {
<#
        if ( $_.Руководитель.Trim() -match '(?<Фамилия>\w+)\s+(?<И>\w)[`.]?\s*(?<О>\w)[`.]?' ) {
            $testInitials = $matches['И'] + '.', $matches['О'] + '.' -join ' ';
            $candidate = $users `
                | ? { ($_.sn -eq $matches['Фамилия']) -and ($_.initials -eq $testInitials) } `
            ;
            $candidate.cn;
        };
#>
        $_.managerCn;
    } `
    | Add-Attribute assistantCn `
    | Add-Attribute secretaryCn `
    ;
} `
| Export-Csv `
    $outputCsvFile `
    -encoding 'UTF8' `
    -UseCulture `
    -NoTypeInformation `
;

Сама процедура транслитерации (ConvertTo-Translit) и описана ранее. Данный скрипт сейчас в упрощённом виде, в дальнейшем оформлю модуль, в котором будет реализована поточная функция, которая обеспечит заполнение атрибутов сотрудников по вышеприведённому алгоритму. А откуда она будет получать вход – из csv файла ли, или из AD, и куда объекты будут сохраняться в итоге – уже не важно, сама функция выполнит работу в любом случае.

Атрибуты взяты из схемы AD, ничего не выдумывал. Описание атрибутов — в MSDN.

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка