diff --git a/src/bastion/HISTORY.rst b/src/bastion/HISTORY.rst index 1ba5d552ef2..d7480d8bfb7 100644 --- a/src/bastion/HISTORY.rst +++ b/src/bastion/HISTORY.rst @@ -3,6 +3,11 @@ Release History =============== +0.2.2 +++++++ +* Bug fixes +* Fixes for IP address connect + 0.2.1 ++++++ * Bug fixes. diff --git a/src/bastion/README.md b/src/bastion/README.md index 9f55ee0e9c7..910fba83774 100644 --- a/src/bastion/README.md +++ b/src/bastion/README.md @@ -36,5 +36,15 @@ az network bastion rdp --name MyBastionHost --resource-group MyResourceGroup --t ### SSH to VM/VMSS using Azure Bastion host machine ```commandline -az network bastion ssh --name MyBastionHost --resource-group MyResourceGroup --enable-tunneling --target-resource-id ResourceId --auth-type password +az network bastion ssh --name MyBastionHost --resource-group MyResourceGroup --target-resource-id ResourceId --auth-type password ``` + +### RDP to Target IP address using Azure Bastion +```commandline +az network bastion rdp --name MyBastionHost --resource-group MyResourceGroup --target-ip-address 10.1.1.1 +``` + +### SSH to Target IP address using Azure Bastion +```commandline +az network bastion ssh --name MyBastionHost --resource-group MyResourceGroup --target-ip-address 10.1.1.1 --auth-type password +``` \ No newline at end of file diff --git a/src/bastion/azext_bastion/_validators.py b/src/bastion/azext_bastion/_validators.py index 5e368869e03..2f0d57292b6 100644 --- a/src/bastion/azext_bastion/_validators.py +++ b/src/bastion/azext_bastion/_validators.py @@ -17,12 +17,9 @@ def _validate_ip_address_format(namespace): input_value = namespace.target_ip_address if ' ' in input_value: raise InvalidArgumentValueError("Spaces not allowed: '{}' ".format(input_value)) - input_ips = input_value.split(',') - if len(input_ips) > 8: - raise InvalidArgumentValueError('Maximum 8 IP addresses are allowed per rule.') - validated_ips = '' - for ip in input_ips: - # Use ipaddress library to validate ip network format - ip_obj = ipaddress.ip_network(ip) - validated_ips += str(ip_obj) + ',' - namespace.target_ip_address = validated_ips[:-1] + try: + ipaddress.ip_address(input_value) + except ValueError as e: + raise InvalidArgumentValueError("""IP address provided is invalid. + Please verify if there are any spaces or other invalid characters.""") from e + namespace.target_ip_address = input_value diff --git a/src/bastion/azext_bastion/custom.py b/src/bastion/azext_bastion/custom.py index 6ef3245b970..1f31e846456 100644 --- a/src/bastion/azext_bastion/custom.py +++ b/src/bastion/azext_bastion/custom.py @@ -150,7 +150,11 @@ def ssh_bastion_host(cmd, auth_type, target_resource_id, target_ip_address, reso if bastion['sku']['name'] == BastionSku.Basic.value or bastion['sku']['name'] == BastionSku.Standard.value and bastion['enableTunneling'] is not True: raise ClientRequestError('Bastion Host SKU must be Standard and Native Client must be enabled.') - _validate_and_generate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) + ip_connect = _is_ipconnect_request(cmd, bastion, target_ip_address) + if ip_connect: + target_resource_id = f"/subscriptions/{get_subscription_id(cmd.cli_ctx)}/resourceGroups/{resource_group_name}/providers/Microsoft.Network/bh-hostConnect/{target_ip_address}" + + _validate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) bastion_endpoint = _get_bastion_endpoint(cmd, bastion, resource_port, target_resource_id) tunnel_server = _get_tunnel(cmd, bastion, bastion_endpoint, target_resource_id, resource_port) @@ -235,7 +239,10 @@ def rdp_bastion_host(cmd, target_resource_id, target_ip_address, resource_group_ raise ClientRequestError('Bastion Host SKU must be Standard and Native Client must be enabled.') ip_connect = _is_ipconnect_request(cmd, bastion, target_ip_address) - _validate_and_generate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) + if ip_connect: + target_resource_id = f"/subscriptions/{get_subscription_id(cmd.cli_ctx)}/resourceGroups/{resource_group_name}/providers/Microsoft.Network/bh-hostConnect/{target_ip_address}" + + _validate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) bastion_endpoint = _get_bastion_endpoint(cmd, bastion, resource_port, target_resource_id) if platform.system() == "Windows": @@ -284,12 +291,8 @@ def _is_ipconnect_request(cmd, bastion, target_ip_address): return False -def _validate_and_generate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address): - if target_ip_address: - if bastion['enableIpConnect'] is not True: - raise InvalidArgumentValueError("Bastion does not have IP Connect feature enabled, please enable and try again") - target_resource_id = f"/subscriptions/{get_subscription_id(cmd.cli_ctx)}/resourceGroups/{resource_group_name}/providers/Microsoft.Network/bh-hostConnect/{target_ip_address}" - elif not is_valid_resource_id(target_resource_id): +def _validate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address): + if not is_valid_resource_id(target_resource_id): err_msg = "Please enter a valid resource ID. If this is not working, " \ "try opening the JSON view of your resource (in the Overview tab), and copying the full resource ID." raise InvalidArgumentValueError(err_msg) @@ -346,7 +349,11 @@ def create_bastion_tunnel(cmd, target_resource_id, target_ip_address, resource_g if bastion['sku']['name'] == BastionSku.Basic.value or bastion['sku']['name'] == BastionSku.Standard.value and bastion['enableTunneling'] is not True: raise ClientRequestError('Bastion Host SKU must be Standard and Native Client must be enabled.') - _validate_and_generate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) + ip_connect = _is_ipconnect_request(cmd, bastion, target_ip_address) + if ip_connect: + target_resource_id = f"/subscriptions/{get_subscription_id(cmd.cli_ctx)}/resourceGroups/{resource_group_name}/providers/Microsoft.Network/bh-hostConnect/{target_ip_address}" + + _validate_resourceid(cmd, bastion, resource_group_name, target_resource_id, target_ip_address) bastion_endpoint = _get_bastion_endpoint(cmd, bastion, resource_port, target_resource_id) tunnel_server = _get_tunnel(cmd, bastion, bastion_endpoint, target_resource_id, resource_port, port) diff --git a/src/bastion/azext_bastion/tunnel.py b/src/bastion/azext_bastion/tunnel.py index 1f9eae1e6ea..dc5a75bb566 100644 --- a/src/bastion/azext_bastion/tunnel.py +++ b/src/bastion/azext_bastion/tunnel.py @@ -93,6 +93,7 @@ def _get_auth_token(self): else: custom_header = {} + logger.debug("Content: %s", str(content)) web_address = f"https://{self.bastion_endpoint}/api/tokens" response = requests.post(web_address, data=content, headers=custom_header, verify=(not should_disable_connection_verify())) @@ -219,4 +220,5 @@ def get_port(self): return self.local_port def set_host_name(self, hostname): + logger.debug("hereeeeeee") self.host_name = hostname diff --git a/src/bastion/setup.py b/src/bastion/setup.py index d6bfe98eb92..8b7405e9e8b 100644 --- a/src/bastion/setup.py +++ b/src/bastion/setup.py @@ -10,7 +10,7 @@ # HISTORY.rst entry. -VERSION = '0.2.1' +VERSION = '0.2.2' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers