Creación de un recurso del Lector inmersivo y configuración de la autenticación de Microsoft Entra

En este artículo se explica cómo crear un recurso Immersive Reader mediante el script proporcionado. Este script también configura la autenticación de Microsoft Entra. Cada vez que se crea un recurso de Immersive Reader, ya sea con este script o en el portal, debe configurarse con permisos de Microsoft Entra.

El script crea y configura todos los recursos de Immersive Reader y Microsoft Entra necesarios. Sin embargo, también puede configurar la autenticación de Microsoft Entra para un recurso del Immersive Reader existente si ya ha creado uno en Azure Portal. El script primero busca los recursos de Immersive Reader y Microsoft Entra existentes en la suscripción y los crea solo si aún no existen.

En el caso de algunos clientes, puede que sea necesario crear varios recursos de Immersive Reader, para desarrollo frente a producción, o quizás para varias regiones diferentes en las que se implemente el servicio. En esos casos, puede volver y usar el script varias veces para crear diferentes recursos de Immersive Reader y configurarlos con los permisos de Microsoft Entra.

Permisos

El Propietario de la lista de su suscripción de Azure tiene todos los permisos necesarios para crear un recurso del Lector inmersivo y configurar la autenticación de Microsoft Entra.

Si no fuera propietario, se necesitarán los siguientes permisos específicos del ámbito:

  • Colaborador. Deberá tener al menos un rol de colaborador asociado a la suscripción de Azure:

    Screenshot of contributor built-in role description.

  • Desarrollador de aplicaciones. Debe tener al menos un rol de desarrollador de aplicaciones asociado en Microsoft Entra ID:

    Screenshot of the developer built-in role description.

Para más información, consulte Roles integrados de Microsoft Entra.

