Oktatóanyag: Az Azure Remote Rendering és a modelltároló biztonságossá tétele

Ebben az oktatóanyagban az alábbiakkal fog megismerkedni:

  • Azure Remote Rendering-modelleket tartalmazó Azure Blob Storage biztonságossá tétele
  • Hitelesítés a Microsoft Entra-azonosítóval az Azure Remote Rendering-példány eléréséhez
  • Azure-hitelesítő adatok használata az Azure Remote Rendering-hitelesítéshez

Előfeltételek

Miért van szükség extra biztonságra?

Az alkalmazás jelenlegi állapota és az Azure-erőforrásokhoz való hozzáférése a következőképpen néz ki:

Initial security

Az "AccountID + AccountKey" és az "URL + SAS Token" egyaránt alapvetően egy felhasználónevet és jelszót tárol együtt. Ha például az "AccountID + AccountKey" ki van téve, akkor a támadó számára jelentéktelen lenne, ha az Ön engedélye nélkül használná az ARR-erőforrásokat az Ön költségére.

Tartalom védelme az Azure Blob Storage-ban

Az Azure Remote Rendering biztonságosan elérheti az Azure Blob Storage tartalmát a megfelelő konfigurációval. Lásd : Útmutató: Tárfiókok összekapcsolása az Azure Remote Rendering-példány blobtároló-fiókokkal való konfigurálásához.

Csatolt blobtároló használata esetén a modellek betöltéséhez kissé eltérő módszereket kell használnia:

var loadModelParams = new LoadModelFromSasOptions(modelPath, modelEntity);
var task = ARRSessionService.CurrentActiveSession.Connection.LoadModelFromSasAsync(loadModelParams);

A fenti sorok a FromSas paramok és a munkamenet-művelet verzióját használják. Ezeket nem SAS-verziókra kell konvertálni:

var loadModelParams = LoadModelOptions.CreateForBlobStorage(storageAccountPath, blobName, modelPath, modelEntity);
var task = ARRSessionService.CurrentActiveSession.Connection.LoadModelAsync(loadModelParams);

