Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ def cf_replicas(cli_ctx, *_):
return get_appconfig_service_client(cli_ctx).replicas


def cf_nsp_configurations(cli_ctx, *_):
return get_appconfig_service_client(cli_ctx).network_security_perimeter_configurations


def cf_configstore_operations(cli_ctx, *_):
try:
return get_appconfig_service_client(cli_ctx).operations
Expand Down
14 changes: 14 additions & 0 deletions src/azure-cli/azure/cli/command_modules/appconfig/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def configstore_snapshot_output_format(result):
return _output_format(result, _snapshot_output_format_group)


def configstore_nsp_output_format(result):
return _output_format(result, _configstore_nsp_format_group)


def _output_format(result, format_group):
if 'value' in result and isinstance(result['value'], list):
result = result['value']
Expand Down Expand Up @@ -164,6 +168,16 @@ def _featurefilter_entry_format_group(item):
])


def _configstore_nsp_format_group(item):
return OrderedDict([
('PERIMETER ID', _get_value(item, 'properties', 'networkSecurityPerimeter', 'id')),
('PROFILE NAME', _get_value(item, 'properties', 'profile', 'name')),
('ACCESS MODE', _get_value(item, 'properties', 'resourceAssociation', 'accessMode')),
('ACCESS RULES VERSION', _get_value(item, 'properties', 'profile', 'accessRulesVersion')),
('DIAGNOSTIC SETTINGS VERSION', _get_value(item, 'properties', 'profile', 'diagnosticSettingsVersion'))
])


def _format_datetime(date_string):
from dateutil.parser import parse
try:
Expand Down
32 changes: 32 additions & 0 deletions src/azure-cli/azure/cli/command_modules/appconfig/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,38 @@
short-summary: Manage snapshots associated with an app configuration store.
"""

helps['appconfig network-security-perimeter-configuration'] = """
type: group
short-summary: Manage network security perimeter configurations for an App Configuration store.
"""

helps['appconfig network-security-perimeter-configuration list'] = """
type: command
short-summary: List all network security perimeter configurations for an App Configuration store.
examples:
- name: List all network security perimeter configurations for an App Configuration store.
text:
az appconfig network-security-perimeter-configuration list --store-name MyAppConfiguration -g MyResourceGroup
"""

helps['appconfig network-security-perimeter-configuration show'] = """
type: command
short-summary: Show a specific network security perimeter configuration for an App Configuration store.
examples:
- name: Show a network security perimeter configuration by name.
text:
az appconfig network-security-perimeter-configuration show --store-name MyAppConfiguration -g MyResourceGroup --name MyNspConfigurationName
"""

helps['appconfig network-security-perimeter-configuration reconcile'] = """
type: command
short-summary: Force a refresh of the specified network security perimeter configuration for an App Configuration store.
examples:
- name: Reconcile a network security perimeter configuration.
text:
az appconfig network-security-perimeter-configuration reconcile --store-name MyAppConfiguration -g MyResourceGroup --name MyNspConfigurationName
"""

helps['appconfig snapshot create'] = """
type: command
short-summary: Create an app configuration snapshot.
Expand Down
26 changes: 23 additions & 3 deletions src/azure-cli/azure/cli/command_modules/appconfig/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
validate_resolve_keyvault, validate_export_profile, validate_import_profile,
validate_strict_import, validate_export_as_reference, validate_snapshot_filters,
validate_snapshot_export, validate_snapshot_import, validate_tag_filters,
validate_import_tag_filters, validate_dry_run, validate_kv_revision_retention_period)
validate_import_tag_filters, validate_dry_run, validate_kv_revision_retention_period,
validate_public_network_args)


