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

[Container App]: Add az containerapp ingress access-restriction group #5546

Merged
merged 32 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2e3db8a
bump version
StrawnSC Sep 14, 2022
3665e8b
Custom Domains on Managed Environments (#152)
runefa Sep 15, 2022
f38613a
Fixed style issues.
Sep 16, 2022
e6a2bce
Reran failing tests.
Sep 19, 2022
bba5c1f
Migrating containerapp-compose into containerapp
pauldotyu Sep 20, 2022
56c2777
Merge pull request #155 from smurawski/compose-migration
StrawnSC Sep 21, 2022
226c11e
fix style
StrawnSC Sep 21, 2022
bb564dc
fix tests
StrawnSC Sep 22, 2022
77be903
Revert "Migrating containerapp-compose into containerapp"
StrawnSC Sep 22, 2022
a77a1a9
Merge pull request #157 from calvinsID/revert-155-compose-migration
StrawnSC Sep 22, 2022
474cb50
Added exposedPort to models.
Sep 23, 2022
f47f244
Merge branch 'containerapp-0.3.12' of https://github.com/calvinsID/az…
Sep 23, 2022
8efcac5
TCP support. (#156)
runefa Sep 23, 2022
e2569be
Initial work.
Sep 30, 2022
15e05e4
Finished work.
runefa Oct 10, 2022
b750ed6
Finished ip restriction tests. Moved supporting function to util.
runefa Oct 20, 2022
3ad79cf
Deleted test recordings.
runefa Nov 14, 2022
45417c9
Merge remote-tracking branch 'upstream/main' into ipsecurity
runefa Nov 14, 2022
fb762a9
Added help. Fixed style issues.
runefa Nov 14, 2022
a89012b
Added tests for deny restrictions.
runefa Nov 15, 2022
802f5bf
Updated help text.
runefa Nov 17, 2022
f937ad1
Updated command names and associated help and params.
runefa Nov 17, 2022
4ae10c6
Updated tests.
runefa Nov 17, 2022
93a2109
Update src/containerapp/azext_containerapp/_params.py
runefa Nov 17, 2022
25cde45
Update src/containerapp/azext_containerapp/_params.py
runefa Nov 17, 2022
6794a01
Update src/containerapp/azext_containerapp/_params.py
runefa Nov 17, 2022
6a4bee4
Update src/containerapp/azext_containerapp/_params.py
runefa Nov 17, 2022
77ef1da
Update src/containerapp/azext_containerapp/_help.py
runefa Nov 17, 2022
1b67c30
Update src/containerapp/azext_containerapp/_help.py
runefa Nov 17, 2022
32a4963
Update src/containerapp/azext_containerapp/_help.py
runefa Nov 17, 2022
447c78c
Update src/containerapp/azext_containerapp/_help.py
runefa Nov 17, 2022
21f557a
Update src/containerapp/azext_containerapp/_help.py
runefa Nov 17, 2022
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/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

0.3.15
++++++
* Add 'az containerapp containerapp ingress ip-restriction' command group to manage IP restrictions on the ingress of a container app.

0.3.14
++++++
* 'az containerapp logs show'/'az containerapp exec': Fix "KeyError" bug
Expand Down
32 changes: 32 additions & 0 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,38 @@
az containerapp ingress traffic show -n MyContainerapp -g MyResourceGroup
"""

helps['containerapp ingress ip-restriction'] = """
type: group
short-summary: Commands to manage ip security restrictions.
"""

helps['containerapp ingress ip-restriction set'] = """
type: command
short-summary: Configure ip security restrictions for a container app.
examples:
- name: Add an allow ip security restriction.
text: |
az containerapp ingress ip-restriction set --ip-restriction-name restrictionName --ip-address-range 192.168.1.1/32 --description "Restriction description." --allow-access
"""

helps['containerapp ingress ip-restriction remove'] = """
type: command
short-summary: Remove ip security restrictions from a container app.
examples:
- name: Remove an ip security restriction.
text: |
az containerapp ingress ip-restriction remove --ip-restriction-name restrictionName
"""

helps['containerapp ingress ip-restriction show'] = """
type: command
short-summary: Show ip security restrictions for a container app.
examples:
- name: Show ip security restrictions.
text: |
az containerapp ingress ip-restriction show
runefa marked this conversation as resolved.
Show resolved Hide resolved
"""

# Registry Commands
helps['containerapp registry'] = """
type: group
Expand Down
6 changes: 6 additions & 0 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ def load_arguments(self, _):
c.argument('target_port', type=int, validator=validate_target_port, help="The application port used for ingress traffic.")
c.argument('exposed_port', type=int, help="Additional exposed port. Only supported by tcp transport protocol. Must be unique per environment if the app ingress is external.")

with self.argument_context('containerapp ingress ip-restriction') as c:
c.argument('allow_access', help='Boolean indicating whether the ip security restriction allows or denies access.')
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we define this parameter as action='store_true' ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This parameter changes frequently, and we wouldn't want the default behavior to change (i.e. customers might create an ip restriction that allows when they want to block an ip range)

Copy link
Contributor

@zhoxing-ms zhoxing-ms Nov 18, 2022

Choose a reason for hiding this comment

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

@haroonf If the design of this parameter is not stable and has not been finalized, please add the is_preview flag to it.

c.argument('ip_restriction_name', help="The ip security restriction name.")
c.argument('description', help="The description of the ip security restriction.")
runefa marked this conversation as resolved.
Show resolved Hide resolved
c.argument('ip_address_range', help="The ip address range of the ip security restriction.")

with self.argument_context('containerapp ingress traffic') as c:
c.argument('revision_weights', nargs='+', options_list=['--revision-weight', c.deprecate(target='--traffic-weight', redirect='--revision-weight')], help="A list of revision weight(s) for the container app. Space-separated values in 'revision_name=weight' format. For latest revision, use 'latest=weight'")
c.argument('label_weights', nargs='+', options_list=['--label-weight'], help="A list of label weight(s) for the container app. Space-separated values in 'label_name=weight' format.")
Expand Down
20 changes: 20 additions & 0 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,26 @@ def list_environment_locations(cmd):
return res_locations


def set_ip_restrictions(ip_restrictions, ip_restriction_name, ip_address_range, description, allow_access):
updated = False
for e in ip_restrictions:
if ip_restriction_name.lower() == e["name"].lower():
e["description"] = description
e["ipAddressRange"] = ip_address_range
e["action"] = "Allow" if allow_access else "Deny"
updated = True
break
if not updated:
new_ip_restriction = {
"name": ip_restriction_name,
"description": description,
"ipAddressRange": ip_address_range,
"action": "Allow" if allow_access else "Deny"
}
ip_restrictions.append(new_ip_restriction)
return ip_restrictions


def _azure_monitor_quickstart(cmd, name, resource_group_name, storage_account, logs_destination):
if logs_destination != "azure-monitor":
if storage_account:
Expand Down
5 changes: 5 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ def load_command_table(self, _):
g.custom_command('set', 'set_ingress_traffic', exception_handler=ex_handler_factory())
g.custom_show_command('show', 'show_ingress_traffic')

with self.command_group('containerapp ingress ip-restriction') as g:
g.custom_command('set', 'set_ip_restriction', exception_handler=ex_handler_factory())
g.custom_command('remove', 'remove_ip_restriction')
runefa marked this conversation as resolved.
Show resolved Hide resolved
g.custom_show_command('show', 'show_ip_restrictions')

with self.command_group('containerapp registry') as g:
g.custom_command('set', 'set_registry', exception_handler=ex_handler_factory())
g.custom_show_command('show', 'show_registry')
Expand Down
85 changes: 84 additions & 1 deletion src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
generate_randomized_cert_name, _get_name, load_cert_file, check_cert_name_availability,
validate_hostname, patch_new_custom_domain, get_custom_domains, _validate_revision_name, set_managed_identity,
create_acrpull_role_assignment, is_registry_msi_system, clean_null_values, _populate_secret_values,
validate_environment_location, safe_set, parse_metadata_flags, parse_auth_flags, _azure_monitor_quickstart)
validate_environment_location, safe_set, parse_metadata_flags, parse_auth_flags, _azure_monitor_quickstart,
set_ip_restrictions)
from ._validators import validate_create, validate_revision_suffix
from ._ssh_utils import (SSH_DEFAULT_ENCODING, WebSocketConnection, read_ssh, get_stdin_writer, SSH_CTRL_C_MSG,
SSH_BACKUP_ENCODING)
Expand Down Expand Up @@ -1951,6 +1952,88 @@ def show_ingress_traffic(cmd, name, resource_group_name):
raise ValidationError("Ingress must be enabled to show ingress traffic. Try running `az containerapp ingress -h` for more info.") from e


