Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge previews/msi to master #1948

Merged
merged 4 commits into from
May 10, 2021
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: 2 additions & 0 deletions e2e/test/config/Configuration.IoTHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public static string GetIotHubSharedAccessSignature(TimeSpan timeToLive)

#endif

public static string UserAssignedMsiResourceId => GetValue("IOTHUB_USER_ASSIGNED_MSI_RESOURCE_ID");

public static X509Certificate2 GetCertificateWithPrivateKey()
{
const string hubPfxCert = "IOTHUB_X509_PFX_CERTIFICATE";
Expand Down
20 changes: 16 additions & 4 deletions e2e/test/iothub/service/RegistryManagerExportDevicesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ public class RegistryManagerExportDevicesTests : E2EMsTestBase
[TestCategory("LongRunning")]
[Timeout(120000)]
[DoNotParallelize]
[DataRow(StorageAuthenticationType.KeyBased)]
[DataRow(StorageAuthenticationType.IdentityBased)]
public async Task RegistryManager_ExportDevices(StorageAuthenticationType storageAuthenticationType)
[DataRow(StorageAuthenticationType.KeyBased, false)]
[DataRow(StorageAuthenticationType.IdentityBased, false)]
[DataRow(StorageAuthenticationType.IdentityBased, true)]
public async Task RegistryManager_ExportDevices(StorageAuthenticationType storageAuthenticationType, bool isUserAssignedMsi)
{
// arrange

Expand Down Expand Up @@ -86,13 +87,24 @@ await registryManager
{
try
{
ManagedIdentity identity = null;
if (isUserAssignedMsi)
{
string userAssignedMsiResourceId = Configuration.IoTHub.UserAssignedMsiResourceId;
identity = new ManagedIdentity
{
userAssignedIdentity = userAssignedMsiResourceId
};
}

exportJobResponse = await registryManager
.ExportDevicesAsync(
JobProperties.CreateForExportJob(
containerUri.ToString(),
true,
null,
storageAuthenticationType))
storageAuthenticationType,
identity))
.ConfigureAwait(false);
break;
}
Expand Down
17 changes: 14 additions & 3 deletions e2e/test/iothub/service/RegistryManagerImportDevicesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ public class RegistryManagerImportDevicesTests : E2EMsTestBase
[TestCategory("LongRunning")]
[Timeout(120000)]
[DoNotParallelize]
[DataRow(StorageAuthenticationType.KeyBased)]
[DataRow(StorageAuthenticationType.IdentityBased)]
public async Task RegistryManager_ImportDevices(StorageAuthenticationType storageAuthenticationType)
[DataRow(StorageAuthenticationType.KeyBased, false)]
[DataRow(StorageAuthenticationType.IdentityBased, false)]
[DataRow(StorageAuthenticationType.IdentityBased, true)]
public async Task RegistryManager_ImportDevices(StorageAuthenticationType storageAuthenticationType, bool isUserAssignedMsi)
{
// arrange

Expand Down Expand Up @@ -84,6 +85,16 @@ public async Task RegistryManager_ImportDevices(StorageAuthenticationType storag
{
try
{
ManagedIdentity identity = null;
if (isUserAssignedMsi)
{
string userAssignedMsiResourceId = Configuration.IoTHub.UserAssignedMsiResourceId;
identity = new ManagedIdentity
{
userAssignedIdentity = userAssignedMsiResourceId
};
}

importJobResponse = await registryManager
.ImportDevicesAsync(
JobProperties.CreateForImportJob(
Expand Down
18 changes: 15 additions & 3 deletions iothub/service/src/JobProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ public JobProperties()
[JsonProperty(PropertyName = "storageAuthenticationType", NullValueHandling = NullValueHandling.Ignore)]
public StorageAuthenticationType? StorageAuthenticationType { get; set; }

/// <summary>
/// The managed identity used to access the storage account for import and export jobs.
/// </summary>
[JsonProperty(PropertyName = "identity", NullValueHandling = NullValueHandling.Ignore)]
public ManagedIdentity Identity { get; set; }

#pragma warning disable CA1054 // Uri parameters should not be strings

/// <summary>
Expand All @@ -127,12 +133,14 @@ public JobProperties()
/// <param name="outputBlobContainerUri">URI to a blob container. This is used to output the status of the job and the results. Including a SAS token is dependent on the <see cref="StorageAuthenticationType" /> parameter.</param>
/// <param name="inputBlobName">The blob name to be used when importing from the provided input blob container</param>
/// <param name="storageAuthenticationType">Specifies authentication type being used for connecting to storage account</param>
/// <param name="identity">User assigned managed identity used to access storage account for import and export jobs.</param>
/// <returns>An instance of JobProperties</returns>
public static JobProperties CreateForImportJob(
string inputBlobContainerUri,
string outputBlobContainerUri,
string inputBlobName = null,
StorageAuthenticationType? storageAuthenticationType = null)
StorageAuthenticationType? storageAuthenticationType = null,
ManagedIdentity identity = null)
{
return new JobProperties
{
Expand All @@ -141,22 +149,25 @@ public static JobProperties CreateForImportJob(
OutputBlobContainerUri = outputBlobContainerUri,
InputBlobName = inputBlobName,
StorageAuthenticationType = storageAuthenticationType,
Identity = identity
};
}

/// <summary>
/// Creates an instance of JobProperties with paramters ready to start an Import job
/// Creates an instance of JobProperties with parameters ready to start an Import job
/// </summary>
/// <param name="outputBlobContainerUri">URI to a blob container. This is used to output the status of the job and the results. Including a SAS token is dependent on the <see cref="StorageAuthenticationType" /> parameter.</param>
/// <param name="excludeKeysInExport">Indicates if authorization keys are included in export output</param>
/// <param name="outputBlobName">The name of the blob that will be created in the provided output blob container</param>
/// <param name="storageAuthenticationType">Specifies authentication type being used for connecting to storage account</param>
/// <param name="identity">User assigned managed identity used to access storage account for import and export jobs.</param>
/// <returns>An instance of JobProperties</returns>
public static JobProperties CreateForExportJob(
string outputBlobContainerUri,
bool excludeKeysInExport,
string outputBlobName = null,
StorageAuthenticationType? storageAuthenticationType = null)
StorageAuthenticationType? storageAuthenticationType = null,
ManagedIdentity identity = null)
{
return new JobProperties
{
Expand All @@ -165,6 +176,7 @@ public static JobProperties CreateForExportJob(
ExcludeKeysInExport = excludeKeysInExport,
OutputBlobName = outputBlobName,
StorageAuthenticationType = storageAuthenticationType,
Identity = identity
};
}

Expand Down
22 changes: 22 additions & 0 deletions iothub/service/src/ManagedIdentity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;

namespace Microsoft.Azure.Devices
{
/// <summary>
/// The managed identity used to access the storage account for IoT hub import and export jobs.
/// </summary>
public class ManagedIdentity
{
/// <summary>
/// The user identity resource Id used to access the storage account for import and export jobs.
/// </summary>
[JsonProperty(PropertyName = "userAssignedIdentity", NullValueHandling = NullValueHandling.Ignore)]
public string userAssignedIdentity { get; set; }
}
}
2 changes: 2 additions & 0 deletions vsts/test-release-nuget.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ jobs:
AZURE_IOT_LOCALPACKAGES: $(Build.ArtifactStagingDirectory)/nuget
IOTHUB_CLIENT_ID: $(IOTHUB-CLIENT-ID)
IOTHUB_CLIENT_SECRET: $(IOTHUB-CLIENT-SECRET)
IOTHUB_USER_ASSIGNED_MSI_RESOURCE_ID: $(IOTHUB-USER-ASSIGNED-MSI-RESOURCE-ID)

- task: CopyFiles@2
displayName: 'Copy files to the artifacts folder'
Expand Down Expand Up @@ -208,6 +209,7 @@ jobs:
AZURE_IOT_LOCALPACKAGES: $(Build.ArtifactStagingDirectory)/nuget
IOTHUB_CLIENT_ID: $(IOTHUB-CLIENT-ID)
IOTHUB_CLIENT_SECRET: $(IOTHUB-CLIENT-SECRET)
IOTHUB_USER_ASSIGNED_MSI_RESOURCE_ID: $(IOTHUB-USER-ASSIGNED-MSI-RESOURCE-ID)

- task: CopyFiles@2
displayName: 'Copy TRX files to the artifacts folder'
Expand Down
2 changes: 2 additions & 0 deletions vsts/vsts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
FRAMEWORK: $(FRAMEWORK)
IOTHUB_CLIENT_ID: $(IOTHUB-CLIENT-ID)
IOTHUB_CLIENT_SECRET: $(IOTHUB-CLIENT-SECRET)
IOTHUB_USER_ASSIGNED_MSI_RESOURCE_ID: $(IOTHUB-USER-ASSIGNED-MSI-RESOURCE-ID)

- task: CopyFiles@2
displayName: "Copy files to the artifacts folder"
Expand Down Expand Up @@ -193,6 +194,7 @@ jobs:
FRAMEWORK: $(FRAMEWORK)
IOTHUB_CLIENT_ID: $(IOTHUB-CLIENT-ID)
IOTHUB_CLIENT_SECRET: $(IOTHUB-CLIENT-SECRET)
IOTHUB_USER_ASSIGNED_MSI_RESOURCE_ID: $(IOTHUB-USER-ASSIGNED-MSI-RESOURCE-ID)

- task: CopyFiles@2
displayName: "Copy TRX files to the artifacts folder"
Expand Down