def load_arguments(self, _):
Expand Down Expand Up @@ -180,7 +181,12 @@ def load_arguments(self, _):
c.argument('assign_identity', arg_type=identities_arg_type,
help='Space-separated list of managed identities to be assigned. Use "[system]" to refer to system-assigned managed identity or a resource ID to refer to user-assigned managed identity. If this argument is provided without any value, system-assigned managed identity will be assigned by default. If this argument is not provided, no managed identities will be assigned to this App Configuration store.')
c.argument('enable_public_network', options_list=['--enable-public-network', '-e'], arg_type=get_three_state_flag(),
help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.')
help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.',
deprecate_info=c.deprecate(redirect='--public-network-access', hide=False))
c.argument('public_network_access', options_list=['--public-network-access'],
arg_type=get_enum_type(['Disabled', 'Enabled', 'SecuredByPerimeter']),
help='Control permission for data plane traffic coming from public networks. Possible values include: Disabled, Enabled, SecuredByPerimeter. NOTE: The SecuredByPerimeter mode is currently in preview.',
validator=validate_public_network_args)
c.argument('disable_local_auth', arg_type=get_three_state_flag(), help='Disable all authentication methods other than AAD authentication.')
c.argument('retention_days', arg_type=retention_days_arg_type)
c.argument('enable_purge_protection', options_list=['--enable-purge-protection', '-p'], arg_type=get_three_state_flag(), help='Property specifying whether protection against purge is enabled for this App Configuration store. Setting this property to true activates protection against purge for this App Configuration store and its contents. Enabling this functionality is irreversible.')
Expand All @@ -197,7 +203,12 @@ def load_arguments(self, _):
c.argument('sku', help='The sku of the App Configuration store', arg_type=get_enum_type(['Free', 'Developer', 'Premium', 'Standard']))
c.argument('tags', arg_type=tags_type)
c.argument('enable_public_network', options_list=['--enable-public-network', '-e'], arg_type=get_three_state_flag(),
help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.')
help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.',
deprecate_info=c.deprecate(redirect='--public-network-access', hide=False))
c.argument('public_network_access', options_list=['--public-network-access'],
arg_type=get_enum_type(['Disabled', 'Enabled', 'SecuredByPerimeter']),
help='Control permission for data plane traffic coming from public networks. Possible values include: Disabled, Enabled, SecuredByPerimeter. NOTE: The SecuredByPerimeter mode is currently in preview.',
validator=validate_public_network_args)
c.argument('disable_local_auth', arg_type=get_three_state_flag(), help='Disable all authentication methods other than AAD authentication.')
c.argument('enable_purge_protection', options_list=['--enable-purge-protection', '-p'], arg_type=get_three_state_flag(), help='Property specifying whether protection against purge is enabled for this App Configuration store. Setting this property to true activates protection against purge for this App Configuration store and its contents. Enabling this functionality is irreversible.')
c.argument('arm_auth_mode', arg_type=arm_auth_mode_arg_type)
Expand Down Expand Up @@ -473,3 +484,12 @@ def load_arguments(self, _):
c.argument('snapshot_name', options_list=['--snapshot-name', '-s'], help='If no name specified, return all snapshots by default. Support star sign as filters, for instance abc* means snapshots with abc as prefix to the name.')
c.argument('status', arg_type=snapshot_status_arg_type)
c.argument('fields', arg_type=snapshot_fields_arg_type)

with self.argument_context('appconfig network-security-perimeter-configuration') as c:
c.argument('store_name', arg_type=store_name_arg_type)

with self.argument_context('appconfig network-security-perimeter-configuration show') as c:
c.argument('name', options_list=['--name', '-n'], help='Name of the network security perimeter configuration to show.', required=True)

with self.argument_context('appconfig network-security-perimeter-configuration reconcile') as c:
c.argument('name', options_list=['--name', '-n'], help='Name of the network security perimeter configuration to reconcile.', required=True)
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,14 @@ def validate_snapshot_import(namespace):
raise MutuallyExclusiveArgumentError("'--src-snapshot' cannot be specified with '--src-key', '--src-label', or '--skip-features' arguments.")


def validate_public_network_args(namespace):
if namespace.enable_public_network is not None and namespace.public_network_access is not None:
raise MutuallyExclusiveArgumentError("Cannot specify both '--enable-public-network' and '--public-network-access'. "
"Please use '--public-network-access' as '--enable-public-network' has been deprecated.")
if namespace.public_network_access is not None and namespace.public_network_access.lower() == 'securedbyperimeter':
logger.warning("The 'SecuredByPerimeter' value is currently in preview.")


def validate_sku(namespace):
if namespace.sku.lower() == 'free':
if (namespace.enable_purge_protection or namespace.retention_days or namespace.replica_name or namespace.replica_location or namespace.no_replica or namespace.enable_arm_private_network_access): # pylint: disable=too-many-boolean-expressions
Expand Down
17 changes: 15 additions & 2 deletions src/azure-cli/azure/cli/command_modules/appconfig/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from azure.cli.core.commands import CliCommandType

from ._client_factory import cf_configstore, cf_configstore_operations, cf_replicas
from ._client_factory import cf_configstore, cf_configstore_operations, cf_replicas, cf_nsp_configurations
from ._format import (configstore_credential_format,
configstore_identity_format,
configstore_output_format,
Expand All @@ -16,7 +16,8 @@
featurefilter_entry_format,
deleted_configstore_output_format,
configstore_replica_output_format,
configstore_snapshot_output_format)
configstore_snapshot_output_format,
configstore_nsp_output_format)


def load_command_table(self, _):
Expand Down Expand Up @@ -56,6 +57,12 @@ def load_command_table(self, _):
table_transformer=configstore_snapshot_output_format
)

configstore_nsp_util = CliCommandType(
operations_tmpl='azure.cli.command_modules.appconfig.network_security_perimeter#{}',
table_transformer=configstore_nsp_output_format,
client_factory=cf_nsp_configurations
)

