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
13 changes: 13 additions & 0 deletions src/azure-cli/azure/cli/command_modules/keyvault/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,19 @@
material of a key itself cannot be changed. This operation requires the keys/update permission.
"""

helps['keyvault key get-attestation'] = """
type: command
short-summary: Get a key's attestation blob.
long-summary: This command is applicable to any key stored in Azure Key Vault Managed HSM. This operation requires the keys/get permission.
examples:
- name: Get a key's attestation.
text: |
az keyvault key get-attestation --hsm-name myhsm -n mykey
- name: Save the key's attestation to local file.
text: |
az keyvault key get-attestation --hsm-name myhsm -n mykey -f mykeyattestation.json
"""

helps['keyvault key show-deleted'] = """
type: command
short-summary: Get the public part of a deleted key.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ class CLISecurityDomainOperation(str, Enum):
# keys track2
for scope in ['create', 'import', 'set-attributes', 'show', 'show-deleted', 'delete', 'list', 'list-deleted',
'list-versions', 'encrypt', 'decrypt', 'sign', 'verify', 'recover', 'purge', 'download',
'backup', 'restore', 'rotate', 'rotation-policy show', 'rotation-policy update']:
'backup', 'restore', 'rotate', 'get-attestation', 'rotation-policy show', 'rotation-policy update']:
with self.argument_context('keyvault key {}'.format(scope), arg_group='Id') as c:
c.argument('name', options_list=['--name', '-n'], id_part='child_name_1',
required=False, completer=get_keyvault_name_completion_list('key'),
Expand All @@ -315,6 +315,13 @@ class CLISecurityDomainOperation(str, Enum):
help='The recovery id of the key. If specified all other \'Id\' arguments should be omitted.',
validator=validate_keyvault_resource_id('key'))

with self.argument_context('keyvault key get-attestation') as c:
c.argument('file_path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(),
help="File to receive the key's attestation if you want to save it.")
c.extra('hsm_name', data_plane_hsm_name_type, required=False, arg_group='Id',
help='Name of the HSM. Required if --id is not specified.')
c.ignore('vault_base_url')

with self.argument_context('keyvault key list') as c:
c.extra('include_managed', arg_type=get_three_state_flag(), default=False,
help='Include managed keys.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ def transform_key_output(result, **command_args):
if value and isinstance(value, bytes):
setattr(result.key, attr, base64.b64encode(value))

# Avoid returning attestation info together with key properties
# Customer should use specific `az keyvault key get-attestation` command
if result.properties._attributes:
result.properties._attributes.attestation = None

output = {
'attributes': result.properties._attributes,
'key': result.key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ def load_command_table(self, _):
g.keyvault_custom('create', 'create_key', transform=transform_key_output, validator=validate_key_create)
g.keyvault_command('set-attributes', 'update_key_properties', transform=transform_key_output)
g.keyvault_command('show', 'get_key', transform=transform_key_output)
g.keyvault_custom('get-attestation', 'get_key_attestation')
g.keyvault_custom('import', 'import_key', transform=transform_key_output)
g.keyvault_custom('get-policy-template', 'get_policy_template', is_preview=True)
g.keyvault_custom('encrypt', 'encrypt_key', is_preview=True, transform=transform_key_encryption_output)
Expand Down
22 changes: 20 additions & 2 deletions src/azure-cli/azure/cli/command_modules/keyvault/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from cryptography.x509 import load_pem_x509_certificate

from knack.log import get_logger
from knack.util import CLIError
from knack.util import CLIError, todict


logger = get_logger(__name__)
Expand Down Expand Up @@ -1102,6 +1102,25 @@ def list_keys(client, maxresults=None, include_managed=False):
return result


def get_key_attestation(client, name, version=None, file_path=None):
key = client.get_key_attestation(name=name, version=version)
key_attestation = key.properties.attestation
if not file_path:
return key_attestation

if os.path.isfile(file_path) or os.path.isdir(file_path):
raise CLIError("File or directory named '{}' already exists.".format(file_path))

try:
from ._command_type import _encode_hex
with open(file_path, 'w') as outfile:
json.dump(todict(_encode_hex(key_attestation)), outfile)
except Exception as ex: # pylint: disable=broad-except
if os.path.isfile(file_path):
os.remove(file_path)
raise ex


def delete_key(client, name):
return client.begin_delete_key(name).result()

Expand Down Expand Up @@ -2116,7 +2135,6 @@ def full_backup(cmd, client, storage_resource_uri=None, storage_account_name=Non
storage_resource_uri = construct_storage_uri(
cmd.cli_ctx.cloud.suffixes.storage_endpoint, storage_account_name, blob_container_name)
poller = client.begin_backup(storage_resource_uri, sas_token=token, use_managed_identity=use_managed_identity)
from knack.util import todict
result = todict(poller.result())
result['status'] = poller.status()
return result
Expand Down
Loading