Изменение параметров Advanced Edge через API с помощью PowerShell 7

В данной статье мы рассмотрим, какие действия с Advanced Edge Gateway доступны тенанту (клиенту) и как работать с ним через API используя PowerShell. Ссылки на официальную документацию приведены в конце статьи. Но, если кратко, то через API вы можете выполнить те же самые действия, что и через веб-интерфейс управления вашим облаком.

Согласно ролевой модели доступа, клиенту доступны изменения в разделе Services > Firewall / NAT / VPN / ... Например, следующие настройки доступны только на просмотр, т.к. их изменением занимаются инженеры C4Y:

  • Rate Limits
  • IP Allocations
  • General > Name / Edge Gateway Configuration / ...

Чтобы вам было проще разобраться с официальной документацией, мы по-этапно разберём работу через API на примере добавления DNAT правила для подключения к Windows-серверу по RDP.

0 - подготовка

Для начала, необходимо указать данные для работы - облако, тенант (вОрг), учётную запись Organization Administrator и имя Edge, с которым будем работать.

#Requires -Version 7.2  # скрипт разрабатывался и тестировался с интерпретатором "C:\Program Files\PowerShell\7\pwsh.exe"

$Auth = @{
    'cloud'     = 'vcd.cloud4y.ru'      # облако, с которым собираемся работать по API
    'tenant'    = 'demo-tenant'         # имя вашей вОрг, определить можно по URL https://vcd.cloud4y.ru/tenant/demo-tenant/vdcs
    'user'      = 'administrator'       # имя учётной записи с ролью 'Organization Administrator'
    'password'  = '3CQvyk3aZ0ZVCav4U'   # пароль учётной записи
}

$Edge = 'demo-tenant_K41_VDC_Edge'      # имя Edge, с которым вы собираетесь работать через API

$DemoAddingNatRule = $true              # $true - добавить новое NAT-правило для демонстрации, $false - перечислить существующие правила

1 - открываем сессию

Общий принцип работы с облаком через API следующий:

  1. узнать последнюю актуальную версию API
  2. открыть рабочую сессию, выполнив базовую авторизацию в облаке в своём тенанте по логину и паролю
  3. для всех остальных запросов в качестве авторизации используется токен сессии, открытой на предыдущем шаге
$rApiVer = Invoke-WebRequest -UseBasicParsing -Method 'Get' -Headers @{"Accept"="application/*+json"} -Uri ('https://{0}/api/versions' -f $Auth['cloud'])
    
$rApiVerJson = [System.Text.Encoding]::UTF8.GetString($rApiVer.Content) | ConvertFrom-Json

$ApiVer = ($rApiVerJson.versionInfo | Where-Object {$_.deprecated -eq $false} | Select-Object -Last 1).version

$objCredential = '{0}@{1}:{2}' -f $Auth['user'], $Auth['tenant'], $Auth['password']  # Login@vOrg:Password

$CredentialBytes = [System.Text.Encoding]::UTF8.GetBytes($objCredential)

$CredentialBase64 = [System.Convert]::ToBase64String($CredentialBytes)

$HeadersAuthBasic = @{
    'Accept'        = 'application/*+json;version={0};multisite=global' -f $ApiVer
    'Authorization' = 'Basic {0}' -f $CredentialBase64
}

$rAuth = Invoke-WebRequest -UseBasicParsing -Method 'Post' -Headers $HeadersAuthBasic -Uri ('https://{0}/api/sessions' -f $Auth['cloud'])

$rAuthBody = [System.Text.Encoding]::UTF8.GetString($rAuth.Content) | ConvertFrom-Json

$AuthHeaders = @{
    'Accept'        = 'application/*+json;version={0};multisite=global' -f $ApiVer
    'Authorization' = '{0} {1}' -f ($rAuth.Headers['X-VMWARE-VCLOUD-TOKEN-TYPE'] -join ''), ($rAuth.Headers['X-VMWARE-VCLOUD-ACCESS-TOKEN'] -join '')
}

