From 6ca2db98d4e59a370f2adbf6f8a740624b44653d Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 5 Feb 2026 18:28:28 -0600 Subject: [PATCH 1/3] Implement IAzurePrivateEndpointTarget on more Azure resources Follow up to #13108 Contributes to #13750 --- .../AzureAppConfigurationExtensions.cs | 29 ++- .../AzureAppConfigurationResource.cs | 15 +- .../AzureCosmosDBExtensions.cs | 57 ++++-- .../AzureCosmosDBResource.cs | 16 +- .../AzureEventHubsExtensions.cs | 14 +- .../AzureEventHubsResource.cs | 15 +- .../AzureKeyVaultResource.cs | 15 +- .../AzureKeyVaultResourceExtensions.cs | 68 ++++--- .../AzurePostgresExtensions.cs | 90 ++++++--- .../AzurePostgresFlexibleServerResource.cs | 15 +- .../AzureManagedRedisExtensions.cs | 13 +- .../AzureManagedRedisResource.cs | 15 +- .../AzureSearchExtensions.cs | 35 +++- .../AzureSearchResource.cs | 15 +- .../AzureServiceBusExtensions.cs | 14 +- .../AzureServiceBusResource.cs | 15 +- .../AzureSignalRExtensions.cs | 53 +++-- .../AzureSignalRResource.cs | 15 +- .../AzureSqlExtensions.cs | 39 ++-- .../AzureSqlServerResource.cs | 15 +- .../AzureDataLakeStorageResource.cs | 11 +- .../AzureTableStorageResource.cs | 14 +- .../AzureWebPubSubExtensions.cs | 21 +- .../AzureWebPubSubResource.cs | 15 +- .../AzurePrivateEndpointLockdownTests.cs | 185 ++++++++++++++++++ ...zureStoragePrivateEndpointLockdownTests.cs | 39 ++++ ...vironmentWorksWithSqlServer.verified.bicep | 2 + ...e_NoAccessKeyAuthentication.verified.bicep | 4 +- ...ntication_kvName=mykeyvault.verified.bicep | 4 +- ...yAuthentication_kvName=null.verified.bicep | 4 +- ...ishMode_WithDefaultAzureSku.verified.bicep | 4 +- ...e_NoAccessKeyAuthentication.verified.bicep | 4 +- ...ntication_kvName=mykeyvault.verified.bicep | 4 +- ...yAuthentication_kvName=null.verified.bicep | 4 +- ..._useAcaInfrastructure=False.verified.bicep | 4 +- ...B_useAcaInfrastructure=True.verified.bicep | 4 +- ...ccessKeyAuth_ChildResources.verified.bicep | 4 +- ...tHubAndConsumerGroupName#00.verified.bicep | 3 + ...ddKeyVaultViaPublishMode#00.verified.bicep | 4 +- ...Tests.AddKeyVaultViaRunMode.verified.bicep | 4 +- ...crets_GeneratesCorrectBicep.verified.bicep | 4 +- ...ource_GeneratesCorrectBicep.verified.bicep | 4 +- ...ssion_GeneratesCorrectBicep.verified.bicep | 4 +- ...ntication_kvName=mykeyvault.verified.bicep | 2 + ...yAuthentication_kvName=null.verified.bicep | 2 + ...eAcaInfrastructure=False#00.verified.bicep | 2 + ...seAcaInfrastructure=True#00.verified.bicep | 2 + ...eAcaInfrastructure=False#00.verified.bicep | 2 + ...seAcaInfrastructure=True#00.verified.bicep | 2 + ...eAcaInfrastructure=False#00.verified.bicep | 2 + ...ord=False_kvName=mykeyvault.verified.bicep | 2 + ...yPassword=False_kvName=null.verified.bicep | 2 + ...word=True_kvName=mykeyvault.verified.bicep | 2 + ...fyPassword=True_kvName=null.verified.bicep | 2 + ...ord=False_kvName=mykeyvault.verified.bicep | 2 + ...yPassword=False_kvName=null.verified.bicep | 2 + ...word=True_kvName=mykeyvault.verified.bicep | 2 + ...fyPassword=True_kvName=null.verified.bicep | 2 + ...point_GeneratesCorrectBicep.verified.bicep | 23 +++ ...point_GeneratesCorrectBicep.verified.bicep | 36 ++++ ...point_GeneratesCorrectBicep.verified.bicep | 27 +++ ...point_GeneratesCorrectBicep.verified.bicep | 25 +++ ...point_GeneratesCorrectBicep.verified.bicep | 31 +++ ...point_GeneratesCorrectBicep.verified.bicep | 43 ++++ ...point_GeneratesCorrectBicep.verified.bicep | 28 +++ ...point_GeneratesCorrectBicep.verified.bicep | 27 +++ ...point_GeneratesCorrectBicep.verified.bicep | 36 ++++ ...point_GeneratesCorrectBicep.verified.bicep | 35 ++++ ...point_GeneratesCorrectBicep.verified.bicep | 28 +++ ...ceOptionsCanBeConfigured#00.verified.bicep | 3 + ...ceOptionsCanBeConfigured#01.verified.bicep | 2 + ...ensionsTests.AddAzureSearch.verified.bicep | 4 +- ...us_useObsoleteMethods=False.verified.bicep | 3 + ...Bus_useObsoleteMethods=True.verified.bicep | 3 + ...anBeDifferentThanAzureNames.verified.bicep | 3 + ...24_useObsoleteMethods=False.verified.bicep | 3 + ...n24_useObsoleteMethods=True.verified.bicep | 3 + ...onsTests.AddAzureSignalR#00.verified.bicep | 4 +- ...ddServerlessAzureSignalR#00.verified.bicep | 4 +- ..._useAcaInfrastructure=False.verified.bicep | 2 + ...e_useAcaInfrastructure=True.verified.bicep | 2 + ..._useAcaInfrastructure=False.verified.bicep | 2 + ...reSqlDatabaseViaPublishMode.verified.bicep | 2 + ...sAzureSqlDatabaseViaRunMode.verified.bicep | 2 + ...point_GeneratesCorrectBicep.verified.bicep | 36 ++++ ...point_GeneratesCorrectBicep.verified.bicep | 36 ++++ ...ddAzureWebPubSubHubSettings.verified.bicep | 4 +- ...EventHandlerExpressionWorks.verified.bicep | 4 +- ...s.AddAzureWebPubSubHubWorks.verified.bicep | 4 +- ...zureWebPubSubWithParameters.verified.bicep | 4 +- ...ts.AddDefaultAzureWebPubSub.verified.bicep | 4 +- ...ddWebPubSubWithHubConfigure.verified.bicep | 4 +- ...uctOverridesAddEventHandler.verified.bicep | 4 +- ...zureServiceBusInPublishMode.verified.bicep | 2 + ...ingAzureServiceBusInRunMode.verified.bicep | 2 + ...lishAsExistingInPublishMode.verified.bicep | 3 + ...figurationWithResourceGroup.verified.bicep | 4 +- ...reCosmosDBWithResourceGroup.verified.bicep | 2 + ...BWithResourceGroupAccessKey.verified.bicep | 4 +- ...EnterpriseWithResourceGroup.verified.bicep | 2 + ...sourceGroupAndAccessKeyAuth.verified.bicep | 2 + ...zureSearchWithResourceGroup.verified.bicep | 2 + ...ureSignalRWithResourceGroup.verified.bicep | 4 +- ...tingAzureSqlServerInRunMode.verified.bicep | 2 + ...eSqlServerWithResourceGroup.verified.bicep | 2 + ...eWebPubSubWithResourceGroup.verified.bicep | 4 +- ...gEventHubsWithResourceGroup.verified.bicep | 2 + ...ngKeyVaultWithResourceGroup.verified.bicep | 4 +- ...ostgresSqlWithResourceGroup.verified.bicep | 2 + ...sourceGroupWithPasswordAuth.verified.bicep | 2 + ...sourceGroupInPublishMode#00.verified.bicep | 2 + ...rviceBusWithStaticArguments.verified.bicep | 2 + 112 files changed, 1310 insertions(+), 163 deletions(-) create mode 100644 tests/Aspire.Hosting.Azure.Tests/AzurePrivateEndpointLockdownTests.cs create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureAppConfiguration_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureCosmosDB_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureEventHubs_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureKeyVault_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureManagedRedis_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzurePostgresFlexibleServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSearch_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureServiceBus_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSignalR_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSqlServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureWebPubSub_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithDataLakePrivateEndpoint_GeneratesCorrectBicep.verified.bicep create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithTablePrivateEndpoint_GeneratesCorrectBicep.verified.bicep diff --git a/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationExtensions.cs b/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationExtensions.cs index 9ad605bcc5f..60649e25038 100644 --- a/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationExtensions.cs +++ b/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Aspire.Hosting.Azure.AppConfiguration; @@ -36,6 +38,11 @@ public static IResourceBuilder AddAzureAppConfigu var configureInfrastructure = (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureAppConfigurationResource)infrastructure.AspireResource; + + // Check if this App Configuration has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var store = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -43,17 +50,31 @@ public static IResourceBuilder AddAzureAppConfigu resource.Name = name; return resource; }, - (infrastructure) => new AppConfigurationStore(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - SkuName = "standard", - DisableLocalAuth = true, - Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + var appConfig = new AppConfigurationStore(infrastructure.AspireResource.GetBicepIdentifier()) + { + SkuName = "standard", + DisableLocalAuth = true, + Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + appConfig.PublicNetworkAccess = AppConfigurationPublicNetworkAccess.Disabled; + } + + return appConfig; }); infrastructure.Add(new ProvisioningOutput("appConfigEndpoint", typeof(string)) { Value = store.Endpoint.ToBicepExpression() }); // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = store.Name.ToBicepExpression() }); + + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = store.Id.ToBicepExpression() }); }; var resource = new AzureAppConfigurationResource(name, configureInfrastructure); diff --git a/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationResource.cs b/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationResource.cs index 8f18944f71f..b3e11a7c663 100644 --- a/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationResource.cs +++ b/src/Aspire.Hosting.Azure.AppConfiguration/AzureAppConfigurationResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning.AppConfiguration; using Azure.Provisioning.Primitives; @@ -14,7 +16,7 @@ namespace Aspire.Hosting.Azure; /// Callback to configure the Azure resources. public class AzureAppConfigurationResource(string name, Action configureInfrastructure) : AzureProvisioningResource(name, configureInfrastructure), - IResourceWithConnectionString, IResourceWithEndpoints + IResourceWithConnectionString, IResourceWithEndpoints, IAzurePrivateEndpointTarget { private EndpointReference EmulatorEndpoint => new(this, "emulator"); @@ -33,6 +35,11 @@ public class AzureAppConfigurationResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the connection string template for the manifest for the Azure App Configuration resource. /// @@ -69,4 +76,10 @@ public override ProvisionableResource AddAsExistingResource(AzureResourceInfrast infra.Add(store); return store; } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["configurationStores"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.azconfig.io"; } diff --git a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs index 42d1adfaa80..f67a41291d4 100644 --- a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs +++ b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics.CodeAnalysis; using System.Globalization; using Aspire.Hosting; @@ -454,6 +456,9 @@ private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure var azureResource = (AzureCosmosDBResource)infrastructure.AspireResource; bool disableLocalAuth = !azureResource.UseAccessKeyAuthentication; + // Check if this CosmosDB has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var cosmosAccount = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -461,28 +466,39 @@ private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure resource.Name = name; return resource; }, - (infrastructure) => new CosmosDBAccount(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - Kind = CosmosDBAccountKind.GlobalDocumentDB, - Capabilities = azureResource.UseDefaultAzureSku ? [] : new BicepList - { - new CosmosDBAccountCapability { Name = CosmosConstants.EnableServerlessCapability } - }, - ConsistencyPolicy = new ConsistencyPolicy() - { - DefaultConsistencyLevel = DefaultConsistencyLevel.Session - }, - DatabaseAccountOfferType = CosmosDBAccountOfferType.Standard, - Locations = + var account = new CosmosDBAccount(infrastructure.AspireResource.GetBicepIdentifier()) { - new CosmosDBAccountLocation + Kind = CosmosDBAccountKind.GlobalDocumentDB, + Capabilities = azureResource.UseDefaultAzureSku ? [] : new BicepList { - LocationName = new IdentifierExpression("location"), - FailoverPriority = 0 - } - }, - DisableLocalAuth = disableLocalAuth, - Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + new CosmosDBAccountCapability { Name = CosmosConstants.EnableServerlessCapability } + }, + ConsistencyPolicy = new ConsistencyPolicy() + { + DefaultConsistencyLevel = DefaultConsistencyLevel.Session + }, + DatabaseAccountOfferType = CosmosDBAccountOfferType.Standard, + Locations = + { + new CosmosDBAccountLocation + { + LocationName = new IdentifierExpression("location"), + FailoverPriority = 0 + } + }, + DisableLocalAuth = disableLocalAuth, + Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + account.PublicNetworkAccess = CosmosDBPublicNetworkAccess.Disabled; + } + + return account; }); foreach (var database in azureResource.Databases) @@ -594,6 +610,9 @@ private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = cosmosAccount.Name.ToBicepExpression() }); + + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = cosmosAccount.Id.ToBicepExpression() }); } internal static void AddContributorRoleAssignment(AzureResourceInfrastructure infra, CosmosDBAccount cosmosAccount, BicepValue principalId) diff --git a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs index ca6ba6fccf8..54ecaed01a3 100644 --- a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs +++ b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; @@ -18,7 +20,8 @@ public class AzureCosmosDBResource(string name, Action Databases { get; } = []; @@ -66,6 +69,11 @@ public class AzureCosmosDBResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets a value indicating whether the resource uses access key authentication. /// @@ -251,4 +259,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("ConnectionString", ConnectionStringExpression); } } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["Sql"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.documents.azure.com"; } diff --git a/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsExtensions.cs b/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsExtensions.cs index 148e28546c1..a8534721741 100644 --- a/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsExtensions.cs +++ b/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Text; using System.Text.Json; using System.Text.Json.Nodes; @@ -45,6 +47,11 @@ public static IResourceBuilder AddAzureEventHubs( var configureInfrastructure = static (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureEventHubsResource)infrastructure.AspireResource; + + // Check if this Event Hubs has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var eventHubsNamespace = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -67,6 +74,10 @@ public static IResourceBuilder AddAzureEventHubs( { Name = skuParameter }, + // When using private endpoints, disable public network access. + PublicNetworkAccess = hasPrivateEndpoint + ? AzureProvisioning.EventHubsPublicNetworkAccess.Disabled + : AzureProvisioning.EventHubsPublicNetworkAccess.Enabled, Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } }; return resource; @@ -92,7 +103,8 @@ public static IResourceBuilder AddAzureEventHubs( // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = eventHubsNamespace.Name.ToBicepExpression() }); - var azureResource = (AzureEventHubsResource)infrastructure.AspireResource; + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = eventHubsNamespace.Id.ToBicepExpression() }); foreach (var hub in azureResource.Hubs) { diff --git a/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsResource.cs b/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsResource.cs index 41c6af1f7d5..d41cf08fe33 100644 --- a/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsResource.cs +++ b/src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning.EventHubs; using Azure.Provisioning.Primitives; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// Callback to configure the Azure Event Hubs resource. public class AzureEventHubsResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithEndpoints, IResourceWithAzureFunctionsConfig + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithEndpoints, IResourceWithAzureFunctionsConfig, IAzurePrivateEndpointTarget { private static readonly string[] s_eventHubClientNames = [ @@ -43,6 +45,11 @@ public class AzureEventHubsResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + internal EndpointReference EmulatorEndpoint => new(this, "emulator"); /// @@ -205,4 +212,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("ConnectionString", ReferenceExpression.Create($"Endpoint={EmulatorEndpoint.Property(EndpointProperty.HostAndPort)};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true")); } } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["namespace"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.servicebus.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResource.cs b/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResource.cs index 2fc502be765..c070dd76ba0 100644 --- a/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResource.cs +++ b/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning.KeyVault; using Azure.Provisioning.Primitives; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// Callback to configure the Azure resources. public class AzureKeyVaultResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithEndpoints, IResourceWithConnectionString, IAzureKeyVaultResource + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithEndpoints, IResourceWithConnectionString, IAzureKeyVaultResource, IAzurePrivateEndpointTarget { /// /// The secrets for this Key Vault. @@ -29,6 +31,11 @@ public class AzureKeyVaultResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the Azure Key Vault resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets a value indicating whether the Azure Key Vault resource is running in the local emulator. /// @@ -139,4 +146,10 @@ IEnumerable> IResourceWithConnectionSt { yield return new("Uri", UriExpression); } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["vault"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.vaultcore.azure.net"; } diff --git a/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResourceExtensions.cs b/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResourceExtensions.cs index cb30d4e06e9..b6bdd58c277 100644 --- a/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResourceExtensions.cs +++ b/src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResourceExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Azure.Provisioning; @@ -65,6 +67,11 @@ public static IResourceBuilder AddAzureKeyVault(this IDis var configureInfrastructure = static (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureKeyVaultResource)infrastructure.AspireResource; + + // Check if this Key Vault has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var keyVault = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -72,19 +79,30 @@ public static IResourceBuilder AddAzureKeyVault(this IDis resource.Name = name; return resource; }, - (infrastructure) => new KeyVaultService(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - Properties = new KeyVaultProperties() + var kv = new KeyVaultService(infrastructure.AspireResource.GetBicepIdentifier()) { - TenantId = BicepFunction.GetTenant().TenantId, - Sku = new KeyVaultSku() + Properties = new KeyVaultProperties() { - Family = KeyVaultSkuFamily.A, - Name = KeyVaultSkuName.Standard + TenantId = BicepFunction.GetTenant().TenantId, + Sku = new KeyVaultSku() + { + Family = KeyVaultSkuFamily.A, + Name = KeyVaultSkuName.Standard + }, + EnableRbacAuthorization = true, }, - EnableRbacAuthorization = true, - }, - Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + kv.Properties.PublicNetworkAccess = "Disabled"; + } + + return kv; }); infrastructure.Add(new ProvisioningOutput("vaultUri", typeof(string)) @@ -93,31 +111,31 @@ public static IResourceBuilder AddAzureKeyVault(this IDis }); // Process all secret resources - if (infrastructure.AspireResource is AzureKeyVaultResource kvResource) + foreach (var secretResource in azureResource.Secrets) { - foreach (var secretResource in kvResource.Secrets) - { - var value = secretResource.Value as IManifestExpressionProvider ?? throw new NotSupportedException( - $"Secret value for '{secretResource.SecretName}' is an unsupported type."); + var value = secretResource.Value as IManifestExpressionProvider ?? throw new NotSupportedException( + $"Secret value for '{secretResource.SecretName}' is an unsupported type."); - var paramValue = value.AsProvisioningParameter(infrastructure, isSecure: true); + var paramValue = value.AsProvisioningParameter(infrastructure, isSecure: true); - var secret = new KeyVaultSecret(Infrastructure.NormalizeBicepIdentifier($"secret_{secretResource.SecretName}")) + var secret = new KeyVaultSecret(Infrastructure.NormalizeBicepIdentifier($"secret_{secretResource.SecretName}")) + { + Name = secretResource.SecretName, + Properties = new SecretProperties { - Name = secretResource.SecretName, - Properties = new SecretProperties - { - Value = paramValue - }, - Parent = keyVault, - }; + Value = paramValue + }, + Parent = keyVault, + }; - infrastructure.Add(secret); - } + infrastructure.Add(secret); } // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = keyVault.Name.ToBicepExpression() }); + + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = keyVault.Id.ToBicepExpression() }); }; var resource = new AzureKeyVaultResource(name, configureInfrastructure); diff --git a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs index 16b581cc253..81d871c3c9e 100644 --- a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs +++ b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics.CodeAnalysis; using System.Net; using Aspire.Hosting.ApplicationModel; @@ -401,6 +403,11 @@ public static IResourceBuilder With private static PostgreSqlFlexibleServer CreatePostgreSqlFlexibleServer(AzureResourceInfrastructure infrastructure, IDistributedApplicationBuilder distributedApplicationBuilder, IReadOnlyDictionary databases) { + var azureResource = (AzurePostgresFlexibleServerResource)infrastructure.AspireResource; + + // Check if this PostgreSQL server has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var postgres = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -408,47 +415,65 @@ private static PostgreSqlFlexibleServer CreatePostgreSqlFlexibleServer(AzureReso resource.Name = name; return resource; }, - (infrastructure) => new PostgreSqlFlexibleServer(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - StorageSizeInGB = 32, - Sku = new PostgreSqlFlexibleServerSku() - { - Name = "Standard_B1ms", - Tier = PostgreSqlFlexibleServerSkuTier.Burstable - }, - Version = new StringLiteralExpression("16"), - HighAvailability = new PostgreSqlFlexibleServerHighAvailability() + var server = new PostgreSqlFlexibleServer(infrastructure.AspireResource.GetBicepIdentifier()) { - Mode = PostgreSqlFlexibleServerHighAvailabilityMode.Disabled - }, - Backup = new PostgreSqlFlexibleServerBackupProperties() + StorageSizeInGB = 32, + Sku = new PostgreSqlFlexibleServerSku() + { + Name = "Standard_B1ms", + Tier = PostgreSqlFlexibleServerSkuTier.Burstable + }, + Version = new StringLiteralExpression("16"), + HighAvailability = new PostgreSqlFlexibleServerHighAvailability() + { + Mode = PostgreSqlFlexibleServerHighAvailabilityMode.Disabled + }, + Backup = new PostgreSqlFlexibleServerBackupProperties() + { + BackupRetentionDays = 7, + GeoRedundantBackup = PostgreSqlFlexibleServerGeoRedundantBackupEnum.Disabled + }, + AvailabilityZone = "1", + Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) { - BackupRetentionDays = 7, - GeoRedundantBackup = PostgreSqlFlexibleServerGeoRedundantBackupEnum.Disabled - }, - AvailabilityZone = "1", - Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } - }); + server.Network = new PostgreSqlFlexibleServerNetwork() + { + PublicNetworkAccess = PostgreSqlFlexibleServerPublicNetworkAccessState.Disabled + }; + } - // Opens access to all Azure services. - infrastructure.Add(new PostgreSqlFlexibleServerFirewallRule("postgreSqlFirewallRule_AllowAllAzureIps") - { - Parent = postgres, - Name = "AllowAllAzureIps", - StartIPAddress = new IPAddress([0, 0, 0, 0]), - EndIPAddress = new IPAddress([0, 0, 0, 0]) - }); + return server; + }); - if (distributedApplicationBuilder.ExecutionContext.IsRunMode) + // Only add firewall rules when not using private endpoints + if (!hasPrivateEndpoint) { - // Opens access to the Internet. - infrastructure.Add(new PostgreSqlFlexibleServerFirewallRule("postgreSqlFirewallRule_AllowAllIps") + // Opens access to all Azure services. + infrastructure.Add(new PostgreSqlFlexibleServerFirewallRule("postgreSqlFirewallRule_AllowAllAzureIps") { Parent = postgres, - Name = "AllowAllIps", + Name = "AllowAllAzureIps", StartIPAddress = new IPAddress([0, 0, 0, 0]), - EndIPAddress = new IPAddress([255, 255, 255, 255]) + EndIPAddress = new IPAddress([0, 0, 0, 0]) }); + + if (distributedApplicationBuilder.ExecutionContext.IsRunMode) + { + // Opens access to the Internet. + infrastructure.Add(new PostgreSqlFlexibleServerFirewallRule("postgreSqlFirewallRule_AllowAllIps") + { + Parent = postgres, + Name = "AllowAllIps", + StartIPAddress = new IPAddress([0, 0, 0, 0]), + EndIPAddress = new IPAddress([255, 255, 255, 255]) + }); + } } foreach (var databaseNames in databases) @@ -546,6 +571,9 @@ private static void ConfigurePostgreSqlInfrastructure(AzureResourceInfrastructur // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = postgres.Name.ToBicepExpression() }); + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = postgres.Id.ToBicepExpression() }); + // Always output the hostName for the PostgreSQL server. infrastructure.Add(new ProvisioningOutput("hostName", typeof(string)) { Value = postgres.FullyQualifiedDomainName.ToBicepExpression() }); } diff --git a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresFlexibleServerResource.cs b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresFlexibleServerResource.cs index 67729fd1858..ee53b338bb7 100644 --- a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresFlexibleServerResource.cs +++ b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresFlexibleServerResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; @@ -17,7 +19,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// Callback to configure infrastructure. public class AzurePostgresFlexibleServerResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithEndpoints, IResourceWithConnectionString + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithEndpoints, IResourceWithConnectionString, IAzurePrivateEndpointTarget { private readonly Dictionary _databases = new Dictionary(StringComparers.ResourceName); @@ -40,6 +42,11 @@ public class AzurePostgresFlexibleServerResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the "hostName" output reference from the bicep template for the Azure Postgres Flexible Server. /// @@ -306,4 +313,10 @@ IEnumerable> IResourceWithConnectionSt return propertiesDictionary; } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["postgresqlServer"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.postgres.database.azure.com"; } diff --git a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisExtensions.cs b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisExtensions.cs index c243fd4d5f6..b540998e385 100644 --- a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisExtensions.cs +++ b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Azure.Provisioning; @@ -178,6 +180,9 @@ private static void ConfigureRedisInfrastructure(AzureResourceInfrastructure inf { var redisResource = (AzureManagedRedisResource)infrastructure.AspireResource; + // Check if this Redis has a private endpoint (via annotation) + var hasPrivateEndpoint = redisResource.HasAnnotationOfType(); + var redis = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -194,7 +199,10 @@ private static void ConfigureRedisInfrastructure(AzureResourceInfrastructure inf Name = RedisEnterpriseSkuName.BalancedB0 }, MinimumTlsVersion = RedisEnterpriseTlsVersion.Tls1_2, - PublicNetworkAccess = RedisEnterprisePublicNetworkAccess.Enabled + // When using private endpoints, disable public network access. + PublicNetworkAccess = hasPrivateEndpoint + ? RedisEnterprisePublicNetworkAccess.Disabled + : RedisEnterprisePublicNetworkAccess.Enabled }; infra.Add(cluster); @@ -267,6 +275,9 @@ private static void ConfigureRedisInfrastructure(AzureResourceInfrastructure inf // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = redis.Name.ToBicepExpression() }); + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = redis.Id.ToBicepExpression() }); + // Always output the hostName for the Redis server. infrastructure.Add(new ProvisioningOutput("hostName", typeof(string)) { Value = redis.HostName.ToBicepExpression() }); } diff --git a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs index 8cad266015b..d25738ed43f 100644 --- a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs +++ b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; @@ -17,7 +19,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// Callback to configure the Azure resources. public class AzureManagedRedisResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IAzurePrivateEndpointTarget { /// /// Gets the "connectionString" output reference from the bicep template for the Azure Managed Redis resource. @@ -45,6 +47,11 @@ public class AzureManagedRedisResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the "hostName" output reference from the bicep template for the Azure Redis resource. /// @@ -240,4 +247,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("Password", Password); } } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["redisEnterprise"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.redisenterprise.cache.azure.net"; } diff --git a/src/Aspire.Hosting.Azure.Search/AzureSearchExtensions.cs b/src/Aspire.Hosting.Azure.Search/AzureSearchExtensions.cs index 9f7fd41d1e8..86a688b3838 100644 --- a/src/Aspire.Hosting.Azure.Search/AzureSearchExtensions.cs +++ b/src/Aspire.Hosting.Azure.Search/AzureSearchExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Azure.Provisioning; @@ -43,6 +45,11 @@ public static IResourceBuilder AddAzureSearch(this IDistrib void ConfigureSearch(AzureResourceInfrastructure infrastructure) { + var azureResource = (AzureSearchResource)infrastructure.AspireResource; + + // Check if this Search service has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var search = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -50,14 +57,25 @@ void ConfigureSearch(AzureResourceInfrastructure infrastructure) resource.Name = name; return resource; }, - (infrastructure) => new SearchService(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - SearchSkuName = SearchServiceSkuName.Basic, - ReplicaCount = 1, - PartitionCount = 1, - HostingMode = SearchServiceHostingMode.Default, - IsLocalAuthDisabled = true, - Tags = { { "aspire-resource-name", name } } + var svc = new SearchService(infrastructure.AspireResource.GetBicepIdentifier()) + { + SearchSkuName = SearchServiceSkuName.Basic, + ReplicaCount = 1, + PartitionCount = 1, + HostingMode = SearchServiceHostingMode.Default, + IsLocalAuthDisabled = true, + Tags = { { "aspire-resource-name", name } } + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + svc.PublicNetworkAccess = SearchServicePublicNetworkAccess.Disabled; + } + + return svc; }); // TODO: The endpoint format should move into Azure.Provisioning so we can maintain this @@ -75,6 +93,9 @@ void ConfigureSearch(AzureResourceInfrastructure infrastructure) // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = search.Name.ToBicepExpression() }); + + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = search.Id.ToBicepExpression() }); } } diff --git a/src/Aspire.Hosting.Azure.Search/AzureSearchResource.cs b/src/Aspire.Hosting.Azure.Search/AzureSearchResource.cs index 9a439d0616a..b607946d586 100644 --- a/src/Aspire.Hosting.Azure.Search/AzureSearchResource.cs +++ b/src/Aspire.Hosting.Azure.Search/AzureSearchResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning.Primitives; using Azure.Provisioning.Search; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource /// Callback to configure the Azure AI Search resource. public class AzureSearchResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IAzurePrivateEndpointTarget { /// /// Gets the "connectionString" output reference from the Azure AI Search resource. @@ -28,6 +30,11 @@ public class AzureSearchResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the service endpoint URI expression for the Azure AI Search resource. /// @@ -83,4 +90,10 @@ IEnumerable> IResourceWithConnectionSt { yield return new("Uri", UriExpression); } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["searchService"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.search.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusExtensions.cs b/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusExtensions.cs index db495738f8d..9699d2668d5 100644 --- a/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusExtensions.cs +++ b/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Text; using System.Text.Json; using System.Text.Json.Nodes; @@ -44,6 +46,11 @@ public static IResourceBuilder AddAzureServiceBus(this var configureInfrastructure = static (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureServiceBusResource)infrastructure.AspireResource; + + // Check if this Service Bus has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + AzureProvisioning.ServiceBusNamespace serviceBusNamespace = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -65,6 +72,10 @@ public static IResourceBuilder AddAzureServiceBus(this Name = skuParameter }, DisableLocalAuth = true, + // When using private endpoints, disable public network access. + PublicNetworkAccess = hasPrivateEndpoint + ? AzureProvisioning.ServiceBusPublicNetworkAccess.Disabled + : AzureProvisioning.ServiceBusPublicNetworkAccess.Enabled, Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } }; return resource; @@ -90,7 +101,8 @@ public static IResourceBuilder AddAzureServiceBus(this // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = serviceBusNamespace.Name.ToBicepExpression() }); - var azureResource = (AzureServiceBusResource)infrastructure.AspireResource; + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = serviceBusNamespace.Id.ToBicepExpression() }); foreach (var queue in azureResource.Queues) { diff --git a/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusResource.cs b/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusResource.cs index b04b9546858..332feb78b66 100644 --- a/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusResource.cs +++ b/src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning.Primitives; using Azure.Provisioning.ServiceBus; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// Callback to configure the Azure Service Bus resource. public class AzureServiceBusResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithAzureFunctionsConfig, IResourceWithEndpoints + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithAzureFunctionsConfig, IResourceWithEndpoints, IAzurePrivateEndpointTarget { internal List Queues { get; } = []; internal List Topics { get; } = []; @@ -33,6 +35,11 @@ public class AzureServiceBusResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + internal EndpointReference EmulatorEndpoint => new(this, "emulator"); /// @@ -185,4 +192,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("ConnectionString", ConnectionStringExpression); } } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["namespace"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.servicebus.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs b/src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs index 30b3118f549..ebcc31ef56c 100644 --- a/src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs +++ b/src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Aspire.Hosting.Azure.SignalR; @@ -59,6 +61,11 @@ public static IResourceBuilder AddAzureSignalR(this IDistr var configureInfrastructure = (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureSignalRResource)infrastructure.AspireResource; + + // Check if this SignalR service has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var service = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { var resource = SignalRService.FromExisting(identifier); @@ -66,31 +73,45 @@ public static IResourceBuilder AddAzureSignalR(this IDistr return resource; }, - (infrastructure) => new SignalRService(infrastructure.AspireResource.GetBicepIdentifier()) + (infrastructure) => { - Kind = SignalRServiceKind.SignalR, - Sku = new SignalRResourceSku() + var svc = new SignalRService(infrastructure.AspireResource.GetBicepIdentifier()) { - Name = "Free_F1", - Capacity = 1 - }, - Features = - [ - new SignalRFeature() + Kind = SignalRServiceKind.SignalR, + Sku = new SignalRResourceSku() { - Flag = SignalRFeatureFlag.ServiceMode, - Value = serviceMode.ToString() - } - ], - CorsAllowedOrigins = ["*"], - Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }, - DisableLocalAuth = true, + Name = "Free_F1", + Capacity = 1 + }, + Features = + [ + new SignalRFeature() + { + Flag = SignalRFeatureFlag.ServiceMode, + Value = serviceMode.ToString() + } + ], + CorsAllowedOrigins = ["*"], + Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }, + DisableLocalAuth = true, + }; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + svc.PublicNetworkAccess = "Disabled"; + } + + return svc; }); infrastructure.Add(new ProvisioningOutput("hostName", typeof(string)) { Value = service.HostName.ToBicepExpression() }); // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = service.Name.ToBicepExpression() }); + + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = service.Id.ToBicepExpression() }); }; List defaultRoles = [SignalRBuiltInRole.SignalRAppServer]; diff --git a/src/Aspire.Hosting.Azure.SignalR/AzureSignalRResource.cs b/src/Aspire.Hosting.Azure.SignalR/AzureSignalRResource.cs index 1f4051a158d..a38431efde0 100644 --- a/src/Aspire.Hosting.Azure.SignalR/AzureSignalRResource.cs +++ b/src/Aspire.Hosting.Azure.SignalR/AzureSignalRResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.Azure; using Azure.Provisioning.Primitives; using Azure.Provisioning.SignalR; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.ApplicationModel; /// The name of the resource. /// Callback to configure the Azure resources. public class AzureSignalRResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithEndpoints + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IResourceWithEndpoints, IAzurePrivateEndpointTarget { internal EndpointReference EmulatorEndpoint => new(this, "emulator"); @@ -32,6 +34,11 @@ public class AzureSignalRResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the endpoint URI expression for the SignalR service. /// @@ -86,4 +93,10 @@ IEnumerable> IResourceWithConnectionSt { yield return new("Uri", UriExpression); } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["signalr"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.service.signalr.net"; } diff --git a/src/Aspire.Hosting.Azure.Sql/AzureSqlExtensions.cs b/src/Aspire.Hosting.Azure.Sql/AzureSqlExtensions.cs index 6015a2478bb..02860e5ea08 100644 --- a/src/Aspire.Hosting.Azure.Sql/AzureSqlExtensions.cs +++ b/src/Aspire.Hosting.Azure.Sql/AzureSqlExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Azure.Provisioning; @@ -271,6 +273,9 @@ private static SqlServer CreateSqlServerResourceOnly(AzureResourceInfrastructure { var azureResource = (AzureSqlServerResource)infrastructure.AspireResource; + // Check if this SQL Server has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var sqlServer = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => @@ -302,29 +307,34 @@ private static SqlServer CreateSqlServerResourceOnly(AzureResourceInfrastructure TenantId = BicepFunction.GetSubscription().TenantId }, Version = "12.0", - PublicNetworkAccess = ServerNetworkAccessFlag.Enabled, + // When using private endpoints, disable public network access. + PublicNetworkAccess = hasPrivateEndpoint ? ServerNetworkAccessFlag.Disabled : ServerNetworkAccessFlag.Enabled, MinTlsVersion = SqlMinimalTlsVersion.Tls1_2, Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } }; }); - infrastructure.Add(new SqlFirewallRule("sqlFirewallRule_AllowAllAzureIps") - { - Parent = sqlServer, - Name = "AllowAllAzureIps", - StartIPAddress = "0.0.0.0", - EndIPAddress = "0.0.0.0" - }); - - if (distributedApplicationBuilder.ExecutionContext.IsRunMode) + // Only add firewall rules when not using private endpoints + if (!hasPrivateEndpoint) { - infrastructure.Add(new SqlFirewallRule("sqlFirewallRule_AllowAllIps") + infrastructure.Add(new SqlFirewallRule("sqlFirewallRule_AllowAllAzureIps") { Parent = sqlServer, - Name = "AllowAllIps", + Name = "AllowAllAzureIps", StartIPAddress = "0.0.0.0", - EndIPAddress = "255.255.255.255" + EndIPAddress = "0.0.0.0" }); + + if (distributedApplicationBuilder.ExecutionContext.IsRunMode) + { + infrastructure.Add(new SqlFirewallRule("sqlFirewallRule_AllowAllIps") + { + Parent = sqlServer, + Name = "AllowAllIps", + StartIPAddress = "0.0.0.0", + EndIPAddress = "255.255.255.255" + }); + } } infrastructure.Add(new ProvisioningOutput("sqlServerFqdn", typeof(string)) { Value = sqlServer.FullyQualifiedDomainName.ToBicepExpression() }); @@ -332,6 +342,9 @@ private static SqlServer CreateSqlServerResourceOnly(AzureResourceInfrastructure // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = sqlServer.Name.ToBicepExpression() }); + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = sqlServer.Id.ToBicepExpression() }); + infrastructure.Add(new ProvisioningOutput("sqlServerAdminName", typeof(string)) { Value = sqlServer.Administrators.Login.ToBicepExpression() }); return sqlServer; diff --git a/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs b/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs index 94d578ed391..baf22e07682 100644 --- a/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs +++ b/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; using Azure.Provisioning; @@ -15,7 +17,7 @@ namespace Aspire.Hosting.Azure; /// /// Represents an Azure Sql Server resource. /// -public class AzureSqlServerResource : AzureProvisioningResource, IResourceWithConnectionString +public class AzureSqlServerResource : AzureProvisioningResource, IResourceWithConnectionString, IAzurePrivateEndpointTarget { private readonly Dictionary _databases = new Dictionary(StringComparers.ResourceName); private readonly bool _createdWithInnerResource; @@ -51,6 +53,11 @@ public AzureSqlServerResource(SqlServerServerResource innerResource, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + private BicepOutputReference AdminName => new("sqlServerAdminName", this); /// @@ -324,4 +331,10 @@ IEnumerable> IResourceWithConnectionSt return result; } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["sqlServer"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.database.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.Storage/AzureDataLakeStorageResource.cs b/src/Aspire.Hosting.Azure.Storage/AzureDataLakeStorageResource.cs index 43608d76979..e632379e651 100644 --- a/src/Aspire.Hosting.Azure.Storage/AzureDataLakeStorageResource.cs +++ b/src/Aspire.Hosting.Azure.Storage/AzureDataLakeStorageResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; namespace Aspire.Hosting.Azure; @@ -11,7 +13,8 @@ namespace Aspire.Hosting.Azure; public class AzureDataLakeStorageResource(string name, AzureStorageResource storage) : Resource(name), IResourceWithConnectionString, IResourceWithParent, - IResourceWithAzureFunctionsConfig + IResourceWithAzureFunctionsConfig, + IAzurePrivateEndpointTarget { /// /// Gets the parent AzureStorageResource of this AzureDataLakeResource. @@ -76,4 +79,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("Uri", UriExpression); } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Parent.Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["dfs"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.dfs.core.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.Storage/AzureTableStorageResource.cs b/src/Aspire.Hosting.Azure.Storage/AzureTableStorageResource.cs index 568764bf8f9..b31aa83a7e1 100644 --- a/src/Aspire.Hosting.Azure.Storage/AzureTableStorageResource.cs +++ b/src/Aspire.Hosting.Azure.Storage/AzureTableStorageResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Azure.Provisioning; @@ -12,7 +14,11 @@ namespace Aspire.Hosting.Azure; /// The name of the resource. /// The that the resource is stored in. public class AzureTableStorageResource(string name, AzureStorageResource storage) - : Resource(name), IResourceWithConnectionString, IResourceWithParent, IResourceWithAzureFunctionsConfig + : Resource(name), + IResourceWithConnectionString, + IResourceWithParent, + IResourceWithAzureFunctionsConfig, + IAzurePrivateEndpointTarget { /// /// Gets the parent AzureStorageResource of this AzureTableStorageResource. @@ -69,4 +75,10 @@ IEnumerable> IResourceWithConnectionSt yield return new("ConnectionString", ConnectionStringExpression); } } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Parent.Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["table"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.table.core.windows.net"; } diff --git a/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubExtensions.cs b/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubExtensions.cs index 07d3150960e..0761d3d3952 100644 --- a/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubExtensions.cs +++ b/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Azure.Provisioning; @@ -38,6 +40,11 @@ public static IResourceBuilder AddAzureWebPubSub(this ID var configureInfrastructure = (AzureResourceInfrastructure infrastructure) => { + var azureResource = (AzureWebPubSubResource)infrastructure.AspireResource; + + // Check if this Web PubSub service has a private endpoint (via annotation) + var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var service = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => { @@ -61,7 +68,7 @@ public static IResourceBuilder AddAzureWebPubSub(this ID }; infrastructure.Add(capacityParameter); - var service = new WebPubSubService(infrastructure.AspireResource.GetBicepIdentifier()) + var svc = new WebPubSubService(infrastructure.AspireResource.GetBicepIdentifier()) { IsLocalAuthDisabled = true, Sku = new BillingInfoSku() @@ -71,7 +78,14 @@ public static IResourceBuilder AddAzureWebPubSub(this ID }, Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } } }; - return service; + + // When using private endpoints, disable public network access. + if (hasPrivateEndpoint) + { + svc.PublicNetworkAccess = "Disabled"; + } + + return svc; } ); @@ -80,6 +94,9 @@ public static IResourceBuilder AddAzureWebPubSub(this ID // We need to output name to externalize role assignments. infrastructure.Add(new ProvisioningOutput("name", typeof(string)) { Value = service.Name.ToBicepExpression() }); + // Output the resource id for private endpoint support. + infrastructure.Add(new ProvisioningOutput("id", typeof(string)) { Value = service.Id.ToBicepExpression() }); + var resource = (AzureWebPubSubResource)infrastructure.AspireResource; foreach (var setting in resource.Hubs) { diff --git a/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubResource.cs b/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubResource.cs index afa75ac95d0..6869a8b0cc6 100644 --- a/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubResource.cs +++ b/src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubResource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + using Aspire.Hosting.Azure; using Azure.Provisioning.Primitives; using Azure.Provisioning.WebPubSub; @@ -13,7 +15,7 @@ namespace Aspire.Hosting.ApplicationModel; /// The name of the resource. /// Callback to configure the Azure resources. public class AzureWebPubSubResource(string name, Action configureInfrastructure) - : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString + : AzureProvisioningResource(name, configureInfrastructure), IResourceWithConnectionString, IAzurePrivateEndpointTarget { internal Dictionary Hubs { get; } = new(StringComparer.OrdinalIgnoreCase); @@ -27,6 +29,11 @@ public class AzureWebPubSubResource(string name, Action public BicepOutputReference NameOutputReference => new("name", this); + /// + /// Gets the "id" output reference for the resource. + /// + public BicepOutputReference Id => new("id", this); + /// /// Gets the connection string template for the manifest for Azure Web PubSub. /// @@ -73,4 +80,10 @@ IEnumerable> IResourceWithConnectionSt { yield return new("Uri", UriExpression); } + + BicepOutputReference IAzurePrivateEndpointTarget.Id => Id; + + IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["webpubsub"]; + + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.webpubsub.azure.com"; } diff --git a/tests/Aspire.Hosting.Azure.Tests/AzurePrivateEndpointLockdownTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzurePrivateEndpointLockdownTests.cs new file mode 100644 index 00000000000..2dc611cc090 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/AzurePrivateEndpointLockdownTests.cs @@ -0,0 +1,185 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Hosting.Utils; + +namespace Aspire.Hosting.Azure.Tests; + +public class AzurePrivateEndpointLockdownTests +{ + [Fact] + public async Task AddAzureCosmosDB_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var cosmos = builder.AddAzureCosmosDB("cosmos"); + + subnet.AddPrivateEndpoint(cosmos); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(cosmos.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureSqlServer_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var sql = builder.AddAzureSqlServer("sql"); + + subnet.AddPrivateEndpoint(sql); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(sql.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzurePostgresFlexibleServer_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var postgres = builder.AddAzurePostgresFlexibleServer("postgres"); + + subnet.AddPrivateEndpoint(postgres); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(postgres.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureManagedRedis_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var redis = builder.AddAzureManagedRedis("redis"); + + subnet.AddPrivateEndpoint(redis); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(redis.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureServiceBus_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var serviceBus = builder.AddAzureServiceBus("servicebus"); + + subnet.AddPrivateEndpoint(serviceBus); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(serviceBus.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureEventHubs_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var eventHubs = builder.AddAzureEventHubs("eventhubs"); + + subnet.AddPrivateEndpoint(eventHubs); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(eventHubs.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureKeyVault_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var keyVault = builder.AddAzureKeyVault("keyvault"); + + subnet.AddPrivateEndpoint(keyVault); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(keyVault.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureAppConfiguration_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var appConfig = builder.AddAzureAppConfiguration("appconfig"); + + subnet.AddPrivateEndpoint(appConfig); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(appConfig.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureSearch_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var search = builder.AddAzureSearch("search"); + + subnet.AddPrivateEndpoint(search); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(search.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureSignalR_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var signalR = builder.AddAzureSignalR("signalr"); + + subnet.AddPrivateEndpoint(signalR); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(signalR.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureWebPubSub_WithPrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var webPubSub = builder.AddAzureWebPubSub("webpubsub"); + + subnet.AddPrivateEndpoint(webPubSub); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(webPubSub.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } +} diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureStoragePrivateEndpointLockdownTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureStoragePrivateEndpointLockdownTests.cs index e5b8bfcba07..65bc24e123c 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureStoragePrivateEndpointLockdownTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureStoragePrivateEndpointLockdownTests.cs @@ -51,4 +51,43 @@ public async Task AddAzureStorage_WithPrivateEndpoint_GeneratesCorrectBicep() await Verify(manifest.BicepText, extension: "bicep"); } + + [Fact] + public async Task AddAzureStorage_WithTablePrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var storage = builder.AddAzureStorage("storage"); + var tables = storage.AddTables("tables"); + + subnet.AddPrivateEndpoint(tables); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(storage.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } + + [Fact] + public async Task AddAzureStorage_WithDataLakePrivateEndpoint_GeneratesCorrectBicep() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var vnet = builder.AddAzureVirtualNetwork("myvnet"); + var subnet = vnet.AddSubnet("pesubnet", "10.0.1.0/24"); + var storage = builder.AddAzureStorage("storage").ConfigureInfrastructure(infra => + { + // Need to enable HNS for DataLake + var storageAccount = infra.GetProvisionableResources().OfType().Single(); + storageAccount.IsHnsEnabled = true; + }); + var dataLake = storage.AddDataLake("datalake"); + + subnet.AddPrivateEndpoint(dataLake); + + var manifest = await AzureManifestUtils.GetManifestWithBicep(storage.Resource); + + await Verify(manifest.BicepText, extension: "bicep"); + } } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWorksWithSqlServer.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWorksWithSqlServer.verified.bicep index 0fa2c7ad436..9dd82de2d2b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWorksWithSqlServer.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWorksWithSqlServer.verified.bicep @@ -45,4 +45,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_NoAccessKeyAuthentication.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_NoAccessKeyAuthentication.verified.bicep index cc352c76a17..a2a49b3a54b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_NoAccessKeyAuthentication.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_NoAccessKeyAuthentication.verified.bicep @@ -58,4 +58,6 @@ resource mycontainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/contain output connectionString string = cosmos.properties.documentEndpoint -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep index 2428383be1e..af53e0f8af2 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep @@ -94,4 +94,6 @@ resource mycontainer_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11 parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=null.verified.bicep index cb1e26fc2ba..b2306c81154 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithAccessKeyAuthentication_kvName=null.verified.bicep @@ -94,4 +94,6 @@ resource mycontainer_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11 parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithDefaultAzureSku.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithDefaultAzureSku.verified.bicep index 754aa4d3bd2..148ac47e17b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithDefaultAzureSku.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaPublishMode_WithDefaultAzureSku.verified.bicep @@ -26,4 +26,6 @@ resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-08-15' = { output connectionString string = cosmos.properties.documentEndpoint -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_NoAccessKeyAuthentication.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_NoAccessKeyAuthentication.verified.bicep index cc352c76a17..a2a49b3a54b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_NoAccessKeyAuthentication.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_NoAccessKeyAuthentication.verified.bicep @@ -58,4 +58,6 @@ resource mycontainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/contain output connectionString string = cosmos.properties.documentEndpoint -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep index e973f9850c9..036ef583769 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep @@ -94,4 +94,6 @@ resource container_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-0 parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=null.verified.bicep index c31338c3410..ab0097a0549 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDBViaRunMode_WithAccessKeyAuthentication_kvName=null.verified.bicep @@ -94,4 +94,6 @@ resource container_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-0 parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=False.verified.bicep index dfd64f03eb9..ddbe6722954 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=False.verified.bicep @@ -30,4 +30,6 @@ resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-08-15' = { output connectionString string = cosmos.properties.documentEndpoint -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=True.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=True.verified.bicep index dfd64f03eb9..ddbe6722954 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=True.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDB_useAcaInfrastructure=True.verified.bicep @@ -30,4 +30,6 @@ resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-08-15' = { output connectionString string = cosmos.properties.documentEndpoint -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDatabase_WorksWithAccessKeyAuth_ChildResources.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDatabase_WorksWithAccessKeyAuth_ChildResources.verified.bicep index aafb6a09e69..f34303d2ca2 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDatabase_WorksWithAccessKeyAuth_ChildResources.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureCosmosDBExtensionsTests.AddAzureCosmosDatabase_WorksWithAccessKeyAuth_ChildResources.verified.bicep @@ -94,4 +94,6 @@ resource container1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11- parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEventHubsExtensionsTests.CanSetHubAndConsumerGroupName#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEventHubsExtensionsTests.CanSetHubAndConsumerGroupName#00.verified.bicep index 6a3316b493b..4aa1564bf2a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEventHubsExtensionsTests.CanSetHubAndConsumerGroupName#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEventHubsExtensionsTests.CanSetHubAndConsumerGroupName#00.verified.bicep @@ -8,6 +8,7 @@ resource eh 'Microsoft.EventHub/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -35,3 +36,5 @@ output eventHubsEndpoint string = eh.properties.serviceBusEndpoint output eventHubsHostName string = split(replace(eh.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = eh.name + +output id string = eh.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaPublishMode#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaPublishMode#00.verified.bicep index 4c5b6449df8..2574f26b95d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaPublishMode#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaPublishMode#00.verified.bicep @@ -19,4 +19,6 @@ resource mykv 'Microsoft.KeyVault/vaults@2024-11-01' = { output vaultUri string = mykv.properties.vaultUri -output name string = mykv.name \ No newline at end of file +output name string = mykv.name + +output id string = mykv.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaRunMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaRunMode.verified.bicep index 4c5b6449df8..2574f26b95d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaRunMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddKeyVaultViaRunMode.verified.bicep @@ -19,4 +19,6 @@ resource mykv 'Microsoft.KeyVault/vaults@2024-11-01' = { output vaultUri string = mykv.properties.vaultUri -output name string = mykv.name \ No newline at end of file +output name string = mykv.name + +output id string = mykv.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithMultipleSecrets_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithMultipleSecrets_GeneratesCorrectBicep.verified.bicep index e6f68bbf613..4dfc77de442 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithMultipleSecrets_GeneratesCorrectBicep.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithMultipleSecrets_GeneratesCorrectBicep.verified.bicep @@ -52,4 +52,6 @@ resource secret_connection_string 'Microsoft.KeyVault/vaults/secrets@2024-11-01' output vaultUri string = mykv.properties.vaultUri -output name string = mykv.name \ No newline at end of file +output name string = mykv.name + +output id string = mykv.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithParameterResource_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithParameterResource_GeneratesCorrectBicep.verified.bicep index a581e7e529b..c092396a5cb 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithParameterResource_GeneratesCorrectBicep.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithParameterResource_GeneratesCorrectBicep.verified.bicep @@ -30,4 +30,6 @@ resource secret_my_secret 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output vaultUri string = mykv.properties.vaultUri -output name string = mykv.name \ No newline at end of file +output name string = mykv.name + +output id string = mykv.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithReferenceExpression_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithReferenceExpression_GeneratesCorrectBicep.verified.bicep index 4d9e0409be1..dd54523bb9d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithReferenceExpression_GeneratesCorrectBicep.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureKeyVaultTests.AddSecret_WithReferenceExpression_GeneratesCorrectBicep.verified.bicep @@ -30,4 +30,6 @@ resource secret_connection_string 'Microsoft.KeyVault/vaults/secrets@2024-11-01' output vaultUri string = mykv.properties.vaultUri -output name string = mykv.name \ No newline at end of file +output name string = mykv.name + +output id string = mykv.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep index 11fbde83504..0a5acc18646 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=mykeyvault.verified.bicep @@ -46,4 +46,6 @@ resource primaryAccessKey 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = redis_cache.name +output id string = redis_cache.id + output hostName string = redis_cache.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=null.verified.bicep index f02b16b90cb..ae2d0fdc3bf 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedisWithAccessKeyAuthentication_kvName=null.verified.bicep @@ -46,4 +46,6 @@ resource primaryAccessKey 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = redis_cache.name +output id string = redis_cache.id + output hostName string = redis_cache.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=False#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=False#00.verified.bicep index 939fdb3c2f2..71ed3138d28 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=False#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=False#00.verified.bicep @@ -26,4 +26,6 @@ output connectionString string = '${redis_cache.properties.hostName}:10000,ssl=t output name string = redis_cache.name +output id string = redis_cache.id + output hostName string = redis_cache.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=True#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=True#00.verified.bicep index 939fdb3c2f2..71ed3138d28 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=True#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureManagedRedisExtensionsTests.AddAzureManagedRedis_useAcaInfrastructure=True#00.verified.bicep @@ -26,4 +26,6 @@ output connectionString string = '${redis_cache.properties.hostName}:10000,ssl=t output name string = redis_cache.name +output id string = redis_cache.id + output hostName string = redis_cache.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=False#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=False#00.verified.bicep index 74088ce383f..79f8b981ce9 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=False#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=False#00.verified.bicep @@ -53,4 +53,6 @@ output connectionString string = 'Host=${postgres_data.properties.fullyQualified output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=True#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=True#00.verified.bicep index 74088ce383f..79f8b981ce9 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=True#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=False_useAcaInfrastructure=True#00.verified.bicep @@ -53,4 +53,6 @@ output connectionString string = 'Host=${postgres_data.properties.fullyQualified output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=True_useAcaInfrastructure=False#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=True_useAcaInfrastructure=False#00.verified.bicep index e6febd9521f..0c4a5833ca7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=True_useAcaInfrastructure=False#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresFlexibleServer_publishMode=True_useAcaInfrastructure=False#00.verified.bicep @@ -44,4 +44,6 @@ output connectionString string = 'Host=${postgres_data.properties.fullyQualified output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=mykeyvault.verified.bicep index 436c615bb0a..a062f09759a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=mykeyvault.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=null.verified.bicep index 09303c6281e..d928f1ca208 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=False_kvName=null.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=mykeyvault.verified.bicep index 436c615bb0a..a062f09759a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=mykeyvault.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=null.verified.bicep index 09303c6281e..d928f1ca208 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=False_specifyPassword=True_kvName=null.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=mykeyvault.verified.bicep index 436c615bb0a..a062f09759a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=mykeyvault.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=null.verified.bicep index 09303c6281e..d928f1ca208 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=False_kvName=null.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=mykeyvault.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=mykeyvault.verified.bicep index 436c615bb0a..a062f09759a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=mykeyvault.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=mykeyvault.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=null.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=null.verified.bicep index 09303c6281e..d928f1ca208 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=null.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePostgresExtensionsTests.AddAzurePostgresWithPasswordAuth_specifyUserName=True_specifyPassword=True_kvName=null.verified.bicep @@ -85,4 +85,6 @@ resource db1_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgres_data.name +output id string = postgres_data.id + output hostName string = postgres_data.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureAppConfiguration_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureAppConfiguration_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..cbdce230099 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureAppConfiguration_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,23 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource appconfig 'Microsoft.AppConfiguration/configurationStores@2024-06-01' = { + name: take('appconfig-${uniqueString(resourceGroup().id)}', 50) + location: location + properties: { + disableLocalAuth: true + publicNetworkAccess: 'Disabled' + } + sku: { + name: 'standard' + } + tags: { + 'aspire-resource-name': 'appconfig' + } +} + +output appConfigEndpoint string = appconfig.properties.endpoint + +output name string = appconfig.name + +output id string = appconfig.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureCosmosDB_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureCosmosDB_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..64733bba6cd --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureCosmosDB_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,36 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2024-08-15' = { + name: take('cosmos-${uniqueString(resourceGroup().id)}', 44) + location: location + properties: { + locations: [ + { + locationName: location + failoverPriority: 0 + } + ] + capabilities: [ + { + name: 'EnableServerless' + } + ] + consistencyPolicy: { + defaultConsistencyLevel: 'Session' + } + databaseAccountOfferType: 'Standard' + disableLocalAuth: true + publicNetworkAccess: 'Disabled' + } + kind: 'GlobalDocumentDB' + tags: { + 'aspire-resource-name': 'cosmos' + } +} + +output connectionString string = cosmos.properties.documentEndpoint + +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureEventHubs_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureEventHubs_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..9b9fdfd591c --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureEventHubs_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,27 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param sku string = 'Standard' + +resource eventhubs 'Microsoft.EventHub/namespaces@2024-01-01' = { + name: take('eventhubs-${uniqueString(resourceGroup().id)}', 256) + location: location + properties: { + disableLocalAuth: true + publicNetworkAccess: 'Disabled' + } + sku: { + name: sku + } + tags: { + 'aspire-resource-name': 'eventhubs' + } +} + +output eventHubsEndpoint string = eventhubs.properties.serviceBusEndpoint + +output eventHubsHostName string = split(replace(eventhubs.properties.serviceBusEndpoint, 'https://', ''), ':')[0] + +output name string = eventhubs.name + +output id string = eventhubs.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureKeyVault_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureKeyVault_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..c9876426360 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureKeyVault_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,25 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource keyvault 'Microsoft.KeyVault/vaults@2024-11-01' = { + name: take('keyvault-${uniqueString(resourceGroup().id)}', 24) + location: location + properties: { + tenantId: tenant().tenantId + sku: { + family: 'A' + name: 'standard' + } + enableRbacAuthorization: true + publicNetworkAccess: 'Disabled' + } + tags: { + 'aspire-resource-name': 'keyvault' + } +} + +output vaultUri string = keyvault.properties.vaultUri + +output name string = keyvault.name + +output id string = keyvault.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureManagedRedis_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureManagedRedis_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..2e4c21f4ed1 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureManagedRedis_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,31 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource redis 'Microsoft.Cache/redisEnterprise@2025-07-01' = { + name: take('redis-${uniqueString(resourceGroup().id)}', 60) + location: location + sku: { + name: 'Balanced_B0' + } + properties: { + minimumTlsVersion: '1.2' + publicNetworkAccess: 'Disabled' + } +} + +resource redis_default 'Microsoft.Cache/redisEnterprise/databases@2025-07-01' = { + name: 'default' + properties: { + accessKeysAuthentication: 'Disabled' + port: 10000 + } + parent: redis +} + +output connectionString string = '${redis.properties.hostName}:10000,ssl=true' + +output name string = redis.name + +output id string = redis.id + +output hostName string = redis.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzurePostgresFlexibleServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzurePostgresFlexibleServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..4ddca74fcf3 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzurePostgresFlexibleServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,43 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource postgres 'Microsoft.DBforPostgreSQL/flexibleServers@2024-08-01' = { + name: take('postgres-${uniqueString(resourceGroup().id)}', 63) + location: location + properties: { + authConfig: { + activeDirectoryAuth: 'Enabled' + passwordAuth: 'Disabled' + } + availabilityZone: '1' + backup: { + backupRetentionDays: 7 + geoRedundantBackup: 'Disabled' + } + highAvailability: { + mode: 'Disabled' + } + network: { + publicNetworkAccess: 'Disabled' + } + storage: { + storageSizeGB: 32 + } + version: '16' + } + sku: { + name: 'Standard_B1ms' + tier: 'Burstable' + } + tags: { + 'aspire-resource-name': 'postgres' + } +} + +output connectionString string = 'Host=${postgres.properties.fullyQualifiedDomainName}' + +output name string = postgres.name + +output id string = postgres.id + +output hostName string = postgres.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSearch_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSearch_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..941ff9917b4 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSearch_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,28 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource search 'Microsoft.Search/searchServices@2023-11-01' = { + name: take('search-${uniqueString(resourceGroup().id)}', 60) + location: location + properties: { + hostingMode: 'default' + disableLocalAuth: true + partitionCount: 1 + publicNetworkAccess: 'disabled' + replicaCount: 1 + } + sku: { + name: 'basic' + } + tags: { + 'aspire-resource-name': 'search' + } +} + +output connectionString string = 'Endpoint=https://${search.name}.search.windows.net' + +output endpoint string = 'https://${search.name}.search.windows.net' + +output name string = search.name + +output id string = search.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureServiceBus_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureServiceBus_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..83542945cf7 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureServiceBus_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,27 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param sku string = 'Standard' + +resource servicebus 'Microsoft.ServiceBus/namespaces@2024-01-01' = { + name: take('servicebus-${uniqueString(resourceGroup().id)}', 50) + location: location + properties: { + disableLocalAuth: true + publicNetworkAccess: 'Disabled' + } + sku: { + name: sku + } + tags: { + 'aspire-resource-name': 'servicebus' + } +} + +output serviceBusEndpoint string = servicebus.properties.serviceBusEndpoint + +output serviceBusHostName string = split(replace(servicebus.properties.serviceBusEndpoint, 'https://', ''), ':')[0] + +output name string = servicebus.name + +output id string = servicebus.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSignalR_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSignalR_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..7b5cd7f9950 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSignalR_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,36 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = { + name: take('signalr-${uniqueString(resourceGroup().id)}', 63) + location: location + properties: { + cors: { + allowedOrigins: [ + '*' + ] + } + disableLocalAuth: true + features: [ + { + flag: 'ServiceMode' + value: 'Default' + } + ] + publicNetworkAccess: 'Disabled' + } + kind: 'SignalR' + sku: { + name: 'Free_F1' + capacity: 1 + } + tags: { + 'aspire-resource-name': 'signalr' + } +} + +output hostName string = signalr.properties.hostName + +output name string = signalr.name + +output id string = signalr.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSqlServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSqlServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..741375c5385 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureSqlServer_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,35 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource sqlServerAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('sql-admin-${uniqueString(resourceGroup().id)}', 63) + location: location +} + +resource sql 'Microsoft.Sql/servers@2023-08-01' = { + name: take('sql-${uniqueString(resourceGroup().id)}', 63) + location: location + properties: { + administrators: { + administratorType: 'ActiveDirectory' + login: sqlServerAdminManagedIdentity.name + sid: sqlServerAdminManagedIdentity.properties.principalId + tenantId: subscription().tenantId + azureADOnlyAuthentication: true + } + minimalTlsVersion: '1.2' + publicNetworkAccess: 'Disabled' + version: '12.0' + } + tags: { + 'aspire-resource-name': 'sql' + } +} + +output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName + +output name string = sql.name + +output id string = sql.id + +output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureWebPubSub_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureWebPubSub_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..3724c9b1baa --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzurePrivateEndpointLockdownTests.AddAzureWebPubSub_WithPrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,28 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param sku string = 'Free_F1' + +param capacity int = 1 + +resource webpubsub 'Microsoft.SignalRService/webPubSub@2024-03-01' = { + name: take('webpubsub-${uniqueString(resourceGroup().id)}', 63) + location: location + properties: { + disableLocalAuth: true + publicNetworkAccess: 'Disabled' + } + sku: { + name: sku + capacity: capacity + } + tags: { + 'aspire-resource-name': 'webpubsub' + } +} + +output endpoint string = 'https://${webpubsub.properties.hostName}' + +output name string = webpubsub.name + +output id string = webpubsub.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#00.verified.bicep index 0c17943411e..45a5d7c6d0d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#00.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -22,3 +23,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#01.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#01.verified.bicep index 8df7d4966e3..66ab6ca8194 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#01.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureResourceOptionsTests.AzureResourceOptionsCanBeConfigured#01.verified.bicep @@ -45,4 +45,6 @@ output sqlServerFqdn string = sql_server.properties.fullyQualifiedDomainName output name string = sql_server.name +output id string = sql_server.id + output sqlServerAdminName string = sql_server.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSearchExtensionsTests.AddAzureSearch.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSearchExtensionsTests.AddAzureSearch.verified.bicep index 018ad7333bf..865f0cbeccb 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSearchExtensionsTests.AddAzureSearch.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSearchExtensionsTests.AddAzureSearch.verified.bicep @@ -24,4 +24,6 @@ output connectionString string = 'Endpoint=https://${search.name}.search.windows output endpoint string = 'https://${search.name}.search.windows.net' -output name string = search.name \ No newline at end of file +output name string = search.name + +output id string = search.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=False.verified.bicep index fbafbafca6f..2acba3843ba 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=False.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -47,3 +48,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=True.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=True.verified.bicep index fbafbafca6f..2acba3843ba 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=True.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.AddAzureServiceBus_useObsoleteMethods=True.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -47,3 +48,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.ResourceNamesCanBeDifferentThanAzureNames.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.ResourceNamesCanBeDifferentThanAzureNames.verified.bicep index 48994c06128..81690a1c446 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.ResourceNamesCanBeDifferentThanAzureNames.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.ResourceNamesCanBeDifferentThanAzureNames.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -51,3 +52,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=False.verified.bicep index 9b4d6debd4d..1f1355e5079 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=False.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -27,3 +28,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=True.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=True.verified.bicep index 9b4d6debd4d..1f1355e5079 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=True.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureServiceBusExtensionsTests.TopicNamesCanBeLongerThan24_useObsoleteMethods=True.verified.bicep @@ -8,6 +8,7 @@ resource sb 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -27,3 +28,5 @@ output serviceBusEndpoint string = sb.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(sb.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = sb.name + +output id string = sb.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddAzureSignalR#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddAzureSignalR#00.verified.bicep index 79e66c65e22..16287b9afdd 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddAzureSignalR#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddAzureSignalR#00.verified.bicep @@ -1,4 +1,4 @@ -@description('The location for the resource(s) to be deployed.') +@description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = { @@ -31,3 +31,5 @@ resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = { output hostName string = signalr.properties.hostName output name string = signalr.name + +output id string = signalr.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddServerlessAzureSignalR#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddServerlessAzureSignalR#00.verified.bicep index f6aed77e3a5..755a53a3cc2 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddServerlessAzureSignalR#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSignalRExtensionsTests.AddServerlessAzureSignalR#00.verified.bicep @@ -1,4 +1,4 @@ -@description('The location for the resource(s) to be deployed.') +@description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = { @@ -31,3 +31,5 @@ resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = { output hostName string = signalr.properties.hostName output name string = signalr.name + +output id string = signalr.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=False.verified.bicep index 841de050e2e..9327ead500a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=False.verified.bicep @@ -80,4 +80,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=True.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=True.verified.bicep index 841de050e2e..9327ead500a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=True.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=False_useAcaInfrastructure=True.verified.bicep @@ -80,4 +80,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=True_useAcaInfrastructure=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=True_useAcaInfrastructure=False.verified.bicep index 925724b2e9c..23a6451a309 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=True_useAcaInfrastructure=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AddAzureSqlServer_publishMode=True_useAcaInfrastructure=False.verified.bicep @@ -71,4 +71,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaPublishMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaPublishMode.verified.bicep index b48e7f9f901..4c6a552b4df 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaPublishMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaPublishMode.verified.bicep @@ -45,4 +45,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaRunMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaRunMode.verified.bicep index b8e89040352..a21e86f62ea 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaRunMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlExtensionsTests.AsAzureSqlDatabaseViaRunMode.verified.bicep @@ -54,4 +54,6 @@ output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName output name string = sql.name +output id string = sql.id + output sqlServerAdminName string = sql.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithDataLakePrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithDataLakePrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..d208a7b5445 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithDataLakePrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,36 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource storage 'Microsoft.Storage/storageAccounts@2024-01-01' = { + name: take('storage${uniqueString(resourceGroup().id)}', 24) + kind: 'StorageV2' + location: location + sku: { + name: 'Standard_GRS' + } + properties: { + accessTier: 'Hot' + allowSharedKeyAccess: false + isHnsEnabled: true + minimumTlsVersion: 'TLS1_2' + networkAcls: { + defaultAction: 'Deny' + } + publicNetworkAccess: 'Disabled' + } + tags: { + 'aspire-resource-name': 'storage' + } +} + +output blobEndpoint string = storage.properties.primaryEndpoints.blob + +output dataLakeEndpoint string = storage.properties.primaryEndpoints.dfs + +output queueEndpoint string = storage.properties.primaryEndpoints.queue + +output tableEndpoint string = storage.properties.primaryEndpoints.table + +output name string = storage.name + +output id string = storage.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithTablePrivateEndpoint_GeneratesCorrectBicep.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithTablePrivateEndpoint_GeneratesCorrectBicep.verified.bicep new file mode 100644 index 00000000000..84e807f8a64 --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureStoragePrivateEndpointLockdownTests.AddAzureStorage_WithTablePrivateEndpoint_GeneratesCorrectBicep.verified.bicep @@ -0,0 +1,36 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource storage 'Microsoft.Storage/storageAccounts@2024-01-01' = { + name: take('storage${uniqueString(resourceGroup().id)}', 24) + kind: 'StorageV2' + location: location + sku: { + name: 'Standard_GRS' + } + properties: { + accessTier: 'Hot' + allowSharedKeyAccess: false + isHnsEnabled: false + minimumTlsVersion: 'TLS1_2' + networkAcls: { + defaultAction: 'Deny' + } + publicNetworkAccess: 'Disabled' + } + tags: { + 'aspire-resource-name': 'storage' + } +} + +output blobEndpoint string = storage.properties.primaryEndpoints.blob + +output dataLakeEndpoint string = storage.properties.primaryEndpoints.dfs + +output queueEndpoint string = storage.properties.primaryEndpoints.queue + +output tableEndpoint string = storage.properties.primaryEndpoints.table + +output name string = storage.name + +output id string = storage.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubSettings.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubSettings.verified.bicep index a6478f1fbef..81e8eb3c38a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubSettings.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubSettings.verified.bicep @@ -83,4 +83,6 @@ resource hub2 'Microsoft.SignalRService/webPubSub/hubs@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWithEventHandlerExpressionWorks.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWithEventHandlerExpressionWorks.verified.bicep index e1612c6b1b6..78d08f34d7a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWithEventHandlerExpressionWorks.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWithEventHandlerExpressionWorks.verified.bicep @@ -37,4 +37,6 @@ resource abc 'Microsoft.SignalRService/webPubSub/hubs@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWorks.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWorks.verified.bicep index 0dcba14366c..fde7670ec5c 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWorks.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubHubWorks.verified.bicep @@ -27,4 +27,6 @@ resource abc 'Microsoft.SignalRService/webPubSub/hubs@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubWithParameters.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubWithParameters.verified.bicep index cb27f57f530..eddd7caac0f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubWithParameters.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddAzureWebPubSubWithParameters.verified.bicep @@ -22,4 +22,6 @@ resource wps1 'Microsoft.SignalRService/webPubSub@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddDefaultAzureWebPubSub.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddDefaultAzureWebPubSub.verified.bicep index cb27f57f530..eddd7caac0f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddDefaultAzureWebPubSub.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddDefaultAzureWebPubSub.verified.bicep @@ -22,4 +22,6 @@ resource wps1 'Microsoft.SignalRService/webPubSub@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddWebPubSubWithHubConfigure.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddWebPubSubWithHubConfigure.verified.bicep index 491853b7731..2778cf77763 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddWebPubSubWithHubConfigure.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.AddWebPubSubWithHubConfigure.verified.bicep @@ -30,4 +30,6 @@ resource abc 'Microsoft.SignalRService/webPubSub/hubs@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.ConfigureConstructOverridesAddEventHandler.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.ConfigureConstructOverridesAddEventHandler.verified.bicep index ee68936f233..9006aa5d428 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.ConfigureConstructOverridesAddEventHandler.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureWebPubSubExtensionsTests.ConfigureConstructOverridesAddEventHandler.verified.bicep @@ -38,4 +38,6 @@ resource ABC 'Microsoft.SignalRService/webPubSub/hubs@2024-03-01' = { output endpoint string = 'https://${wps1.properties.hostName}' -output name string = wps1.name \ No newline at end of file +output name string = wps1.name + +output id string = wps1.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInPublishMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInPublishMode.verified.bicep index ff96148d214..2272633771f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInPublishMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInPublishMode.verified.bicep @@ -17,3 +17,5 @@ output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(messaging.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = messaging.name + +output id string = messaging.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInRunMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInRunMode.verified.bicep index ff96148d214..2272633771f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInRunMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.AddExistingAzureServiceBusInRunMode.verified.bicep @@ -17,3 +17,5 @@ output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(messaging.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = messaging.name + +output id string = messaging.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.RequiresPublishAsExistingInPublishMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.RequiresPublishAsExistingInPublishMode.verified.bicep index 03c728144fa..db315246ee7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.RequiresPublishAsExistingInPublishMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.RequiresPublishAsExistingInPublishMode.verified.bicep @@ -8,6 +8,7 @@ resource messaging 'Microsoft.ServiceBus/namespaces@2024-01-01' = { location: location properties: { disableLocalAuth: true + publicNetworkAccess: 'Enabled' } sku: { name: sku @@ -27,3 +28,5 @@ output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(messaging.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = messaging.name + +output id string = messaging.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAppConfigurationWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAppConfigurationWithResourceGroup.verified.bicep index bd20e1b25de..9d006b923ad 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAppConfigurationWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAppConfigurationWithResourceGroup.verified.bicep @@ -9,4 +9,6 @@ resource appConfig 'Microsoft.AppConfiguration/configurationStores@2024-06-01' e output appConfigEndpoint string = appConfig.properties.endpoint -output name string = appConfig.name \ No newline at end of file +output name string = appConfig.name + +output id string = appConfig.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroup.verified.bicep index fd18a8c0fdc..7ce69082e7b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroup.verified.bicep @@ -38,3 +38,5 @@ resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/container output connectionString string = cosmos.properties.documentEndpoint output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroupAccessKey.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroupAccessKey.verified.bicep index 7345e3c05fa..9197becec11 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroupAccessKey.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureCosmosDBWithResourceGroupAccessKey.verified.bicep @@ -73,4 +73,6 @@ resource container_connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-0 parent: keyVault } -output name string = cosmos.name \ No newline at end of file +output name string = cosmos.name + +output id string = cosmos.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroup.verified.bicep index 7b541468742..0cc56f81350 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroup.verified.bicep @@ -11,4 +11,6 @@ output connectionString string = '${redis.properties.hostName}:10000,ssl=true' output name string = redis.name +output id string = redis.id + output hostName string = redis.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroupAndAccessKeyAuth.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroupAndAccessKeyAuth.verified.bicep index 67aaa1e62f5..7dbd3c92b72 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroupAndAccessKeyAuth.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureRedisEnterpriseWithResourceGroupAndAccessKeyAuth.verified.bicep @@ -37,4 +37,6 @@ resource primaryAccessKey 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = redis.name +output id string = redis.id + output hostName string = redis.properties.hostName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSearchWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSearchWithResourceGroup.verified.bicep index 6a248463328..fb1c1e62140 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSearchWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSearchWithResourceGroup.verified.bicep @@ -12,3 +12,5 @@ output connectionString string = 'Endpoint=https://${existingResourceName}.searc output endpoint string = 'https://${existingResourceName}.search.windows.net' output name string = search.name + +output id string = search.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSignalRWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSignalRWithResourceGroup.verified.bicep index 47ea51b2770..83fdbd8c601 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSignalRWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSignalRWithResourceGroup.verified.bicep @@ -9,4 +9,6 @@ resource signalR 'Microsoft.SignalRService/signalR@2024-03-01' existing = { output hostName string = signalR.properties.hostName -output name string = signalR.name \ No newline at end of file +output name string = signalR.name + +output id string = signalR.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerInRunMode.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerInRunMode.verified.bicep index 42faef05e83..c97cf9bbf36 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerInRunMode.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerInRunMode.verified.bicep @@ -29,4 +29,6 @@ output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName output name string = sqlServer.name +output id string = sqlServer.id + output sqlServerAdminName string = sqlServer.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerWithResourceGroup.verified.bicep index b5a8aba35ca..0ee9866be57 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureSqlServerWithResourceGroup.verified.bicep @@ -20,4 +20,6 @@ output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName output name string = sqlServer.name +output id string = sqlServer.id + output sqlServerAdminName string = sqlServer.properties.administrators.login \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureWebPubSubWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureWebPubSubWithResourceGroup.verified.bicep index eff38edfb13..1e31241d498 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureWebPubSubWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureWebPubSubWithResourceGroup.verified.bicep @@ -9,4 +9,6 @@ resource webPubSub 'Microsoft.SignalRService/webPubSub@2024-03-01' existing = { output endpoint string = 'https://${webPubSub.properties.hostName}' -output name string = webPubSub.name \ No newline at end of file +output name string = webPubSub.name + +output id string = webPubSub.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingEventHubsWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingEventHubsWithResourceGroup.verified.bicep index fbfb14e9387..13f7f0c4129 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingEventHubsWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingEventHubsWithResourceGroup.verified.bicep @@ -12,3 +12,5 @@ output eventHubsEndpoint string = eventHubs.properties.serviceBusEndpoint output eventHubsHostName string = split(replace(eventHubs.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = eventHubs.name + +output id string = eventHubs.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingKeyVaultWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingKeyVaultWithResourceGroup.verified.bicep index e19f847a774..5e728ee6fa7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingKeyVaultWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingKeyVaultWithResourceGroup.verified.bicep @@ -9,4 +9,6 @@ resource keyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = { output vaultUri string = keyVault.properties.vaultUri -output name string = keyVault.name \ No newline at end of file +output name string = keyVault.name + +output id string = keyVault.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroup.verified.bicep index 5edf04c650c..738ff1bc5c0 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroup.verified.bicep @@ -20,4 +20,6 @@ output connectionString string = 'Host=${postgresSql.properties.fullyQualifiedDo output name string = postgresSql.name +output id string = postgresSql.id + output hostName string = postgresSql.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroupWithPasswordAuth.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroupWithPasswordAuth.verified.bicep index b0ad0df8db3..4b27a3862c4 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroupWithPasswordAuth.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingPostgresSqlWithResourceGroupWithPasswordAuth.verified.bicep @@ -37,4 +37,6 @@ resource connectionString 'Microsoft.KeyVault/vaults/secrets@2024-11-01' = { output name string = postgresSql.name +output id string = postgresSql.id + output hostName string = postgresSql.properties.fullyQualifiedDomainName \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithResourceGroupInPublishMode#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithResourceGroupInPublishMode#00.verified.bicep index ff96148d214..2272633771f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithResourceGroupInPublishMode#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithResourceGroupInPublishMode#00.verified.bicep @@ -17,3 +17,5 @@ output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(messaging.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = messaging.name + +output id string = messaging.id \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithStaticArguments.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithStaticArguments.verified.bicep index 65ac1ae9599..2d0fd5e0ccc 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithStaticArguments.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingServiceBusWithStaticArguments.verified.bicep @@ -15,3 +15,5 @@ output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint output serviceBusHostName string = split(replace(messaging.properties.serviceBusEndpoint, 'https://', ''), ':')[0] output name string = messaging.name + +output id string = messaging.id \ No newline at end of file From be3c41a8e403fadfd423900064b008e826ca4250 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 5 Feb 2026 19:01:43 -0600 Subject: [PATCH 2/3] Fix tests --- .../AzurePostgresExtensions.cs | 4 +--- .../AzureAppConfigurationExtensionsTests.cs | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs index 81d871c3c9e..727197c8855 100644 --- a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs +++ b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs @@ -403,10 +403,8 @@ public static IResourceBuilder With private static PostgreSqlFlexibleServer CreatePostgreSqlFlexibleServer(AzureResourceInfrastructure infrastructure, IDistributedApplicationBuilder distributedApplicationBuilder, IReadOnlyDictionary databases) { - var azureResource = (AzurePostgresFlexibleServerResource)infrastructure.AspireResource; - // Check if this PostgreSQL server has a private endpoint (via annotation) - var hasPrivateEndpoint = azureResource.HasAnnotationOfType(); + var hasPrivateEndpoint = infrastructure.AspireResource.HasAnnotationOfType(); var postgres = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure, (identifier, name) => diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureAppConfigurationExtensionsTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureAppConfigurationExtensionsTests.cs index a4d84ae222d..ee4ed55ad9a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureAppConfigurationExtensionsTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureAppConfigurationExtensionsTests.cs @@ -57,6 +57,8 @@ public async Task AddAzureAppConfiguration() output appConfigEndpoint string = appConfig.properties.endpoint output name string = appConfig.name + + output id string = appConfig.id """; output.WriteLine(manifest.BicepText); Assert.Equal(expectedBicep, manifest.BicepText); From 4a3bd8350f0a3325611e95de306b31b6eb065875 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 6 Feb 2026 09:39:46 -0600 Subject: [PATCH 3/3] Fix Redis private dns zone name. --- src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs index d25738ed43f..14aa1526830 100644 --- a/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs +++ b/src/Aspire.Hosting.Azure.Redis/AzureManagedRedisResource.cs @@ -252,5 +252,5 @@ IEnumerable> IResourceWithConnectionSt IEnumerable IAzurePrivateEndpointTarget.GetPrivateLinkGroupIds() => ["redisEnterprise"]; - string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.redisenterprise.cache.azure.net"; + string IAzurePrivateEndpointTarget.GetPrivateDnsZoneName() => "privatelink.redis.azure.net"; }