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
1 change: 1 addition & 0 deletions src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Release History

**Key Vault**

* Fix #8921: Command `az keyvault key/secret/certificate list/list-deleted/list-versions` with parameter `--maxresults` do not work as intended
* Fix #10846: Calling az keyvault secret show-deleted --id <value> still says secret_name "can not" be none
* Fix #11084: Confusing encoding information

Expand Down
13 changes: 13 additions & 0 deletions src/azure-cli/azure/cli/command_modules/keyvault/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ def load_arguments(self, _):

with self.argument_context('keyvault key set-attributes') as c:
c.attributes_argument('key', KeyAttributes)

for scope in ['list', 'list-deleted', 'list-versions']:
with self.argument_context('keyvault key {}'.format(scope)) as c:
c.argument('maxresults', options_list=['--maxresults'], type=int)
Copy link
Member

Choose a reason for hiding this comment

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

is it necessary to set a upper limit on maxresults?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

What would happen if maxresults passed in is greater than 25?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fengzhou-msft CLI will throw an error message:

(env3) D:\repos\azure-cli>az keyvault secret list --vault-name bim-foo --maxresults 100
Parameter 'maxresults' must be less than 25.

Copy link
Member

Choose a reason for hiding this comment

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

Ok. At least users know the limit from the error message. If you could put it in help text, that will be more clear, just a suggestion though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fengzhou-msft Yes, I agree. I think it's a better idea that the upcoming CLI codegen system auto-generates such type of help messages from swagger file.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good to know that you will collect all these feedbacks and backpropagate to CodeGen team.

# endregion

