Skip to content
Merged
4 changes: 4 additions & 0 deletions src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ Release History

* Support app creation/update with the new sku name ST0, ST1, ST2.

**Key Vault**

* Add a new command `az keyvault key download` for downloading keys.

**Misc**

* Fix #6371: Support filename and environment variable completion in Bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
# CUSTOM CHOICE LISTS

secret_encoding_values = secret_text_encoding_values + secret_binary_encoding_values
certificate_format_values = ['PEM', 'DER']
key_format_values = certificate_format_values = ['PEM', 'DER']


# pylint: disable=too-many-locals, too-many-branches, too-many-statements, line-too-long
Expand Down Expand Up @@ -160,6 +160,10 @@ def load_arguments(self, _):
with self.argument_context('keyvault key backup') as c:
c.argument('file_path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(), help='Local file path in which to store key backup.')

with self.argument_context('keyvault key download') as c:
c.argument('file_path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(), help='File to receive the key contents.')
c.argument('encoding', arg_type=get_enum_type(key_format_values), options_list=['--encoding', '-e'], help='Encoding of the key, default: PEM', default='PEM')

with self.argument_context('keyvault key restore') as c:
c.argument('file_path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(), help='Local key backup from which to restore key.')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def load_command_table(self, _):
g.keyvault_custom('backup', 'backup_key', doc_string_source=data_doc_string.format('backup_key'))
g.keyvault_custom('restore', 'restore_key', doc_string_source=data_doc_string.format('restore_key'))
g.keyvault_custom('import', 'import_key')
g.keyvault_custom('download', 'download_key')

with self.command_group('keyvault secret', kv_data_sdk) as g:
g.keyvault_command('list', 'get_secrets')
Expand Down
121 changes: 119 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 @@ -4,19 +4,21 @@
# --------------------------------------------------------------------------------------------

# pylint: disable=too-many-lines

import codecs
import json
import math
import os
import time
import struct


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

from OpenSSL import crypto
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, ec
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.serialization import load_pem_private_key, Encoding, PublicFormat
from cryptography.exceptions import UnsupportedAlgorithm


Expand Down Expand Up @@ -694,6 +696,121 @@ def _private_ec_key_to_jwk(ec_key, jwk):
key_obj.t = byok_data

return client.import_key(vault_base_url, key_name, key_obj, protection == 'hsm', key_attrs, tags)


def download_key(client, file_path, vault_base_url=None, key_name=None, key_version='',
encoding=None, identifier=None): # pylint: disable=unused-argument
""" Download a key from a KeyVault. """
if os.path.isfile(file_path) or os.path.isdir(file_path):
raise CLIError("File or directory named '{}' already exists.".format(file_path))

def _bytes_to_int(b):
len_diff = 4 - len(b) % 4 if len(b) % 4 > 0 else 0
b = len_diff * b'\x00' + b # We have to patch leading zeros for using struct.unpack
bytes_num = int(math.floor(len(b) / 4))
ans = 0
items = struct.unpack('>' + 'I' * bytes_num, b)
for sub_int in items:
ans *= 2 ** 32
ans += sub_int
return ans

def _jwk_to_dict(jwk):
d = {}
if jwk.crv:
d['crv'] = jwk.crv
if jwk.kid:
d['kid'] = jwk.kid
if jwk.kty:
d['kty'] = jwk.kty
if jwk.d:
d['d'] = _bytes_to_int(jwk.d)
if jwk.dp:
d['dp'] = _bytes_to_int(jwk.dp)
if jwk.dq:
d['dq'] = _bytes_to_int(jwk.dq)
if jwk.e:
d['e'] = _bytes_to_int(jwk.e)
if jwk.k:
d['k'] = _bytes_to_int(jwk.k)
if jwk.n:
d['n'] = _bytes_to_int(jwk.n)
if jwk.p:
d['p'] = _bytes_to_int(jwk.p)
if jwk.q:
d['q'] = _bytes_to_int(jwk.q)
if jwk.qi:
d['qi'] = _bytes_to_int(jwk.qi)
if jwk.t:
d['t'] = _bytes_to_int(jwk.t)
if jwk.x:
d['x'] = _bytes_to_int(jwk.x)
if jwk.y:
d['y'] = _bytes_to_int(jwk.y)

return d

def _extract_rsa_public_key_from_jwk(jwk_dict):
e = jwk_dict.get('e', 256)
n = jwk_dict.get('n')
public = rsa.RSAPublicNumbers(e, n)
return public.public_key(default_backend())

def _extract_ec_public_key_from_jwk(jwk_dict):
if not all(k in jwk_dict for k in ['x', 'y', 'crv']):
raise CLIError('Invalid EC key: missing properties(x, y, crv)')

x = jwk_dict.get('x')
y = jwk_dict.get('y')
curves = {
'P-256': ec.SECP256R1,
'P-384': ec.SECP384R1,
'P-521': ec.SECP521R1,
'SECP256K1': ec.SECP256K1
}
curve = curves[jwk_dict['crv']]
public = ec.EllipticCurvePublicNumbers(x, y, curve())
return public.public_key(default_backend())

key = client.get_key(vault_base_url, key_name, key_version)
json_web_key = _jwk_to_dict(key.key)
key_type = json_web_key['kty']
pub_key = ''

if key_type in ['RSA', 'RSA-HSM']:
pub_key = _extract_rsa_public_key_from_jwk(json_web_key)
elif key_type in ['EC', 'EC-HSM']:
pub_key = _extract_ec_public_key_from_jwk(json_web_key)
else:
raise CLIError('Unsupported key type: {}'.format(key_type))

def _to_der(k):
return k.public_bytes(
encoding=Encoding.DER,
format=PublicFormat.SubjectPublicKeyInfo
)

def _to_pem(k):
return k.public_bytes(
encoding=Encoding.PEM,
format=PublicFormat.SubjectPublicKeyInfo
)

methods = {
'DER': _to_der,
'PEM': _to_pem
}

if encoding not in methods.keys():
raise CLIError('Unsupported encoding: {}'.format(encoding))
Copy link
Member

Choose a reason for hiding this comment

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

Let's prompt the supported encoding as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jiasli Good idea, I will add this.


try:
with open(file_path, 'wb') as f:
f.write(methods[encoding](pub_key))
except Exception as ex: # pylint: disable=broad-except
if os.path.isfile(file_path):
os.remove(file_path)
raise ex
# endregion


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIe338KHD5vHeNeB1Fhs68Kpx2jHjpqh/QZptSME/iL0oAoGCCqGSM49
AwEHoUQDQgAEclUrtHdYtNdfl7cueN47hqM6SuyPn18rpsLutGJ/qHeHqvZdnL1b
+aJBNReZlaS24LlJVjsmxn/Zcg1BID0RWg==
-----END EC PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEclUrtHdYtNdfl7cueN47hqM6SuyP
n18rpsLutGJ/qHeHqvZdnL1b+aJBNReZlaS24LlJVjsmxn/Zcg1BID0RWg==
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIMy+ZSqbwORvuWLCmEH12TJUM6zD7QGxgYczeU/2AZCyoAcGBSuBBAAK
oUQDQgAEH7Thoa/qhy7HoBSFPKOL9edHRqr305sCa7ozYkRLIe0WR98MA4LwXpZD
F3do0CMNqIYLzTJsG37DLngQZ4rJPw==
-----END EC PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH7Thoa/qhy7HoBSFPKOL9edHRqr305sC
a7ozYkRLIe0WR98MA4LwXpZDF3do0CMNqIYLzTJsG37DLngQZ4rJPw==
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDBG234N7Zwr021c4vi6M9mMz+Q3DVsAyahEqsNNY/XT3k5X3z4tfnth
/rgciYIxv1agBwYFK4EEACKhZANiAAReoBk8F60AVNazrJ9zUK1BU887MT41d5OA
oxPC5OocJGPvkSaK4NDZOOYj0IEvIw5F5y1QybXqhyfvj/0ydAxDulvvfDfmdcJ/
5o6rVip7XyFq9Kz6gnBNbQVVMbR7E/M=
-----END EC PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXqAZPBetAFTWs6yfc1CtQVPPOzE+NXeT
gKMTwuTqHCRj75EmiuDQ2TjmI9CBLyMORectUMm16ocn74/9MnQMQ7pb73w35nXC
f+aOq1Yqe18havSs+oJwTW0FVTG0exPz
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIBnqXLzys3RKGPLPC7jIbo6rIAXiXVjx4bnZu/CpuiFpnZiqUB5+pf
Kd/X1Av6ikeVYCmM1bXAxIfP4BGCUWGy2wugBwYFK4EEACOhgYkDgYYABAB8/6kF
Fy9ujL9GRaW1c2Fz9wXb1h6bg1zCWCgNWljOIEXcis8m+9Q4wfYFu51zKUI3QXqs
DkPJts9ru/xm2NOZJQDJaU+9LNPHryvkd44xniyWbWDbvPD/js6zKDCVMlvmo7CS
aOYj3QWEzoWDMVxV39KrxYVYeSrRQW2czlYrtGQQGg==
-----END EC PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAfP+pBRcvboy/RkWltXNhc/cF29Ye
m4NcwlgoDVpYziBF3IrPJvvUOMH2BbudcylCN0F6rA5DybbPa7v8ZtjTmSUAyWlP
vSzTx68r5HeOMZ4slm1g27zw/47OsygwlTJb5qOwkmjmI90FhM6FgzFcVd/Sq8WF
WHkq0UFtnM5WK7RkEBo=
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzJEYKuhIeHvKqZZtJRDtQjg17ChAZtY/yJfNqv30xnzkzOZw
Vmy7NViVQIRnkCYvAMCstja+EpEpeW02LD83teNQRKM9Nie74g7ehDn6ZZCSdQQ5
4TQemt26hMfnFVaUl376p0E398IP1leHcvYOaiVgT/ffUhNhgIUJ5sIphtf4D1p5
bWFYvs/Gd+A+Fk38hnerpl7JRF4y6p5WGJzvXKKs0QVSaQ1NHD7L1tQ0xTKra3FS
/BGwD7ZdgBZerqzBPgxRjuxzq2DQJlHtvINsFjJhsMtwI11UV5+tIBOEWPSBTIoQ
pUWGB+/4jZ44IpKlBDQuc1kqa2Y8+eO53Gxn+QIDAQABAoIBAQDK3zIai1YjtpDb
8oS3d7v0Kg6/74M++Uc0Ref/pe90UTQPSJEsBJT8aKdL3oNeX5/JnUsrQcrqWu/I
rlhFNUSoq5BVIZZ4+JrJq3ldpKoAw4mbZt+Hycp4R2DMgftYHA8s1w75hCJfISPX
q+J2TjMpbXvAks/0c6gEbuvM382THSDa+bA+BvYwilBBT347WkLdtuN9J+9qFyV9
ROJRRMYh3xGOcgs/mmlOgTSubU3Q2sIQHBTLtngOA4g456g4IH5G09GoEpAIQA8e
G7xzmkv+ECtqe9V0A/9njWIXNbO+V+01dUDiAKnnT5uzbPGT48hnA05WLUAQO2qP
5ZE4H6shAoGBAPQUXR2ByYX0e/VBF3lUo94yikRae6giM0k8MQwE1Y49FfuZwqp8
7E4hmuxlOJnvAQjzIQoHawL0fO7qLkvYcDJPxT5ROCeHKOCyJ6tGmVojppqiuq1G
RpOZ2XfIEt00rQguufYIr0V7OeP2X27Sveq0sJ/CYgX4rGABvq5OOW91AoGBANaO
t5T4qkuuxvxARx65S+imTg66U4aGz25rCj7LvcVhKmm2XCYz1ynAR81Tnh/t0RMd
8M3mUxRZU1MrbMCeYZbt5ClWmMfHKtZa29PYYcvVvqNBnqlbPGD7fBK+JyGnnd57
CQLA0WnmSDT0vBOSN+wH/Gk2IX3ekLMGBk1Zzyn1AoGAUhsfj7N/NR6fLEtvOBNu
5Gof9QpzGoYWtoYXAbIGnMiTwoVg5LUNUOMhGHCcb7vknzwaWyNPrjjMZhpE5KK0
a1hGQ8ZSm4luCNglXAptv9LKUq53GZ7QUwqoCxE0t1Dm/B+r0sXtH/Rp7vOL+t3N
oUyTNcrP6q5SXiF4IW6TB5kCgYAwNDhCm+uGvWmvWrGf0Xmgd1yqKmqBmuAXqqzO
lu+33LCut23Ul2kL1EtNci/gdIm4hc2INOsNc1QpJ2RzkiHSyver4ezJVZHmPtuM
qNyv8wG1pBSFcB4Mm/OwMlCQWxw40+OeXrut0zL90s4+h2dQ/CpVaPf1U3+m+P+J
eVf10QKBgDJZ0xVeun+aPMXqcwNppqvfKfMWsLb/Xx77O3q9SYG1JRXgIIneL8nD
8RwVQn8PbPcqdayFHZrmwhdgzIH/7dVEwd+QQKzeYos8Fvc4egpTZUrmZ1y5XeFt
OHl9TmHLSA1h8cJj0HrWCjyyi2cW+2PhY9K88V57KEn0yv5hjoBg
-----END RSA PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzJEYKuhIeHvKqZZtJRDt
Qjg17ChAZtY/yJfNqv30xnzkzOZwVmy7NViVQIRnkCYvAMCstja+EpEpeW02LD83
teNQRKM9Nie74g7ehDn6ZZCSdQQ54TQemt26hMfnFVaUl376p0E398IP1leHcvYO
aiVgT/ffUhNhgIUJ5sIphtf4D1p5bWFYvs/Gd+A+Fk38hnerpl7JRF4y6p5WGJzv
XKKs0QVSaQ1NHD7L1tQ0xTKra3FS/BGwD7ZdgBZerqzBPgxRjuxzq2DQJlHtvINs
FjJhsMtwI11UV5+tIBOEWPSBTIoQpUWGB+/4jZ44IpKlBDQuc1kqa2Y8+eO53Gxn
+QIDAQAB
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAt6f3peMvTmrOtW1Zzzl1
z05xGYVck3KeWnBb/TvPSZp8XczOa0QNCLJ+FFmvP7wyGrz7tsN3QNveITRqsk9/
1PA3MQfxHCmBziSj2NDXPynuquwfu+ew5mhgWsI/Wbx7UpAgXWTfdmrLkcWwCXqb
fR74emxVsMiItpg8aOwFhihid4ziEamMc3UX9IB6zKJN+VY3RHWa1QnFvMYXDTHj
uqFIYGEGR8I5ZlJZDV/Cxkg1LqqtXjd1gNglmcRVDOaMtvLy3WvObb8QLAJsdq+3
xUzgh6YWLb9ErQZ5WdbdEL3YVQwRCi6yYHk5dOMyLfGUtqJg6zxMLxW8Abso5ZAn
/4ULOlgsTwCZ+IT7fMa+QnrF6CjJtD93U2jdVURTGUo9PV41SO43L69Z83FqzJUZ
hIZNScERIZd5Km4EAhNJN59DNge7T+089Y3iWmLGnywwoFYjoEjXVEizZPdvSSZj
MECP3lLF0peFiWhcN2V2p3Q1yY3FF1TfNleTsIydz5O/AgMBAAE=
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Binary file not shown.
Loading