def get_custom_sdk(custom_module, client_factory, table_transformer):
"""Returns a CliCommandType instance with specified operation template based on the given custom module name.
This is useful when the command is not defined in the default 'custom' module but instead in a module under
Expand Down Expand Up @@ -141,3 +148,9 @@ def get_custom_sdk(custom_module, client_factory, table_transformer):
g.command('list', 'list_snapshots')
g.command('archive', 'archive_snapshot')
g.command('recover', 'recover_snapshot')

# NSP Commands
with self.command_group('appconfig network-security-perimeter-configuration', configstore_nsp_util, is_preview=True) as g:
g.command('list', 'list_nsp_configurations')
g.show_command('show', 'show_nsp_configuration')
g.command('reconcile', 'reconcile_nsp_configuration')
14 changes: 11 additions & 3 deletions src/azure-cli/azure/cli/command_modules/appconfig/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from azure.cli.core.commands.progress import IndeterminateStandardOut
from azure.cli.core.util import user_confirmation
from azure.core.exceptions import ResourceNotFoundError
from azure.cli.core.azclierror import RequiredArgumentMissingError
from azure.cli.core.azclierror import MutuallyExclusiveArgumentError, RequiredArgumentMissingError
from azure.mgmt.appconfiguration.models import (ConfigurationStoreUpdateParameters,
ConfigurationStore,
Sku,
Expand Down Expand Up @@ -48,6 +48,7 @@ def create_configstore(cmd, # pylint: disable=too-many-locals
tags=None,
assign_identity=None,
enable_public_network=None,
public_network_access=None,
disable_local_auth=None,
retention_days=None,
enable_purge_protection=None,
Expand All @@ -62,7 +63,10 @@ def create_configstore(cmd, # pylint: disable=too-many-locals
if assign_identity is not None and not assign_identity:
assign_identity = [SYSTEM_ASSIGNED_IDENTITY]

public_network_access = None
if public_network_access is not None and enable_public_network is not None:
raise MutuallyExclusiveArgumentError("Cannot specify both '--enable-public-network' and '--public-network-access'. "
"Please use '--public-network-access' as '--enable-public-network' has been deprecated.")

Comment on lines +66 to +69
if enable_public_network is not None:
public_network_access = PublicNetworkAccess.ENABLED if enable_public_network else PublicNetworkAccess.DISABLED

Expand Down Expand Up @@ -193,6 +197,7 @@ def update_configstore(cmd, # pylint: disable=too-many-locals
encryption_key_version=None,
identity_client_id=None,
enable_public_network=None,
public_network_access=None,
disable_local_auth=None,
enable_purge_protection=None,
arm_auth_mode=None,
Expand All @@ -204,7 +209,10 @@ def update_configstore(cmd, # pylint: disable=too-many-locals
if resource_group_name is None:
resource_group_name, _ = resolve_store_metadata(cmd, name)

public_network_access = None
if public_network_access is not None and enable_public_network is not None:
raise MutuallyExclusiveArgumentError("Cannot specify both '--enable-public-network' and '--public-network-access'. "
"Please use '--public-network-access' as '--enable-public-network' has been deprecated.")

if enable_public_network is not None:
public_network_access = PublicNetworkAccess.ENABLED if enable_public_network else PublicNetworkAccess.DISABLED

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long

from azure.core.exceptions import ResourceNotFoundError

from ._utils import resolve_store_metadata


def list_nsp_configurations(cmd, client, store_name, resource_group_name=None):
if resource_group_name is None:
resource_group_name, _ = resolve_store_metadata(cmd, store_name)
return client.list_by_configuration_store(resource_group_name=resource_group_name, config_store_name=store_name)


def show_nsp_configuration(cmd, client, store_name, name, resource_group_name=None):
if resource_group_name is None:
resource_group_name, _ = resolve_store_metadata(cmd, store_name)
try:
return client.get(
resource_group_name=resource_group_name,
config_store_name=store_name,
network_security_perimeter_configuration_name=name
)
except ResourceNotFoundError:
raise ResourceNotFoundError(
"The network security perimeter configuration '{}' for App Configuration '{}' was not found.".format(
name, store_name))
Comment on lines +28 to +31


def reconcile_nsp_configuration(cmd, client, store_name, name, resource_group_name=None):
if resource_group_name is None:
resource_group_name, _ = resolve_store_metadata(cmd, store_name)
try:
return client.begin_reconcile(
resource_group_name=resource_group_name,
config_store_name=store_name,
network_security_perimeter_configuration_name=name
)
except ResourceNotFoundError:
raise ResourceNotFoundError(
"The network security perimeter configuration '{}' for App Configuration '{}' was not found.".format(
name, store_name))
Loading
Loading