# region KeyVault Secret
Expand All @@ -186,6 +190,11 @@ def load_arguments(self, _):
for scope in ['backup', 'restore']:
with self.argument_context('keyvault secret {}'.format(scope)) as c:
c.argument('file_path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(), help='File to receive the secret contents.')

for scope in ['list', 'list-deleted', 'list-versions']:
with self.argument_context('keyvault secret {}'.format(scope)) as c:
c.argument('maxresults', options_list=['--maxresults'], type=int)

# endregion

# region KeyVault Storage Account
Expand Down Expand Up @@ -295,4 +304,8 @@ def load_arguments(self, _):
c.argument('admin_last_name')
c.argument('admin_email')
c.argument('admin_phone')

for scope in ['list', 'list-deleted', 'list-versions']:
with self.argument_context('keyvault certificate {}'.format(scope)) as c:
c.argument('maxresults', options_list=['--maxresults'], type=int)
# endregion

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ class KeyVaultKeyScenarioTest(ScenarioTest):

@ResourceGroupPreparer(name_prefix='cli_test_keyvault_key')
def test_keyvault_key(self, resource_group):

self.kwargs.update({
'kv': self.create_random_name('cli-test-keyvault-', 24),
'loc': 'westus',
Expand All @@ -154,6 +153,8 @@ def test_keyvault_key(self, resource_group):
# list keys
self.cmd('keyvault key list --vault-name {kv}',
checks=self.check('length(@)', 1))
self.cmd('keyvault key list --vault-name {kv} --maxresults 10',
checks=self.check('length(@)', 1))

# create a new key version
key = self.cmd('keyvault key create --vault-name {kv} -n {key} -p software --disabled --ops encrypt decrypt --tags test=foo', checks=[
Expand All @@ -165,6 +166,8 @@ def test_keyvault_key(self, resource_group):
# list key versions
self.cmd('keyvault key list-versions --vault-name {kv} -n {key}',
checks=self.check('length(@)', 2))
self.cmd('keyvault key list-versions --vault-name {kv} -n {key} --maxresults 10',
checks=self.check('length(@)', 2))

# show key (latest)
self.cmd('keyvault key show --vault-name {kv} -n {key}',
Expand Down Expand Up @@ -194,13 +197,15 @@ def test_keyvault_key(self, resource_group):
self.kwargs['key_file'] = key_file
self.cmd('keyvault key backup --vault-name {kv} -n {key} --file {key_file}')
self.cmd('keyvault key delete --vault-name {kv} -n {key}')
self.cmd('keyvault key list --vault-name {kv}',
checks=self.is_empty())
self.cmd('keyvault key list --vault-name {kv}', checks=self.is_empty())
self.cmd('keyvault key list --vault-name {kv} --maxresults 10', checks=self.is_empty())

# restore key from backup
self.cmd('keyvault key restore --vault-name {kv} --file {key_file}')
self.cmd('keyvault key list-versions --vault-name {kv} -n {key}',
checks=self.check('length(@)', 2))
self.cmd('keyvault key list-versions --vault-name {kv} -n {key} --maxresults 10',
checks=self.check('length(@)', 2))
if os.path.isfile(key_file):
os.remove(key_file)

Expand Down Expand Up @@ -232,6 +237,34 @@ def test_keyvault_key(self, resource_group):
checks=[self.check('key.kty', 'EC'), self.check('key.crv', 'P-521')])


class KeyVaultSecretSoftDeleteScenarioTest(ScenarioTest):
@ResourceGroupPreparer(name_prefix='cli_test_keyvault_secret')
def test_keyvault_secret_soft_delete(self, resource_group):
self.kwargs.update({
'kv': self.create_random_name('cli-test-keyvault-', 24),
'loc': 'westus',
'sec': 'secret1'
})
_create_keyvault(self, self.kwargs, additional_args='--enable-soft-delete')
self.cmd('keyvault show -n {kv}', checks=self.check('properties.enableSoftDelete', True))
if self.is_live:
time.sleep(20)

# show deleted
self.cmd('keyvault secret set --vault-name {kv} -n {sec} --value ABC123',
checks=self.check('value', 'ABC123'))
data = self.cmd('keyvault secret delete --vault-name {kv} -n {sec}').get_output_in_json()
if self.is_live:
time.sleep(20)

self.kwargs['secret_id'] = data['id']
self.kwargs['secret_recovery_id'] = data['recoveryId']
self.cmd('keyvault secret list-deleted --vault-name {kv}', checks=self.check('length(@)', 1))
self.cmd('keyvault secret list-deleted --vault-name {kv} --maxresults 10', checks=self.check('length(@)', 1))
self.cmd('keyvault secret show-deleted --id {secret_recovery_id}', checks=self.check('id', '{secret_id}'))
self.cmd('keyvault secret show-deleted --vault-name {kv} -n {sec}', checks=self.check('id', '{secret_id}'))


class KeyVaultSecretScenarioTest(ScenarioTest):

def _test_download_secret(self):
Expand All @@ -257,7 +290,7 @@ def _test_set_and_download(encoding):
@ResourceGroupPreparer(name_prefix='cli_test_keyvault_secret')
def test_keyvault_secret(self, resource_group):
self.kwargs.update({
'kv': self.create_random_name('cli-test-kevault-', 24),
'kv': self.create_random_name('cli-test-keyvault-', 24),
'loc': 'westus',
'sec': 'secret1'
})
Expand All @@ -275,6 +308,7 @@ def test_keyvault_secret(self, resource_group):

# list secrets
self.cmd('keyvault secret list --vault-name {kv}', checks=self.check('length(@)', 1))
self.cmd('keyvault secret list --vault-name {kv} --maxresults 10', checks=self.check('length(@)', 1))

# create a new secret version
secret = self.cmd('keyvault secret set --vault-name {kv} -n {sec} --value DEF456 --tags test=foo --description "test type"', checks=[
Expand All @@ -287,6 +321,8 @@ def test_keyvault_secret(self, resource_group):
# list secret versions
self.cmd('keyvault secret list-versions --vault-name {kv} -n {sec}',
checks=self.check('length(@)', 2))
self.cmd('keyvault secret list-versions --vault-name {kv} -n {sec} --maxresults 10',
checks=self.check('length(@)', 2))

# show secret (latest)
self.cmd('keyvault secret show --vault-name {kv} -n {sec}',
Expand Down Expand Up @@ -322,30 +358,11 @@ def test_keyvault_secret(self, resource_group):

# delete secret
self.cmd('keyvault secret delete --vault-name {kv} -n {sec}')
self.cmd('keyvault secret list --vault-name {kv}',
checks=self.is_empty())
self.cmd('keyvault secret list --vault-name {kv}', checks=self.is_empty())
self.cmd('keyvault secret list --vault-name {kv} --maxresults 10', checks=self.is_empty())

self._test_download_secret()

# show deleted
self.cmd('keyvault update -n {kv} --enable-soft-delete',
checks=self.check('properties.enableSoftDelete', True))
if self.is_live:
time.sleep(20)

self.cmd('keyvault secret set --vault-name {kv} -n {sec} --value ABC123',
checks=self.check('value', 'ABC123'))
data = self.cmd('keyvault secret delete --vault-name {kv} -n {sec}').get_output_in_json()
if self.is_live:
time.sleep(20)

self.kwargs['secret_id'] = data['id']
self.kwargs['secret_recovery_id'] = data['recoveryId']
self.cmd('keyvault secret show-deleted --id {secret_recovery_id}',
checks=self.check('id', '{secret_id}'))
self.cmd('keyvault secret show-deleted --vault-name {kv} -n {sec}',
checks=self.check('id', '{secret_id}'))


class KeyVaultCertificateContactsScenarioTest(ScenarioTest):

Expand Down Expand Up @@ -570,13 +587,17 @@ def test_keyvault_certificate_crud(self, resource_group):
# list certificates
self.cmd('keyvault certificate list --vault-name {kv}',
checks=self.check('length(@)', 1))
self.cmd('keyvault certificate list --vault-name {kv} --maxresults 10',
checks=self.check('length(@)', 1))

# create a new certificate version
self.cmd('keyvault certificate create --vault-name {kv} -n cert1 -p @"{policy2_path}"', checks=[
self.check('status', 'completed'),
])

# list certificate versions
self.cmd('keyvault certificate list-versions --vault-name {kv} -n cert1 --maxresults 10',
checks=self.check('length(@)', 2))
ver_list = self.cmd('keyvault certificate list-versions --vault-name {kv} -n cert1',
checks=self.check('length(@)', 2)).get_output_in_json()

Expand Down Expand Up @@ -611,6 +632,8 @@ def test_keyvault_certificate_crud(self, resource_group):
self.cmd('keyvault certificate delete --vault-name {kv} -n cert1')
self.cmd('keyvault certificate list --vault-name {kv}',
checks=self.is_empty())
self.cmd('keyvault certificate list --vault-name {kv} --maxresults 10',
checks=self.is_empty())


def _generate_certificate(path, keyfile=None, password=None):
Expand Down