From d408ee11a02f19296533123eae59f94054785db6 Mon Sep 17 00:00:00 2001 From: Jon Gallant Date: Thu, 18 Jun 2020 20:16:12 -0700 Subject: [PATCH] Change .net to AzureIdentityCredentialAdapter --- .gitignore | 6 +- README.md | 56 +++++++++++++++---- iac/terraform/main.tf | 29 ++++++++++ iac/terraform/providers.tf | 24 ++++++++ iac/terraform/variables.tf | 11 ++++ .../Fluent/ResourceGroupTests.cs | 27 +++++---- ...ant.Azure.Identity.Extensions.Tests.csproj | 21 +++---- .../Mgmt/AppInsightsTests.cs | 20 +++++-- .../Mgmt/CosmosDBTests.cs | 4 +- .../Mgmt/InteractiveBrowserTests.cs | 16 +++--- .../Mgmt/ResourceGroupTests.cs | 10 ++-- .../Mgmt/RoleAssignmentTests.cs | 46 --------------- .../Mgmt/StorageTests.cs | 12 ++-- .../ServiceBus/ServiceBusTests.cs | 18 +++--- .../AzureIdentityCredentialAdapter.cs | 17 ++++++ ...> AzureIdentityFluentCredentialAdapter.cs} | 28 +++++----- ...ureIdentityServiceBusCredentialAdapter.cs} | 25 +++++---- ...vider.cs => AzureIdentityTokenProvider.cs} | 28 ++++------ .../DefaultAzureMgmtCredential.cs | 19 ------- ...onGallant.Azure.Identity.Extensions.csproj | 2 +- 20 files changed, 245 insertions(+), 174 deletions(-) create mode 100644 iac/terraform/main.tf create mode 100644 iac/terraform/providers.tf create mode 100644 iac/terraform/variables.tf delete mode 100644 net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/RoleAssignmentTests.cs create mode 100644 net/JonGallant.Azure.Identity.Extensions/AzureIdentityCredentialAdapter.cs rename net/JonGallant.Azure.Identity.Extensions/{DefaultAzureFluentCredential.cs => AzureIdentityFluentCredentialAdapter.cs} (81%) rename net/JonGallant.Azure.Identity.Extensions/{DefaultAzureServiceBusCredential.cs => AzureIdentityServiceBusCredentialAdapter.cs} (57%) rename net/JonGallant.Azure.Identity.Extensions/{DefaultAzureCredentialTokenProvider.cs => AzureIdentityTokenProvider.cs} (58%) delete mode 100644 net/JonGallant.Azure.Identity.Extensions/DefaultAzureMgmtCredential.cs diff --git a/.gitignore b/.gitignore index 4d50c20..c8ba18f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,8 @@ *.factorypath *.project *.prefs -.vscode/* \ No newline at end of file +.vscode/* +terraform. +.terraform +terraform.tfstate* +tf.plan \ No newline at end of file diff --git a/README.md b/README.md index 37c3b0c..24421bc 100644 --- a/README.md +++ b/README.md @@ -17,38 +17,38 @@ The classes contained in this repo are only meant to be a temporary stopgap betw ## .NET -### DefaultAzureMgmtCredential.cs +### AzureIdentityCredentialAdapter.cs -The `DefaultAzureMgmtCredential` class allows you to use all the goodness of `Azure.Identity.DefaultAzureCredential` in the Azure Management libraries. You can use it in place of `ServiceClientCredential` when calling your Azure Management APIs. The Azure Management libraries will be updated to support Azure Identity and Azure Core in early 2020, so this should just be used a a stopgap between now and then. +The `AzureIdentityCredentialAdapter` class allows you to use all the goodness of `Azure.Identity.DefaultAzureCredential` in the Azure Management libraries. You can use it in place of `ServiceClientCredential` when calling your Azure Management APIs. The Azure Management libraries will be updated to support Azure Identity and Azure Core in early 2020, so this should just be used a a stopgap between now and then. ```cmd dotnet add package Microsoft.Azure.Management.ApplicationInsights --version 0.2.0-preview ``` -Use DefaultAzureMgmtCredential in place of ServiceClientCredential: +Use `AzureIdentityCredentialAdapter` in place of `ServiceClientCredential`: ```csharp using JonGallant.Azure.Identity.Extensions; using Microsoft.Azure.Management.ApplicationInsights.Management; -var appInsightsClient = new ApplicationInsightsManagementClient(new DefaultAzureMgmtCredential()); +var appInsightsClient = new ApplicationInsightsManagementClient(new AzureIdentityCredentialAdapter()); ``` -### DefaultAzureFluentCredential.cs +### AzureIdentityFluentCredentialAdapter.cs -The `DefaultAzureFluentCredential` class allows you to use all the goodness of `Azure.Identity.DefaultAzureCredential` in the [Azure Management **Fluent** libraries](https://github.com/Azure/azure-libraries-for-net). You can use it in place of `AzureCredentials` when calling your Azure Management Fluent APIs. +The `AzureIdentityFluentCredentialAdapter` class allows you to use all the goodness of `Azure.Identity.DefaultAzureCredential` in the [Azure Management **Fluent** libraries](https://github.com/Azure/azure-libraries-for-net). You can use it in place of `AzureCredentials` when calling your Azure Management Fluent APIs. ```cmd dotnet add package Microsoft.Azure.Management.Fluent --version 1.30.0 ``` -Use `DefaultAzureFluentCredential` in place of `AzureCredentials`: +Use `AzureIdentityFluentCredentialAdapter` in place of `AzureCredentials`: ```csharp using JonGallant.Azure.Identity.Extensions; using Microsoft.Azure.Management.ResourceManager.Fluent; -var creds = new DefaultAzureFluentCredential(tenantId, AzureEnvironment.AzureGlobalCloud); +var creds = new AzureIdentityFluentCredentialAdapter(tenantId, AzureEnvironment.AzureGlobalCloud); var resourceGroup = Azure.Authenticate(creds) .WithSubscription(subId) @@ -58,9 +58,9 @@ var resourceGroup = Azure.Authenticate(creds) .Create(); ``` -### DefaultAzureServiceBusCredential.cs +### AzureIdentityServiceBusCredentialAdapter.cs -The `DefaultAzureServiceBusCredential` class allows you to use all of the goodness of `Azure.Identity.DefaultAzureCredential` with the Service Bus SDKs. Service Bus will officially be supported by the new SDKs soon, this is a stopgap that enables you to use the same credential flow throughout your application. +The `AzureIdentityServiceBusCredentialAdapter` class allows you to use all of the goodness of `Azure.Identity.DefaultAzureCredential` with the Service Bus SDKs. Service Bus will officially be supported by the new SDKs soon, this is a stopgap that enables you to use the same credential flow throughout your application. ```cmd dotnet add package Microsoft.Azure.ServiceBus --version 4.1.1 @@ -70,9 +70,14 @@ dotnet add package Microsoft.Azure.ServiceBus --version 4.1.1 using JonGallant.Azure.Identity.Extensions; using Microsoft.Azure.ServiceBus; -var client = new TopicClient("sbendpoint", "entitypath", new DefaultAzureServiceBusCredential()); +var client = new TopicClient("sbendpoint", "entitypath", new AzureIdentityServiceBusCredentialAdapter()); ``` +## Testing .NET + +1. Setup test resources with "Test Setup" section below. +2. Open the .Tests project and run dotnet build. + ## Java ### DefaultAzureServiceBusCredential.java @@ -102,7 +107,7 @@ Azure azure = Azure.authenticate(new DefaultAzureCredentialAdapter(tenantId)).wi Above code will provide an instance of `Azure` fluent type from which you can access all Azure Resource Managers. -#### Testing DefaultAzureCredentialAdapter +#### Testing AzureIdentityCredentialAdapter This repository has a test class called `DefaultAzureCredentailAdapterTest` that tests creation of a storage account, listing all storage accounts in a resource group to validate successful creation, then deleting the account created earlier in this test and listing again to ensure successful deletion. @@ -170,3 +175,30 @@ Once you have the `.env` file configured and the venv loaded, run the tests simp More to come soon. Please file a GitHub issue with any questions/suggestions. +## Test Setup + +1. Create a service principal with `az ad sp create-for-rbac` +2. Rename .env.tmp to .env and update the the following values from the SP + + `AZURE_CLIENT_ID=appId` + `AZURE_CLIENT_SECRET=password` + `AZURE_TENANT_ID=tenantId` + +3. Run `az account show` to get your subscription id and update the .env file with that. + + `AZURE_SUBSCRIPTION_ID=` + +4. Deploy the Service Bus resources with terraform files in iac/terraform + + - Open variables.tf and change the basename value to something unique. + - Run the following commands: + - `terraform init` + - `terraform plan --out tf.plan` + - `terraform apply tf.plan` + +5. Update AZURE_BASE_NAME in .env file to the base name you used for terraform deployment + + - AZURE_BASE_NAME=azidexttest1 + + +6. See each language "Test" section above for instructions on how to run the tests. diff --git a/iac/terraform/main.tf b/iac/terraform/main.tf new file mode 100644 index 0000000..e93ddde --- /dev/null +++ b/iac/terraform/main.tf @@ -0,0 +1,29 @@ +resource "azurerm_resource_group" "rg" { + name = "${var.basename}rg" + location = var.location +} + +resource "azurerm_servicebus_namespace" "sbns" { + name = "${var.basename}sbns" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + sku = "Standard" +} + +resource "azurerm_servicebus_topic" "sbtopic" { + name = "topic1" + resource_group_name = azurerm_resource_group.rg.name + namespace_name = azurerm_servicebus_namespace.sbns.name +} + +resource "azurerm_servicebus_subscription" "sbsub" { + name = "sub1" + resource_group_name = azurerm_resource_group.rg.name + namespace_name = azurerm_servicebus_namespace.sbns.name + topic_name = azurerm_servicebus_topic.sbtopic.name + max_delivery_count = 1 +} + +output "sb_connection_string" { + value = azurerm_servicebus_namespace.sbns.default_primary_connection_string +} diff --git a/iac/terraform/providers.tf b/iac/terraform/providers.tf new file mode 100644 index 0000000..d6e4669 --- /dev/null +++ b/iac/terraform/providers.tf @@ -0,0 +1,24 @@ +#Set the terraform required version +terraform { + required_version = ">= 0.12.6" +} + +# Configure the Azure Provider +provider "azurerm" { + # It is recommended to pin to a given version of the Provider + version = "~>2" + features {} +} + +provider "random" { + version = "~>2" +} + +provider "null" { + version = "~> 2.1" +} + +# Data + +# Make client_id, tenant_id, subscription_id and object_id variables +data "azurerm_client_config" "current" {} diff --git a/iac/terraform/variables.tf b/iac/terraform/variables.tf new file mode 100644 index 0000000..a534164 --- /dev/null +++ b/iac/terraform/variables.tf @@ -0,0 +1,11 @@ +variable "basename" { + type = string + description = "The base name for all resources" + default = "azidexttest1" +} + +variable "location" { + type = string + description = "Azure region where to create resources." + default = "West US" +} diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Fluent/ResourceGroupTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Fluent/ResourceGroupTests.cs index 4ed81df..a965463 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Fluent/ResourceGroupTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Fluent/ResourceGroupTests.cs @@ -1,26 +1,31 @@ -using DotNetEnv; -using Microsoft.Azure.Management.ResourceManager.Fluent; using System; +using Microsoft.Azure.Management.ResourceManager.Fluent; +using DotNetEnv; +using JonGallant.Azure.Identity.Extensions; using Xunit; +using System.Threading.Tasks; +using static DotNetEnv.Env; namespace JonGallant.Azure.Identity.Extensions.Tests.Fluent { public class ResourceGroupTests { [Fact] - public void CreateAzCredsTest() + public async Task CheckIfResourceGroupExistsTest() { - Env.Load("../../../.env"); + Env.Load("../../../../../.env"); + + var creds = new AzureIdentityFluentCredentialAdapter( + Environment.GetEnvironmentVariable("AZURE_TENANT_ID"), + AzureEnvironment.AzureGlobalCloud); + + var name = Guid.NewGuid().ToString("n").Substring(0, 8); - var creds = new DefaultAzureFluentCredential(Environment.GetEnvironmentVariable("AZURE_TENANT_ID"), AzureEnvironment.AzureGlobalCloud); - - var name = Environment.GetEnvironmentVariable("AZURE_RESOURCE_GROUP") + Guid.NewGuid().ToString("n").Substring(0, 8); - - var resourceGroup = Microsoft.Azure.Management.Fluent.Azure.Authenticate(creds). + var resourceGroupExists = await Microsoft.Azure.Management.Fluent.Azure.Authenticate(creds). WithSubscription(Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID")). - ResourceGroups.Define(name).WithRegion(Environment.GetEnvironmentVariable("AZURE_REGION")).Create(); + ResourceGroups.ContainAsync(name); - Assert.Equal(resourceGroup.Name, name); + Assert.False(resourceGroupExists); } } } diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/JonGallant.Azure.Identity.Extensions.Tests.csproj b/net/JonGallant.Azure.Identity.Extensions.Tests/JonGallant.Azure.Identity.Extensions.Tests.csproj index a222f91..61a8af3 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/JonGallant.Azure.Identity.Extensions.Tests.csproj +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/JonGallant.Azure.Identity.Extensions.Tests.csproj @@ -8,17 +8,18 @@ - + - - - - - - - - - + + + + + + + + + + diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/AppInsightsTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/AppInsightsTests.cs index 377e34c..aa672e8 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/AppInsightsTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/AppInsightsTests.cs @@ -1,6 +1,8 @@ using DotNetEnv; using Microsoft.Azure.Management.ApplicationInsights.Management; using Microsoft.Azure.Management.ApplicationInsights.Management.Models; +using Microsoft.Azure.Management.ResourceManager; +using Microsoft.Azure.Management.ResourceManager.Models; using System; using Xunit; @@ -9,19 +11,27 @@ namespace JonGallant.Azure.Identity.Extensions.Tests.Mgmt public class AppInsightsTests { [Fact] - public async void CreateAppInsightsTest() + public async void CreateAndDeleteAppInsightsTest() { Env.Load("../../../../../.env"); - var client = new ApplicationInsightsManagementClient(new DefaultAzureMgmtCredential()); + var baseName = Environment.GetEnvironmentVariable("AZURE_BASE_NAME"); + var rgName = string.Format("{0}rg", baseName); + + // App Insights + var client = new ApplicationInsightsManagementClient(new AzureIdentityCredentialAdapter()); client.SubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var component = new ApplicationInsightsComponent(Environment.GetEnvironmentVariable("AZURE_REGION"), "web", "web"); - var name = Environment.GetEnvironmentVariable("APPINSIGHTS_NAME") + Guid.NewGuid().ToString("n").Substring(0, 8); + var component = new ApplicationInsightsComponent("westus", "web", "web"); + var aiName = "appinsightsname" + Guid.NewGuid().ToString("n").Substring(0, 8); - component = await client.Components.CreateOrUpdateAsync(Environment.GetEnvironmentVariable("AZURE_RESOURCE_GROUP"), name, component); + component = await client.Components.CreateOrUpdateAsync(rgName, aiName, component); Assert.NotNull(component.CreationDate); + + await client.Components.DeleteAsync(rgName, aiName); + + } } } diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/CosmosDBTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/CosmosDBTests.cs index 327163d..e5c6008 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/CosmosDBTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/CosmosDBTests.cs @@ -15,10 +15,10 @@ public async void CheckCosmosNameExistsTest() Env.Load("../../../../../.env"); - var client = new CosmosDBManagementClient(new DefaultAzureMgmtCredential()); + var client = new CosmosDBManagementClient(new AzureIdentityCredentialAdapter()); client.SubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var name = Environment.GetEnvironmentVariable("COSMOSDB_NAME") + Guid.NewGuid().ToString("n").Substring(0, 8); + var name = "cosmos" + Guid.NewGuid().ToString("n").Substring(0, 8); var results = await client.DatabaseAccounts.CheckNameExistsAsync(name); diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/InteractiveBrowserTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/InteractiveBrowserTests.cs index 60bb9fe..8501714 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/InteractiveBrowserTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/InteractiveBrowserTests.cs @@ -2,13 +2,14 @@ using Microsoft.Azure.Management.Storage; using System; using Xunit; +using Azure.Identity; namespace JonGallant.Azure.Identity.Extensions.Tests.Mgmt { public class InteractiveBrowserTests { - [Fact] - public async void InteractiveBrowserTest() + [Fact(Skip = "Requires user interaction")] + public async void CheckIfStorageNameAvailableWithInteractiveBrowserTest() { // Pre-req: Storage account created. Env.Load("../../../../../.env"); @@ -16,15 +17,14 @@ public async void InteractiveBrowserTest() Environment.SetEnvironmentVariable("AZURE_CLIENT_SECRET", ""); Environment.SetEnvironmentVariable("AZURE_TENANT_ID", ""); - var client = new StorageManagementClient(new DefaultAzureMgmtCredential(true)); - + var client = new StorageManagementClient(new AzureIdentityCredentialAdapter(new DefaultAzureCredential(true))); client.SubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var props = await client.StorageAccounts.GetPropertiesAsync( - Environment.GetEnvironmentVariable("AZURE_RESOURCE_GROUP"), - Environment.GetEnvironmentVariable("AZURE_STORAGE_ACCOUNT_NAME")); + var name = "azidext" + Guid.NewGuid().ToString("n").Substring(0, 8); + + var nameAvailable = await client.StorageAccounts.CheckNameAvailabilityAsync(name); - Assert.Equal(props.Location, Environment.GetEnvironmentVariable("AZURE_REGION")); + Assert.True(nameAvailable.NameAvailable); } } } diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/ResourceGroupTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/ResourceGroupTests.cs index f6932f7..3b4320d 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/ResourceGroupTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/ResourceGroupTests.cs @@ -9,20 +9,22 @@ namespace JonGallant.Azure.Identity.Extensions.Tests.Mgmt public class ResourceGroupTests { [Fact] - public async void CreateResourceGroupTest() + public async void CreateAndDeleteResourceGroupTest() { Env.Load("../../../../../.env"); - var client = new ResourceManagementClient(new DefaultAzureMgmtCredential()); + var client = new ResourceManagementClient(new AzureIdentityCredentialAdapter()); client.SubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var name = Environment.GetEnvironmentVariable("AZURE_RESOURCE_GROUP") + Guid.NewGuid().ToString("n").Substring(0, 8); + var name = "azidextrg" + Guid.NewGuid().ToString("n").Substring(0, 8); - var rg = new ResourceGroup(location:Environment.GetEnvironmentVariable("AZURE_REGION"), name:name); + var rg = new ResourceGroup(location:"westus", name:name); var result = await client.ResourceGroups.CreateOrUpdateAsync(name, rg); Assert.Equal(result.Name, name); + + await client.ResourceGroups.DeleteAsync(name); } } } diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/RoleAssignmentTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/RoleAssignmentTests.cs deleted file mode 100644 index 6b662d4..0000000 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/RoleAssignmentTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -//dotnet add package Microsoft.Azure.Management.Authorization --version 2.11.0-preview -using System; - -using Microsoft.Azure.Management.Authorization; -using Microsoft.Azure.Management.Authorization.Models; - -using DotNetEnv; - -using Xunit; - -namespace JonGallant.Azure.Identity.Extensions.Tests.Mgmt -{ - public class RoleAssignmentTests - { - [Fact] - public async void RoleAssignmentTest() - { - Env.Load("../../../../../.env"); - - var azurePrincipalId = Environment.GetEnvironmentVariable("AZURE_PRINCIPAL_ID"); - // Needs to be in Owner role in Azure Subscription, az role assignment create --assignee AZURE_CLIENT_ID --role 8e3af657-a8ff-443c-a75c-2fe8c4bcb635 - // You can get the principalId from the AZURE_CLIENT_ID with this command, az ad sp show --id AZURE_CLIENT_ID --query objectId - var azureSubId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var azureRoleDefinitionId = "673868aa-7521-48a0-acc6-0f60742d39f5"; // Data Factory Contributor - var roleAssignmentName = Guid.NewGuid().ToString(); - var roleAssignmentScope = $"/subscriptions/{azureSubId}/"; - - var client = new AuthorizationManagementClient(new DefaultAzureMgmtCredential()); - client.SubscriptionId = azureSubId; - - var roleDefinitionId = $"/subscriptions/{client.SubscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{azureRoleDefinitionId}"; - - var roleAssignmentParameters = new RoleAssignmentCreateParameters(roleDefinitionId, azurePrincipalId); - - var roleAssignment = await client.RoleAssignments.CreateAsync(roleAssignmentScope, roleAssignmentName, roleAssignmentParameters); - - Assert.Equal(roleAssignment.RoleDefinitionId, roleDefinitionId); - - var roleAssignmentDelete = await client.RoleAssignments.DeleteAsync(roleAssignmentScope, roleAssignmentName); - - Exception ex = await Assert.ThrowsAsync(async () => await client.RoleAssignments.GetAsync(roleAssignmentScope, roleAssignmentName)); - - Assert.EndsWith("is not found.", ex.Message); - } - } -} diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/StorageTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/StorageTests.cs index 0816d20..60aa167 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/StorageTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/Mgmt/StorageTests.cs @@ -8,20 +8,20 @@ namespace JonGallant.Azure.Identity.Extensions.Tests.Mgmt public class StorageTests { [Fact] - public async void ReadStorageAccountLocationTest() + public async void CheckIfStorageNameAvailableTest() { // Pre-req: Storage account created. Env.Load("../../../../../.env"); - var client = new StorageManagementClient(new DefaultAzureMgmtCredential()); + var client = new StorageManagementClient(new AzureIdentityCredentialAdapter()); client.SubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); - var props = await client.StorageAccounts.GetPropertiesAsync( - Environment.GetEnvironmentVariable("AZURE_RESOURCE_GROUP"), - Environment.GetEnvironmentVariable("AZURE_STORAGE_ACCOUNT_NAME")); + var name = "azidext" + Guid.NewGuid().ToString("n").Substring(0, 8); - Assert.Equal(props.Location, Environment.GetEnvironmentVariable("AZURE_REGION")); + var nameAvailable = await client.StorageAccounts.CheckNameAvailabilityAsync(name); + + Assert.True(nameAvailable.NameAvailable); } } } diff --git a/net/JonGallant.Azure.Identity.Extensions.Tests/ServiceBus/ServiceBusTests.cs b/net/JonGallant.Azure.Identity.Extensions.Tests/ServiceBus/ServiceBusTests.cs index eb0b636..53dc1f2 100644 --- a/net/JonGallant.Azure.Identity.Extensions.Tests/ServiceBus/ServiceBusTests.cs +++ b/net/JonGallant.Azure.Identity.Extensions.Tests/ServiceBus/ServiceBusTests.cs @@ -1,4 +1,5 @@ using DotNetEnv; +using Microsoft.Azure.Management.ServiceBus; using Microsoft.Azure.ServiceBus; using System; using System.Text; @@ -15,9 +16,12 @@ public async void TopicClientTests() { Env.Load("../../../../../.env"); - var client = new TopicClient(Environment.GetEnvironmentVariable("AZURE_SERVICE_BUS_ENDPOINT"), - Environment.GetEnvironmentVariable("AZURE_SERVICE_BUS_ENTITY_PATH"), - new DefaultAzureServiceBusCredential()); + var baseName = Environment.GetEnvironmentVariable("AZURE_BASE_NAME"); + var sbEndpoint = string.Format("{0}sbns.servicebus.windows.net", baseName); + + var client = new TopicClient(sbEndpoint, + "topic1", + new AzureIdentityServiceBusCredentialAdapter()); var messageText = "Hello World " + Guid.NewGuid().ToString("n").Substring(0, 8); @@ -25,10 +29,10 @@ public async void TopicClientTests() await client.CloseAsync(); - var subscription = new SubscriptionClient(Environment.GetEnvironmentVariable("AZURE_SERVICE_BUS_ENDPOINT"), - Environment.GetEnvironmentVariable("AZURE_SERVICE_BUS_ENTITY_PATH"), - Environment.GetEnvironmentVariable("AZURE_SERVICE_BUS_SUBSCRIPTION_NAME"), - new DefaultAzureServiceBusCredential()); + var subscription = new SubscriptionClient(sbEndpoint, + "topic1", + "sub1", + new AzureIdentityServiceBusCredentialAdapter()); var messageHandlerOptions = new MessageHandlerOptions((ExceptionReceivedEventArgs exceptionReceivedEventArgs) => { diff --git a/net/JonGallant.Azure.Identity.Extensions/AzureIdentityCredentialAdapter.cs b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityCredentialAdapter.cs new file mode 100644 index 0000000..97186b5 --- /dev/null +++ b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityCredentialAdapter.cs @@ -0,0 +1,17 @@ +using Microsoft.Rest; +using Azure.Core; + +namespace JonGallant.Azure.Identity.Extensions +{ + public class AzureIdentityCredentialAdapter : TokenCredentials + { + public AzureIdentityCredentialAdapter(string[] scopes = null) : base(new AzureIdentityTokenProvider(scopes)) + { + } + + public AzureIdentityCredentialAdapter(TokenCredential tokenCredential, string[] scopes = null) : base(new AzureIdentityTokenProvider(tokenCredential, scopes)) + { + + } + } +} \ No newline at end of file diff --git a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureFluentCredential.cs b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityFluentCredentialAdapter.cs similarity index 81% rename from net/JonGallant.Azure.Identity.Extensions/DefaultAzureFluentCredential.cs rename to net/JonGallant.Azure.Identity.Extensions/AzureIdentityFluentCredentialAdapter.cs index 615e1df..981aea0 100644 --- a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureFluentCredential.cs +++ b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityFluentCredentialAdapter.cs @@ -1,9 +1,4 @@ -using Azure.Identity; -using Microsoft.Azure.Management.ResourceManager.Fluent; -using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication; -using Microsoft.Rest; -using Microsoft.Rest.Azure.Authentication; -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -11,22 +6,29 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.Azure.Management.ResourceManager.Fluent; +using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication; +using Microsoft.Rest; +using Microsoft.Rest.Azure.Authentication; +using Azure.Core; +using Azure.Identity; + namespace JonGallant.Azure.Identity.Extensions { - public class DefaultAzureFluentCredential : AzureCredentials + public class AzureIdentityFluentCredentialAdapter : AzureCredentials { private IDictionary credentialsCache = new ConcurrentDictionary(); - private DefaultAzureCredential defaultAzureCredential; + private TokenCredential tokenCredential; - public DefaultAzureFluentCredential(DefaultAzureCredential defaultAzureCredential, string tenantId, AzureEnvironment environment) : base(default(DeviceCredentialInformation), tenantId, environment) + public AzureIdentityFluentCredentialAdapter(TokenCredential tokenCredential, string tenantId, AzureEnvironment environment) : base(default(DeviceCredentialInformation), tenantId, environment) { - this.defaultAzureCredential = defaultAzureCredential; + this.tokenCredential = tokenCredential; } - public DefaultAzureFluentCredential(string tenantId, AzureEnvironment environment) : base(default(DeviceCredentialInformation), tenantId, environment) + public AzureIdentityFluentCredentialAdapter(string tenantId, AzureEnvironment environment) : base(default(DeviceCredentialInformation), tenantId, environment) { - this.defaultAzureCredential = new DefaultAzureCredential(); + this.tokenCredential = new DefaultAzureCredential(); } public async override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken) @@ -78,7 +80,7 @@ public async override Task ProcessHttpRequestAsync(HttpRequestMessage request, C if (!credentialsCache.ContainsKey(adSettings.TokenAudience)) { - credentialsCache[adSettings.TokenAudience] = new DefaultAzureMgmtCredential(this.defaultAzureCredential); + credentialsCache[adSettings.TokenAudience] = new AzureIdentityCredentialAdapter(this.tokenCredential); } await credentialsCache[adSettings.TokenAudience].ProcessHttpRequestAsync(request, cancellationToken); } diff --git a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureServiceBusCredential.cs b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityServiceBusCredentialAdapter.cs similarity index 57% rename from net/JonGallant.Azure.Identity.Extensions/DefaultAzureServiceBusCredential.cs rename to net/JonGallant.Azure.Identity.Extensions/AzureIdentityServiceBusCredentialAdapter.cs index 53aea1c..f974343 100644 --- a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureServiceBusCredential.cs +++ b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityServiceBusCredentialAdapter.cs @@ -1,22 +1,25 @@ -using Azure.Identity; -using Microsoft.Azure.ServiceBus; -using Microsoft.Azure.ServiceBus.Primitives; -using System; +using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Azure.ServiceBus; +using Microsoft.Azure.ServiceBus.Primitives; +using Azure.Core; +using Azure.Identity; + namespace JonGallant.Azure.Identity.Extensions { - public class DefaultAzureServiceBusCredential : ITokenProvider + public class AzureIdentityServiceBusCredentialAdapter : ITokenProvider { - private DefaultAzureCredential defaultAzureCredential; + private TokenCredential tokenCredential; - public DefaultAzureServiceBusCredential() : this(new DefaultAzureCredential()) + public AzureIdentityServiceBusCredentialAdapter() : this(new DefaultAzureCredential()) { } - public DefaultAzureServiceBusCredential(DefaultAzureCredential defaultAzureCredential) + + public AzureIdentityServiceBusCredentialAdapter(TokenCredential tokenCredential) { - this.defaultAzureCredential = defaultAzureCredential; + this.tokenCredential = tokenCredential; } public async Task GetTokenAsync(string appliesTo, TimeSpan timeout) @@ -24,8 +27,8 @@ public async Task GetTokenAsync(string appliesTo, TimeSpan timeou var cts = new CancellationTokenSource(); cts.CancelAfter((int)timeout.TotalMilliseconds); - var token = await new DefaultAzureCredentialTokenProvider( - this.defaultAzureCredential, + var token = await new AzureIdentityTokenProvider( + this.tokenCredential, new string[] { "https://servicebus.azure.net/.default" }) .GetTokenAsync(cts.Token); diff --git a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureCredentialTokenProvider.cs b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityTokenProvider.cs similarity index 58% rename from net/JonGallant.Azure.Identity.Extensions/DefaultAzureCredentialTokenProvider.cs rename to net/JonGallant.Azure.Identity.Extensions/AzureIdentityTokenProvider.cs index ea566c7..e91738d 100644 --- a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureCredentialTokenProvider.cs +++ b/net/JonGallant.Azure.Identity.Extensions/AzureIdentityTokenProvider.cs @@ -1,35 +1,27 @@ -using Azure.Core; -using Azure.Identity; -using Microsoft.Rest; using System; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using Microsoft.Rest; +using Azure.Core; +using Azure.Identity; + namespace JonGallant.Azure.Identity.Extensions { - public class DefaultAzureCredentialTokenProvider : ITokenProvider - + public class AzureIdentityTokenProvider : ITokenProvider { private AccessToken? accessToken; private static readonly TimeSpan ExpirationThreshold = TimeSpan.FromMinutes(5); private string[] scopes; - private DefaultAzureCredential defaultAzureCredential; - - public DefaultAzureCredentialTokenProvider(string[] scopes = null) : this(new DefaultAzureCredential(), scopes) - { - } - - public DefaultAzureCredentialTokenProvider(bool includeInteractiveCredentials = false, string[] scopes = null) : this(new DefaultAzureCredential(includeInteractiveCredentials), scopes) - { - } + private TokenCredential tokenCredential; - public DefaultAzureCredentialTokenProvider(DefaultAzureCredentialOptions options, string[] scopes = null) : this(new DefaultAzureCredential(options), scopes) + public AzureIdentityTokenProvider(string[] scopes = null) : this(new DefaultAzureCredential(), scopes) { } - public DefaultAzureCredentialTokenProvider(DefaultAzureCredential defaultAzureCredential, string[] scopes = null) + public AzureIdentityTokenProvider(TokenCredential tokenCredential, string[] scopes = null) { if (scopes == null || scopes.Length == 0) { @@ -37,7 +29,7 @@ public DefaultAzureCredentialTokenProvider(DefaultAzureCredential defaultAzureCr } this.scopes = scopes; - this.defaultAzureCredential = defaultAzureCredential; + this.tokenCredential = tokenCredential; } public virtual async Task GetAuthenticationHeaderAsync(CancellationToken cancellationToken) @@ -50,7 +42,7 @@ public virtual async Task GetTokenAsync(CancellationToken cancellat { if (!this.accessToken.HasValue || AccessTokenExpired) { - this.accessToken = await this.defaultAzureCredential.GetTokenAsync(new TokenRequestContext(this.scopes), cancellationToken).ConfigureAwait(false); + this.accessToken = await this.tokenCredential.GetTokenAsync(new TokenRequestContext(this.scopes), cancellationToken).ConfigureAwait(false); } return this.accessToken.Value; diff --git a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureMgmtCredential.cs b/net/JonGallant.Azure.Identity.Extensions/DefaultAzureMgmtCredential.cs deleted file mode 100644 index d098a88..0000000 --- a/net/JonGallant.Azure.Identity.Extensions/DefaultAzureMgmtCredential.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Azure.Identity; -using Microsoft.Rest; -using System; - -namespace JonGallant.Azure.Identity.Extensions -{ - public class DefaultAzureMgmtCredential : TokenCredentials - { - public DefaultAzureMgmtCredential(bool includeInteractiveCredentials = false, string[] scopes = null) : base(new DefaultAzureCredentialTokenProvider(includeInteractiveCredentials, scopes)) - { - } - - public DefaultAzureMgmtCredential(DefaultAzureCredentialOptions options, string[] scopes = null) : base(new DefaultAzureCredentialTokenProvider(options, scopes)) - { - } - - public DefaultAzureMgmtCredential(DefaultAzureCredential defaultAzureCredential, string[] scopes = null) : base(new DefaultAzureCredentialTokenProvider(defaultAzureCredential, scopes)) { } - } -} \ No newline at end of file diff --git a/net/JonGallant.Azure.Identity.Extensions/JonGallant.Azure.Identity.Extensions.csproj b/net/JonGallant.Azure.Identity.Extensions/JonGallant.Azure.Identity.Extensions.csproj index c26bfb6..4190f0b 100644 --- a/net/JonGallant.Azure.Identity.Extensions/JonGallant.Azure.Identity.Extensions.csproj +++ b/net/JonGallant.Azure.Identity.Extensions/JonGallant.Azure.Identity.Extensions.csproj @@ -4,7 +4,7 @@ netcoreapp3.1 JonGallant.Azure.Identity.Extensions A library that extends the base Azure.Identity functionality. - 0.0.4-preview + 0.0.5-preview Jon Gallant Jon Gallant MIT