Делаем FTP для Windows Azure Pack

Автор статьи — Сергей Груздов (egel@egel.su), ведущий инженер, Dataline


Windows Azure Pack предоставляет подписчикам возможность использовать собственные ISO- и VHD (X)-файлы, расположенные в выделенной только для подписчика папке библиотеки. На данный момент единственным способом закачки файлов в эту папку является организация FTP с корневой папкой, указывающей на папку библиотеки, выделенной подписчикам. В данной статье я продемонстрирую, как с помощью ранбуков (runbook) Service Manager Automation (SMA) создавать и удалять папки подписчиков при заведении или удалении пользователя, и как с помощью расширения Microsoft FTP собственными провайдерами авторизации и домашних каталогов авторизовывать пользователей непосредственно через Azure Pack, исключая необходимость дублировать учетные записи в Active Directory.
Предварительно необходимо добавить активы SMA:

  1. VMMConnection — переменная типа «Соединение», в которой указывается FQDN сервера VMM и учетные данные. Учетная запись должна входить в группу локальных администраторов на сервере библиотеки, сервере VMM и в VMM входить в группу «Администраторы»
  2. VMMLibPath — переменная с общей папкой корневого каталога библиотеки подписчиков


Обработка события создания подписчика


Подготовим ранбук для создания каталога подписчика и привязки его к учетной записи в VMM. Текст ранбука ниже. В качестве бонуса — код, оповещающий пользователя после заведения его на админском портале (или любым другим способом) о необходимости смены пароля. Это избавляет от надобности генерации паролей и пересылкой их открытым текстом пользователю.

