def read_ldap_credentials(self): """Read ldap credentials (rootdn, sgiam) from the openldap_config file.""" try: # Load the openldap config file index_id = 'openldap_config_file_read_index' Conf.load(index_id, f'yaml://{self.openldap_config_file}') # Read the cluster id from openldap_config file self.cluster_id = Conf.get(index_id, f'{self.cluster_id_key}') cipher_key = Cipher.generate_key( self.cluster_id, self.get_confkey('CONFSTORE_OPENLDAP_CONST_KEY')) # rootdn username/password self.ldap_root_user = Conf.get(index_id, f'{self.rootdn_user_key}') encrypted_rootdn_pass = Conf.get(index_id, f'{self.rootdn_pass_key}') if encrypted_rootdn_pass != None: self.rootdn_passwd = Cipher.decrypt( cipher_key, bytes(str(encrypted_rootdn_pass), 'utf-8')) except Exception as e: Log.error(f'read ldap credentials failed, error: {e}') raise e
def decrypt(key, text, caller=None): '''Decrypt the <text>''' decrypt_text = text try: decrypt_text = Cipher.decrypt(key, text.encode("utf-8")) except CipherInvalidToken as e: logger.error("{0}:Password decryption failed requested by {1}.".format(e, caller)) return decrypt_text.decode("utf-8")
def test_stonith_ok(self): """Check Stonith configuration.""" for node in self.node_list: bmc_ip = self.bmc_data[node]['ip'] bmc_user = self.bmc_data[node]['user'] secret = self.bmc_data[node]['secret'] key = Cipher.generate_key(self.cluster_id, 'cluster') bmc_passwd = Cipher.decrypt(key, secret.encode('ascii')).decode() BmcV().validate('stonith', [node, bmc_ip, bmc_user, bmc_passwd])
def decrypt(key, text): '''Decrypt the <text>''' decrypt_text = text try: decrypt_text = Cipher.decrypt(key, text).decode() return decrypt_text except CipherInvalidToken as e: print("Password decryption failed requested by %s" % SECTION) return decrypt_text.decode()
def test_accessibility_ok(self): """Check BMC accessibility for nodes in cluster.""" for node in self.node_list: bmc_ip = self.bmc_data[node]['ip'] bmc_user = self.bmc_data[node]['user'] secret = self.bmc_data[node]['secret'] key = Cipher.generate_key(self.cluster_id, 'cluster') bmc_passwd = Cipher.decrypt(key, secret.encode('ascii')).decode() BmcV().validate('accessible', [node, bmc_ip, bmc_user, bmc_passwd])
def test_accessibility_error_on_invalid_bmc_ip(self): """Check 'accessible' validation type for fake bmc_ip argument.""" node = self.node_list[0] bmc_ip = "10.256.256.10" user = self.bmc_data[node]['user'] secret = self.bmc_data[node]['secret'] key = Cipher.generate_key(self.cluster_id, 'cluster') passwd = Cipher.decrypt(key, secret.encode('ascii')).decode() self.assertRaises(VError, BmcV().validate, 'accessible', [node, bmc_ip, user, passwd])
async def get(self, name: str) -> bytes: """ Gets bytes from the encrypted storage. Acquires the data from the storage and decrypts it with the default CORTX cipher Raises CipherInvalidToken if decryption fails. """ neb = await self._get_item(name) if neb is None: return None decrypted_bytes = Cipher.decrypt(self._key, neb.data.encode('ascii')) return decrypted_bytes
def decrypt(component, secret): """ Decrypt secret. Args: secret: Secret to be decrypted. """ retval = None cluster_id = __grains__['cluster_id'] cipher_key = Cipher.generate_key(cluster_id, component) if secret: retval = (Cipher.decrypt(cipher_key, secret.encode("utf-8"))).decode("utf-8") return retval
def decrypt_passwd(self, encr_pass): """Returns decrypted password""" _component = "storage" try: cipher_key = Cipher.generate_key(enc_id_on_node, _component) return ( Cipher.decrypt( cipher_key, encr_pass.encode("utf-8") ) ).decode("utf-8") except Exception as exc: self.logger.error( "Could not decrypt the password stored in the configuration\n" ) raise exc
def decrypt(component, secret): """ Decrypt secret. Args: secret: Secret to be decrypted. """ from cortx.utils.security.cipher import Cipher, CipherInvalidToken retval = None cluster_id = __grains__['cluster_id'] cipher_key = Cipher.generate_key(cluster_id, component) if secret: retval = (Cipher.decrypt(cipher_key, secret.encode("utf-8"))).decode("utf-8") return retval
def test_bmc_config(args): """Check if BMC configuration are valid. Testing BMC config with ipmitool is possible only when ipmi over lan is configured(out-band setup). It is taken care by test_bmc_is_accessible. So, validation on bmc onfiguration with bmc ip, user and secret value through ssh is fine at this time. """ bmc_ip = Conf.get(GLOBAL_CONF, BMC_IP_KEY) bmc_user = Conf.get(GLOBAL_CONF, BMC_USER_KEY) bmc_secret = Conf.get(GLOBAL_CONF, BMC_SECRET_KEY) bmc_key = Cipher.generate_key(MACHINE_ID, "server_node") bmc_passwd = Cipher.decrypt(bmc_key, bmc_secret.encode("utf-8")).decode("utf-8") # check BMC ip, user, password are valid session = SSHChannel(bmc_ip, bmc_user, bmc_passwd) session.disconnect()
def decrypt(component, secret): """Decrypt secret. Args: secret: Secret to be decrypted. """ from cortx.utils.security.cipher import Cipher retval = None cluster_id = getattr(sys.modules[__name__], '__grains__')['cluster_id'] cipher_key = Cipher.generate_key(cluster_id, component) if secret: retval = (Cipher.decrypt(cipher_key, secret.encode("utf-8"))).decode("utf-8") return retval
def test_bmc_is_accessible(args): """Check if BMC is accessible through KCS or LAN.""" channel_interface = Conf.get(SSPL_CONF, "BMC_INTERFACE>default", 'system') if channel_interface == "system": # Check BMC is accessible through KCS cmd = "sudo ipmitool channel info" expected_channel = "KCS" channel_found = None res_op, res_err, res_rc = SimpleProcess(cmd).run() if res_rc == 0: res_op = res_op.decode() search_res = re.search( r"%s[\s]+:[\s]+(\w+)(.*)" % CHANNEL_PROTOCOL, res_op) if search_res: channel_found = search_res.groups()[0] if expected_channel != channel_found: print("UNEXPECTED BMC CHANNEL TYPE FOUND.") print("Expected: %s" % expected_channel) print("Found: %s" % channel_found) else: res_err = res_err.decode() kcs_errors = ("could not find inband device", "driver timeout") if not any(err for err in kcs_errors if err in res_err): raise Exception( "BMC is NOT accessible through KCS - ERROR: %s" % res_err) elif channel_interface == "lan": # Check BMC is accessible through LAN subcommand = "channel info" bmc_ip = Conf.get(GLOBAL_CONF, BMC_IP_KEY) bmc_user = Conf.get(GLOBAL_CONF, BMC_USER_KEY) bmc_secret = Conf.get(GLOBAL_CONF, BMC_SECRET_KEY) bmc_key = Cipher.generate_key(MACHINE_ID, "server_node") bmc_passwd = Cipher.decrypt(bmc_key, bmc_secret.encode("utf-8")).decode("utf-8") cmd = "sudo ipmitool -H %s -U %s -P %s -I lan %s" % ( bmc_ip, bmc_user, bmc_passwd, subcommand) res_op, res_err, res_rc = SimpleProcess(cmd).run() if res_rc != 0: raise Exception("BMC is NOT accessible over lan - ERROR: %s" % res_err.decode())
def validate(self): """Check below requirements. 1. Validate input configs 2. Validate BMC connectivity 3. Validate storage controller connectivity 4. Validate network interface availability """ machine_id = Utility.get_machine_id() mgmt_interfaces = [] data_private_interfaces = [] data_public_interfaces = [] # Validate input/provisioner configs node_type = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>type" % machine_id) cluster_id = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>cluster_id" % machine_id) if node_type.lower() not in ["virtual", "vm"]: bmc_ip = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>bmc>ip" % machine_id) bmc_user = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>bmc>user" % machine_id) bmc_secret = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>bmc>secret" % machine_id) bmc_key = Cipher.generate_key(machine_id, ServiceTypes.SERVER_NODE.value) bmc_passwd = Cipher.decrypt( bmc_key, bmc_secret.encode("utf-8")).decode("utf-8") data_private_interfaces = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>data>private_interfaces" % machine_id) data_public_interfaces = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>data>public_interfaces" % machine_id) mgmt_public_fqdn = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>management>public_fqdn" % machine_id) mgmt_interfaces = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>management>interfaces" % machine_id) data_private_fqdn = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>data>private_fqdn" % machine_id) data_public_fqdn = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>network>data>public_fqdn" % machine_id) enclosure_id = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "server_node>%s>storage>enclosure_id" % machine_id) primary_ip = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "storage_enclosure>%s>controller>primary>ip" % enclosure_id) secondary_ip = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "storage_enclosure>%s>controller>secondary>ip" % enclosure_id) cntrlr_user = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "storage_enclosure>%s>controller>user" % enclosure_id) cntrlr_secret = Utility.get_config_value( PRVSNR_CONFIG_INDEX, "storage_enclosure>%s>controller>secret" % enclosure_id) cntrlr_key = Cipher.generate_key(enclosure_id, ServiceTypes.STORAGE_ENCLOSURE.value) cntrlr_passwd = Cipher.decrypt( cntrlr_key, cntrlr_secret.encode("utf-8")).decode("utf-8") # Validate BMC connectivity & storage controller accessibility if node_type.lower() not in ["virtual", "vm"]: NetworkV().validate("connectivity", [bmc_ip, primary_ip, secondary_ip]) BmcV().validate("accessible", [socket.getfqdn(), bmc_ip, bmc_user, bmc_passwd]) c_validator = ControllerV() c_validator.validate("accessible", [primary_ip, cntrlr_user, cntrlr_passwd]) c_validator.validate("accessible", [secondary_ip, cntrlr_user, cntrlr_passwd]) # Validate network fqdn reachability NetworkV().validate( "connectivity", [mgmt_public_fqdn, data_private_fqdn, data_public_fqdn]) # Validate network interface availability for i_list in [ mgmt_interfaces, data_private_interfaces, data_public_interfaces ]: self.validate_nw_cable_connection(i_list) self.validate_nw_interfaces(i_list)
def decrypt(key, text, caller=None): """Decrypt the <text>.""" decrypt_text = Cipher.decrypt(key, text.encode("utf-8")).decode("utf-8") return decrypt_text
def decrypt(key: str, data: str): ddata = Cipher.decrypt(bytes(key, 'utf-8'), bytes(data, 'utf-8')) return ddata.decode("utf-8")
def process(self): """ Process config command. """ Log.info("Processing config command") # Read machine-id and using machine-id read minion name from confstore # This minion name will be used for adding the node to the cluster. nodelist = [] command = "cat /etc/machine-id" machine_id, err, rc = self._execute.run_cmd(command, check_error=True) Log.info(f"Read machine-id. Output: {machine_id}, Err: {err}, RC: {rc}") minion_name = Conf.get(self._index, f"cluster.server_nodes.{machine_id.strip()}") nodelist.append(minion_name) # The config step will be called from primary node alwasys, # see how to get and use the node name then. # Read cluster name and cluster user cluster_name = Conf.get(self._index, 'corosync-pacemaker.cluster_name') cluster_user = Conf.get(self._index, 'corosync-pacemaker.user') # Read cluster user password and decrypt the same cluster_id = Conf.get(self._index, 'cluster.cluster_id') cluster_secret = Conf.get(self._index, 'corosync-pacemaker.secret') key = Cipher.generate_key(cluster_id, 'corosync-pacemaker') cluster_secret = Cipher.decrypt(key, cluster_secret.encode('ascii')).decode() # Get s3 instance count try: s3_instances = Conf.get(self._index, f"cluster.{minion_name}.s3_instances") if int(s3_instances) < 1: raise HaConfigException(f"Found {s3_instances} which is invalid s3 instance count.") except Exception as e: Log.error(f"Found {s3_instances} which is invalid s3 instance count. Error: {e}") raise HaConfigException(f"Found {s3_instances} which is invalid s3 instance count.") # Check if the cluster exists already, if yes skip creating the cluster. output, err, rc = self._execute.run_cmd(const.PCS_CLUSTER_STATUS, check_error=False) Log.info(f"Cluster status. Output: {output}, Err: {err}, RC: {rc}") if rc != 0: if(err.find("No such file or directory: 'pcs'") != -1): Log.error("Cluster config failed; pcs not installed") raise HaConfigException("Cluster config failed; pcs not installed") # If cluster is not created; create a cluster. elif(err.find("cluster is not currently running on this node") != -1): try: Log.info(f"Creating cluster: {cluster_name} with node: {minion_name}") cluster_auth(cluster_user, cluster_secret, nodelist) cluster_create(cluster_name, nodelist) Log.info(f"Created cluster: {cluster_name} successfully") Log.info("Creating pacemaker resources") create_all_resources(s3_instances=s3_instances) Log.info("Created pacemaker resources successfully") except Exception as e: Log.error(f"Cluster creation failed; destroying the cluster. Error: {e}") output = self._execute.run_cmd(const.PCS_CLUSTER_DESTROY, check_error=True) Log.info(f"Cluster destroyed. Output: {output}") raise HaConfigException("Cluster creation failed") else: pass # Nothing to do else: # Cluster exists already, check if it is a new node and add it to the existing cluster. Log.info("The cluster exists already, check and add new node") Log.info("config command is successful")
def process(self): """ Process config command. """ Log.info("Processing config command") # Read machine-id and using machine-id read minion name from confstore # This minion name will be used for adding the node to the cluster. node_name: str = self.get_node_name() nodelist: list = self.get_nodelist(fetch_from=ConfigCmd.PROV_CONFSTORE) # Read cluster name and cluster user machine_id = self.get_machine_id() cluster_id = Conf.get(self._index, f"server_node.{machine_id}.cluster_id") cluster_name = Conf.get(self._index, f"cluster.{cluster_id}.name") cluster_user = Conf.get( self._index, f"cortx.software.{const.HA_CLUSTER_SOFTWARE}.user") node_type = Conf.get(self._index, f"server_node.{machine_id}.type").strip() # Read cluster user password and decrypt the same cluster_secret = Conf.get( self._index, f"cortx.software.{const.HA_CLUSTER_SOFTWARE}.secret") key = Cipher.generate_key(cluster_id, const.HACLUSTER_KEY) cluster_secret = Cipher.decrypt( key, cluster_secret.encode('ascii')).decode() mgmt_info: dict = self._get_mgmt_vip(machine_id, cluster_id) s3_instances = ConfigCmd.get_s3_instance(machine_id) self._update_env(node_name, node_type, const.HA_CLUSTER_SOFTWARE) self._fetch_fids() self._update_cluster_manager_config() # Update cluster and resources self._cluster_manager = CortxClusterManager(default_log_enable=False) Log.info("Checking if cluster exists already") cluster_exists = bool( json.loads( self._cluster_manager.cluster_controller.cluster_exists()).get( "msg")) Log.info(f"Cluster exists? {cluster_exists}") if not cluster_exists: node_count: int = len( self.get_nodelist(fetch_from=ConfigCmd.HA_CONFSTORE)) if node_count == 0: Log.info( f"Creating cluster: {cluster_name} with node: {node_name}") # Create cluster try: self._create_cluster(cluster_name, cluster_user, cluster_secret, node_name) self._create_resource(s3_instances=s3_instances, mgmt_info=mgmt_info) self._confstore.set( f"{const.CLUSTER_CONFSTORE_NODES_KEY}/{node_name}") except Exception as e: Log.error( f"Cluster creation failed; destroying the cluster. Error: {e}" ) output = self._execute.run_cmd(const.PCS_CLUSTER_DESTROY) Log.error(f"Cluster destroyed. Output: {output}") # Delete the node from nodelist if it was added in the store if self._confstore.key_exists( f"{const.CLUSTER_CONFSTORE_NODES_KEY}/{node_name}" ): self._confstore.delete( f"{const.CLUSTER_CONFSTORE_NODES_KEY}/{node_name}") raise HaConfigException("Cluster creation failed") # Add Other Node for node in nodelist: if node != node_name: Log.info( f"Adding node {node} to Cluster {cluster_name}") self._add_node(node, cluster_user, cluster_secret) else: # Add node with SSH self._add_node_remotely(node_name, cluster_user, cluster_secret) else: for node in nodelist: if node != node_name: Log.info(f"Adding node {node} to Cluster {cluster_name}") self._add_node(node, cluster_user, cluster_secret) self._execute.run_cmd(const.PCS_CLEANUP) Log.info("config command is successful")
def decrypt(key, text): ''' Decrypt the <text> ''' return Cipher.decrypt(key, text.encode("utf-8")).decode("utf-8")
def decrypt(key, text): ''' Decrypt the <text> ''' return Cipher.decrypt(key, text).decode()
def decrypt(key, text, caller=None): """Decrypt the <text>.""" decrypt_text = Cipher.decrypt(key, text).decode() return decrypt_text