def __init__(self, parent, client_iqn, client_settings): UINode.__init__(self, client_iqn, parent) self.client_iqn = client_iqn self.parent.client_map[client_iqn] = self self.group_name = '' self.ip_address = '' self.alias = '' for k, v in client_settings.items(): self.__setattr__(k, v) # decode the chap password if necessary if 'username' in self.auth and 'password' in self.auth: self.chap = CHAP(self.auth['username'], self.auth['password'], self.auth['password_encryption_enabled']) self.auth['username'] = self.chap.user self.auth['password'] = self.chap.password else: self.auth['username'] = '' self.auth['password'] = '' # decode the chap_mutual password if necessary if 'mutual_username' in self.auth and 'mutual_password' in self.auth: self.chap_mutual = CHAP( self.auth['mutual_username'], self.auth['mutual_password'], self.auth['mutual_password_encryption_enabled']) self.auth['mutual_username'] = self.chap_mutual.user self.auth['mutual_password'] = self.chap_mutual.password else: self.auth['mutual_username'] = '' self.auth['mutual_password'] = '' self.refresh_luns()
def test_chap_upgrade(self): private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) priv_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) priv_key_file = tempfile.mkstemp() with open(priv_key_file[1], "wb") as kf: kf.write(priv_pem) pub_pem = private_key.public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) pub_key_file = tempfile.mkstemp() with open(pub_key_file[1], "wb") as kf: kf.write(pub_pem) settings.config.priv_key = priv_key_file[1] settings.config.pub_key = pub_key_file[1] settings.config.ceph_config_dir = "" key = private_key.public_key() encrypted_pw = b64encode( key.encrypt( "passwordverylonglong".encode('utf-8'), padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None))).decode('utf-8') chap2 = CHAP("username/{}".format(encrypted_pw)) self.assertEqual(chap2._get_chap_str(), "username/passwordverylonglong")
def test_chap_encryption(self): private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) priv_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) priv_key_file = tempfile.mkstemp() with open(priv_key_file[1], "wb") as kf: kf.write(priv_pem) pub_pem = private_key.public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) pub_key_file = tempfile.mkstemp() with open(pub_key_file[1], "wb") as kf: kf.write(pub_pem) settings.config.priv_key = priv_key_file[1] settings.config.pub_key = pub_key_file[1] settings.config.ceph_config_dir = "" chap = CHAP("username", "passwordverylonglong", False) encrypted_password = chap.encrypted_password(True) chap2 = CHAP(chap.user, encrypted_password, True) self.assertEqual(chap2.user, "username") self.assertEqual(chap2.password, "passwordverylonglong") self.assertEqual(chap2.password_str, encrypted_password) self.assertNotEqual(encrypted_password, "passwordverylonglong")
def __init__(self, parent, client_iqn, client_settings): UINode.__init__(self, client_iqn, parent) self.client_iqn = client_iqn self.parent.client_map[client_iqn] = self self.group_name = '' self.ip_address = '' self.alias = '' for k, v in client_settings.items(): self.__setattr__(k, v) # decode the chap password if necessary if 'chap' in self.auth: self.chap = CHAP(self.auth['chap']) if self.chap.chap_str != '': self.auth['chap'] = self.chap.chap_str else: self.auth['chap'] = "None" else: self.auth['chap'] = "None" # decode the chap_mutual password if necessary if 'chap_mutual' in self.auth: self.chap_mutual = CHAP(self.auth['chap_mutual']) if self.chap_mutual.chap_str != '': self.auth['chap_mutual'] = self.chap_mutual.chap_str else: self.auth['chap_mutual'] = "None" else: self.auth['chap_mutual'] = "None" self.refresh_luns()
def create_tpg(self, ip): try: gateway_name = self._get_gateway_name(ip) tpg = self.get_tpg_by_gateway_name(gateway_name) if not tpg: tpg = TPG(self.target) # Use initiator name based ACL by default. tpg.set_attribute('authentication', '0') self.logger.debug("(Gateway.create_tpg) Added tpg for portal " "ip {}".format(ip)) if ip in self.active_portal_ips: target_config = self.config.config['targets'][self.iqn] auth_config = target_config['auth'] config_chap = CHAP(auth_config['username'], auth_config['password'], auth_config['password_encryption_enabled']) if config_chap.error: self.error = True self.error_msg = config_chap.error_msg return config_chap_mutual = CHAP(auth_config['mutual_username'], auth_config['mutual_password'], auth_config['mutual_password_encryption_enabled']) if config_chap_mutual.error: self.error = True self.error_msg = config_chap_mutual.error_msg return self.update_auth(tpg, config_chap.user, config_chap.password, config_chap_mutual.user, config_chap_mutual.password) if self.enable_portal: NetworkPortal(tpg, normalize_ip_literal(ip)) tpg.enable = True self.logger.debug("(Gateway.create_tpg) Added tpg for " "portal ip {} is enabled".format(ip)) else: NetworkPortal(tpg, normalize_ip_literal(ip)) # disable the tpg on this host tpg.enable = False # by disabling tpg_enabled_sendtargets, discovery to just one # node will return all portals (default is 1) tpg.set_attribute('tpg_enabled_sendtargets', '0') self.logger.debug("(Gateway.create_tpg) Added tpg for " "portal ip {} as disabled".format(ip)) self.tpg_list.append(tpg) self.tpg_tag_by_gateway_name[gateway_name] = tpg.tag except RTSLibError as err: self.error_msg = err self.error = True else: self.changes_made = True self.logger.info("(Gateway.create_tpg) created TPG '{}' " "for target iqn '{}'".format(tpg.tag, self.iqn))
def set_discovery_auth_lio(chap_str, chap_mutual_str): iscsi_fabric = ISCSIFabricModule() if chap_str == '': iscsi_fabric.clear_discovery_auth_settings() else: chap = CHAP(chap_str) chap_mutual = CHAP(chap_mutual_str) iscsi_fabric.discovery_userid = chap.user iscsi_fabric.discovery_password = chap.password iscsi_fabric.discovery_mutual_userid = chap_mutual.user iscsi_fabric.discovery_mutual_password = chap_mutual.password iscsi_fabric.discovery_enable_auth = True
def set_discovery_auth_lio(username, password, password_encryption_enabled, mutual_username, mutual_password, mutual_password_encryption_enabled): iscsi_fabric = ISCSIFabricModule() if username == '': iscsi_fabric.clear_discovery_auth_settings() else: chap = CHAP(username, password, password_encryption_enabled) chap_mutual = CHAP(mutual_username, mutual_password, mutual_password_encryption_enabled) iscsi_fabric.discovery_userid = chap.user iscsi_fabric.discovery_password = chap.password iscsi_fabric.discovery_mutual_userid = chap_mutual.user iscsi_fabric.discovery_mutual_password = chap_mutual.password iscsi_fabric.discovery_enable_auth = True
def define_clients(): """ define the clients (nodeACLs) to the gateway definition """ # Client configurations (NodeACL's) for client_iqn in config.config['clients']: client_metadata = config.config['clients'][client_iqn] client_chap = CHAP(client_metadata['auth']['chap']) image_list = client_metadata['luns'].keys() chap_str = client_chap.chap_str if client_chap.error: logger.debug("Password decode issue : " "{}".format(client_chap.error_msg)) halt("Unable to decode password for " "{}".format(client_iqn)) client = GWClient(logger, client_iqn, image_list, chap_str) client.manage('present') # ensure the client exists
def __init__(self, target_iqn, parent): UIGroup.__init__(self, target_iqn, parent) self.target_iqn = target_iqn self.control_values = [] self.controls = {} self.gateway_group = GatewayGroup(self) self.client_group = Clients(self) self.host_groups = HostGroups(self) self.target_disks = TargetDisks(self) config = self.parent.parent._get_config() if not config: self.logger.error("Unable to refresh local config") raise GatewayError self.auth = config['targets'][target_iqn]['auth'] # decode the chap password if necessary if 'username' in self.auth and 'password' in self.auth: self.chap = CHAP(self.auth['username'], self.auth['password'], self.auth['password_encryption_enabled']) self.auth['username'] = self.chap.user self.auth['password'] = self.chap.password else: self.auth['username'] = '' self.auth['password'] = '' # decode the chap_mutual password if necessary if 'mutual_username' in self.auth and 'mutual_password' in self.auth: self.chap_mutual = CHAP( self.auth['mutual_username'], self.auth['mutual_password'], self.auth['mutual_password_encryption_enabled']) self.auth['mutual_username'] = self.chap_mutual.user self.auth['mutual_password'] = self.chap_mutual.password else: self.auth['mutual_username'] = '' self.auth['mutual_password'] = ''
def __init__(self, parent, client_iqn, client_settings): UINode.__init__(self, client_iqn, parent) self.client_iqn = client_iqn self.parent.client_map[client_iqn] = self self.group_name = '' for k, v in client_settings.iteritems(): self.__setattr__(k, v) # decode the password if necessary if 'chap' in self.auth: self.chap = CHAP(self.auth['chap']) self.auth['chap'] = self.chap.chap_str self.refresh_luns()
def __init__(self, parent, client_iqn, client_settings): UINode.__init__(self, client_iqn, parent) self.client_iqn = client_iqn self.logger = self.parent.logger for k, v in client_settings.iteritems(): self.__setattr__(k, v) # decode the password if necessary if 'chap' in self.auth: self.chap = CHAP(self.auth['chap']) self.auth['chap'] = self.chap.chap_str for rbd_path in self.luns.keys(): lun_id = self.luns[rbd_path]['lun_id'] self.parent.update_lun_map('add', rbd_path, self.client_iqn) MappedLun(self, rbd_path, lun_id)
def set_discovery_auth_config(username, password, mutual_username, mutual_password, config): encryption_enabled = encryption_available() discovery_auth_config = { 'username': '', 'password': '', 'password_encryption_enabled': encryption_enabled, 'mutual_username': '', 'mutual_password': '', 'mutual_password_encryption_enabled': encryption_enabled } if username != '': chap = CHAP(username, password, encryption_enabled) chap_mutual = CHAP(mutual_username, mutual_password, encryption_enabled) discovery_auth_config['username'] = chap.user discovery_auth_config['password'] = chap.encrypted_password( encryption_enabled) discovery_auth_config['mutual_username'] = chap_mutual.user discovery_auth_config['mutual_password'] = \ chap_mutual.encrypted_password(encryption_enabled) config.update_item('discovery_auth', '', discovery_auth_config)
def activate(self): disk = self.config.config['disks'].get(self.config_key, None) if not disk: raise CephiSCSIError("Image {} not found.".format(self.image)) wwn = disk.get('wwn', None) if not wwn: raise CephiSCSIError("LUN {} missing wwn".format(self.image)) # re-add backend storage object so = self.lio_stg_object() if not so: self.add_dev_to_lio(wwn) if self.error: raise CephiSCSIError("LUN activate failure - {}".format( self.error_msg)) # re-add LUN to target local_gw = this_host() targets_items = [ item for item in self.config.config['targets'].items() if self.config_key in item[1]['disks'] and local_gw in item[1]['portals'] ] for target_iqn, target in targets_items: ip_list = target['ip_list'] # Add the mapping for the lun to ensure the block device is # present on all TPG's gateway = GWTarget(self.logger, target_iqn, ip_list) gateway.manage('map') if gateway.error: raise CephiSCSIError("LUN mapping failed - {}".format( gateway.error_msg)) # re-map LUN to hosts client_err = '' for client_iqn in target['clients']: client_metadata = target['clients'][client_iqn] if client_metadata.get('group_name', ''): continue image_list = list(client_metadata['luns'].keys()) if self.config_key not in image_list: continue client_chap = CHAP(client_metadata['auth']['chap']) chap_str = client_chap.chap_str if client_chap.error: raise CephiSCSIError("Password decode issue : " "{}".format(client_chap.error_msg)) client_chap_mutual = CHAP( client_metadata['auth']['chap_mutual']) chap_mutual_str = client_chap_mutual.chap_str if client_chap_mutual.error: raise CephiSCSIError("Password decode issue : " "{}".format( client_chap_mutual.error_msg)) client = GWClient(self.logger, client_iqn, image_list, chap_str, chap_mutual_str, target_iqn) client.manage('present') if client.error: client_err = "LUN mapping failed {} - {}".format( client_iqn, client.error_msg) # re-map LUN to host groups for group_name in target['groups']: host_group = target['groups'][group_name] members = host_group.get('members') disks = host_group.get('disks').keys() if self.config_key not in disks: continue group = Group(self.logger, target_iqn, group_name, members, disks) group.apply() if group.error: client_err = "LUN mapping failed {} - {}".format( group_name, group.error_msg) if client_err: raise CephiSCSIError(client_err)
def test_chap_no_encryption(self): chap = CHAP("") chap._set_chap_str("username/password") self.assertEqual(chap._get_chap_str(), "username/password")
def test_chap_no_encryption(self): chap = CHAP("username", "password", False) self.assertEqual(chap.user, "username") self.assertEqual(chap.password, "password") self.assertEqual(chap.password_str, "password")
def all_client_luns(client_iqn): """ Coordinate the addition(PUT) and removal(DELETE) of a disk from a client :param client_iqn: (str) IQN of the client :param disk: (str) rbd image name of the format pool.image **RESTRICTED** """ http_mode = 'https' if settings.config.api_secure else 'http' local_gw = this_host() logger.debug("this host is {}".format(local_gw)) gateways = [ key for key in config.config['gateways'] if isinstance(config.config['gateways'][key], dict) ] logger.debug("other gateways - {}".format(gateways)) gateways.remove(local_gw) disk = request.form.get('disk') lun_list = config.config['clients'][client_iqn]['luns'].keys() if request.method == 'PUT': lun_list.append(disk) else: # this is a delete request if disk in lun_list: lun_list.remove(disk) else: return jsonify(message="disk not mapped to client"), 400 chap_obj = CHAP(config.config['clients'][client_iqn]['auth']['chap']) chap = "{}/{}".format(chap_obj.user, chap_obj.password) image_list = ','.join(lun_list) client_usable = valid_client(mode='disk', client_iqn=client_iqn, image_list=image_list) if client_usable != 'ok': logger.error("Bad disk request for client {} : " "{}".format(client_iqn, client_usable)) return jsonify(message=client_usable), 400 # committing host is the local LIO node api_vars = { "committing_host": local_gw, "image_list": image_list, "chap": chap } clientlun_api = '{}://127.0.0.1:{}/api/clientlun/{}'.format( http_mode, settings.config.api_port, client_iqn) api = APIRequest(clientlun_api, data=api_vars) api.put() if api.response.status_code == 200: logger.info("disk mapping update for {} successful".format(client_iqn)) for gw in gateways: clientlun_api = '{}://{}:{}/api/clientlun/{}'.format( http_mode, gw, settings.config.api_port, client_iqn) logger.debug("Updating disk map for {} on GW {}".format( client_iqn, gw)) api = APIRequest(clientlun_api, data=api_vars) api.put() if api.response.status_code == 200: logger.debug("gateway '{}' updated".format(gw)) continue else: logger.error("disk mapping update on {} failed".format(gw)) return jsonify(message="disk map updated failed on " "{}".format(gw)), \ api.response.status_code return jsonify(message="ok"), 200 else: # disk map update failed at the first hurdle! logger.error("disk map update failed on the local LIO instance") return jsonify(message="failed to update local LIO instance"), \ api.response.status_code