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
90 changes: 88 additions & 2 deletions src/azure-cli/azure/cli/command_modules/keyvault/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,110 @@
short-summary: Manage vault private endpoint connections.
"""

helps['keyvault private-endpoint-connection approve'] = """
type: command
short-summary: Approve a private endpoint connection request for a Key Vault.
examples:
- name: Approve a private endpoint connection request for a Key Vault by ID.
text: |
az keyvault private-endpoint-connection approve --id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.KeyVault/vaults/mykv/privateEndpointConnections/mykv.00000000-0000-0000-0000-000000000000"
- name: Approve a private endpoint connection request for a Key Vault by ID.
text: |
id = (az keyvault show -n mykv --query "privateEndpointConnections[0].id")
az keyvault private-endpoint-connection approve --id $id
- name: Approve a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
az keyvault private-endpoint-connection approve -g myrg --vault-name mykv --name myconnection
- name: Approve a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
name = (az keyvault show -n mykv --query "privateEndpointConnections[0].name")
az keyvault private-endpoint-connection approve -g myrg --vault-name mykv --name $name
"""

helps['keyvault private-endpoint-connection reject'] = """
type: command
short-summary: Reject a private endpoint connection request for a Key Vault.
examples:
- name: Reject a private endpoint connection request for a Key Vault by ID.
text: |
az keyvault private-endpoint-connection reject --id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.KeyVault/vaults/mykv/privateEndpointConnections/mykv.00000000-0000-0000-0000-000000000000"
- name: Reject a private endpoint connection request for a Key Vault by ID.
text: |
id = (az keyvault show -n mykv --query "privateEndpointConnections[0].id")
az keyvault private-endpoint-connection reject --id $id
- name: Reject a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
az keyvault private-endpoint-connection reject -g myrg --vault-name mykv --name myconnection
- name: Reject a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
name = (az keyvault show -n mykv --query "privateEndpointConnections[0].name")
az keyvault private-endpoint-connection reject -g myrg --vault-name mystorageaccount --name $name
"""

helps['keyvault private-endpoint-connection delete'] = """
type: command
short-summary: Delete the specified private endpoint connection associated with a Key Vault.
examples:
- name: Delete a private endpoint connection request for a Key Vault by ID.
text: |
az keyvault private-endpoint-connection delete --id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.KeyVault/vaults/mykv/privateEndpointConnections/mykv.00000000-0000-0000-0000-000000000000"
- name: Delete a private endpoint connection request for a Key Vault by ID.
text: |
id = (az keyvault show -n mykv --query "privateEndpointConnections[0].id")
az keyvault private-endpoint-connection delete --id $id
- name: Delete a private endpoint connection request for a Key Vault using account name and connection name.
text: |
az keyvault private-endpoint-connection delete -g myrg --vault-name mykv --name myconnection
- name: Delete a private endpoint connection request for a Key Vault using account name and connection name.
text: |
name = (az keyvault show -n mykv --query "privateEndpointConnections[0].name")
az keyvault private-endpoint-connection delete -g myrg --vault-name mykv --name $name
"""

helps['keyvault private-endpoint-connection show'] = """
type: command
short-summary: Show details of a private endpoint connection associated with a Key Vault.
examples:
- name: Show details of a private endpoint connection request for a Key Vault by ID.
text: |
az keyvault private-endpoint-connection show --id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.KeyVault/vaults/mykv/privateEndpointConnections/mykv.00000000-0000-0000-0000-000000000000"
- name: Show details of a private endpoint connection request for a Key Vault by ID.
text: |
id = (az keyvault show -n mykv --query "privateEndpointConnections[0].id")
az keyvault private-endpoint-connection show --id $id
- name: Show details of a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
az keyvault private-endpoint-connection show -g myrg --vault-name mykv --name myconnection
- name: Show details of a private endpoint connection request for a Key Vault using vault name and connection name.
text: |
name = (az keyvault show -n mykv --query "privateEndpointConnections[0].name")
az keyvault private-endpoint-connection show -g myrg --vault-name mykv --name $name
"""

helps['keyvault private-endpoint-connection wait'] = """
type: command
short-summary: Place the CLI in a waiting state until a condition of the private endpoint connection is met.
examples:
- name: Pause CLI until the private endpoint connection is approved/rejected by ID.
text: |
az keyvault private-endpoint-connection wait --id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.KeyVault/vaults/mykv/privateEndpointConnections/mykv.00000000-0000-0000-0000-000000000000" --created
- name: Pause CLI until the private endpoint connection is approved/rejected using vault name and connection name.
text: |
az keyvault private-endpoint-connection wait -g myrg --vault-name mykv --name myconnection --created
"""

helps['keyvault private-link-resource'] = """
type: group
short-summary: Manage vault private link resources.
"""

helps['keyvault private-link-resource show'] = """
helps['keyvault private-link-resource list'] = """
type: command
short-summary: Show the private link resources supported for a Key Vault.
short-summary: List the private link resources supported for a Key Vault.
examples:
- name: Get the private link resources that need to be created for a Key Vault.
text: |
az keyvault private-link-resource list --vault-name mykv
"""

