Skip to content

Commit 25102ba

Browse files
committed
feat: support managed identity on vnet-gateway and cert auth on vpn-connection
1 parent a3298ec commit 25102ba

File tree

24 files changed

+8567
-44
lines changed

24 files changed

+8567
-44
lines changed

src/azure-cli/azure/cli/command_modules/network/_help.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5576,6 +5576,16 @@
55765576
text: |
55775577
az network vpn-connection create --local-gateway2 MyLocalGateway --location westus2 --name MyConnection --resource-group MyResourceGroup --shared-key Abc123 --vnet-gateway1 MyVnetGateway
55785578
crafted: true
5579+
- name: Create a VPN connection with Certificate authentication using JSON file.
5580+
text: |
5581+
az network vpn-connection create -g MyResourceGroup -n MyConnection \
5582+
--vnet-gateway1 MyVnetGateway --local-gateway2 MyLocalGateway \
5583+
--auth-type Certificate --cert-auth @cert_auth.json
5584+
- name: Create a VPN connection with Certificate authentication using inline JSON.
5585+
text: |
5586+
az network vpn-connection create -g MyResourceGroup -n MyConnection \
5587+
--vnet-gateway1 MyVnetGateway --local-gateway2 MyLocalGateway \
5588+
--auth-type Certificate --cert-auth '{"outboundAuthCertificate":"https://customerKv.vault/Certificates/outBoundcert/Version","inboundAuthCertificateChain":["MIIC+TCCAeGgAwIBAgIQFOJUqDaxV5xJcKpTKO..","MIIC+TCCAeGgAwIBAgIQPJerInitNblK7yBgkqh.."],"inboundAuthCertificateSubjectName":"CN=rootCert.com"}'
55795589
"""
55805590

55815591
helps['network vpn-connection delete'] = """
@@ -5689,13 +5699,32 @@
56895699
helps['network vpn-connection update'] = """
56905700
type: command
56915701
short-summary: Update a VPN connection.
5702+
long-summary: |
5703+
Modify properties including authentication type (PSK/Certificate) and certificate authentication payload.
5704+
parameters:
5705+
- name: --auth-type
5706+
short-summary: Set authentication type (PSK or Certificate).
5707+
- name: --cert-auth
5708+
short-summary: Certificate authentication payload can be a Json string or a file path. Expected keys (outboundAuthCertificate, inboundAuthCertificateChain, inboundAuthCertificateSubjectName).
56925709
examples:
56935710
- name: Add BGP to an existing connection.
56945711
text: az network vpn-connection update -g MyResourceGroup -n MyConnection --enable-bgp True
56955712
- name: Update a VPN connection. (autogenerated)
56965713
text: |
56975714
az network vpn-connection update --name MyConnection --resource-group MyResourceGroup --use-policy-based-traffic-selectors true
56985715
crafted: true
5716+
- name: Switch a PSK connection to Certificate auth using a JSON file
5717+
text: |
5718+
az network vpn-connection update -g MyResourceGroup -n MyConnection --auth-type Certificate --cert-auth @cert_auth.json
5719+
- name: Update Certificate chain and subject name inline
5720+
text: |
5721+
az network vpn-connection update -g MyResourceGroup -n MyConnection --cert-auth '{
5722+
"inboundAuthCertificateChain": [
5723+
"MIIC+TCCAeGgAwIBAgIQFOJUqDaxV5xJcKpTKO...",
5724+
"MIIC+TCCAeGgAwIBAgIQPJerInitNblK7yBgkqh..."
5725+
],
5726+
"inboundAuthCertificateSubjectName": "CN=rootCert.com"
5727+
}'
56995728
"""
57005729