Recursos de configuración de PowerShell

  1. Para empezar, abra Azure Cloud Shell. Asegúrese de que Cloud Shell está establecido en PowerShell en la lista desplegable de la parte superior izquierda o escriba pwsh.

  2. Copie y pegue el siguiente fragmento de código en el shell.

    function Create-ImmersiveReaderResource(
        [Parameter(Mandatory=$true, Position=0)] [String] $SubscriptionName,
        [Parameter(Mandatory=$true)] [String] $ResourceName,
        [Parameter(Mandatory=$true)] [String] $ResourceSubdomain,
        [Parameter(Mandatory=$true)] [String] $ResourceSKU,
        [Parameter(Mandatory=$true)] [String] $ResourceLocation,
        [Parameter(Mandatory=$true)] [String] $ResourceGroupName,
        [Parameter(Mandatory=$true)] [String] $ResourceGroupLocation,
        [Parameter(Mandatory=$true)] [String] $AADAppDisplayName,
        [Parameter(Mandatory=$true)] [String] $AADAppIdentifierUri,
        [Parameter(Mandatory=$true)] [String] $AADAppClientSecretExpiration
    )
    {
        $unused = ''
        if (-not [System.Uri]::TryCreate($AADAppIdentifierUri, [System.UriKind]::Absolute, [ref] $unused)) {
            throw "Error: AADAppIdentifierUri must be a valid URI"
        }
    
        Write-Host "Setting the active subscription to '$SubscriptionName'"
        $subscriptionExists = Get-AzSubscription -SubscriptionName $SubscriptionName
        if (-not $subscriptionExists) {
            throw "Error: Subscription does not exist"
        }
        az account set --subscription $SubscriptionName
    
        $resourceGroupExists = az group exists --name $ResourceGroupName
        if ($resourceGroupExists -eq "false") {
            Write-Host "Resource group does not exist. Creating resource group"
            $groupResult = az group create --name $ResourceGroupName --location $ResourceGroupLocation
            if (-not $groupResult) {
                throw "Error: Failed to create resource group"
            }
            Write-Host "Resource group created successfully"
        }
    
        # Create an Immersive Reader resource if it doesn't already exist
        $resourceId = az cognitiveservices account show --resource-group $ResourceGroupName --name $ResourceName --query "id" -o tsv
        if (-not $resourceId) {
            Write-Host "Creating the new Immersive Reader resource '$ResourceName' (SKU '$ResourceSKU') in '$ResourceLocation' with subdomain '$ResourceSubdomain'"
            $resourceId = az cognitiveservices account create `
                            --name $ResourceName `
                            --resource-group $ResourceGroupName `
                            --kind ImmersiveReader `
                            --sku $ResourceSKU `
                            --location $ResourceLocation `
                            --custom-domain $ResourceSubdomain `
                            --query "id" `
                            -o tsv
    
            if (-not $resourceId) {
                throw "Error: Failed to create Immersive Reader resource"
            }
            Write-Host "Immersive Reader resource created successfully"
        }
    
        # Create an Microsoft Entra app if it doesn't already exist
        $clientId = az ad app show --id $AADAppIdentifierUri --query "appId" -o tsv
        if (-not $clientId) {
            Write-Host "Creating new Microsoft Entra app"
            $clientId = az ad app create --display-name $AADAppDisplayName --identifier-uris $AADAppIdentifierUri --query "appId" -o tsv
            if (-not $clientId) {
                throw "Error: Failed to create Microsoft Entra application"
            }
            Write-Host "Microsoft Entra application created successfully."
    
            $clientSecret = az ad app credential reset --id $clientId --end-date "$AADAppClientSecretExpiration" --query "password" | % { $_.Trim('"') }
            if (-not $clientSecret) {
                throw "Error: Failed to create Microsoft Entra application client secret"
            }
            Write-Host "Microsoft Entra application client secret created successfully."
    
            Write-Host "NOTE: To manage your Microsoft Entra application client secrets after this Immersive Reader Resource has been created please visit https://portal.azure.com and go to Home -> Microsoft Entra ID -> App Registrations -> (your app) '$AADAppDisplayName' -> Certificates and Secrets blade -> Client Secrets section" -ForegroundColor Yellow
        }
    
        # Create a service principal if it doesn't already exist
        $principalId = az ad sp show --id $AADAppIdentifierUri --query "id" -o tsv
        if (-not $principalId) {
            Write-Host "Creating new service principal"
            az ad sp create --id $clientId | Out-Null
            $principalId = az ad sp show --id $AADAppIdentifierUri --query "id" -o tsv
    
            if (-not $principalId) {
                throw "Error: Failed to create new service principal"
            }
            Write-Host "New service principal created successfully"
    
            # Sleep for 5 seconds to allow the new service principal to propagate
            Write-Host "Sleeping for 5 seconds"
            Start-Sleep -Seconds 5
        }
    
        Write-Host "Granting service principal access to the newly created Immersive Reader resource"
        $accessResult = az role assignment create --assignee $principalId --scope $resourceId --role "Cognitive Services Immersive Reader User"
        if (-not $accessResult) {
            throw "Error: Failed to grant service principal access"
        }
        Write-Host "Service principal access granted successfully"
    
        # Grab the tenant ID, which is needed when obtaining a Microsoft Entra token
        $tenantId = az account show --query "tenantId" -o tsv
    
        # Collect the information needed to obtain a Microsoft Entra token into one object
        $result = @{}
        $result.TenantId = $tenantId
        $result.ClientId = $clientId
        $result.ClientSecret = $clientSecret
        $result.Subdomain = $ResourceSubdomain
    
        Write-Host "`nSuccess! " -ForegroundColor Green -NoNewline
        Write-Host "Save the following JSON object to a text file for future reference."
        Write-Host "*****"
        if($clientSecret -ne $null) {
    
            Write-Host "This function has created a client secret (password) for you. This secret is used when calling Microsoft Entra to fetch access tokens."
            Write-Host "This is the only time you will ever see the client secret for your Microsoft Entra application, so save it now." -ForegroundColor Yellow
        }
        else{
            Write-Host "You will need to retrieve the ClientSecret from your original run of this function that created it. If you don't have it, you will need to go create a new client secret for your Microsoft Entra application. Please visit https://portal.azure.com and go to Home -> Microsoft Entra ID -> App Registrations -> (your app) '$AADAppDisplayName' -> Certificates and Secrets blade -> Client Secrets section." -ForegroundColor Yellow
        }
        Write-Host "*****`n"
        Write-Output (ConvertTo-Json $result)
    }
    
  3. Ejecute la función Create-ImmersiveReaderResource, proporcionando los marcadores de posición "<PARAMETER_VALUES>" con sus propios valores, según corresponda.

    Create-ImmersiveReaderResource -SubscriptionName '<SUBSCRIPTION_NAME>' -ResourceName '<RESOURCE_NAME>' -ResourceSubdomain '<RESOURCE_SUBDOMAIN>' -ResourceSKU '<RESOURCE_SKU>' -ResourceLocation '<RESOURCE_LOCATION>' -ResourceGroupName '<RESOURCE_GROUP_NAME>' -ResourceGroupLocation '<RESOURCE_GROUP_LOCATION>' -AADAppDisplayName '<MICROSOFT_ENTRA_DISPLAY_NAME>' -AADAppIdentifierUri '<MICROSOFT_ENTRA_IDENTIFIER_URI>' -AADAppClientSecretExpiration '<MICROSOFT_ENTRA_CLIENT_SECRET_EXPIRATION>'
    

    El comando completo tendrá un aspecto similar al siguiente. Aquí colocamos cada parámetro en su propia línea para mayor claridad, para que pueda ver el comando completo. No copie ni use este comando tal cual. Copie y use el comando con sus propios valores. Este ejemplo tiene valores ficticios de <PARAMETER_VALUES>. Los suyos serán diferentes, ya que tendrá sus propios nombres para estos valores.

    Create-ImmersiveReaderResource
        -SubscriptionName 'MyOrganizationSubscriptionName'
        -ResourceName 'MyOrganizationImmersiveReader'
        -ResourceSubdomain 'MyOrganizationImmersiveReader'
        -ResourceSKU 'S0'
        -ResourceLocation 'westus2'
        -ResourceGroupName 'MyResourceGroupName'
        -ResourceGroupLocation 'westus2'
        -AADAppDisplayName 'MyOrganizationImmersiveReaderAADApp'
        -AADAppIdentifierUri 'api://MyOrganizationImmersiveReaderAADApp'
        -AADAppClientSecretExpiration '2021-12-31'
    
    Parámetro Comentarios
    SubscriptionName Nombre de la suscripción a Azure que se va a usar para el recurso del Lector inmersivo. Debe tener una suscripción para poder crear un recurso.
    nombreDelRecurso Debe ser alfanumérico y puede contener -, siempre y cuando - no sea el primero ni el último carácter. La longitud no puede tener más de 63 caracteres.
    ResourceSubdomain Subdominio personalizado necesario para el recurso del Lector inmersivo. El SDK usa el subdominio al llamar al servicio del Lector inmersivo para iniciar el Lector. El subdominio debe ser único globalmente. El subdominio debe ser alfanumérico y puede contener -, siempre y cuando - no sea el primero ni el último carácter. La longitud no puede tener más de 63 caracteres. Este parámetro es opcional si el recurso ya existe.
    ResourceSKU Opciones: S0 (nivel Estándar) o S1 (organizaciones educativas o sin ánimo de lucro). Para obtener más información sobre cada SKU disponible, visite nuestra página de precios de servicios de Azure AI. Este parámetro es opcional si el recurso ya existe.
    ResourceLocation Opciones: australiaeast, brazilsouth, canadacentral, centralindia, centralus, eastasia, eastus, eastus2, francecentral, germanywestcentral, japaneast, japanwest, jioindiawest, koreacentral, northcentralus, northeurope, norwayeast, southafricanorth, southcentralus, southeastasia, swedencentral, switzerlandnorth, switzerlandwest, uaenorth, uksouth, westcentralus, westeurope, westus, westus2, westus3. Este parámetro es opcional si el recurso ya existe.
    ResourceGroupName Los recursos se crean en grupos de recursos dentro de las suscripciones. Suministre el nombre de un grupo de recursos existente. Si el grupo de recursos todavía no existiera, se creará uno con este nombre.
    ResourceGroupLocation Si el grupo de recursos no existe, debe proporcionar una ubicación donde se creará el grupo. Ejecute az account list-locations para obtener una lista de ubicaciones. Use la propiedad name (sin espacios) del resultado devuelto. Este parámetro es opcional si el grupo de recursos ya existe.
    AADAppDisplayName Nombre para mostrar de la aplicación Microsoft Entra. Si no se encuentra una aplicación existente de Microsoft Entra, se crea una nueva con este nombre. Este parámetro es opcional si la aplicación Microsoft Entra ya existe.
    AADAppIdentifierUri Identificador URI de la aplicación Microsoft Entra. Si no se encuentra una aplicación existente de Microsoft Entra, se crea una nueva con este URI. Por ejemplo, api://MyOrganizationImmersiveReaderAADApp. Aquí se usa el prefijo predeterminado del esquema URI de Microsoft Entraapi:// para la compatibilidad con la directiva de Microsoft Entra de usar dominios comprobados.
    AADAppClientSecretExpiration La fecha o datetime después de la cual expira el secreto de cliente de aplicación (contraseña) de Microsoft Entra (por ejemplo, "2020-12-31T11:59:59+00:00" o "2020-12-31"). Esta función creará un secreto de cliente de manera automática.

    Para administrar los secretos de cliente de aplicaciones de Microsoft Entra después de crear este recurso, visite Azure Portal y vaya a Inicio ->Microsoft Entra ID ->Registros de aplicaciones -> (la aplicación) [AADAppDisplayName] ->sección Certificados y secretos -> sección Secretos de cliente.

    Screenshot of the Azure portal Certificates and Secrets pane.

  4. Copie la salida JSON en un archivo de texto para usarla en otro momento. La salida debe tener un aspecto similar al siguiente.

    {
      "TenantId": "...",
      "ClientId": "...",
      "ClientSecret": "...",
      "Subdomain": "..."
    }
    

Paso siguiente