helps['keyvault recover'] = """
Expand Down
22 changes: 10 additions & 12 deletions src/azure-cli/azure/cli/command_modules/keyvault/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
validate_principal,
validate_resource_group_name, validate_x509_certificate_chain,
secret_text_encoding_values, secret_binary_encoding_values, validate_subnet,
validate_vault_id, validate_sas_definition_id, validate_storage_account_id, validate_storage_disabled_attribute,
validate_vault_id, validate_sas_definition_id,
validate_storage_account_id, validate_storage_disabled_attribute,
validate_deleted_vault_name)

# CUSTOM CHOICE LISTS
Expand Down Expand Up @@ -123,23 +124,20 @@ class CLIJsonWebKeyOperation(str, Enum):
c.argument('subnet', help='Name or ID of subnet. If name is supplied, `--vnet-name` must be supplied.')
c.argument('vnet_name', help='Name of a virtual network.', validator=validate_subnet)

with self.argument_context('keyvault private-endpoint-connection', min_api='2018-02-14') as c:
c.argument('approval_description', help='Comments for the approval.')
c.argument('private_endpoint_connection_name', options_list=['--name', '-n'], required=False,
help='The name of the private endpoint connection associated with the Key Vault. '
'Required if --id is not specified')
c.argument('vault_name', vault_name_type, required=False,
help='Name of the Key Vault. Required if --id is not specified')
c.argument('rejection_description', help='Comments for the rejection.')

for item in ['approve', 'reject', 'delete', 'show']:
for item in ['approve', 'reject', 'delete', 'show', 'wait']:
with self.argument_context('keyvault private-endpoint-connection {}'.format(item), min_api='2018-02-14') as c:
c.extra('connection_id', options_list=['--id'], required=False,
help='The ID of the private endpoint connection associated with the Key Vault. '
'If specified --vault-name and --name/-n, this should be omitted.')
c.argument('description', help='Comments for the {} operation.'.format(item))
c.argument('private_endpoint_connection_name', options_list=['--name', '-n'], required=False,
help='The name of the private endpoint connection associated with the Key Vault. '
'Required if --id is not specified')
c.argument('vault_name', vault_name_type, required=False,
help='Name of the Key Vault. Required if --id is not specified')

with self.argument_context('keyvault private-link-resource', min_api='2018-02-14') as c:
c.argument('vault_name', vault_name_type, required=True, help='Name of the Key Vault.')
c.argument('vault_name', vault_name_type, help='Name of the Key Vault.')
# endregion

# region Shared
Expand Down
30 changes: 13 additions & 17 deletions src/azure-cli/azure/cli/command_modules/keyvault/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,20 @@ def validate_policy_permissions(ns):


def validate_private_endpoint_connection_id(cmd, ns):
connection_id = ns.connection_id
connection_name = ns.private_endpoint_connection_name
vault_name = ns.vault_name
if ns.connection_id:
from azure.cli.core.util import parse_proxy_resource_id
result = parse_proxy_resource_id(ns.connection_id)
ns.resource_group_name = result['resource_group']
ns.vault_name = result['name']
ns.private_endpoint_connection_name = result['child_name_1']

if not connection_id:
if not all([connection_name, vault_name]):
raise argparse.ArgumentError(
None, 'specify both: --name/-n and --vault-name')
ns.resource_group_name = _get_resource_group_from_vault_name(cmd.cli_ctx, vault_name)
else:
if any([connection_name, vault_name]):
raise argparse.ArgumentError(
None, 'you don\'t need to specify --name/-n or --vault-name if --id is specified')

id_parts = connection_id.split('/')
ns.private_endpoint_connection_name = id_parts[-1]
ns.vault_name = id_parts[-3]
ns.resource_group_name = id_parts[-7]
if ns.vault_name and not ns.resource_group_name:
ns.resource_group_name = _get_resource_group_from_vault_name(cmd.cli_ctx, ns.vault_name)

if not all([ns.vault_name, ns.resource_group_name, ns.private_endpoint_connection_name]):
raise CLIError('incorrect usage: [--id ID | --name NAME --vault-name NAME]')

del ns.connection_id


def validate_principal(ns):
Expand Down
11 changes: 7 additions & 4 deletions src/azure-cli/azure/cli/command_modules/keyvault/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
keyvault_client_private_link_resources_factory, keyvault_data_plane_factory)

from ._validators import (
process_secret_set_namespace, process_certificate_cancel_namespace, validate_private_endpoint_connection_id)
process_secret_set_namespace, process_certificate_cancel_namespace,
validate_private_endpoint_connection_id)


# pylint: disable=too-many-locals, too-many-statements
Expand Down Expand Up @@ -82,19 +83,21 @@ def load_command_table(self, _):
min_api='2018-02-14',
client_factory=keyvault_client_private_endpoint_connections_factory,
is_preview=True) as g:
g.custom_command('approve', 'approve_private_endpoint_connection',
g.custom_command('approve', 'approve_private_endpoint_connection', supports_no_wait=True,
validator=validate_private_endpoint_connection_id)
g.custom_command('reject', 'reject_private_endpoint_connection',
g.custom_command('reject', 'reject_private_endpoint_connection', supports_no_wait=True,
validator=validate_private_endpoint_connection_id)
g.command('delete', 'delete', validator=validate_private_endpoint_connection_id)
g.show_command('show', 'get', validator=validate_private_endpoint_connection_id)
g.wait_command('wait', validator=validate_private_endpoint_connection_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

You have an additional wait command here, but I don't find you have support_no_wait for approve/reject/delete. Is there anything I missed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You have an additional wait command here, but I don't find you have support_no_wait for approve/reject/delete. Is there anything I missed?

Nice catch, I noticed this just after I submitted the PR... I will add support_no_wait for approve and reject.


with self.command_group('keyvault private-link-resource',
kv_private_link_resources_sdk,
min_api='2018-02-14',
client_factory=keyvault_client_private_link_resources_factory,
is_preview=True) as g:
g.show_command('show', 'list_by_vault')
from azure.cli.core.commands.transform import gen_dict_to_list_transform
g.command('list', 'list_by_vault', transform=gen_dict_to_list_transform(key='value'))

# Data Plane Commands
with self.command_group('keyvault key', kv_data_sdk) as g:
Expand Down
45 changes: 36 additions & 9 deletions src/azure-cli/azure/cli/command_modules/keyvault/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ def restore_storage_account(client, vault_base_url, file_path):
# region private_endpoint
def _update_private_endpoint_connection_status(cmd, client, resource_group_name, vault_name,
private_endpoint_connection_name, is_approved=True, description=None,
connection_id=None): # pylint: disable=unused-argument
no_wait=False):
PrivateEndpointServiceConnectionStatus = cmd.get_models('PrivateEndpointServiceConnectionStatus',
resource_type=ResourceType.MGMT_KEYVAULT)

Expand All @@ -1171,28 +1171,55 @@ def _update_private_endpoint_connection_status(cmd, client, resource_group_name,
private_endpoint_connection.private_link_service_connection_state.status = new_status
private_endpoint_connection.private_link_service_connection_state.description = description

return client.put(resource_group_name=resource_group_name,
vault_name=vault_name,
private_endpoint_connection_name=private_endpoint_connection_name,
properties=private_endpoint_connection)
retval = client.put(resource_group_name=resource_group_name,
vault_name=vault_name,
private_endpoint_connection_name=private_endpoint_connection_name,
properties=private_endpoint_connection)

if no_wait:
return retval

new_retval = \
_wait_private_link_operation(client, resource_group_name, vault_name, private_endpoint_connection_name)

if new_retval:
return new_retval
return retval


def _wait_private_link_operation(client, resource_group_name, vault_name, private_endpoint_connection_name):
retries = 0
max_retries = 10
wait_second = 1
while retries < max_retries:
pl = client.get(resource_group_name=resource_group_name,
vault_name=vault_name,
private_endpoint_connection_name=private_endpoint_connection_name)

if pl.provisioning_state == 'Succeeded':
return pl
time.sleep(wait_second)
retries += 1

return None


def approve_private_endpoint_connection(cmd, client, resource_group_name, vault_name, private_endpoint_connection_name,
approval_description=None, connection_id=None):
description=None, no_wait=False):
"""Approve a private endpoint connection request for a Key Vault."""

return _update_private_endpoint_connection_status(
cmd, client, resource_group_name, vault_name, private_endpoint_connection_name, is_approved=True,
description=approval_description, connection_id=connection_id
description=description, no_wait=no_wait
)


def reject_private_endpoint_connection(cmd, client, resource_group_name, vault_name, private_endpoint_connection_name,
rejection_description=None, connection_id=None):
description=None, no_wait=False):
"""Reject a private endpoint connection request for a Key Vault."""

return _update_private_endpoint_connection_status(
cmd, client, resource_group_name, vault_name, private_endpoint_connection_name, is_approved=False,
description=rejection_description, connection_id=connection_id
description=description, no_wait=no_wait
)
# endregion
Loading