Notify-Created-User
workflow Notify-Created-User
{
    param
    (
        [Parameter(Mandatory=$true)]
        [object] $params
    )    
    
    $VmmConnection = Get-AutomationConnection -Name 'VmmConnection'
    $VmmServerName = $VmmConnection.ComputerName

    $SecurePassword = ConvertTo-SecureString -AsPlainText -String $VmmConnection.Password -Force
    $VmmCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $VmmConnection.Username, $SecurePassword
    $eMail = $params.Name.SubString(0, $params.Name.IndexOf("_"))
    
    $vmmLib = Get-AutomationVariable -Name 'VMMLibPath'
    
    $libServer = $vmmLib.SubString(2)
    $libServer = $libServer.SubString(0, $libServer.IndexOf("\"))
    
    $tenantPath = "{0}\{1}" -f $vmmLib, $eMail
    
    Write-Output "Invoke create folder on $libServer"
    inlinescript
    {
        try 
        { 
            if (!(Test-Path $Using:tenantPath))
            {
                Write-Output "Creating folder $($Using:tenantPath)"
                New-Item -Type Directory -Path $Using:tenantPath -ErrorAction Stop | Out-Null 
            }
            else
            {
                Write-Output "Folder $($Using:tenantPath) already exist"
            }
        }  
        catch
        { 
            Write-Output $_ 
        }
    } –PSComputer $libServer –PSCredential $VmmCredential
    
    inlinescript
    {
        $tenantSite = "https://my.azureline.ru" # здесь необходимо указать URL Tenant Site
        $authSite = "https://auth.azureline.ru" # здесь необходимо указать URL Tenant Auth Site
        $mail = $Using:eMail
        $roles = Get-SCUserRole -VMMServer $Using:VmmServerName | ?{$_.Name.Contains($mail)}

        # Для каждой подписки создается UserRole в SCVMM. Во избежание дубликатов писем, посылаем оповещение только если роль одна (при создании первой подписки)

        if (!($roles -is [System.Array]))
        {
            try
            {
                [reflection.assembly]::loadwithpartialname("System.Net.Http") | Out-Null
                $forget = New-Object System.Net.Http.HttpClient
                
                $getMess = $forget.GetAsync($tenantSite).Result
                $getMess.EnsureSuccessStatusCode() | Out-Null
                $authPage = $getMess.Content.ReadAsStringAsync().Result
                $forgRegex = [regex]'form id="__AjaxAntiForgeryForm".*?__RequestVerificationToken.*?value="(?.*?)"'
                $m = $forgRegex.Match($authPage);
                if ($m.Success)
                {
                    $forget.DefaultRequestHeaders.Add("x-ms-client-antiforgery-id", $m.Groups["Token"].Value);
                    $data = New-Object System.Net.Http.StringContent("{`"emailAddress`":`"$($Using:eMail)`"}", [System.Text.Encoding]::UTF8, "application/json")
                    $mess = $forget.PostAsync("$authSite/Account/SendMeResetPasswordLink", $data).Result
                    $mess.EnsureSuccessStatusCode() | Out-Null
                
                    Write-Output "Successfuly sent reset password link to $($Using:eMail)"
                }
            }
            catch
            {
                Write-Output $_
            }
            
            Write-Output "Set library share for $($roles.Name). Share path $($Using:tenantPath)"
            Set-SCUserRole -UserRole $roles -UserRoleDataPath $Using:tenantPath -VMMServer $Using:VmmServerName | Out-Null
        }
        else
        {
            Write-Output "Nothing to do"
        }       
    } –PSComputer $VmmServerName –PSCredential $VmmCredential
}


Очистка каталога FTP


Для очистки каталога FTP от каталогов удаленных подписчиков придется сделать ранбук, выполняющийся по расписанию, так как обработка некоторых событий VMM (нам необходимо для объекта «VMM UserRole» событие «Delete») в данное время в SMA не реализована.

CleanUp-Ftp-Folder
workflow CleanUp-Ftp-Folder
{
    $VmmConnection = Get-AutomationConnection -Name 'VmmConnection'
    $VmmServerName = $VmmConnection.ComputerName
    $SecurePassword = ConvertTo-SecureString -AsPlainText -String $VmmConnection.Password -Force
    $VmmCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $VmmConnection.Username, $SecurePassword
    
    $vmmLib = Get-AutomationVariable -Name 'VMMLibPath'
    
    $libServer = $vmmLib.SubString(2)
    $libServer = $libServer.SubString(0, $libServer.IndexOf("\"))
    
    $dataPaths = inlinescript
    {
        $dataPaths = Get-SCUserRole -VMMServer $Using:VmmServerName | %{ $_.UserRoleDataPath }
        
        $dataPaths
    } -PSComputer $VmmServerName –PSCredential $VmmCredential

    inlinescript
    {
        $ftpFolders = Get-ChildItem -Directory -Path $Using:vmmLib | %{ $($_.FullName + '\') }
        
        if ($Using:dataPaths -ne $null)
        {
            $diffList = $ftpFolders | ?{ $Using:dataPaths -notcontains $_ }
        }
        
        if ($diffList)
        {
            foreach ($diff in $diffList)
            {
                if ([String]::IsNullOrEmpty($diff))
                {
                    continue
                }
                Write-Output "Deleting $diff"
                Remove-Item -Recurse -Force -Confirm:$false -Path $diff
            }
        }
        else
        {
            Write-Output "Nothing to delete"
        }
    } –PSComputer $libServer –PSCredential $VmmCredential
}


Данные ранбуки необходимо импортировать, опубликовать, ранбуку «Notify-Created-User» присвоить тэг SPF и привязать к событию «Создать» объекта «SPF-клиент»:

c874f219789240db9ce288d7bf957c3d.png

Для ранбука «Cleanup-ftp-folder» необходимо создать расписание, чтобы он выполнялся раз в день:

0fe25d0646cf49eeb7e71a2cd51db618.png


Необходимо, чтобы службы Framework 2.0/3.5 были предварительно установлены

С помощью диспетчера сервера добавляем роль FTP с поддержкой расширения:

5f95264eb01045ac9ab5482144d1c9dc.png
e500a66f850645d697c9568913ff1e45.png

Создаем FTP-сервер:

2e83b109936245658c55240101c0f333.png

В качестве пути в мастере указываем физический путь к корню библиотеки подписчиков. Если FTP сервер разворачивается не на сервере библиотеки наилучшим выходом будет создание символической связи с общим ресурсом, например:

mklink /D C:\TenantsData \\vmmlibserver\TenantsData

4b1fc827fc684996bd818856a8246aff.png

На следующей странице мастера указываем дополнительные параметры (использование SSL, номер порта и т.д.):

357c4f889c824f1199b09299e01f87d8.png

На завершающей странице указываем, что все пользователи имеют право на чтение и запись, но не указываем поддерживаемые типы аутентификации:

3a71edecbbbd4ae78bdbfbb5e7025d38.png

На этом первоначальная настройка закончена. Остальные параметры будут указаны после установки модуля расширения.


Скачайте приложенный к статье архив «Module.zip» и распакуйте (например, в «C:\Module»). Запустите интерпретатор cmd с правами администратора. Выполните следующие команды (если Ваш FTP называется по другому, укажите его имя в качестве параметра):

6d714fdc7ee54afa98eb177cd7bfc0f6.png

Получите следующий вывод:

095707c3bb8442ee99e71e265a37b167.png

После этого необходимо исправить файл «CustomFTPHomeDirectoryProvider.dll.config», указав там значения ключей «auth» и «root». Ключ «auth» содержит URL сайта TenantAuth, ключ «root» указывает физический путь к библиотеке подписчиков. Пример:


  
    
    
  



После этого файл «CustomFTPHomeDirectoryProvider.dll.config» необходимо скопировать по физическому пути «C:\Windows\Microsoft.NET\assembly\GAC_MSIL\CustomFTPHomeDirectoryProvider\v4.0_1.0.0.0__a8ad38bd3b2a69ea».
Открываем консоль IIS Management, выбираем FTP-сайт, открываем настройку «FTP Authentication». Должен быть включен единственный провайдер аутентификации «CustomAuth»:

c9dc1be01d7d4f0d9151c716aba335fe.png

Открываем настройку «FTP User Isolation», убеждаемся, что включено «Custom»:

daca6c108a954a3bb64afa0d30e6532d.png

Данная настройка указывает уровень изоляции пользователя. При помощи кастомного провайдера подписчик «запирается» в собственном каталоге.
Теперь тестируем. Я использовал FTP-клиент входящий в FAR. Подключаемся:

50e4f85f25904598905db7260101818f.png

Закачиваем файл:

a2c1e8e4dd2f4d4fb3cb7a332ad3818a.png

После обновления библиотеки видим загруженный файл:

f29e6193dbd647aaa6a323b667992765.png

На портале Azure Pack этот образ теперь можно подключить:

9caa7be3784c4f4fbd5f714de5cc1e79.png

Таким образом, практически без дополнительных усилий, как то, контроль дополнительных учетных записей в AD для доступа к FTP, получилась удобная для подписчика точка загрузки ISO- и VHD (X)-файлов.

Материалы (архивы с готовым модулем, исходниками и ранбуками) можно скачать по этой ссылке. На этом все, до новых встреч!

© Habrahabr.ru