$uriNsx = $rAuthBody.link | Where-Object {$_.rel -eq 'nsx'} | Select-Object -ExpandProperty 'href'

$uriQuery = $rAuthBody.link | Where-Object {$_.href -match 'query' -and $_.type -match 'json'} | Select-Object -ExpandProperty 'href'

$uriSession = $rAuthBody.href

"`n{0}`nApiVer`t`t`t{1}`nQuery Service URL`t{2}`nNSX URL`t`t`t{3}`nHeaders`n{4}" -f 'step 1 - open session', $ApiVer, $uriQuery, $uriNsx, ($AuthHeaders | ConvertTo-Json) | Out-Default
step 1 - open session
ApiVer			35.0
Query Service URL	https://vcd.cloud4y.ru/api/query
NSX URL			https://vcd.cloud4y.ru/network
Headers
{
    "Accept":  "application/*+json;version=35.0;multisite=global",
    "Authorization":  "Bearer eyJhb...Zpa9FQ"
}

2 - Query Service

Query Service позволяет получить основную информацию, в т.ч. ИД объектов облака: вОрг, вДЦ, ВМ, сетям, Edge Gateway и т.д. Далее, зная ИД объекта, можно через API получить детальные свойства объекта, включая ссылки для изменения.

Посмотрим допустимые запросы и выберем относящиеся к маршрутизатору.

# посмотреть все возможные типы запросов можно так:
$rPossibleQueriesList = Invoke-WebRequest -UseBasicParsing -Method 'Get' -Headers $AuthHeaders -Uri $uriQuery

$rPossibleQueriesListBody = [System.Text.Encoding]::UTF8.GetString($rPossibleQueriesList.Content) | ConvertFrom-Json

"`n{0}" -f 'step 2 - list of queries' | Out-Default

$rPossibleQueriesListBody.link | Where-Object { $_.type -match 'json' -and $_.href -match '=records' } | Select-Object -Property 'name', 'href' | Sort-Object -Property 'name' | Out-Default

# а так мы узнаем допустимые запросы по Edge Gateway, которые вернут информацию в json-формате в records-представлении
$rPossibleQueriesListBody.link | Where-Object { $_.type -match 'json' -and $_.href -match '=records' -and $_.name -match 'gate' } | Format-List | Out-Default
step 2 - list of queries

name                      href                                                                          
----                      ----                                                                          
adminApiDefinition        https://vcd.cloud4y.ru/api/query?type=adminApiDefinition&format=records       
adminFileDescriptor       https://vcd.cloud4y.ru/api/query?type=adminFileDescriptor&format=records      
adminService              https://vcd.cloud4y.ru/api/query?type=adminService&format=records             
apiDefinition             https://vcd.cloud4y.ru/api/query?type=apiDefinition&format=records            
catalog                   https://vcd.cloud4y.ru/api/query?type=catalog&format=records                  
catalogItem               https://vcd.cloud4y.ru/api/query?type=catalogItem&format=records              
disk                      https://vcd.cloud4y.ru/api/query?type=disk&format=records                     
edgeGateway               https://vcd.cloud4y.ru/api/query?type=edgeGateway&format=records              
event                     https://vcd.cloud4y.ru/api/query?type=event&format=records                    
externalLocalization      https://vcd.cloud4y.ru/api/query?type=externalLocalization&format=records     
fileDescriptor            https://vcd.cloud4y.ru/api/query?type=fileDescriptor&format=records           
fromCloudTunnel           https://vcd.cloud4y.ru/api/query?type=fromCloudTunnel&format=records          
gatewayUplinks            https://vcd.cloud4y.ru/api/query?type=gatewayUplinks&format=records           
group                     https://vcd.cloud4y.ru/api/query?type=group&format=records                    
media                     https://vcd.cloud4y.ru/api/query?type=media&format=records                    
organization              https://vcd.cloud4y.ru/api/query?type=organization&format=records             
orgNetwork                https://vcd.cloud4y.ru/api/query?type=orgNetwork&format=records               
orgVdc                    https://vcd.cloud4y.ru/api/query?type=orgVdc&format=records                   
orgVdcNetwork             https://vcd.cloud4y.ru/api/query?type=orgVdcNetwork&format=records            
orgVdcStorageProfile      https://vcd.cloud4y.ru/api/query?type=orgVdcStorageProfile&format=records     
orgVdcTemplate            https://vcd.cloud4y.ru/api/query?type=orgVdcTemplate&format=records           
right                     https://vcd.cloud4y.ru/api/query?type=right&format=records                    
role                      https://vcd.cloud4y.ru/api/query?type=role&format=records                     
service                   https://vcd.cloud4y.ru/api/query?type=service&format=records                  
strandedUser              https://vcd.cloud4y.ru/api/query?type=strandedUser&format=records             
task                      https://vcd.cloud4y.ru/api/query?type=task&format=records                     
toCloudTunnel             https://vcd.cloud4y.ru/api/query?type=toCloudTunnel&format=records            
user                      https://vcd.cloud4y.ru/api/query?type=user&format=records                     
vApp                      https://vcd.cloud4y.ru/api/query?type=vApp&format=records                     
vAppNetwork               https://vcd.cloud4y.ru/api/query?type=vAppNetwork&format=records              
vAppOrgVdcNetworkRelation https://vcd.cloud4y.ru/api/query?type=vAppOrgVdcNetworkRelation&format=records
vAppTemplate              https://vcd.cloud4y.ru/api/query?type=vAppTemplate&format=records             
vm                        https://vcd.cloud4y.ru/api/query?type=vm&format=records                       
vmDiskRelation            https://vcd.cloud4y.ru/api/query?type=vmDiskRelation&format=records           