Módosítsa a RemoteRenderingCoordinatort úgy, hogy egy egyéni modellt töltsön be egy csatolt Blob Storage-fiókból.

  1. Ha még nem tette meg, végezze el a Útmutató: Tárfiókok összekapcsolása című témakört, hogy engedélyt adjon az ARR-példánynak a Blob Storage-példány elérésére.

  2. Adja hozzá a következő módosított LoadModel-metódust a RemoteRenderingCoordinatorhoz az aktuális LoadModel metódus alatt:

    /// <summary>
    /// Loads a model from blob storage that has been linked to the ARR instance
    /// </summary>
    /// <param name="storageAccountName">The storage account name, this contains the blob containers </param>
    /// <param name="blobName">The blob container name, i.e. arroutput</param>
    /// <param name="modelPath">The relative path inside the container to the model, i.e. test/MyCustomModel.arrAsset</param>
    /// <param name="parent">The parent Transform for this remote entity</param>
    /// <param name="progress">A call back method that accepts a float progress value [0->1]</param>
    /// <returns></returns>
    public async Task<Entity> LoadModel(string storageAccountName, string blobName, string modelPath, UnityEngine.Transform parent = null, Action<float> progress = null)
    {
        //Create a root object to parent a loaded model to
        var modelEntity = ARRSessionService.CurrentActiveSession.Connection.CreateEntity();
    
        //Get the game object representation of this entity
        var modelGameObject = modelEntity.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
    
        //Ensure the entity will sync its transform with the server
        var sync = modelGameObject.GetComponent<RemoteEntitySyncObject>();
        sync.SyncEveryFrame = true;
    
        //Parent the new object under the defined parent
        if (parent != null)
        {
            modelGameObject.transform.SetParent(parent, false);
            modelGameObject.name = parent.name + "_Entity";
        }
    
        //Load a model that will be parented to the entity
        var loadModelParams = LoadModelOptions.CreateForBlobStorage($"{storageAccountName}.blob.core.windows.net", blobName, modelPath, modelEntity);
        var loadModelAsync = ARRSessionService.CurrentActiveSession.Connection.LoadModelAsync(loadModelParams, progress);
        var result = await loadModelAsync;
        return modelEntity;
    }
    

    Ez a kód megegyezik az eredeti LoadModel metódussal, de a metódushívások SAS-verzióját lecseréltük a nem SAS-verziókra.

    A további bemenetek storageAccountName és blobName az argumentumok is hozzá lettek adva. Ezt az új LoadModel metódust az első oktatóanyagban létrehozott első LoadTestModel metódushoz hasonló metódusból hívjuk.

  3. Adja hozzá a következő metódust a RemoteRenderingCoordinatorhoz a LoadTestModel után

    private bool loadingLinkedCustomModel = false;
    
    [SerializeField]
    private string storageAccountName;
    public string StorageAccountName {
        get => storageAccountName.Trim();
        set => storageAccountName = value;
    }
    
    [SerializeField]
    private string blobContainerName;
    public string BlobContainerName {
        get => blobContainerName.Trim();
        set => blobContainerName = value;
    }
    
    [SerializeField]
    private string modelPath;
    public string ModelPath {
        get => modelPath.Trim();
        set => modelPath = value;
    }
    
    [ContextMenu("Load Linked Custom Model")]
    public async void LoadLinkedCustomModel()
    {
        if (CurrentCoordinatorState != RemoteRenderingState.RuntimeConnected)
        {
            Debug.LogError("Please wait for the runtime to connect before loading the test model. Try again later.");
            return;
        }
        if (loadingLinkedCustomModel)
        {
            Debug.Log("Linked Test model already loading or loaded!");
            return;
        }
        loadingLinkedCustomModel = true;
    
        // Create a parent object to use for positioning
        GameObject testParent = new GameObject("LinkedCustomModel");
        testParent.transform.position = new Vector3(0f, 0f, 3f);
    
        await LoadModel(StorageAccountName, BlobContainerName, ModelPath, testParent.transform, (progressValue) => Debug.Log($"Loading Test Model progress: {Math.Round(progressValue * 100, 2)}%"));
    }
    

    Ez a kód három további sztringváltozót ad hozzá a RemoteRenderingCoordinator összetevőhöz. Screenshot that highlights the Storage Account Name, Blob Container Name, and Model Path of the RemoteRenderingCoordinator component.

  4. Adja hozzá az értékeket a RemoteRenderingCoordinator összetevőhöz. Miután követte a modellátalakítás rövid útmutatóját, az értékeknek a következőnek kell lenniük:

    • Tárfiók neve: A tárfiók neve, a tárfiókhoz választott globálisan egyedi név. A rövid útmutatóban ez az arrtutorialstorage volt, az ön értéke más.
    • Blobtároló neve: arroutput, a Blob Storage-tároló
    • Modell elérési útja: Az arrconfig.json fájlban definiált "outputFolderPath" és "outputAssetFileName" kombinációja. A rövid útmutatóban ez volt a "outputFolderPath":"converted/robot", "outputAssetFileName": "robot.arrAsset". Ami a "konvertált/robot/robot.arrAsset" modellútvonal-értéket eredményezné, az ön értéke eltérő.

    Tipp.

    Ha a Conversion.ps1 szkriptet a "-UseContainerSas" argumentum nélkül futtatja, a szkript az SAS-jogkivonat helyett a fenti értékek mindegyikét megjeleníti. Linked Model

  5. Egyelőre távolítsa el vagy tiltsa le a GameObject TestModelt, hogy helyet biztosítson az egyéni modell betöltésének.

  6. Játssza le a jelenetet, és csatlakozzon egy távoli munkamenethez.

  7. Nyissa meg a RemoteRenderingCoordinator helyi menüjét, és válassza a Csatolt egyéni modell betöltése lehetőséget. Load linked model

Ezek a lépések megnövelték az alkalmazás biztonságát azáltal, hogy eltávolítják az SAS-jogkivonatot a helyi alkalmazásból.

Az alkalmazás jelenlegi állapota és az Azure-erőforrásokhoz való hozzáférése így néz ki:

Better security

Van még egy "jelszó", az AccountKey, amely eltávolítható a helyi alkalmazásból. Ez a Microsoft Entra-hitelesítéssel végezhető el.

Microsoft Entra authentication

A Microsoft Entra-hitelesítés lehetővé teszi annak meghatározását, hogy mely személyek vagy csoportok használják az ARR-t szabályozottabb módon. Az ARR beépített támogatást nyújtott az Access-jogkivonatok fiókkulcs használata helyett való elfogadásához. Az Access-jogkivonatokat időkorlátos, felhasználóspecifikus kulcsnak tekintheti, amely csak a kért erőforrás bizonyos részeit oldja fel.

