Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for bastion developer create #8366

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions src/bastion/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Release History
===============
1.4.0
++++++
* Add support for bastion developer create.

1.3.1
++++++
* Remove dependency on msazurerest.
Expand Down
96 changes: 78 additions & 18 deletions src/bastion/azext_bastion/aaz/latest/network/bastion/_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,17 @@ class Create(AAZCommand):
:example: Create a Azure Bastion host machine.
az network bastion create --location westus2 --name MyBastionHost --public-ip-address MyPublicIpAddress --resource-group MyResourceGroup --vnet-name MyVnet

:example: Create a Azure Bastion host machine with zones.
:example: Create Bastion Host With Zones
az network bastion create --location westus2 --name MyBastionHost --public-ip-address MyPublicIpAddress --resource-group MyResourceGroup --vnet-name MyVnet --zones 1 2 3

:example: Create Bastion Host with Session Recording.
az network bastion create --location westus2 --name MyBastionHost --public-ip-address MyPublicIpAddress --resource-group MyResourceGroup --vnet-name MyVnet --zones 1 2 3 --sku Premium --session-recording

:example: Create Developer SKU Bastion
az network bastion create --name MyBastion --resource-group MyResourceGroup --sku Developer --vnet-name MyVnet

:example: Create Developer SKU Bastion with Network ACLs IP rules
az network bastion create --name MyBastion --resource-group MyResourceGroup --sku Developer --vnet-name MyVnet --network-acls-ips "1.1.1.1/16 100.64.0.0/10"
"""

_aaz_info = {
Expand Down Expand Up @@ -57,6 +66,12 @@ def _build_arguments_schema(cls, *args, **kwargs):
help="Resource group name of the Bastion Host.",
required=True,
)
_args_schema.sku = AAZStrArg(
options=["--sku"],
help="The name of the sku of this Bastion Host.",
default="Standard",
enum={"Basic": "Basic", "Developer": "Developer", "Premium": "Premium", "Standard": "Standard"},
)

# define Arg Group "Parameters"

Expand All @@ -68,25 +83,18 @@ def _build_arguments_schema(cls, *args, **kwargs):
resource_group_arg="resource_group",
),
)

_args_schema.tags = AAZDictArg(
options=["--tags"],
arg_group="Parameters",
help="Resource tags.",
default={},
)
_args_schema.zones = AAZListArg(
options=["--zones"],
arg_group="Parameters",
help="A list of availability zones denoting where the resource needs to come from.",
)

_args_schema.sku = AAZStrArg(
options=["--sku"],
help="Sku of this Bastion Host.",
default="Standard",
enum={"Basic": "Basic", "Premium": "Premium", "Standard": "Standard"},
)

tags = cls._args_schema.tags
tags.Element = AAZStrArg()

Expand Down Expand Up @@ -143,6 +151,11 @@ def _build_arguments_schema(cls, *args, **kwargs):
arg_group="Properties",
help="IP configuration of the Bastion Host resource.",
)
_args_schema.network_acls = AAZListArg(
options=["--network-acls"],
arg_group="Properties",
help="[Supported in Developer SKU only] The Network ACLs IP rules.",
)
_args_schema.scale_units = AAZIntArg(
options=["--scale-units"],
arg_group="Properties",
Expand All @@ -153,6 +166,12 @@ def _build_arguments_schema(cls, *args, **kwargs):
minimum=2,
),
)
_args_schema.virtual_network = AAZObjectArg(
options=["--virtual-network"],
arg_group="Properties",
help="Reference to an existing virtual network required for Developer Bastion Host only.",
)
cls._build_args_sub_resource_create(_args_schema.virtual_network)

ip_configurations = cls._args_schema.ip_configurations
ip_configurations.Element = AAZObjectArg()
Expand Down Expand Up @@ -182,6 +201,14 @@ def _build_arguments_schema(cls, *args, **kwargs):
)
cls._build_args_sub_resource_create(_element.subnet)

network_acls = cls._args_schema.network_acls
network_acls.Element = AAZObjectArg()

_element = cls._args_schema.network_acls.Element
_element.address_prefix = AAZStrArg(
options=["address-prefix"],
help="Specifies the IP or IP range in CIDR format. Only IPV4 address is allowed.",
)
return cls._args_schema

_args_sub_resource_create = None
Expand Down Expand Up @@ -316,15 +343,19 @@ def content(self):

properties = _builder.get(".properties")
if properties is not None:
properties.set_prop("disableCopyPaste", AAZBoolType, ".disable_copy_paste")
properties.set_prop("enableFileCopy", AAZBoolType, ".enable_file_copy")
properties.set_prop("enableIpConnect", AAZBoolType, ".enable_ip_connect")
properties.set_prop("enableKerberos", AAZBoolType, ".enable_kerberos")
properties.set_prop("enableSessionRecording", AAZBoolType, ".enable_session_recording")
properties.set_prop("enableShareableLink", AAZBoolType, ".enable_shareable_link")
properties.set_prop("enableTunneling", AAZBoolType, ".enable_tunneling")
properties.set_prop("ipConfigurations", AAZListType, ".ip_configurations")
properties.set_prop("scaleUnits", AAZIntType, ".scale_units")
if (self.ctx.args.sku == "Developer"):
properties.set_prop("networkAcls", AAZObjectType)
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("virtualNetwork", AAZObjectType, ".virtual_network"))
else:
properties.set_prop("disableCopyPaste", AAZBoolType, ".disable_copy_paste")
properties.set_prop("enableFileCopy", AAZBoolType, ".enable_file_copy")
properties.set_prop("enableIpConnect", AAZBoolType, ".enable_ip_connect")
properties.set_prop("enableKerberos", AAZBoolType, ".enable_kerberos")
properties.set_prop("enableSessionRecording", AAZBoolType, ".enable_session_recording")
properties.set_prop("enableShareableLink", AAZBoolType, ".enable_shareable_link")
properties.set_prop("enableTunneling", AAZBoolType, ".enable_tunneling")
properties.set_prop("ipConfigurations", AAZListType, ".ip_configurations")
properties.set_prop("scaleUnits", AAZIntType, ".scale_units")

ip_configurations = _builder.get(".properties.ipConfigurations")
if ip_configurations is not None:
Expand All @@ -342,6 +373,18 @@ def content(self):
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("publicIPAddress", AAZObjectType, ".public_ip_address", typ_kwargs={"flags": {"required": True}}))
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("subnet", AAZObjectType, ".subnet", typ_kwargs={"flags": {"required": True}}))

network_acls = _builder.get(".properties.networkAcls")
if network_acls is not None:
network_acls.set_prop("ipRules", AAZListType, ".network_acls")

ip_rules = _builder.get(".properties.networkAcls.ipRules")
if ip_rules is not None:
ip_rules.set_elements(AAZObjectType, ".")

_elements = _builder.get(".properties.networkAcls.ipRules[]")
if _elements is not None:
_elements.set_prop("addressPrefix", AAZStrType, ".address_prefix")

sku = _builder.get(".sku")
if sku is not None:
sku.set_prop("name", AAZStrType, ".sku")
Expand Down Expand Up @@ -420,6 +463,9 @@ def _build_schema_on_200_201(cls):
properties.ip_configurations = AAZListType(
serialized_name="ipConfigurations",
)
properties.network_acls = AAZObjectType(
serialized_name="networkAcls",
)
properties.provisioning_state = AAZStrType(
serialized_name="provisioningState",
flags={"read_only": True},
Expand Down Expand Up @@ -465,6 +511,20 @@ def _build_schema_on_200_201(cls):
flags={"required": True},
)
_CreateHelper._build_schema_sub_resource_read(properties.subnet)

network_acls = cls._schema_on_200_201.properties.network_acls
network_acls.ip_rules = AAZListType(
serialized_name="ipRules",
)

ip_rules = cls._schema_on_200_201.properties.network_acls.ip_rules
ip_rules.Element = AAZObjectType()

_element = cls._schema_on_200_201.properties.network_acls.ip_rules.Element
_element.address_prefix = AAZStrType(
serialized_name="addressPrefix",
)

sku = cls._schema_on_200_201.sku
sku.name = AAZStrType()

Expand Down
39 changes: 34 additions & 5 deletions src/bastion/azext_bastion/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
import time
import json
import uuid
import re

import requests
from azure.cli.core.aaz import AAZUndefined
from azure.cli.core.azclierror import ValidationError, InvalidArgumentValueError, RequiredArgumentMissingError, \
UnrecognizedArgumentError, CLIInternalError, ClientRequestError
from azure.cli.core.commands.client_factory import get_subscription_id
Expand All @@ -38,26 +40,44 @@ def _build_arguments_schema(cls, *args, **kwargs):
# custom arguments
args_schema.public_ip_address = AAZResourceIdArg(
options=["--public-ip-address"],
help="Name or ID of Azure Public IP. The SKU of the public IP must be Standard.",
required=True,
help="[Required for all SKUs but Developer SKU] " +
"Name or Resource ID of the Public IP. The SKU of the public IP must be Standard.",
required=False,
fmt=AAZResourceIdArgFormat(
template="/subscriptions/{subscription}/resourceGroups/{resource_group}/providers/Microsoft.Network"
"/publicIPAddresses/{}",
),
)
args_schema.vnet_name = AAZStrArg(
options=["--vnet-name"],
help="Name of the virtual network. It must have a subnet called AzureBastionSubnet",
help="Name or Resource ID of the Virtual Network. " +
"For all SKUs but Developer SKU, this virtual network must have a subnet called AzureBastionSubnet.",
required=True,
)
args_schema.network_acls_ips = AAZStrArg(
options=["--network-acls-ips"],
arg_group="Properties",
help="[Supported in Developer SKU only] Network ACLs IP rules. Space-separated list of IP addresses.",
required=False,
)
# filter arguments
args_schema.ip_configurations._registered = False
args_schema.virtual_network._registered = False
args_schema.network_acls._registered = False
return args_schema

def pre_operations(self):
args = self.ctx.args
subnet_id = f"/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}" \
f"/providers/Microsoft.Network/virtualNetworks/{args.vnet_name}/subnets/AzureBastionSubnet"

pattern = r"^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft\.Network/virtualNetworks/[^/]+$"
vnet_id = ""
if re.match(pattern, str(args.vnet_name)):
vnet_id = args.vnet_name
else:
vnet_id = f"/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}" \
f"/providers/Microsoft.Network/virtualNetworks/{args.vnet_name}"

subnet_id = f"{vnet_id}/subnets/AzureBastionSubnet"
args.ip_configurations = [{
"name": "bastion_ip_config",
"subnet": {"id": subnet_id}
Expand All @@ -66,6 +86,15 @@ def pre_operations(self):
if args.public_ip_address is not None:
args.ip_configurations[0]['public_ip_address'] = {"id": args.public_ip_address}

if args.vnet_name is not None:
args.virtual_network = {
"id": vnet_id
}

if args.network_acls_ips != AAZUndefined:
addresses = str(args.network_acls_ips).split()
args.network_acls = [{"addressPrefix": address} for address in addresses]


SSH_EXTENSION_NAME = "ssh"
SSH_EXTENSION_MODULE = "azext_ssh.custom"
Expand Down
2 changes: 1 addition & 1 deletion src/bastion/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


# HISTORY.rst entry.
VERSION = '1.3.1'
VERSION = '1.4.0'

# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand Down
Loading