57015730
helps['network vpn-connection show-device-config-script'] = """

src/azure-cli/azure/cli/command_modules/network/_params.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from azure.cli.command_modules.network._actions import (
3636
TrustedClientCertificateCreate,
3737
SslProfilesCreate, AddMappingRequest, WAFRulesCreate)
38+
from azure.cli.core.util import shell_safe_json_parse
3839

3940

4041
# pylint: disable=too-many-locals, too-many-branches, too-many-statements
@@ -781,6 +782,11 @@ def load_arguments(self, _):
781782
for item in ['vnet_gateway2', 'local_gateway2', 'express_route_circuit2']:
782783
c.argument(item, arg_group='Destination')
783784

785+
c.argument('auth_type', options_list=['--authentication-type', '--auth-type'], help='Authentication type for the VPN connection.', arg_type=get_enum_type(['Certificate', 'PSK']))
786+
c.argument('cert_auth', options_list=['--certificate-authentication', '--cert-auth'],
787+
help='Certificate-based authentication configuration. Provide as JSON string or file path with @ prefix, Expected keys (outboundAuthCertificate, inboundAuthCertificateChain, inboundAuthCertificateSubjectName).',
788+
type=shell_safe_json_parse)
789+
784790
with self.argument_context('network routeserver') as c:
785791
c.argument('virtual_hub_name', options_list=['--name', '-n'], id_part='name',
786792
help='Name of the route server.')

src/azure-cli/azure/cli/command_modules/network/_template_builder.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ def build_vnet_resource(_, name, location, tags, vnet_prefix=None, subnet=None,
464464

465465
def build_vpn_connection_resource(cmd, name, location, tags, gateway1, gateway2, vpn_type, authorization_key,
466466
enable_bgp, routing_weight, shared_key, use_policy_based_traffic_selectors,
467-
express_route_gateway_bypass, ingress_nat_rule, egress_nat_rule):
467+
express_route_gateway_bypass, ingress_nat_rule, egress_nat_rule, auth_type, cert_auth):
468468
vpn_properties = {
469469
'virtualNetworkGateway1': {'id': gateway1},
470470
'enableBgp': enable_bgp,
@@ -500,12 +500,18 @@ def build_vpn_connection_resource(cmd, name, location, tags, gateway1, gateway2,
500500
if egress_nat_rule:
501501
vpn_properties['egressNatRules'] = [{'id': rule} for rule in egress_nat_rule]
502502

503+
if auth_type:
504+
vpn_properties['authenticationType'] = auth_type
505+
506+
if cert_auth:
507+
vpn_properties['certificateAuthentication'] = cert_auth
508+
503509
vpn_connection = {
504510
'type': 'Microsoft.Network/connections',
505511
'name': name,
506512
'location': location,
507513
'tags': tags,
508-
'apiVersion': '2015-06-15',
514+
'apiVersion': '2025-01-01',
509515
'dependsOn': [],
510516
'properties': vpn_properties if vpn_type != 'VpnClient' else {}
511517
}

src/azure-cli/azure/cli/command_modules/network/_validators.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,13 @@ def process_vpn_connection_create_namespace(cmd, namespace):
646646
raise ValueError('usage error: --vnet-gateway2 NAME_OR_ID | --local-gateway2 NAME_OR_ID '
647647
'| --express-route-circuit2 NAME_OR_ID')
648648

649+
def _normalize_shared_key_fields(n):
650+
# Turn "" into None so the sdk layer won’t serialize them
651+
if getattr(n, 'shared_key', None) == '':
652+
n.shared_key = None
653+
if getattr(n, 'shared_key_keyvault_id', None) == '':
654+
n.shared_key_keyvault_id = None
655+
649656
def _validate_name_or_id(value, resource_type):
650657
if not is_valid_resource_id(value):
651658
subscription = getattr(namespace, 'subscription', get_subscription_id(cmd.cli_ctx))
@@ -657,6 +664,10 @@ def _validate_name_or_id(value, resource_type):
657664
name=value)
658665
return value
659666

667+
auth = (getattr(namespace, 'auth_type', '') or '').strip().lower()
668+
669+
_normalize_shared_key_fields(namespace)
670+
660671
if (namespace.local_gateway2 or namespace.vnet_gateway2) and not namespace.shared_key:
661672
raise CLIError('--shared-key is required for VNET-to-VNET or Site-to-Site connections.')
662673

@@ -680,6 +691,14 @@ def _validate_name_or_id(value, resource_type):
680691
_validate_name_or_id(namespace.vnet_gateway2, 'virtualNetworkGateways')
681692
namespace.connection_type = 'Vnet2Vnet'
682693

694+
if auth == 'certificate':
695+
# SharedKey/SharedKeyKeyvaultId should be empty when AuthenticationType is Certificate.
696+
# Follow the link for more details : https://go.microsoft.com/fwlink/?linkid=2208263
697+
if getattr(namespace, 'shared_key', None):
698+
namespace.shared_key = None
699+
if getattr(namespace, 'shared_key_keyvault_id', None):
700+
namespace.shared_key_keyvault_id = None
701+
683702

684703
def load_cert_file(param_name):
685704
def load_cert_validator(namespace):

src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/vnet_gateway/_create.py

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ class Create(AAZCommand):
3131
"""
3232

3333
_aaz_info = {
34-
"version": "2024-07-01",
34+
"version": "2025-01-01",
3535
"resources": [
36-
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/virtualnetworkgateways/{}", "2024-07-01"],
36+
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/virtualnetworkgateways/{}", "2025-01-01"],
3737
]
3838
}
3939

