Skip to content

Commit 2fc2c19

Browse files
amih90Ami HollanderCopilot
authored
[Network] az network private-endpoint-connection: Add provider Microsoft.Security/privateLinks (#32396)
Co-authored-by: Ami Hollander <amhollan@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 31f3591 commit 2fc2c19

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

src/azure-cli/azure/cli/command_modules/network/private_link_resource_and_endpoint_connections/custom.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def register_providers():
8686
_register_one_provider('Microsoft.App/managedEnvironments', '2024-02-02-preview', True)
8787
_register_one_provider('Microsoft.FluidRelay/fluidRelayServers', '2025-03-10-preview', True)
8888
_register_one_provider('Microsoft.VideoIndexer/accounts', '2025-04-01', True)
89+
_register_one_provider('Microsoft.Security/privateLinks', '2025-09-01-preview', True)
8990

9091

9192
def _register_one_provider(provider, api_version, support_list_or_not, resource_get_api_version=None, support_connection_operation=True): # pylint: disable=line-too-long
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
3+
"contentVersion": "1.0.0.0",
4+
"parameters": {
5+
"target_resource_name": {
6+
"value": "clitestsecuritypl"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3+
"contentVersion": "1.0.0.0",
4+
"parameters": {
5+
"target_resource_name": {
6+
"defaultValue": "security-privatelink",
7+
"type": "String"
8+
}
9+
},
10+
"variables": {},
11+
"resources": [
12+
{
13+
"type": "Microsoft.Security/privateLinks",
14+
"apiVersion": "2025-09-01-preview",
15+
"name": "[parameters('target_resource_name')]",
16+
"location": "global",
17+
"properties": {}
18+
}
19+
]
20+
}

src/azure-cli/azure/cli/command_modules/network/tests/latest/test_private_endpoint_commands.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,97 @@ def test_private_endpoint_connection_video_indexer(self, resource_group, storage
22592259
vi_name = self.create_random_name(prefix='clitestvideoindexer', length=24)
22602260
self._test_private_endpoint_connection_scenario(resource_group, storage_account, vi_name)
22612261

2262+
class SecurityPrivateLinkNetworkARMTemplateBasedScenarioTest(ScenarioTest):
2263+
def _test_private_endpoint_connection_scenario(self, resource_group, target_resource_name):
2264+
from azure.mgmt.core.tools import resource_id
2265+
resource_type = 'Microsoft.Security/privateLinks'
2266+
self.kwargs.update({
2267+
'target_resource_name': target_resource_name,
2268+
'target_resource_id': resource_id(subscription=self.get_subscription_id(),
2269+
resource_group=resource_group,
2270+
namespace=resource_type.split('/')[0],
2271+
type=resource_type.split('/')[1],
2272+
name=target_resource_name),
2273+
'rg': resource_group,
2274+
'resource_type': resource_type,
2275+
'vnet': self.create_random_name('cli-vnet-', 24),
2276+
'subnet': self.create_random_name('cli-subnet-', 24),
2277+
'pe': self.create_random_name('cli-pe-', 24),
2278+
'pe_connection': self.create_random_name('cli-pec-', 24)
2279+
})
2280+
2281+
split_resource_type = resource_type.split('/')
2282+
resource_type_name = split_resource_type[0].split('.')[1].lower()
2283+
resource_type_kind = split_resource_type[1].lower()
2284+
param_file_name = "{}_{}_parameters.json".format(resource_type_name, resource_type_kind)
2285+
template_file_name = "{}_{}_template.json".format(resource_type_name, resource_type_kind)
2286+
self.kwargs.update({
2287+
'param_path': os.path.join(TEST_DIR, 'private_endpoint_arm_templates', param_file_name),
2288+
'template_path': os.path.join(TEST_DIR, 'private_endpoint_arm_templates', template_file_name)
2289+
})
2290+
self.cmd('az deployment group create -g {rg} -p "@{param_path}" target_resource_name={target_resource_name} -f "{template_path}"')
2291+
2292+
self.cmd('az network vnet create -n {vnet} -g {rg} --subnet-name {subnet} -o json',
2293+
checks=self.check('length(newVNet.subnets)', 1))
2294+
self.cmd('az network vnet subnet update -n {subnet} --vnet-name {vnet} -g {rg} '
2295+
'--disable-private-endpoint-network-policies true -o json',
2296+
checks=self.check('privateEndpointNetworkPolicies', 'Disabled'))
2297+
2298+
target_private_link_resource = self.cmd('az network private-link-resource list --name {target_resource_name} --resource-group {rg} --type {resource_type} -o json').get_output_in_json()
2299+
self.kwargs.update({
2300+
'group_id': target_private_link_resource[0]['properties']['groupId']
2301+
})
2302+
# Create a private endpoint connection
2303+
pe = self.cmd(
2304+
'az network private-endpoint create -g {rg} -n {pe} --vnet-name {vnet} --subnet {subnet} '
2305+
'--connection-name {pe_connection} --private-connection-resource-id {target_resource_id} '
2306+
'--group-id {group_id} -o json').get_output_in_json()
2307+
self.kwargs['pe_id'] = pe['id']
2308+
self.kwargs['pe_name'] = self.kwargs['pe_id'].split('/')[-1]
2309+
2310+
# Show the connection at the target resource side
2311+
list_private_endpoint_conn = self.cmd('az network private-endpoint-connection list --name {target_resource_name} --resource-group {rg} --type {resource_type} -o json').get_output_in_json()
2312+
self.kwargs.update({
2313+
"pec_id": list_private_endpoint_conn[0]['id']
2314+
})
2315+
2316+
self.kwargs.update({
2317+
"pec_name": self.kwargs['pec_id'].split('/')[-1]
2318+
})
2319+
self.cmd('az network private-endpoint-connection show --id {pec_id} -o json',
2320+
checks=self.check('id', '{pec_id}'))
2321+
self.cmd('az network private-endpoint-connection show --resource-name {target_resource_name} --name {pec_name} --resource-group {rg} --type {resource_type} -o json')
2322+
self.cmd('az network private-endpoint-connection show --resource-name {target_resource_name} -n {pec_name} -g {rg} --type {resource_type} -o json')
2323+
2324+
# Test approval/rejection
2325+
self.kwargs.update({
2326+
'approval_desc': 'You are approved!',
2327+
'rejection_desc': 'You are rejected!'
2328+
})
2329+
self.cmd(
2330+
'az network private-endpoint-connection approve --resource-name {target_resource_name} --resource-group {rg} --name {pec_name} --type {resource_type} '
2331+
'--description "{approval_desc}" -o json', checks=[
2332+
self.check('properties.privateLinkServiceConnectionState.status', 'Approved')
2333+
])
2334+
self.cmd('az network private-endpoint-connection reject --id {pec_id} '
2335+
'--description "{rejection_desc}" -o json',
2336+
checks=[
2337+
self.check('properties.privateLinkServiceConnectionState.status', 'Rejected')
2338+
])
2339+
self.cmd(
2340+
'az network private-endpoint-connection list --name {target_resource_name} --resource-group {rg} --type {resource_type} -o json',
2341+
checks=[
2342+
self.check('length(@)', 1)
2343+
])
2344+
2345+
# Test delete
2346+
self.cmd('az network private-endpoint-connection delete --id {pec_id} -y -o json')
2347+
2348+
@live_only()
2349+
@ResourceGroupPreparer(name_prefix="test_private_endpoint_connection_security_privatelink", location="westus")
2350+
def test_private_endpoint_connection_security_privatelink(self, resource_group):
2351+
name = self.create_random_name(prefix='clitestsecuritypl', length=24)
2352+
self._test_private_endpoint_connection_scenario(resource_group, name)
22622353

22632354
class NetworkPrivateLinkDigitalTwinsScenarioTest(ScenarioTest):
22642355
@ResourceGroupPreparer(

0 commit comments

Comments
 (0)