otherAttributes : 
href            : https://vcd.cloud4y.ru/api/query?type=edgeGateway&format=records
id              : 
name            : edgeGateway
type            : application/vnd.vmware.vcloud.query.records+json
model           : 
rel             : down
vCloudExtension : {}

otherAttributes : 
href            : https://vcd.cloud4y.ru/api/query?type=gatewayUplinks&format=records
id              : 
name            : gatewayUplinks
type            : application/vnd.vmware.vcloud.query.records+json
model           : 
rel             : down
vCloudExtension : {}

3 - запрос Edge'ей в своей вОрг (тенанте)

Подходящий тип запроса - edgeGateway, так мы узнаем ИД, необходимый для дальнейшей работы с маршрутизатором. Продробнее про параметры, определённые ниже, вы можете узнать из официальной документации по ссылкам в конце статьи. Если в вашей вОрг несколько вДЦ (виртуальных дата-центров), то можно либо получить список всех своих маршрутизаторов, либо сразу указать нужный с помощью 'filter' = 'name==*edge_name*'.

$params = [ordered] @{
    'format'    = 'records'
    'type'      = 'edgeGateway'
    'page'      = 1
    'pageSize'  = 128
    # 'filter'    = 'name==*{0}*' -f $Edge
}

$paramsStr = ($params.GetEnumerator() | ForEach-Object {$_.Key + '=' + $_.Value}) -join '&'

$rTenantEdges = Invoke-WebRequest -UseBasicParsing -Method 'Get' -Headers $AuthHeaders -Uri ('{0}?{1}' -f $uriQuery, $paramsStr)

$rTenantEdgesBody = [System.Text.Encoding]::UTF8.GetString($rTenantEdges.Content) | ConvertFrom-Json

"`n{0}" -f 'step 3 - edge list' | Out-Default
$rTenantEdgesBody.record | Select-Object -Property 'name', 'href' | Out-Default
step 3 - edge list

name                         href                                                                             
----                         ----                                                                             
demo-tenant_M14_VDC_k8s_Edge https://vcd.cloud4y.ru/api/admin/edgeGateway/1e995b68-e864-45b0-bdb5-6e4fa2d4d487
demo-tenant_K41_VDC_Edge     https://vcd.cloud4y.ru/api/admin/edgeGateway/b056f3c9-3712-46c6-98d1-a6e5eea2b99f