def set_ip_restriction(cmd, name, resource_group_name, ip_restriction_name, ip_address_range, description=None, allow_access=False, no_wait=False):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

containerapp_def = None
try:
containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name)
except:
pass

if not containerapp_def:
raise ResourceNotFoundError(f"The containerapp '{name}' does not exist in group '{resource_group_name}'")

ip_restrictions = safe_get(containerapp_def, "properties", "configuration", "ingress", "ipSecurityRestrictions", default=[])

ip_security_restrictions = set_ip_restrictions(ip_restrictions, ip_restriction_name, ip_address_range, description, allow_access)
containerapp_patch = {}
safe_set(containerapp_patch, "properties", "configuration", "ingress", "ipSecurityRestrictions", value=ip_security_restrictions)
try:
r = ContainerAppClient.update(
cmd=cmd, resource_group_name=resource_group_name, name=name, container_app_envelope=containerapp_patch, no_wait=no_wait)
return r['properties']['configuration']['ingress']['ipSecurityRestrictions']
except Exception as e:
handle_raw_exception(e)


def remove_ip_restriction(cmd, name, resource_group_name, ip_restriction_name, no_wait=False):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

containerapp_def = None
try:
containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name)
except:
pass

if not containerapp_def:
raise ResourceNotFoundError("The containerapp '{}' does not exist".format(name))

