Невозможно обновить регистрацию приложения AAD в B2 C Tenant после первого входа пользователя в систему - PullRequest
0 голосов
/ 04 августа 2020
• 1000 C Клиент.

Я с радостью обновлял URL-адреса ответов, используя автоматизацию с помощью команды az ad app update --id $appIdentifier --add replyUrls "https://<a-valid-dns-zone-record>.

Однако, как только вы используете регистрацию приложения от клиента B2 C, выполните первый вход в систему, указанная выше команда перестает работать. Вы МОЖЕТЕ продолжать использовать портал для добавления новых URL-адресов для ответов, но это не подходит для автоматизации!

Я искал в Google и искал ответы на stackoverflow, но не нашел. Я обратился в Microsoft с просьбой о поддержке уровня Premier и запросил Github по инструменту Azure CLI.

У меня есть временное решение проблемы из моего Github Issue

О чем я подробно расскажу в своем ответе

1 Ответ

0 голосов
/ 04 августа 2020

Решение состоит в том, чтобы использовать команду az rest и использовать ее для прямого вызова Graph API. Вот сценарий PowerShell, который я использую в конвейере yaml Azure DevOps.

[CmdletBinding()]
Param(

    [Parameter(Mandatory)]
    [String]$servicePrincipalId,

    [Parameter(Mandatory)]
    [String]$servicePrincipalPassword,

    [Parameter(Mandatory)]
    [String]$servicePrincipalTenantId,

    [Parameter(Mandatory)]
    [String]$newReplyUrl,

    [Parameter(Mandatory)]
    [String]$appRegIdentifier
)

Write-Host "Logging in as B2C Tenant Service Principal"
$null = az login --service-principal -u $servicePrincipalId -p $servicePrincipalPassword -t $servicePrincipalTenantId --allow-no-subscriptions

# Load some JSON/Text file helpers...
Import-Module $PSScriptRoot\Json-Helpers.psm1

Write-Host "Adding $newReplyUrl if required..."

$appRegObjectId = az ad app show --id $appRegIdentifier --query 'objectId'
$graphAppRegUri = "https://graph.microsoft.com/v1.0/applications/$appRegObjectId"

$appJson = az rest --method GET --uri $graphAppRegUri
$app = $appJson | ConvertFrom-Json

if ($app.web.redirectUris.Contains($newReplyUrl)) {
    # ReplyUrl exists, no-op
    Write-Host "Reply Url already exists, no action required..."
    Exit 0
}

$patchApp = @{ web = @{ redirectUris = @() } }

ForEach ($url in $app.web.redirectUris) {
    $patchApp["web"].redirectUris += $url
}

$patchApp["web"].redirectUris += $newReplyUrl

$tempFile = ".\patchAppTemp-$([System.Guid]::NewGuid()).json"

try {
    $patchApp | ConvertTo-Json -Depth 5 | Format-Json -Minify | Set-Content -Path $tempFile -Encoding UTF8  -NoNewline

    # Update `redirectUris` for `web` property
    Write-Host "Calling Graph API to update Reply Urls"
    az rest --method patch --uri $graphAppRegUri --headers "Content-Type=application/json" --body=@$tempFile
    Write-Host "Successfully added $newReplyUrl to App Registration $appRegIdentifier"
}
finally {
    if (Test-Path $tempFile) {
        Remove-Item -Path $tempFile
    }
}

И для полноты, вот модуль Json -Helpers.psm1 PowerShell:

function Get-Encoding
{
  param
  (
    [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('FullName')]
    [string]
    $Path
  )

  process 
  {
    $bom = New-Object -TypeName System.Byte[](4)
        
    $file = New-Object System.IO.FileStream($Path, 'Open', 'Read')
    
    $null = $file.Read($bom,0,4)
    $file.Close()
    $file.Dispose()
    
    $enc = 'Ascii'
    if ($bom[0] -eq 0x2b -and $bom[1] -eq 0x2f -and $bom[2] -eq 0x76) 
      { $enc =  'Utf7' }

    if ($bom[0] -eq 0xff -and $bom[1] -eq 0xfe) 
      { $enc =  'Unicode' }

    if ($bom[0] -eq 0xfe -and $bom[1] -eq 0xff) 
      { $enc =  'Bigendianunicode' }

    if ($bom[0] -eq 0x00 -and $bom[1] -eq 0x00 -and $bom[2] -eq 0xfe -and $bom[3] -eq 0xff) 
      { $enc =  'Utf32'}

    if ($bom[0] -eq 0xef -and $bom[1] -eq 0xbb -and $bom[2] -eq 0xbf) 
      { $enc =  'Utf8'}
        
    [PSCustomObject]@{
      Encoding = $enc
      Path = $Path
    }
  }
}

function Format-Json {
    <#
    .SYNOPSIS
        Prettifies JSON output.
    .DESCRIPTION
        Reformats a JSON string so the output looks better than what ConvertTo-Json outputs.
    .PARAMETER Json
        Required: [string] The JSON text to prettify.
    .PARAMETER Minify
        Optional: Returns the json string compressed.
    .PARAMETER Indentation
        Optional: The number of spaces (1..1024) to use for indentation. Defaults to 4.
    .PARAMETER AsArray
        Optional: If set, the output will be in the form of a string array, otherwise a single string is output.
    .EXAMPLE
        $json | ConvertTo-Json  | Format-Json -Indentation 2
    #>
    [CmdletBinding(DefaultParameterSetName = 'Prettify')]
    Param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]$Json,

        [Parameter(ParameterSetName = 'Minify')]
        [switch]$Minify,

        [Parameter(ParameterSetName = 'Prettify')]
        [ValidateRange(1, 1024)]
        [int]$Indentation = 4,

        [Parameter(ParameterSetName = 'Prettify')]
        [switch]$AsArray
    )

    if ($PSCmdlet.ParameterSetName -eq 'Minify') {
        return ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100 -Compress
    }

    # If the input JSON text has been created with ConvertTo-Json -Compress
    # then we first need to reconvert it without compression
    if ($Json -notmatch '\r?\n') {
        $Json = ($Json | ConvertFrom-Json) | ConvertTo-Json -Depth 100
    }

    $indent = 0
    $regexUnlessQuoted = '(?=([^"]*"[^"]*")*[^"]*$)'

    $result = $Json -split '\r?\n' |
        ForEach-Object {
            # If the line contains a ] or } character, 
            # we need to decrement the indentation level unless it is inside quotes.
            if ($_ -match "[}\]]$regexUnlessQuoted") {
                $indent = [Math]::Max($indent - $Indentation, 0)
            }

            # Replace all colon-space combinations by ": " unless it is inside quotes.
            $line = (' ' * $indent) + ($_.TrimStart() -replace ":\s+$regexUnlessQuoted", ': ')

            # If the line contains a [ or { character, 
            # we need to increment the indentation level unless it is inside quotes.
            if ($_ -match "[\{\[]$regexUnlessQuoted") {
                $indent += $Indentation
            }

            $line
        }

    if ($AsArray) { return $result }
    return $result -Join [Environment]::NewLine
}

Ключевая строка:

az rest --method patch --uri $graphAppRegUri --headers "Content-Type=application/json" --body=@$tempFile

, которая вызывает Graph API, передавая Json содержимое вашего динамически созданного временного файла. Одним из небольших недостатков этого способа является то, что вы берете текущие URL-адреса, добавляете новый и исправляете весь список, а не просто добавляете тот, который вам нужен. По мере роста списка содержание патча также может увеличиваться.

Но на сегодняшний день это лучший способ обойти обнаруженную мной проблему.

...