4 - проверка Edge на Advanced'ность

Прежде, чем двигаться далее, необходимо проверить, является ли ваш маршрутизатор Advanced, от этого зависит дальнейший способ работы. Если да, то необходимо использовать NSX API. Если нет, то с ним можно работать, как описано в статье Изменение параметров EDGE c помощью vCloud API нашей БЗ.

$uriEdge = $rTenantEdgesBody.record | Where-Object {$_.name -match $Edge} | Select-Object -ExpandProperty 'href'
    
$rEdgeFullInfo = Invoke-WebRequest -UseBasicParsing -Method 'Get' -Headers $AuthHeaders -Uri $uriEdge

$rEdgeFullInfoBody = [System.Text.Encoding]::UTF8.GetString($rEdgeFullInfo.Content) | ConvertFrom-Json

"`n{0}" -f 'step 4 - check target edge "advanced" property' | Out-Default
"`n'{0}' is{1} Advanced because 'AdvancedNetworkingEnabled' is {2}" -f $Edge, (' not' * [int][bool] (-not $rEdgeFullInfoBody.configuration.advancedNetworkingEnabled)), $rEdgeFullInfoBody.configuration.advancedNetworkingEnabled | Out-Default

# Verify that the Edge Gateway is not an Advanced Gateway
if ($rEdgeFullInfoBody.configuration.advancedNetworkingEnabled)
{
    @(  
        'using the VMware Cloud Director API to configure Edge Gateway services can produce unexpected results'
        'Use "VMware Cloud Director API for NSX Programming Guide" instead:'
        '    https://developer.vmware.com/docs/12789/vmware-cloud-director-api-for-nsx-programming-guide'
        '    https://vdc-download.vmware.com/vmwb-repository/dcr-public/6c72dc6b-b5c5-4563-b781-189f11fd7d51/ba3dd30d-4355-4b4f-91ee-a041a51decda/vmware_cloud_director_nsx_api_guide_35_0.pdf'
    ) | Out-Default
}
else
{
    @(  
        'Use "VMware Cloud Director API Programming Guide":'
        '    https://vdc-download.vmware.com/vmwb-repository/dcr-public/715b0387-34d7-4568-b2d8-d11454c52d51/944f905e-fa4e-4005-be7d-19c3cea70ffd/vmware_cloud_director_sp_api_guide_35_0.pdf#unique_93'
        '    https://developer.vmware.com/docs/12676/vmware-cloud-director-api-programming-guide/GUID-1E7274A7-57D3-488F-9EFF-1D097FFE61A8.html'
        '    https://client.cloud4y.ru/knowledgebase.php?action=displayarticle&catid=19&id=665'
    ) | Out-Default
    
    "`n{0}`n{1}" -f 'step 4 - edge full view', $uriEdge
    
    $rEdgeFullInfoBody.link | Where-Object { $_.type -notmatch 'xml' } | Select-Object -Property 'rel', 'type', 'href' | Format-Table -AutoSize
    
    $rEdgeFullInfoBody | ConvertTo-Json -Depth 13 | Out-File -FilePath ('./{0}.json' -f $rEdgeFullInfoBody.name)
}
step 4 - check target edge "advanced" property

'demo-tenant_K41_VDC_Edge' is Advanced because 'AdvancedNetworkingEnabled' is True
using the VMware Cloud Director API to configure Edge Gateway services can produce unexpected results
Use "VMware Cloud Director API for NSX Programming Guide" instead:
    https://developer.vmware.com/docs/12789/vmware-cloud-director-api-for-nsx-programming-guide
    https://vdc-download.vmware.com/vmwb-repository/dcr-public/6c72dc6b-b5c5-4563-b781-189f11fd7d51/ba3dd30d-4355-4b4f-91ee-a041a51decda/vmware_cloud_director_nsx_api_guide_35_0.pdf
$id = $uriEdge -split '/' | Select-Object -Last 1
    
$rNat = Invoke-WebRequest -UseBasicParsing -Method 'Get' -Headers $AuthHeaders -Uri ('{0}/edges/{1}/nat/config' -f $uriNsx, $id)