A RemoteRenderingCoordinator szkript rendelkezik egy ARRCredentialGetter nevű delegáltal, amely egy SessionConfiguration objektumot visszaadó metódust tartalmaz, amely a távoli munkamenet-kezelés konfigurálására szolgál. Hozzárendelhetünk egy másik módszert az ARRCredentialGetterhez, amely lehetővé teszi az Azure bejelentkezési folyamat használatát, és létrehozunk egy SessionConfiguration objektumot, amely egy Azure Access-jogkivonatot tartalmaz. Ez a hozzáférési jogkivonat a bejelentkezett felhasználóra vonatkozik.

  1. Kövesse az útmutatót: Hitelesítés konfigurálása – Hitelesítés üzembe helyezett alkalmazásokhoz, amely magában foglalja egy új Microsoft Entra-alkalmazás regisztrálását és az ARR-példányhoz való hozzáférés konfigurálását.

  2. Az új Microsoft Entra-alkalmazás konfigurálása után ellenőrizze, hogy a Microsoft Entra-alkalmazás a következő képekhez hasonlóan néz-e ki:

    Microsoft Entra-alkalmazás –> HitelesítésApp authentication

    Microsoft Entra-alkalmazás –> API-engedélyekApp APIs

  3. A távoli renderelési fiók konfigurálása után ellenőrizze, hogy a konfiguráció az alábbi képen látható-e:

    ARR –> AccessControl (IAM)ARR Role

    Megjegyzés:

    A tulajdonosi szerepkör nem elegendő a munkamenetek ügyfélalkalmazáson keresztüli kezeléséhez. Minden olyan felhasználó számára, aki lehetővé szeretné tenni a munkamenetek kezelését, meg kell adnia a távoli renderelési ügyfél szerepkört. Minden olyan felhasználó számára, aki munkameneteket szeretne kezelni és modelleket konvertálni, meg kell adnia a Távoli renderelés Rendszergazda istrator szerepkört.