@@ -228,6 +228,8 @@ def _build_arguments_schema(cls, *args, **kwargs):
228228

229229
# define Arg Group "BgpSettings"
230230

231+
# define Arg Group "CustomRoutes"
232+
231233
# define Arg Group "Identity"
232234

233235
_args_schema = cls._args_schema
@@ -423,6 +425,7 @@ def _build_arguments_schema(cls, *args, **kwargs):
423425
def _build_args_address_space_create(cls, _schema):
424426
if cls._args_address_space_create is not None:
425427
_schema.address_prefixes = cls._args_address_space_create.address_prefixes
428+
_schema.ipam_pool_prefix_allocations = cls._args_address_space_create.ipam_pool_prefix_allocations
426429
return
427430

428431
cls._args_address_space_create = AAZObjectArg()
@@ -432,11 +435,29 @@ def _build_args_address_space_create(cls, _schema):
432435
options=["address-prefixes"],
433436
help="A list of address blocks reserved for this virtual network in CIDR notation.",
434437
)
438+
address_space_create.ipam_pool_prefix_allocations = AAZListArg(
439+
options=["ipam-pool-prefix-allocations"],
440+
help="A list of IPAM Pools allocating IP address prefixes.",
441+
)
435442

436443
address_prefixes = cls._args_address_space_create.address_prefixes
437444
address_prefixes.Element = AAZStrArg()
438445

446+
ipam_pool_prefix_allocations = cls._args_address_space_create.ipam_pool_prefix_allocations
447+
ipam_pool_prefix_allocations.Element = AAZObjectArg()
448+
449+
_element = cls._args_address_space_create.ipam_pool_prefix_allocations.Element
450+
_element.number_of_ip_addresses = AAZStrArg(
451+
options=["number-of-ip-addresses"],
452+
help="Number of IP addresses to allocate.",
453+
)
454+
_element.id = AAZResourceIdArg(
455+
options=["id"],
456+
help="Resource id of the associated Azure IpamPool resource.",
457+
)
458+
439459
_schema.address_prefixes = cls._args_address_space_create.address_prefixes
460+
_schema.ipam_pool_prefix_allocations = cls._args_address_space_create.ipam_pool_prefix_allocations
440461

441462
_args_sub_resource_create = None
442463

@@ -537,7 +558,7 @@ def url_parameters(self):
537558
def query_parameters(self):
538559
parameters = {
539560
**self.serialize_query_param(
540-
"api-version", "2024-07-01",
561+
"api-version", "2025-01-01",
541562
required=True,
542563
),
543564
}
@@ -706,7 +727,7 @@ def content(self):
706727
vpn_client_configuration.set_prop("aadIssuer", AAZStrType, ".aad_issuer")
707728
vpn_client_configuration.set_prop("aadTenant", AAZStrType, ".aad_tenant")
708729
vpn_client_configuration.set_prop("radiusServerAddress", AAZStrType, ".radius_server")
709-
vpn_client_configuration.set_prop("radiusServerSecret", AAZStrType, ".radius_secret")
730+
vpn_client_configuration.set_prop("radiusServerSecret", AAZStrType, ".radius_secret", typ_kwargs={"flags": {"secret": True}})
710731
vpn_client_configuration.set_prop("vpnAuthenticationTypes", AAZListType, ".vpn_auth_type")
711732
vpn_client_configuration.set_prop("vpnClientAddressPool", AAZObjectType)
712733
vpn_client_configuration.set_prop("vpnClientProtocols", AAZListType, ".client_protocol")
@@ -1104,6 +1125,7 @@ def _build_schema_on_200_201(cls):
11041125
)
11051126
vpn_client_configuration.radius_server_secret = AAZStrType(
11061127
serialized_name="radiusServerSecret",
1128+
flags={"secret": True},
11071129
)
11081130
vpn_client_configuration.radius_servers = AAZListType(
11091131
serialized_name="radiusServers",
@@ -1144,6 +1166,7 @@ def _build_schema_on_200_201(cls):
11441166
)
11451167
_element.radius_server_secret = AAZStrType(
11461168
serialized_name="radiusServerSecret",
1169+
flags={"secret": True},
11471170
)
11481171