$rNat = $rNat.Content | ConvertFrom-Json

$rNat | ConvertTo-Json -Depth 13 | Out-File -FilePath ('./{0}_nat.json' -f $rEdgeFullInfoBody.name)

if ($DemoAddingNatRule)
{
    $rNat.rules.natRulesDtos += [PSCustomObject] @{
        # ruleId                 = 0
        # ruleTag                = 0
        loggingEnabled         = $false
        enabled                = $false
        description            = 'DEMO - JUST ADDING ONE MORE DISABLING NAT RULE, ALLOWING RDP OVER UDP'
        translatedAddress      = '192.168.0.123'
        ruleType               = 'user'
        action                 = 'dnat'
        vnic                   = '0'
        originalAddress        = '176.53.183.149'
        dnatMatchSourceAddress = 'any'
        protocol               = 'udp'
        originalPort           = '3389'
        translatedPort         = '3389'
        dnatMatchSourcePort    = 'any'
    }
    
    $rNat.rules.natRulesDtos | Format-Table -AutoSize
    
    $rNatMod = Invoke-WebRequest -UseBasicParsing -Method 'Put' -Headers $AuthHeaders -Uri ('{0}/edges/{1}/nat/config' -f $uriNsx, $id) -Body ($rNat | ConvertTo-Json -Depth 13) -ContentType "application/*+json;charset=UTF-8"
    
    $rNatMod | Out-Default
}
else
{
    $rNat.rules.natRulesDtos | Format-Table -AutoSize | Out-Default
}
ruleId ruleTag loggingEnabled enabled description                                                           translatedAddress ruleT
                                                                                                                              ype  
------ ------- -------------- ------- -----------                                                           ----------------- -----
196609  196609          False    True allow Internet access for demo-tenant_K41_VDC_LAN                     176.53.183.149    user 
196610  196610          False    True allow RDP to unexisting VM                                            192.168.0.123     user 
                        False   False DEMO - JUST ADDING ONE MORE DISABLING NAT RULE, ALLOWING RDP OVER UDP 192.168.0.123     user 


StatusCode        : 204
StatusDescription : No Content
Content           : {}
RawContent        : HTTP/1.1 204 No Content
                    Connection: close
                    X-VMWARE-VCLOUD-REQUEST-ID: ff2d5311-a0fa-477e-83e2-30750618e20b
                    Strict-Transport-Security: max-age=31536000
                    X-XSS-Protection: 1; mode=block
                    X-Content-Ty...
Headers           : {[Connection, close], [X-VMWARE-VCLOUD-REQUEST-ID, ff2d5311-a0fa-477e-83e2-30750618e20b], [Strict-Transport-Sec
                    urity, max-age=31536000], [X-XSS-Protection, 1; mode=block]...}
RawContentLength  : 0

Список материалов

  1. Rights in Predefined Global Tenant Roles

  2. VMware Cloud Director Documentation (table of different versions)

  3. VMware Cloud Director API page, "Documentation" tab:

    • "VMware Cloud Director API Programming Guide", chapter "Configure Edge Gateway Services" pdfhtml

    • "VMware Cloud Director API for NSX Programming Guide" pdfhtml

 

 

  • Edge, NSX, API, PowerShell
  • 29 Korisnici koji smatraju članak korisnim
Je li Vam ovaj odgovor pomogao?

Vezani članci

vCloud Director API для NSX. Инструкция для программистов.

Про vCloud Director API для NSXvCloud Director API для NSX.API-интерфейс vCloud Director для NSX...

Как получить доступ к VMware Cloud Director через vCloud API

Обзор Для выполнения некоторых задач в среде CLOUD4Y вам может потребоваться доступ к VMware...

Изменение параметров EDGE c помощью vCloud API

Введение В данном руководстве показано, как получать, изменять и отправлять блоки XML, которые...

vCloud API инструкция по программированию для сервис провайдеров

В этом выпуске руководства по программированию API vCloud для сервис провайдеров предоставляется...