From a5e3accbb036511e618114a988ce19f8af22c9db Mon Sep 17 00:00:00 2001 From: Paymaun Date: Wed, 18 Nov 2020 17:08:36 -0800 Subject: [PATCH] Better key gen (#279) * Generate cryptographicaly secure device key. * Increment version. --- HISTORY.rst | 10 ++++++++++ azext_iot/_help.py | 10 +++++----- azext_iot/_params.py | 8 ++++---- azext_iot/commands.py | 2 +- azext_iot/common/shared.py | 2 +- azext_iot/common/utility.py | 13 +++++++------ azext_iot/constants.py | 2 +- azext_iot/operations/hub.py | 11 ++++++----- azext_iot/tests/test_iot_ext_int.py | 12 ++++++------ 9 files changed, 41 insertions(+), 29 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index a89bc382c..0d24273c0 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,15 @@ Release History =============== + +0.10.7 ++++++++++++++++ + +**IoT Hub updates** + +* Change command name from az iot hub device-identity `regenerate-key` to `renew-key` to better align with az cli core verbs. + + 0.10.6 +++++++++++++++ @@ -24,6 +33,7 @@ Release History * 'az iot hub device-identity remove-children' is deprecated use 'az iot hub device-identity children remove' instead. Deprecated command is planned to be removed by December 2021 * 'az iot hub device-identity list-children' is deprecated use 'az iot hub device-identity children list' instead. Deprecated command group is planned to be removed by December 2021 + 0.10.5 +++++++++++++++ diff --git a/azext_iot/_help.py b/azext_iot/_help.py index 3040dc9a5..7be342f37 100644 --- a/azext_iot/_help.py +++ b/azext_iot/_help.py @@ -216,15 +216,15 @@ """ helps[ - "iot hub device-identity regenerate-key" + "iot hub device-identity renew-key" ] = """ type: command - short-summary: Regenerate target keys of an IoT Hub device with sas authentication. + short-summary: Renew target keys of an IoT Hub device with sas authentication. examples: - - name: Regenerate the primary key. - text: az iot hub device-identity regenerate-key -d {device_id} -n {iothub_name} --kt primary + - name: Renew the primary key. + text: az iot hub device-identity renew-key -d {device_id} -n {iothub_name} --kt primary - name: Swap the primary and secondary keys. - text: az iot hub device-identity regenerate-key -d {device_id} -n {iothub_name} --kt swap + text: az iot hub device-identity renew-key -d {device_id} -n {iothub_name} --kt swap """ helps[ diff --git a/azext_iot/_params.py b/azext_iot/_params.py index 8bb253ed7..58839506e 100644 --- a/azext_iot/_params.py +++ b/azext_iot/_params.py @@ -31,7 +31,7 @@ JobCreateType, JobStatusType, AuthenticationType, - RegenerateKeyType, + RenewKeyType, ) from azext_iot._validators import mode2_iot_login_handler from azext_iot.assets.user_messages import info_param_properties_device @@ -416,11 +416,11 @@ def load_arguments(self, _): deprecate_info=context.deprecate() ) - with self.argument_context('iot hub device-identity regenerate-key') as context: + with self.argument_context('iot hub device-identity renew-key') as context: context.argument( - "regenerate_key", + "renew_key_type", options_list=["--key-type", "--kt"], - arg_type=get_enum_type(RegenerateKeyType), + arg_type=get_enum_type(RenewKeyType), help="Target key type to regenerate." ) diff --git a/azext_iot/commands.py b/azext_iot/commands.py index 1fe5317d5..68a1e021b 100644 --- a/azext_iot/commands.py +++ b/azext_iot/commands.py @@ -40,7 +40,7 @@ def load_command_table(self, _): setter_name="iot_device_update", custom_func_name="update_iot_device_custom" ) - cmd_group.command("regenerate-key", 'iot_device_key_regenerate') + cmd_group.command("renew-key", 'iot_device_key_regenerate') cmd_group.command( "show-connection-string", "iot_get_device_connection_string", diff --git a/azext_iot/common/shared.py b/azext_iot/common/shared.py index 6440659cd..3754e8c0d 100644 --- a/azext_iot/common/shared.py +++ b/azext_iot/common/shared.py @@ -216,7 +216,7 @@ class AuthenticationType(Enum): identityBased = "identity" -class RegenerateKeyType(Enum): +class RenewKeyType(Enum): """ Target key type for regeneration. """ diff --git a/azext_iot/common/utility.py b/azext_iot/common/utility.py index 954eec775..1e21672fe 100644 --- a/azext_iot/common/utility.py +++ b/azext_iot/common/utility.py @@ -18,7 +18,6 @@ import re import hmac import hashlib -import random from threading import Event, Thread from datetime import datetime @@ -519,8 +518,10 @@ def compute_device_key(primary_key, registration_id): def generate_key(byte_length=32): - key = "" - while byte_length > 0: - key += chr(random.randrange(1, 128)) - byte_length -= 1 - return base64.b64encode(key.encode()).decode("utf-8") + """ + Generate cryptographically secure device key. + """ + import secrets + + token_bytes = secrets.token_bytes(byte_length) + return base64.b64encode(token_bytes).decode("utf8") diff --git a/azext_iot/constants.py b/azext_iot/constants.py index 428b4ece9..239b7b3e0 100644 --- a/azext_iot/constants.py +++ b/azext_iot/constants.py @@ -7,7 +7,7 @@ import os -VERSION = "0.10.6" +VERSION = "0.10.7" EXTENSION_NAME = "azure-iot" EXTENSION_ROOT = os.path.dirname(os.path.abspath(__file__)) EXTENSION_CONFIG_ROOT_KEY = "iotext" diff --git a/azext_iot/operations/hub.py b/azext_iot/operations/hub.py index ce0ecfd55..8e70e5bc9 100644 --- a/azext_iot/operations/hub.py +++ b/azext_iot/operations/hub.py @@ -24,7 +24,7 @@ ConfigType, KeyType, SettleType, - RegenerateKeyType, + RenewKeyType, IoTHubStateType ) from azext_iot.iothub.providers.discovery import IotHubDiscovery @@ -417,7 +417,7 @@ def _update_device_key(target, device, auth_method, pk, sk): raise CLIError(err) -def iot_device_key_regenerate(cmd, hub_name, device_id, regenerate_key, resource_group_name=None, login=None): +def iot_device_key_regenerate(cmd, hub_name, device_id, renew_key_type, resource_group_name=None, login=None): discovery = IotHubDiscovery(cmd) target = discovery.get_target( hub_name=hub_name, resource_group_name=resource_group_name, login=login @@ -428,11 +428,12 @@ def iot_device_key_regenerate(cmd, hub_name, device_id, regenerate_key, resource pk = device["authentication"]["symmetricKey"]["primaryKey"] sk = device["authentication"]["symmetricKey"]["secondaryKey"] - if regenerate_key == RegenerateKeyType.primary.value: + + if renew_key_type == RenewKeyType.primary.value: pk = generate_key() - if regenerate_key == RegenerateKeyType.secondary.value: + if renew_key_type == RenewKeyType.secondary.value: sk = generate_key() - if regenerate_key == RegenerateKeyType.swap.value: + if renew_key_type == RenewKeyType.swap.value: temp = pk pk = sk sk = temp diff --git a/azext_iot/tests/test_iot_ext_int.py b/azext_iot/tests/test_iot_ext_int.py index 93cfbeb39..b8b7cde90 100644 --- a/azext_iot/tests/test_iot_ext_int.py +++ b/azext_iot/tests/test_iot_ext_int.py @@ -518,9 +518,9 @@ def test_hub_devices(self): ], ) - # Test 'az iot hub device regenerate-key' + # Test 'az iot hub device renew-key' device = self.cmd( - '''iot hub device-identity regenerate-key -d {} -n {} -g {} --kt primary + '''iot hub device-identity renew-key -d {} -n {} -g {} --kt primary '''.format( edge_device_ids[1], LIVE_HUB, LIVE_RG ), @@ -529,9 +529,9 @@ def test_hub_devices(self): ] ).get_output_in_json() - # Test swap keys 'az iot hub device regenerate-key' + # Test swap keys 'az iot hub device renew-key' self.cmd( - '''iot hub device-identity regenerate-key -d {} -n {} -g {} --kt swap + '''iot hub device-identity renew-key -d {} -n {} -g {} --kt swap '''.format( edge_device_ids[1], LIVE_HUB, LIVE_RG ), @@ -541,8 +541,8 @@ def test_hub_devices(self): ], ) - # Test 'az iot hub device regenerate-key' with non sas authentication - self.cmd("iot hub device-identity regenerate-key -d {} -n {} -g {} --kt secondary" + # Test 'az iot hub device renew-key' with non sas authentication + self.cmd("iot hub device-identity renew-key -d {} -n {} -g {} --kt secondary" .format(device_ids[0], LIVE_HUB, LIVE_RG), expect_failure=True)