ip_restrictions = safe_get(containerapp_def, "properties", "configuration", "ingress", "ipSecurityRestrictions", default=[])

restriction_removed = False
for index, value in enumerate(ip_restrictions):
if value["name"].lower() == ip_restriction_name.lower():
ip_restrictions.pop(index)
restriction_removed = True
break

if not restriction_removed:
raise ValidationError(f"Ip restriction name '{ip_restriction_name}' does not exist.")

containerapp_patch = {}
safe_set(containerapp_patch, "properties", "configuration", "ingress", "ipSecurityRestrictions", value=ip_restrictions)
try:
r = ContainerAppClient.update(
cmd=cmd, resource_group_name=resource_group_name, name=name, container_app_envelope=containerapp_patch, no_wait=no_wait)
ip_restrictions = safe_get(r, "properties", "configuration", "ingress", "ipSecurityRestrictions", default=[])
return ip_restrictions
except Exception as e:
handle_raw_exception(e)


def show_ip_restrictions(cmd, name, resource_group_name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

containerapp_def = None
try:
containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name)
except:
pass

if not containerapp_def:
raise ResourceNotFoundError("The containerapp '{}' does not exist".format(name))

try:
try:
containerapp_def['properties']['configuration']['ingress']
except Exception as e:
raise ValidationError("Ingress must be enabled to show ip restrictions. Try running `az containerapp ingress -h` for more info.") from e
return containerapp_def['properties']['configuration']['ingress']['ipSecurityRestrictions']
except Exception as e:
return []


def show_registry(cmd, name, resource_group_name, server):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

Expand Down
Loading