11491172
vng_client_connection_configurations = cls._schema_on_200_201.properties.vpn_client_configuration.vng_client_connection_configurations
@@ -1278,11 +1301,25 @@ def _build_schema_address_space_create(cls, _builder):
12781301
if _builder is None:
12791302
return
12801303
_builder.set_prop("addressPrefixes", AAZListType, ".address_prefixes")
1304+
_builder.set_prop("ipamPoolPrefixAllocations", AAZListType, ".ipam_pool_prefix_allocations")
12811305

12821306
address_prefixes = _builder.get(".addressPrefixes")
12831307
if address_prefixes is not None:
12841308
address_prefixes.set_elements(AAZStrType, ".")
12851309

1310+
ipam_pool_prefix_allocations = _builder.get(".ipamPoolPrefixAllocations")
1311+
if ipam_pool_prefix_allocations is not None:
1312+
ipam_pool_prefix_allocations.set_elements(AAZObjectType, ".")
1313+
1314+
_elements = _builder.get(".ipamPoolPrefixAllocations[]")
1315+
if _elements is not None:
1316+
_elements.set_prop("numberOfIpAddresses", AAZStrType, ".number_of_ip_addresses")
1317+
_elements.set_prop("pool", AAZObjectType, typ_kwargs={"flags": {"client_flatten": True}})
1318+
1319+
pool = _builder.get(".ipamPoolPrefixAllocations[].pool")
1320+
if pool is not None:
1321+
pool.set_prop("id", AAZStrType, ".id")
1322+
12861323
@classmethod
12871324
def _build_schema_sub_resource_create(cls, _builder):
12881325
if _builder is None:
@@ -1295,6 +1332,7 @@ def _build_schema_sub_resource_create(cls, _builder):
12951332
def _build_schema_address_space_read(cls, _schema):
12961333
if cls._schema_address_space_read is not None:
12971334
_schema.address_prefixes = cls._schema_address_space_read.address_prefixes
1335+
_schema.ipam_pool_prefix_allocations = cls._schema_address_space_read.ipam_pool_prefix_allocations
12981336
return
12991337

13001338
cls._schema_address_space_read = _schema_address_space_read = AAZObjectType()
@@ -1303,11 +1341,36 @@ def _build_schema_address_space_read(cls, _schema):
13031341
address_space_read.address_prefixes = AAZListType(
13041342
serialized_name="addressPrefixes",
13051343
)
1344+
address_space_read.ipam_pool_prefix_allocations = AAZListType(
1345+
serialized_name="ipamPoolPrefixAllocations",
1346+
)
13061347

13071348
address_prefixes = _schema_address_space_read.address_prefixes
13081349
address_prefixes.Element = AAZStrType()
13091350

1351+
ipam_pool_prefix_allocations = _schema_address_space_read.ipam_pool_prefix_allocations
1352+
ipam_pool_prefix_allocations.Element = AAZObjectType()
1353+
1354+
_element = _schema_address_space_read.ipam_pool_prefix_allocations.Element
1355+
_element.allocated_address_prefixes = AAZListType(
1356+
serialized_name="allocatedAddressPrefixes",
1357+
flags={"read_only": True},
1358+
)
1359+
_element.number_of_ip_addresses = AAZStrType(
1360+
serialized_name="numberOfIpAddresses",
1361+
)
1362+
_element.pool = AAZObjectType(
1363+
flags={"client_flatten": True},
1364+
)
1365+
1366+
allocated_address_prefixes = _schema_address_space_read.ipam_pool_prefix_allocations.Element.allocated_address_prefixes
1367+
allocated_address_prefixes.Element = AAZStrType()
1368+
1369+
pool = _schema_address_space_read.ipam_pool_prefix_allocations.Element.pool
1370+
pool.id = AAZStrType()
1371+
13101372
_schema.address_prefixes = cls._schema_address_space_read.address_prefixes
1373+
_schema.ipam_pool_prefix_allocations = cls._schema_address_space_read.ipam_pool_prefix_allocations
13111374

13121375
_schema_sub_resource_read = None
13131376

src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/vnet_gateway/_delete.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ class Delete(AAZCommand):
2424
"""
2525

2626
_aaz_info = {
27-
"version": "2024-07-01",
27+
"version": "2025-01-01",
2828
"resources": [
29-
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/virtualnetworkgateways/{}", "2024-07-01"],
29+
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/virtualnetworkgateways/{}", "2025-01-01"],
3030
]
3131
}
3232

@@ -144,7 +144,7 @@ def url_parameters(self):
144144
def query_parameters(self):
145145
parameters = {
146146
**self.serialize_query_param(
147-
"api-version", "2024-07-01",
147+
"api-version", "2025-01-01",
148148
required=True,
149149
),
150150
}

0 commit comments

Comments
 (0)