Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions sdk/mixedreality/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,3 @@ extends:
Artifacts:
- name: Azure.MixedReality.Authentication
safeName: AzureMixedRealityAuthentication
- name: Azure.MixedReality.RemoteRendering
safeName: AzureMixedRealityRemoteRendering
91 changes: 2 additions & 89 deletions sdk/mixedreality/test-resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,11 @@
"metadata": {
"description": "The location of the resource. By default, this is the same as the resource group."
}
},
"baseTime": {
"type": "string",
"defaultValue": "[utcNow('u')]"
}
},
"variables": {
"apiVersion": "2020-05-01",
"asaAccountName": "[concat(parameters('baseName'), '-asa-account')]",
"arrApiVersion": "2020-04-06-preview",
"arrAccountName": "[concat(parameters('baseName'), '-arr-account')]",
"storageApiVersion": "2019-06-01",
"storageAccountName": "[parameters('baseName')]",
"blobContainerName": "test",
"blobContainerResourceName": "[concat(variables('storageAccountName'), '/default/', variables('blobContainerName'))]",
"sasProperties": {
"signedPermission": "rwl",
"signedExpiry": "[dateTimeAdd(parameters('baseTime'), 'P1D')]",
"signedResource": "c",
"canonicalizedResource": "[concat('/blob/', variables('storageAccountName'), '/', variables('blobContainerName'))]"
}
"asaAccountName": "[concat(parameters('baseName'), '-asa-account')]"
},
"resources": [
{
Expand All @@ -51,45 +35,6 @@
"apiVersion": "[variables('apiVersion')]",
"location": "[parameters('location')]",
"properties": {}
},
{
"type": "Microsoft.MixedReality/remoteRenderingAccounts",
"name": "[variables('arrAccountName')]",
"apiVersion": "[variables('arrApiVersion')]",
"location": "[parameters('location')]",
"properties": {},
"identity": { "type": "systemAssigned" }
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "[variables('storageApiVersion')]",
"name": "[variables('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_RAGRS",
"tier": "Standard"
},
"kind": "StorageV2",
"properties": {
"supportsHttpsTrafficOnly": true,
"encryption": {
"keySource": "Microsoft.Storage",
"services": {
"blob": {
"enabled": true
}
},
},
"accessTier": "Hot"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "[variables('storageApiVersion')]",
"name": "[variables('blobContainerResourceName')]",
"dependsOn": [
"[variables('storageAccountName')]"
]
}
],
"outputs": {
Expand All @@ -104,38 +49,6 @@
"MIXEDREALITY_ACCOUNT_KEY": {
"type": "string",
"value": "[listKeys(resourceId('Microsoft.MixedReality/spatialAnchorsAccounts', variables('asaAccountName')), variables('apiVersion')).primaryKey]"
},
"MIXEDREALITY_ARR_ACCOUNT_ID": {
"type": "string",
"value": "[reference(variables('arrAccountName')).accountId]"
},
"MIXEDREALITY_ARR_ACCOUNT_DOMAIN": {
"type": "string",
"value": "[reference(variables('arrAccountName')).accountDomain]"
},
"MIXEDREALITY_ARR_ACCOUNT_KEY": {
"type": "string",
"value": "[listKeys(resourceId('Microsoft.MixedReality/remoteRenderingAccounts', variables('arrAccountName')), variables('arrApiVersion')).primaryKey]"
},
"MIXEDREALITY_ARR_STORAGE_ACCOUNT_NAME": {
"type": "string",
"value": "[variables('storageAccountName')]"
},
"MIXEDREALITY_ARR_STORAGE_ACCOUNT_KEY": {
"type": "string",
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), variables('storageApiVersion')).keys[0].value]"
},
"MIXEDREALITY_ARR_BLOB_CONTAINER_NAME": {
"type": "string",
"value": "[variables('blobContainerName')]"
},
"MIXEDREALITY_ARR_SAS_TOKEN": {
"type": "string",
"value": "[listServiceSas(variables('storageAccountName'), variables('storageApiVersion'), variables('sasProperties')).serviceSasToken]"
},
"MIXEDREALITY_ARR_SERVICE_ENDPOINT": {
"type": "string",
"value": "[concat('https://remoterendering.', parameters('location'), '.mixedreality.azure.com')]"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30804.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.MixedReality.RemoteRendering", "src\Azure.MixedReality.RemoteRendering.csproj", "{ECE9B1E6-05DF-4DFE-9B1C-52A16B3ABB7A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.MixedReality.RemoteRendering", "src\Azure.MixedReality.RemoteRendering.csproj", "{A3E40E85-87E1-4238-BBBB-00E232EFD822}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.MixedReality.RemoteRendering.Tests", "tests\Azure.MixedReality.RemoteRendering.Tests.csproj", "{2B67CBA1-55D8-491E-80CC-96A590E3F4F7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{85271BAE-8B48-43B6-8A16-BBD3F14F7AA1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.MixedReality.Authentication", "..\Azure.MixedReality.Authentication\src\Azure.MixedReality.Authentication.csproj", "{D918FBC5-CB77-4ADB-9880-8C7F7808D30C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ECE9B1E6-05DF-4DFE-9B1C-52A16B3ABB7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECE9B1E6-05DF-4DFE-9B1C-52A16B3ABB7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECE9B1E6-05DF-4DFE-9B1C-52A16B3ABB7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECE9B1E6-05DF-4DFE-9B1C-52A16B3ABB7A}.Release|Any CPU.Build.0 = Release|Any CPU
{A3E40E85-87E1-4238-BBBB-00E232EFD822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3E40E85-87E1-4238-BBBB-00E232EFD822}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3E40E85-87E1-4238-BBBB-00E232EFD822}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3E40E85-87E1-4238-BBBB-00E232EFD822}.Release|Any CPU.Build.0 = Release|Any CPU
{2B67CBA1-55D8-491E-80CC-96A590E3F4F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B67CBA1-55D8-491E-80CC-96A590E3F4F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B67CBA1-55D8-491E-80CC-96A590E3F4F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -29,10 +27,6 @@ Global
{85271BAE-8B48-43B6-8A16-BBD3F14F7AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85271BAE-8B48-43B6-8A16-BBD3F14F7AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85271BAE-8B48-43B6-8A16-BBD3F14F7AA1}.Release|Any CPU.Build.0 = Release|Any CPU
{D918FBC5-CB77-4ADB-9880-8C7F7808D30C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D918FBC5-CB77-4ADB-9880-8C7F7808D30C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D918FBC5-CB77-4ADB-9880-8C7F7808D30C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D918FBC5-CB77-4ADB-9880-8C7F7808D30C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ Install-Package Azure.MixedReality.RemoteRendering -AllowPrereleaseVersions
From .NET CLI

```dotnetcli
dotnet add package Azure.MixedReality.RemoteRendering --version 1.0.0-beta.1
dotnet add package Azure.MixedReality.RemoteRendering --version 1.0.0-beta.3
```

Add a package reference:

```xml
<PackageReference Include="Azure.MixedReality.RemoteRendering" Version="1.0.0-beta.1" />
<PackageReference Include="Azure.MixedReality.RemoteRendering" Version="1.0.0-beta.3" />
```

### Prerequisites
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Core;
using System;

#nullable enable

namespace Azure.MixedReality.Authentication
{
internal static class AuthenticationEndpoint
{
/// <summary>
/// Constructs an authentication endpoint from a service domain.
/// </summary>
/// <param name="accountDomain">The account domain.</param>
/// <returns><see cref="Uri"/>.</returns>
public static Uri ConstructFromDomain(string accountDomain)
{
Argument.AssertNotNullOrWhiteSpace(accountDomain, nameof(accountDomain));

if (!Uri.TryCreate($"https://sts.{accountDomain}", UriKind.Absolute, out Uri? result))
{
throw new ArgumentException("The value could not be used to construct a valid endpoint.", nameof(accountDomain));
}

return result;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;

namespace Azure.MixedReality.Authentication
{
/// <summary>
/// Represents an object used for Mixed Reality account key authentication.
/// </summary>
/// <seealso cref="TokenCredential" />
internal class MixedRealityAccountKeyCredential : TokenCredential
{
private readonly Guid _accountId;

private readonly AzureKeyCredential _accountKey;

/// <summary>
/// Initializes a new instance of the <see cref="MixedRealityAccountKeyCredential" /> class.
/// </summary>
/// <param name="accountId">The Mixed Reality service account identifier.</param>
/// <param name="accountKey">The Mixed Reality service account primary or secondary key.</param>
public MixedRealityAccountKeyCredential(Guid accountId, string accountKey)
: this(accountId, new AzureKeyCredential(accountKey))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="MixedRealityAccountKeyCredential" /> class.
/// </summary>
/// <param name="accountId">The Mixed Reality service account identifier.</param>
/// <param name="keyCredential">The Mixed Reality service account primary or secondary key credential.</param>
public MixedRealityAccountKeyCredential(Guid accountId, AzureKeyCredential keyCredential)
{
Argument.AssertNotDefault(ref accountId, nameof(accountId));
Argument.AssertNotNull(keyCredential, nameof(keyCredential));

_accountId = accountId;
_accountKey = keyCredential;
}

/// <summary>
/// Gets an <see cref="AccessToken" /> for the specified set of scopes.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> new AccessToken($"{_accountId}:{_accountKey.Key}", DateTimeOffset.MaxValue);

/// <summary>
/// Gets an <see cref="AccessToken" /> for the specified set of scopes.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> new ValueTask<AccessToken>(GetToken(requestContext, cancellationToken));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;

#nullable enable

namespace Azure.MixedReality.Authentication
{
/// <summary>
/// Represents a token credential that can be used to access a Mixed Reality service.
/// Implements <see cref="TokenCredential" />.
/// </summary>
/// <seealso cref="TokenCredential" />
internal class MixedRealityTokenCredential : TokenCredential
{
private readonly MixedRealityStsClient _stsClient;

/// <summary>
/// Initializes a new instance of the <see cref="MixedRealityTokenCredential" /> class.
/// </summary>
/// <param name="accountId">The Mixed Reality service account identifier.</param>
/// <param name="endpoint">The Mixed Reality STS service endpoint.</param>
/// <param name="credential">The credential used to access the Mixed Reality service.</param>
/// <param name="options">The options.</param>
private MixedRealityTokenCredential(Guid accountId, Uri endpoint, TokenCredential credential, MixedRealityStsClientOptions? options = null)
{
_stsClient = new MixedRealityStsClient(accountId, endpoint, credential, options);
}

/// <summary>
/// Gets an <see cref="AccessToken" /> for the specified set of scopes.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> _stsClient.GetToken(cancellationToken);

/// <summary>
/// get token as an asynchronous operation.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> await _stsClient.GetTokenAsync(cancellationToken).ConfigureAwait(false);

/// <summary>
/// Gets a Mixed Reality credential using the specified <paramref name="credential"/>.
/// Azure credentials are exchanged with the Mixed Reality STS service for Mixed Reality access tokens.
/// In the case of a <see cref="StaticAccessTokenCredential"/>, the credential is assumed to be a Mixed Reality
/// access token previously retrieved from the Mixed Reality STS service, so it is simply returned.
/// </summary>
/// <param name="accountId">The Mixed Reality service account identifier.</param>
/// <param name="endpoint">The Mixed Reality STS service endpoint.</param>
/// <param name="credential">The credential used to access the Mixed Reality service.</param>
/// <param name="options">The options.</param>
/// <returns><see cref="TokenCredential"/>.</returns>
public static TokenCredential GetMixedRealityCredential(Guid accountId, Uri endpoint, TokenCredential credential, MixedRealityStsClientOptions? options = null)
{
if (credential is StaticAccessTokenCredential)
{
// Static access tokens are assumed to be Mixed Reality access tokens already, so we don't need to exchange
// them using the MixedRealityTokenCredential.
return credential;
}

return new MixedRealityTokenCredential(accountId, endpoint, credential, options);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Core;
using System.Threading;
using System.Threading.Tasks;

namespace Azure.MixedReality.Authentication
{
/// <summary>
/// Represents a static access token credential.
/// Implements the <see cref="TokenCredential" />.
/// </summary>
/// <seealso cref="TokenCredential" />
internal class StaticAccessTokenCredential : TokenCredential
{
private readonly AccessToken _token;

/// <summary>
/// Initializes a new instance of the <see cref="StaticAccessTokenCredential"/> class.
/// </summary>
/// <param name="token">The token.</param>
public StaticAccessTokenCredential(AccessToken token) => _token = token;

/// <summary>
/// Gets an <see cref="AccessToken" /> for the specified set of scopes.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> this._token;

/// <summary>
/// Gets an <see cref="AccessToken" /> for the specified set of scopes.
/// </summary>
/// <param name="requestContext">The <see cref="TokenRequestContext" /> with authentication information.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken" /> to use.</param>
/// <returns>A valid <see cref="AccessToken" />.</returns>
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
=> new ValueTask<AccessToken>(this._token);
}
}
Loading