A dolgok Azure-oldalán most módosítani kell, hogy a kód hogyan csatlakozik az ARR szolgáltatáshoz. Ehhez implementáljuk a BaseARRAuthentication egy példányát, amely egy új SessionConfiguration objektumot ad vissza. Ebben az esetben a fiókadatok az Azure Access-jogkivonattal lesznek konfigurálva.

  1. Hozzon létre egy új AADAuthentication nevű szkriptet, és cserélje le a kódját a következőre:

    // Copyright (c) Microsoft Corporation. All rights reserved.
    // Licensed under the MIT License. See LICENSE in the project root for license information.
    
    using Microsoft.Azure.RemoteRendering;
    using Microsoft.Identity.Client;
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using UnityEngine;
    
    public class AADAuthentication : BaseARRAuthentication
    {
        [SerializeField]
        private string activeDirectoryApplicationClientID;
        public string ActiveDirectoryApplicationClientID
        {
            get => activeDirectoryApplicationClientID.Trim();
            set => activeDirectoryApplicationClientID = value;
        }
    
        [SerializeField]
        private string azureTenantID;
        public string AzureTenantID
        {
            get => azureTenantID.Trim();
            set => azureTenantID = value;
        }
    
        [SerializeField]
        private string azureRemoteRenderingDomain;
        public string AzureRemoteRenderingDomain
        {
            get => azureRemoteRenderingDomain.Trim();
            set => azureRemoteRenderingDomain = value;
        }
    
        [SerializeField]
        private string azureRemoteRenderingAccountID;
        public string AzureRemoteRenderingAccountID
        {
            get => azureRemoteRenderingAccountID.Trim();
            set => azureRemoteRenderingAccountID = value;
        }
    
        [SerializeField]
        private string azureRemoteRenderingAccountDomain;
        public string AzureRemoteRenderingAccountDomain
        {
            get => azureRemoteRenderingAccountDomain.Trim();
            set => azureRemoteRenderingAccountDomain = value;
        }    
    
        public override event Action<string> AuthenticationInstructions;
    
        string authority => "https://login.microsoftonline.com/" + AzureTenantID;
    
        string redirect_uri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
    
        string[] scopes => new string[] { "https://sts.mixedreality.azure.com//.default" };
    
        public void OnEnable()
        {
            RemoteRenderingCoordinator.ARRCredentialGetter = GetARRCredentials;
            this.gameObject.AddComponent<ExecuteOnUnityThread>();
        }
    
        public async override Task<SessionConfiguration> GetARRCredentials()
        {
            var result = await TryLogin();
            if (result != null)
            {
                Debug.Log("Account signin successful " + result.Account.Username);
    
                var AD_Token = result.AccessToken;
    
                return await Task.FromResult(new SessionConfiguration(AzureRemoteRenderingAccountDomain, AzureRemoteRenderingDomain, AzureRemoteRenderingAccountID, "", AD_Token, ""));
            }
            else
            {
                Debug.LogError("Error logging in");
            }
            return default;
        }
    
        private Task DeviceCodeReturned(DeviceCodeResult deviceCodeDetails)
        {
            //Since everything in this task can happen on a different thread, invoke responses on the main Unity thread
            ExecuteOnUnityThread.Enqueue(() =>
            {
                // Display instructions to the user for how to authenticate in the browser
                Debug.Log(deviceCodeDetails.Message);
                AuthenticationInstructions?.Invoke(deviceCodeDetails.Message);
            });
    
            return Task.FromResult(0);
        }
    
        public override async Task<AuthenticationResult> TryLogin()
        {
            var clientApplication = PublicClientApplicationBuilder.Create(ActiveDirectoryApplicationClientID).WithAuthority(authority).WithRedirectUri(redirect_uri).Build();
            AuthenticationResult result = null;
            try
            {
                var accounts = await clientApplication.GetAccountsAsync();
    
                if (accounts.Any())
                {
                    result = await clientApplication.AcquireTokenSilent(scopes, accounts.First()).ExecuteAsync();
    
                    return result;
                }
                else
                {
                    try
                    {
                        result = await clientApplication.AcquireTokenWithDeviceCode(scopes, DeviceCodeReturned).ExecuteAsync(CancellationToken.None);
                        return result;
                    }
                    catch (MsalUiRequiredException ex)
                    {
                        Debug.LogError("MsalUiRequiredException");
                        Debug.LogException(ex);
                    }
                    catch (MsalServiceException ex)
                    {
                        Debug.LogError("MsalServiceException");
                        Debug.LogException(ex);
                    }
                    catch (MsalClientException ex)
                    {
                        Debug.LogError("MsalClientException");
                        Debug.LogException(ex);
                        // Mitigation: Use interactive authentication
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError("Exception");
                        Debug.LogException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("GetAccountsAsync");
                Debug.LogException(ex);
            }
    
            return null;
        }
    }
    

Megjegyzés:

Ez a kód egyáltalán nem teljes, és nem áll készen kereskedelmi alkalmazásra. Például legalább érdemes hozzáadnia a kijelentkezés lehetőségét is. Ez az Task RemoveAsync(IAccount account) ügyfélalkalmazás által biztosított módszerrel végezhető el. Ez a kód csak oktatóanyagok használatára szolgál, az implementáció az alkalmazásra lesz jellemző.

A kód először megpróbálja csendesen lekérni a jogkivonatot az AquireTokenSilent használatával. Ez akkor sikeres, ha a felhasználó korábban már hitelesítette ezt az alkalmazást. Ha nem sikerül, lépjen tovább egy felhasználó által érintett stratégiára.

Ehhez a kódhoz az eszköz kódfolyamatát használjuk egy hozzáférési jogkivonat beszerzéséhez. Ez a folyamat lehetővé teszi, hogy a felhasználó bejelentkezjen az Azure-fiókjába egy számítógépen vagy mobileszközön, és az eredményül kapott jogkivonatot visszaküldhesse a HoloLens-alkalmazásnak.

Az osztály legfontosabb része az ARR szempontjából ez a sor:

return await Task.FromResult(new SessionConfiguration(AzureRemoteRenderingAccountDomain, AzureRemoteRenderingDomain, AzureRemoteRenderingAccountID, "", AD_Token, ""));

Itt létrehozunk egy új SessionConfiguration objektumot a távoli renderelési tartomány, a fiókazonosító, a fióktartomány és a hozzáférési jogkivonat használatával. Ezt a jogkivonatot az ARR szolgáltatás használja távoli renderelési munkamenetek lekérdezésére, létrehozására és csatlakoztatására mindaddig, amíg a felhasználó a korábban konfigurált szerepköralapú engedélyek alapján jogosult.

Ezzel a módosítással az alkalmazás jelenlegi állapota és az Azure-erőforrásokhoz való hozzáférése a következőképpen néz ki:

Even better security

Mivel a felhasználói hitelesítő adatok nincsenek tárolva az eszközön (vagy ebben az esetben még az eszközön is meg van adva), az expozíciós kockázatuk alacsony. Az eszköz most egy felhasználóspecifikus, időkorlátos hozzáférési jogkivonatot használ az ARR eléréséhez, amely hozzáférés-vezérlést (IAM) használ a Blob Storage eléréséhez. Ez a két lépés eltávolította a "jelszavakat" a forráskódból, és jelentősen növelte a biztonságot. Azonban nem ez a leginkább elérhető biztonság, a modell és a munkamenet-kezelés webszolgáltatásba való áthelyezése tovább növeli a biztonságot. A további biztonsági szempontokat a Kereskedelmi készültség fejezet tárgyalja.

A Microsoft Entra hitelesítésének tesztelése

A Unity-szerkesztőben, amikor a Microsoft Entra hitelesítés aktív, minden alkalommal hitelesítenie kell magát, amikor elindítja az alkalmazást. Az eszközön a hitelesítési lépés az első alkalommal történik, és csak a jogkivonat lejáratakor vagy érvénytelenítésekor lesz szükség újra.

  1. Adja hozzá a Microsoft Entra hitelesítési összetevőt a RemoteRenderingCoordinator GameObjecthez.

    Microsoft Entra auth component

Megjegyzés:

Ha az ARR-minták adattárából származó befejezett projektet használja, a cím melletti jelölőnégyzetre kattintva engedélyezze a Microsoft Entra hitelesítési összetevőt.

  1. Adja meg az ügyfél-azonosító és a bérlőazonosító értékeit. Ezek az értékek az alkalmazásregisztráció áttekintési oldalán találhatók:

    • Az Active Directory alkalmazásügyfél-azonosítója a Microsoft Entra-alkalmazásregisztrációban található alkalmazás-(ügyfél-) azonosító (lásd az alábbi ábrát).
    • Az Azure-bérlőazonosító a Microsoft Entra-alkalmazásregisztrációban található címtár-(bérlői) azonosító (lásd az alábbi ábrát).
    • Az Azure Remote Rendering Domain ugyanaz a tartomány, amelyet a RemoteRenderingCoordinator távoli renderelési tartományában használt.
    • Az Azure Remote Rendering Account ID ugyanaz a fiókazonosító, amelyet a RemoteRenderingCoordinatorhoz használt.
    • Az Azure Remote Rendering Account Domain ugyanaz a fióktartomány , amelyet a RemoteRenderingCoordinatorban használt.

    Screenshot that highlights the Application (client) ID and Directory (tenant) ID.

  2. Nyomja le a Play billentyűt a Unity Szerkesztőben, és hagyja jóvá a munkamenet futtatását. Mivel a Microsoft Entra hitelesítési összetevő rendelkezik nézetvezérlővel, a rendszer automatikusan csatlakoztatja, hogy megjelenítsen egy kérést a munkamenet-engedélyezési modális panel után.

  3. Kövesse az AppMenu jobb oldalán található panelen található utasításokat. Ehhez hasonlót kell látnia: Illustration that shows the instruction panel that appears to the right of the AppMenu.

    Miután megadta a megadott kódot a másodlagos eszközön (vagy a böngészőben ugyanazon az eszközön), és bejelentkezett a hitelesítő adataival, a rendszer visszaad egy hozzáférési jogkivonatot a kérelmező alkalmazásnak, ebben az esetben a Unity-szerkesztőnek.

Ezután az alkalmazás minden elemének a szokásos módon kell haladnia. Ha nem a várt módon halad végig a szakaszokon, ellenőrizze a Unity Konzolon az esetleges hibákat.

Buildelés eszközre

Ha MSAL használatával készít egy alkalmazást az eszközre, egy fájlt kell felvennie a projekt Assets mappájába. Ez segít a fordítónak az alkalmazás helyes összeállításában az oktatóanyag-eszközökben található Microsoft.Identity.Client.dll használatával.

  1. Új fájl hozzáadása a link.xml nevű objektumokban

  2. Adja hozzá a következőt a fájlhoz:

    <linker>
        <assembly fullname="Microsoft.Identity.Client" preserve="all"/>
        <assembly fullname="System.Runtime.Serialization" preserve="all"/>
        <assembly fullname="System.Core">
            <type fullname="System.Linq.Expressions.Interpreter.LightLambda" preserve="all" />
        </assembly>
    </linker>
    
  3. Mentse a módosításokat.

Kövesse a rövid útmutató lépéseit : Unity-minta üzembe helyezése a HoloLensben – A mintaprojekt létrehozása a HoloLensre való buildeléshez.

További lépések

Az oktatóanyag-készlet fennmaradó része fogalmi cikkeket tartalmaz az Azure Remote Renderinget használó, éles használatra kész alkalmazás létrehozásához.