def _process_key_vault(self, key_vault_index, key_vault_name, rg_name, sub_index, sub): """Get details of Key Vault in management and data plane. Arguments: sub_index (int): Subscription index (for logging only). sub (Subscription): Azure subscription object. rg_name (str): Resource group name. key_vault_index (int): Key Vault index (for logging only). key_vault_name (str): Name of the Key Vault. Yields: dict: An Azure Key Vault server record. """ def _auth_callback(server, resource, scope): credentials = self._key_vault_credentials token = credentials.token return token['token_type'], token['access_token'] _log.info('Working on key_vault #%d: %s; %s', key_vault_index, key_vault_name, util.outline_az_sub(sub_index, sub, self._tenant)) subscription_id = sub.get('subscription_id') creds = self._credentials key_vault_mgmt_client = KeyVaultManagementClient( creds, subscription_id) key_vault_details = key_vault_mgmt_client.vaults.get( rg_name, key_vault_name) yield from _get_normalized_key_vault_record(key_vault_details, sub) try: kv_client = \ KeyVaultClient(KeyVaultAuthentication(_auth_callback)) secrets = \ kv_client.get_secrets(key_vault_details.properties.vault_uri) keys = \ kv_client.get_keys(key_vault_details.properties.vault_uri) # Retrieve data using each iterator. for record in itertools.chain( _get_data_record(secrets, 'key_vault_secret', sub_index, sub, self._tenant), _get_data_record(keys, 'key_vault_key', sub_index, sub, self._tenant), ): yield record except CloudError as e: _log.error('Failed to fetch key vault details; %s; error: %s: %s', util.outline_az_sub(sub_index, sub, self._tenant), type(e).__name__, e)
class KV_Repl(object): _repl_break_commands = set(('back', 'b')) _repl_quit_commands = set(('quit', 'q')) def __init__(self, config): self._auth = KeyVaultAuth(config, CLIENT_ID) self._config = config self._mgmt_client = KeyVaultManagementClient( self._auth.get_arm_creds(), config.subscription_id) self._data_client = KeyVaultClient(self._auth.get_keyvault_creds()) self._selected_vault = None self._current_index = None def start(self): try: self._vault_index_loop() except SystemExit: print('\nuser exited\n') def _continue_repl(self, display_action, break_commands=()): display_action() self._selection = input('> ').lower() if self._selection in break_commands: return None elif self._selection in KV_Repl._repl_quit_commands: sys.exit() try: self._selection = int(self._selection) except ValueError: pass return self._selection def _display_vault_index(self): print('\nAvailable Vaults:\n') self._current_index = self._get_vault_list() for idx, vault in enumerate(self._current_index): print('%d. %s' % (idx, vault.name)) print('\n#:select | (a)dd | (d)elete | (q)uit') def _vault_index_loop(self): while self._continue_repl(self._display_vault_index) is not None: vaults = self._current_index if isinstance(self._selection, int): i = self._selection if i >= 0 and i < len(vaults): self._selected_vault = self._mgmt_client.vaults.get( self._config.resource_group, vaults[i].name) self._vault_detail_loop() else: print('invalid vault index') elif self._selection == 'a' or self._selection == 'add': self._add_vault() else: print('invalid input') def _add_vault(self): name = input('\nenter vault name:') all_perms = Permissions() all_perms.keys = [KeyPermissions.all] all_perms.secrets = [SecretPermissions.all] all_perms.certificates = [CertificatePermissions.all] user_policy = AccessPolicyEntry(self._config.tenant_id, self._config.user_oid, all_perms) app_policy = AccessPolicyEntry(CLIENT_TENANT_ID, CLIENT_OID, all_perms) access_policies = [user_policy, app_policy] properties = VaultProperties(self._config.tenant_id, Sku(name='standard'), access_policies) properties.enabled_for_deployment = True properties.enabled_for_disk_encryption = True properties.enabled_for_template_deployment = True vault = VaultCreateOrUpdateParameters(self._config.location, properties) self._mgmt_client.vaults.create_or_update(self._config.resource_group, name, vault) print('vault %s created\n' % name) def _display_selected_vault_detail(self): print('\nName:\t%s' % self._selected_vault.name) print('Uri:\t%s' % self._selected_vault.properties.vault_uri) print('Id:\t%s' % self._selected_vault.id) print( '\n(s)ecrets | (k)eys | (c)ertificates | (e)ncrypt | (d)ecrypt | (b)ack | (q)uit\n' ) def _vault_detail_loop(self): while self._continue_repl( self._display_selected_vault_detail, break_commands=KV_Repl._repl_break_commands) is not None: if self._selection == 's' or self._selection == 'secrets': self._secret_index_loop() elif self._selection == 'k' or self._selection == 'keys': self._key_index_loop() elif self._selection == 'c' or self._selection == 'certificates': print('\nnot yet implemented\n') elif self._selection == 'e' or self._selection == 'encrypt': self._encrypt_file() else: print('invalid input') def _encrypt_file(self): while True: inpath = input('input file: ') if os.path.isfile(inpath): break else: print('error: file not found') while True: outpath = input('output file: ') @staticmethod def _prompt_for_file_path(prompt, verify_exists): inpath = input(prompt) def _display_secret_index(self): self._current_index = [] secret_iter = self._data_client.get_secrets( self._selected_vault.properties.vault_uri) if secret_iter is not None: try: self._current_index = [secret for secret in secret_iter] except TypeError: pass print('\n%s Secrets:\n' % self._selected_vault.name) for idx, s in enumerate(self._current_index): print('%d. %s' % (idx, KV_Repl._get_name_from_url(s.id))) print('\n#:show secret value (a)dd (d)elete (b)ack (q)uit\n') def _secret_index_loop(self): while self._continue_repl( self._display_secret_index, break_commands=KV_Repl._repl_break_commands) is not None: secrets = self._current_index if isinstance(self._selection, int): i = self._selection if i >= 0 and i < len(secrets): print('\n%s = %s\n' % (KV_Repl._get_secret_name_from_url(secrets[i].id), self._data_client.get_secret(secrets[i].id).value)) else: print('invalid secret index') elif self._selection == 'a' or self._selection == 'add': self._add_secret() elif self._selection == 'd' or self._selection == 'delete': print('\nnot yet implemented\n') def _add_secret(self): secret_name = input('\nSecret Name: ') secret_value = input('Secret Value: ') self._data_client.set_secret(self._selected_vault.properties.vault_uri, secret_name, secret_value) print('\nSecret %s added to vault %s' % (secret_name, self._selected_vault.name)) def _display_key_index(self): self._current_index = [] key_iter = self._data_client.get_keys( self._selected_vault.properties.vault_uri) if key_iter is not None: try: self._current_index = [secret for secret in key_iter] except TypeError: print('warning: caught TypeError') pass print('\n%s Keys:\n' % self._selected_vault.name) for idx, k in enumerate(self._current_index): print('%d. %s' % (idx, KV_Repl._get_name_from_url(k.kid))) print('\n#:get key | (a)dd | (i)mport | (d)elete | (b)ack | (q)uit\n') def _key_index_loop(self): while self._continue_repl( self._display_key_index, break_commands=KV_Repl._repl_break_commands) is not None: keys = self._current_index if isinstance(self._selection, int): i = self._selection if i >= 0 and i < len(keys): print('\n%s = %s\n' % (KV_Repl._get_secret_name_from_url(keys[i].id), self._data_client.get_secret(keys[i].id).value)) else: print('invalid key index') elif self._selection == 'a' or self._selection == 'add': self._add_key() elif self._selection == 'd' or self._selection == 'delete': print('\nnot yet implemented\n') def _add_key(self): key_name = input('\nKey Name: ') self._data_client.create_key(self._selected_vault.properties.vault_uri, key_name, kty=JsonWebKeyType.rsa.value) print('\nSecret %s added to vault %s' % (key_name, self._selected_vault.name)) @staticmethod def _get_name_from_url(url): split = url.split('/') return split[len(split) - 1] def _get_vault_list(self): vault_list = [vault for vault in self._mgmt_client.vaults.list()] return vault_list
level=INFO) app = Flask(__name__) config = { 'kv_name_domain': 'testhostname', # this name to be used for the vault domain 'node_addr': 'http://127.0.0.1:8732', 'keys': {}, # to be auto-populated 'bakerid': socket.getfqdn() + '_' + str(uuid4()) } info("Getting public keys from HSM") kvurl = 'https://' + config['kv_name_domain'] + '.vault.azure.net' kvclient = KeyVaultClient( MSIAuthentication(resource='https://vault.azure.net')) keys = kvclient.get_keys(kvurl) for key in keys: keyname = key.kid.split('/') keydat = kvclient.get_key(kvurl, keyname[-1], '').key parity = bytes([2]) if int.from_bytes(keydat.y, 'big') % 2 == 1: parity = bytes([3]) shabytes = sha256(sha256(P2PK_MAGIC + parity + keydat.x).digest()).digest()[:4] public_key = b58encode(P2PK_MAGIC + parity + keydat.x + shabytes).decode() blake2bhash = blake2b(parity + keydat.x, digest_size=20).digest() shabytes = sha256(sha256(P2HASH_MAGIC + blake2bhash).digest()).digest()[:4] pkhash = b58encode(P2HASH_MAGIC + blake2bhash + shabytes).decode() config['keys'].update(