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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,63 +1,68 @@
## Applicability
Az.Network supports the retrieval of private link resource in `Get-AzPrivateLinkResource` as well as the management of private endpoint connection in `Approve-AzPrivateEndpointConnect`, `Deny-AzPrivateEndpointConnect`, `Remove-AzPrivateEndpointConnect` and `Set-AzPrivateEndpointConnect`.
Az.Network supports the retrieval of private link resource in `Get-AzPrivateLinkResource` as well as the management of private endpoint connection by `Get-AzPrivateEndpointConnection`, `Approve-AzPrivateEndpointConnection`, `Deny-AzPrivateEndpointConnection`, `Remove-AzPrivateEndpointConnection` and `Set-AzPrivateEndpointConnection`.

For providers who
- supports the features of private linke resource and private endpoint connection already
- and want to onboard these features in Azure PowerShell,
For provider who
- supports the features of private link resource or private endpoint connection already
- and wants to onboard these features in Azure PowerShell,
You need to register provider configuration in [ProviderConfiguration.cs](https://github.com/Azure/azure-powershell/blob/main/src/Network/Network/PrivateLinkService/PrivateLinkServiceProvider/ProviderConfiguration.cs#L12).

they need register provider configuration in [ProviderConfiguration.cs](https://github.com/Azure/azure-powershell/blob/main/src/Network/Network/PrivateLinkService/PrivateLinkServiceProvider/ProviderConfiguration.cs#L12).

Notes: No additional commands for the features of private linke resource and private endpoint connection need to be added.
Notes: No additional commands for the features of PrivateLinkResource and PrivateEndpointConnection need to be added.

## Prerequisite
We assume the API for `List` private link resource and `Get` private endpoint connection is available in the provider that claims to support private endpoint connection features. That means it supports following APIs:

```
# List Private Link Resource API
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{Top-Level-Resource}/{Top-Level-Resource-Name}/privateLinkResources"
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{topResourceType}/{topResourceName}/privateLinkResources"
```
```
# Get Private Endpoint Connection API
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{Top-Level-Resource}/{Top-Level-Resource-Name}/privateEndpointConnections/{PrivateEndpointConnection-Name}"
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{topResourceType}/{topResourceName}/privateEndpointConnections/{privateEndpointConnectionName}"
```

if "List Private Endpoint Connection API" is not available, `privateEndpointConnections` must be included in the properties of top resource returned by
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{Top-Level-Resource}/{Top-Level-Resource-Name}". So that `Private Endpoint Connections` will be retrieved from the top resource.
if "List Private Endpoint Connection API" below is not available, `privateEndpointConnections` must be included in the properties of top resource returned by
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{topResourceType}/{topResourceName}". So that `Get-AzPrivateEndpointConnect` will retrieve connections from the top resource.

```
# List Private Endpoint Connection API
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{Top-Level-Resource}/{Top-Level-Resource-Name}/privateEndpointConnections"
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{topResourceType}/{topResourceName}/privateEndpointConnections"
```

## Code Changes Needed
To add corresponding {Provider}, {Top-Level-Resource} and {API-Version} into [ProviderConfiguration.cs](https://github.com/Azure/azure-powershell/blob/main/src/Network/Network/PrivateLinkService/PrivateLinkServiceProvider/ProviderConfiguration.cs#L12), we need to follow
in following pattern:
To add corresponding {Provider}, {topResourceType} and {API-Version} into [ProviderConfiguration.cs](https://github.com/Azure/azure-powershell/blob/main/src/Network/Network/PrivateLinkService/PrivateLinkServiceProvider/ProviderConfiguration.cs#L12), we need to follow in following pattern:
```
RegisterConfiguration("{Provider}/{Top-Level-Resource}", "{API-Version}", bool hasPrivateEndppointConnectionsURI, bool hasPrivateLinkResourceURI)
RegisterConfiguration(string type, string apiVersion, bool hasConnectionsURI = false, bool supportGetPrivateLinkResource = false, bool supportPrivateLinkResource = true)
```
- "{Provider}/{Top-Level-Resource}" describes the type of provider. For example, "Microsoft.Sql/servers".
- "{API-Version}" specifies the API version to be used. For example, "2018-06-01-preview".
- `hasPrivateEndppointConnectionsURI` marks the provider whether provides "List Private Endpoint Connection API".
- `type` includes resource provider and resource type which supports PrivateLink feature. For example, "Microsoft.Sql/servers".
- `apiVersion` specifies the API version to be used. For example, "2018-06-01-preview".
- `hasConnectionsURI` marks whether the provider exposes "List Private Endpoint Connection API". Default value is false.
```
# Get Private Link Resource API
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{Top-Level-Resource}/{Top-Level-Resource-Name}/privateLinkResources/{PrivateLinkResource-Name}"
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{provider}/{topResourceType}/{topResourceName}/privateLinkResources/{privateLinkResourceName}"
```
- `hasPrivateLinkResourceURI` marks the provider whether providers "Get Private Endpoint Connection API".
- `supportGetPrivateLinkResource` marks whether the provider supports Get API of PrivateLinkResource. Default value is false.

For instance, for provider "Microsoft.Sql/servers" with API version "2018-06-01-preview", it supports "List Private Endpoint Connection API" and "Get Private Endpoint Connection API". So it's registration configuration should be
For instance, for provider "Microsoft.Sql/servers" with API version "2018-06-01-preview", it supports "List Private Endpoint Connection API" and "Get Private Link Resource API". So its registration configuration should be:
```
RegisterConfiguration("Microsoft.Sql/servers", "2018-06-01-preview", true, true);
```

- `supportListPrivateLinkResource` marks whether the provider supports List API of PrivateLinkResource. Default value is true.

For instance, `Microsoft.Network/privateLinkServices` supports PrivateEndpointConnections but doesn't support resource type PrivateLinkResource (We assume List API is mandatory to resource support). Its configuration should be:
```
RegisterConfiguration("Microsoft.Network/privateLinkServices", "2020-05-01", true, false, false);
```

## End-To-End Test

### Item Needed

+ Top level resource
```
New-Az{Top-Level-Resource} -ResourceGroupName {rg_name} -Name {top_level_resource_name}
New-Az{topResourceType} -ResourceGroupName {rgName} -Name {topResourceName}

$TopLevelResource = Get-Az{Top-Level-Resource} -ResourceGroupName {rg_name} -Name {top_level_resource_name}
$TopLevelResource = Get-Az{topResourceType} -ResourceGroupName {rgName} -Name {topResourceName}
```

+ private link resource
Expand All @@ -67,24 +72,24 @@ $PrivateLinkResource = Get-AzPrivateLinkResource -PrivateLinkResourceId $TopLeve

+ subnet config (object in memory)
```
$SubnetConfig = New-AzVirtualNetworkSubnetConfig -Name {config_name} -AddressPrefix "11.0.1.0/24" -PrivateEndpointNetworkPolicies "Disabled"
$SubnetConfig = New-AzVirtualNetworkSubnetConfig -Name {configName} -AddressPrefix "11.0.1.0/24" -PrivateEndpointNetworkPolicies "Disabled"
```

+ virtual network
```
New-AzVirtualNetwork -ResourceGroupName {rg_name} -Name {vnet_name} -Location {location} -AddressPrefix "11.0.0.0/16" -Subnet $SubnetConfig
New-AzVirtualNetwork -ResourceGroupName {rgName} -Name {vnetName} -Location {location} -AddressPrefix "11.0.0.0/16" -Subnet $SubnetConfig

$VNet=Get-AzVirtualNetwork -ResourceGroupName {rg_name} -Name {vnet_name}
$VNet=Get-AzVirtualNetwork -ResourceGroupName {rgName} -Name {vnetName}
```

+ private link service connection (object in memory)
```
$PLSConnection = New-AzPrivateLinkServiceConnection -Name {pls_connection_name} -PrivateLinkServiceId $TopLevelResource.Id -GroupId $TopLevelResource.GroupId
$PLSConnection = New-AzPrivateLinkServiceConnection -Name {plsConnectionName} -PrivateLinkServiceId $TopLevelResource.Id -GroupId $TopLevelResource.GroupId
```

+ endpoint
```
New-AzPrivateEndpoint -ResourceGroupName {rg_name} -Name {endpoint_name} -Location {location} -Subnet $VNet.subnets[0] -PrivateLinkServiceConnection $PLSConnection -ByManualRequest
New-AzPrivateEndpoint -ResourceGroupName {rgName} -Name {endpointName} -Location {location} -Subnet $VNet.subnets[0] -PrivateLinkServiceConnection $PLSConnection -ByManualRequest
```

### step-by-step
Expand All @@ -99,7 +104,7 @@ $connection = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $TopLevelRe

* To get the connection, if `list` for private endpoint connection was not supported,
```
$TopLevelResource = Get-Az{Top-Level-Resource} -ResourceGroupName {rg_name} -Name {top_level_resource_name}
$TopLevelResource = Get-Az{topResourceType} -ResourceGroupName {rgName} -Name {topResourceName}

$ConnectionId = $TopLevelResource.PrivateEndpointConnection[0].Id

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.Common.Exceptions;
using Microsoft.Azure.Commands.Network.PrivateLinkService.PrivateLinkServiceProvider;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
using System.Management.Automation;
Expand Down Expand Up @@ -62,7 +63,7 @@ public abstract class PrivateEndpointConnectionBaseCmdlet : NetworkBaseCmdlet, I
{
var parameters = new RuntimeDefinedParameterDictionary();
RuntimeDefinedParameter namedParameter;
if (ProviderConfiguration.TryGetProvideServiceParameter(privateEndpointTypeName, NamedContextParameterSet, out namedParameter))
if (ProviderConfiguration.TryGetEndpointConnectionServiceParameter(privateEndpointTypeName, NamedContextParameterSet, out namedParameter))
{
parameters.Add(privateEndpointTypeName, namedParameter);
}
Expand All @@ -76,6 +77,8 @@ public abstract class PrivateEndpointConnectionBaseCmdlet : NetworkBaseCmdlet, I

protected IPrivateLinkProvider BuildProvider(string subscription, string privateLinkResourceType)
{
if (!GenericProvider.SupportsPrivateLinkResourceType(privateLinkResourceType))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please help to rename method to SupportsPrivateLinkFeature because it includes resource type and connection endpoint both.

throw new AzPSApplicationException(string.Format(Properties.Resources.UnsupportPrivateEndpointConnectionType, privateLinkResourceType));
return PrivateLinkProviderFactory.CreatePrivateLinkProvder(this, subscription, privateLinkResourceType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.Common.Exceptions;
using Microsoft.Azure.Commands.Network.Models;
using Microsoft.Azure.Commands.Network.PrivateLinkService.PrivateLinkServiceProvider;
using Microsoft.Azure.Management.Internal.Resources.Utilities.Models;
Expand Down Expand Up @@ -63,9 +64,10 @@ public class GetAzurePrivateLinkResourceCommand : NetworkBaseCmdlet, IDynamicPar

public new object GetDynamicParameters()
{
InvocationInfo invocationInfo = MyInvocation;
var parameters = new RuntimeDefinedParameterDictionary();
RuntimeDefinedParameter namedParameter;
if (ProviderConfiguration.TryGetProvideServiceParameter(privateEndpointTypeName, NamedContextParameterSet, out namedParameter))
if (ProviderConfiguration.TryGetLinkResourceServiceParameter(privateEndpointTypeName, NamedContextParameterSet, out namedParameter))
{
parameters.Add(privateEndpointTypeName, namedParameter);
}
Expand All @@ -89,6 +91,12 @@ public override void Execute()
this.Subscription = DefaultProfile.DefaultContext.Subscription.Id;
this.PrivateLinkResourceType = DynamicParameters[privateEndpointTypeName].Value as string;
}

if (!GenericProvider.SupportsPrivateLinkResourceType(this.PrivateLinkResourceType))
{
throw new ArgumentException(string.Format(Properties.Resources.UnsupportPrivateLinkResourceType, this.PrivateLinkResourceType));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AzPSArgumentException

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use AzPSArgumentException need pass parameter name. We have to hardcode parameter name if use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used AzPSApplicationException

}

IPrivateLinkProvider provider = PrivateLinkProviderFactory.CreatePrivateLinkProvder(this, Subscription, PrivateLinkResourceType);
if (provider == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Microsoft.Azure.Internal.Common;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.Commands.Common.Exceptions;

namespace Microsoft.Azure.Commands.Network.PrivateLinkService.PrivateLinkServiceProvider
{
Expand Down Expand Up @@ -133,20 +134,28 @@ public void DeletePrivateEndpointConnection(string resourceGroupName, string ser

public PSPrivateLinkResource GetPrivateLinkResource(string resourceGroupName, string serviceName, string name)
{
if (_configuration.HasResourceURI)
if (_configuration.SupportGetPrivateLinkResource)
{
string url = BuildPrivateLinkResourceURL(resourceGroupName, serviceName, name);
PrivateLinkResource resource = ServiceClient.Operations.GetResource<PrivateLinkResource>(url, _configuration.ApiVersion);
return ToPsPrivateLinkResource(resource);
}
else
else if (_configuration.SupportListPrivateLinkResource)
{
return ListPrivateLinkResource(resourceGroupName, serviceName).Single(plr => plr.Name.Equals(name));
}
else
{
throw new AzPSApplicationException(string.Format(Properties.Resources.UnsupportPrivateLinkResourceType, $"{_configuration.Type} api {_configuration.ApiVersion}"));
}
}

public List<PSPrivateLinkResource> ListPrivateLinkResource(string resourceGroupName, string serviceName)
{
if (!_configuration.SupportListPrivateLinkResource)
{
throw new AzPSApplicationException(string.Format(Properties.Resources.UnsupportPrivateLinkResourceType, $"{_configuration.Type} api {_configuration.ApiVersion}"));
}
var psPLRs = new List<PSPrivateLinkResource>();
string url = BuildPrivateLinkResourcesURL(resourceGroupName, serviceName);
IPage<PrivateLinkResource> list = ServiceClient.Operations.GetResourcePage<Page<PrivateLinkResource>, PrivateLinkResource>(url, _configuration.ApiVersion);
Expand Down
Loading