def run(self): """Run the task.""" target_content_dir = utils.join_paths(self._sysroot, self._target_directory) utils.ensure_dir_exists(target_content_dir) if self._policy_data.content_type == "scap-security-guide": pass # nothing needed elif self._policy_data.content_type == "datastream": shutil.copy2(self._content_path, target_content_dir) elif self._policy_data.content_type == "rpm": # copy the RPM to the target system shutil.copy2(self._file_path, target_content_dir) # get the path of the RPM content_name = common.get_content_name(self._policy_data) package_path = utils.join_paths(self._target_directory, content_name) # and install it with yum ret = util.execInSysroot( "yum", ["-y", "--nogpg", "install", package_path]) if ret != 0: msg = _(f"Failed to install content RPM to the target system.") terminate(msg) return else: pattern = utils.join_paths(common.INSTALLATION_CONTENT_DIR, "*") utils.universal_copy(pattern, target_content_dir) if os.path.exists(self._tailoring_path): shutil.copy2(self._tailoring_path, target_content_dir)
def get_postinst_content_path(data): """Path to the post-installation content file""" if data.content_type == "datastream": return utils.join_paths(TARGET_CONTENT_DIR, get_content_name(data)) if data.content_type in ("rpm", "scap-security-guide"): # no path magic in case of RPM (SSG is installed as an RPM) return data.content_path return utils.join_paths(TARGET_CONTENT_DIR, data.content_path)
def postinst_content_path(self): """Path to the post-installation content file""" if self.content_type == "datastream": return utils.join_paths(common.TARGET_CONTENT_DIR, self.content_name) elif self.content_type in ("rpm", "scap-security-guide"): # no path magic in case of RPM (SSG is installed as an RPM) return self.xccdf_path else: return utils.join_paths(common.TARGET_CONTENT_DIR, self.xccdf_path)
def preinst_content_path(self): """Path to the pre-installation content file""" if self.content_type == "datastream": return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.content_name) elif self.content_type == "scap-security-guide": # SSG is not copied to the standard place return self.content_path else: return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.content_path)
def preinst_content_path(self): """Path to the pre-installation content file""" if self.content_type == "datastream": return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.content_name) elif self.content_type == "scap-security-guide": # SSG is not copied to the standard place return self.xccdf_path else: return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.xccdf_path)
def execute(self, storage, ksdata, instclass, users, payload): """ The execute method that should make changes to the installed system. It is called only once in the post-install setup phase. :see: setup :param users: information about created users :type users: pyanaconda.users.Users instance """ if self.dry_run or not self.profile_id: # nothing more to be done in the dry-run mode or if no profile is # selected return target_content_dir = utils.join_paths(getSysroot(), common.TARGET_CONTENT_DIR) utils.ensure_dir_exists(target_content_dir) if self.content_type == "datastream": shutil.copy2(self.preinst_content_path, target_content_dir) elif self.content_type == "rpm": # copy the RPM to the target system shutil.copy2(self.raw_preinst_content_path, target_content_dir) # and install it with yum ret = iutil.execInSysroot( "yum", ["-y", "--nogpg", "install", self.raw_postinst_content_path]) if ret != 0: raise common.ExtractionError("Failed to install content " "RPM to the target system") elif self.content_type == "scap-security-guide": # nothing needed pass else: utils.universal_copy( utils.join_paths(common.INSTALLATION_CONTENT_DIR, "*"), target_content_dir) if os.path.exists(self.preinst_tailoring_path): shutil.copy2(self.preinst_tailoring_path, target_content_dir) common.run_oscap_remediate(self.profile_id, self.postinst_content_path, self.datastream_id, self.xccdf_id, self.postinst_tailoring_path, chroot=getSysroot())
def extract_data(archive, out_dir, ensure_has_files=None): """ Fuction that extracts the given archive to the given output directory. It tries to find out the archive type by the file name. :param archive: path to the archive file that should be extracted :type archive: str :param out_dir: output directory the archive should be extracted to :type out_dir: str :param ensure_has_files: relative paths to the files that must exist in the archive :type ensure_has_files: iterable of strings or None :return: a list of files and directories extracted from the archive :rtype: [str] """ # get rid of empty file paths ensure_has_files = [fpath for fpath in ensure_has_files if fpath] if archive.endswith(".zip"): # ZIP file try: zfile = zipfile.ZipFile(archive, "r") except zipfile.BadZipfile as err: raise ExtractionError(err.message) # generator for the paths of the files found in the archive (dirs end # with "/") files = set(info.filename for info in zfile.filelist if not info.filename.endswith("/")) for fpath in ensure_has_files or (): if fpath not in files: msg = "File '%s' not found in the archive '%s'" % (fpath, archive) raise ExtractionError(msg) utils.ensure_dir_exists(out_dir) zfile.extractall(path=out_dir) result = [ utils.join_paths(out_dir, info.filename) for info in zfile.filelist ] zfile.close() return result elif archive.endswith(".tar"): # plain tarball return _extract_tarball(archive, out_dir, ensure_has_files, None) elif archive.endswith(".tar.gz"): # gzipped tarball return _extract_tarball(archive, out_dir, ensure_has_files, "gz") elif archive.endswith(".tar.bz2"): # bzipped tarball return _extract_tarball(archive, out_dir, ensure_has_files, "bz2") elif archive.endswith(".rpm"): # RPM return _extract_rpm(archive, out_dir, ensure_has_files) # elif other types of archives else: raise ExtractionError("Unsuported archive type")
def execute(self, storage, ksdata, users, payload): """ The execute method that should make changes to the installed system. It is called only once in the post-install setup phase. :see: setup :param users: information about created users :type users: pyanaconda.users.Users instance """ if self.dry_run or not self.profile_id: # nothing more to be done in the dry-run mode or if no profile is # selected return target_content_dir = utils.join_paths(getSysroot(), common.TARGET_CONTENT_DIR) utils.ensure_dir_exists(target_content_dir) if self.content_type == "datastream": shutil.copy2(self.preinst_content_path, target_content_dir) elif self.content_type == "rpm": # copy the RPM to the target system shutil.copy2(self.raw_preinst_content_path, target_content_dir) # and install it with yum ret = util.execInSysroot("yum", ["-y", "--nogpg", "install", self.raw_postinst_content_path]) if ret != 0: raise common.ExtractionError("Failed to install content " "RPM to the target system") elif self.content_type == "scap-security-guide": # nothing needed pass else: utils.universal_copy(utils.join_paths(common.INSTALLATION_CONTENT_DIR, "*"), target_content_dir) if os.path.exists(self.preinst_tailoring_path): shutil.copy2(self.preinst_tailoring_path, target_content_dir) common.run_oscap_remediate(self.profile_id, self.postinst_content_path, self.datastream_id, self.xccdf_id, self.postinst_tailoring_path, chroot=getSysroot())
def preinst_tailoring_path(self): """Path to the pre-installation tailoring file (if any)""" if not self.tailoring_path: return None return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.tailoring_path)
def preinst_tailoring_path(self): """Path to the pre-installation tailoring file (if any)""" if not self.tailoring_path: return "" return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.tailoring_path)
def get_raw_preinst_content_path(data): """Path to the raw (unextracted, ...) pre-installation content file""" if data.content_type == "scap-security-guide": log.debug( "OSCAP addon: Using scap-security-guide, no single content file") return None content_name = get_content_name(data) return utils.join_paths(INSTALLATION_CONTENT_DIR, content_name)
def ssg_available(root="/"): """ Tries to find the SCAP Security Guide under the given root. :return: True if SSG was found under the given root, False otherwise """ return os.path.exists(utils.join_paths(root, SSG_DIR + SSG_CONTENT))
def extract_data(archive, out_dir, ensure_has_files=None): """ Fuction that extracts the given archive to the given output directory. It tries to find out the archive type by the file name. :param archive: path to the archive file that should be extracted :type archive: str :param out_dir: output directory the archive should be extracted to :type out_dir: str :param ensure_has_files: relative paths to the files that must exist in the archive :type ensure_has_files: iterable of strings or None :return: a list of files and directories extracted from the archive :rtype: [str] """ # get rid of empty file paths ensure_has_files = [fpath for fpath in ensure_has_files if fpath] if archive.endswith(".zip"): # ZIP file try: zfile = zipfile.ZipFile(archive, "r") except zipfile.BadZipfile as err: raise ExtractionError(str(err)) # generator for the paths of the files found in the archive (dirs end # with "/") files = set(info.filename for info in zfile.filelist if not info.filename.endswith("/")) for fpath in ensure_has_files or (): if fpath not in files: msg = "File '%s' not found in the archive '%s'" % (fpath, archive) raise ExtractionError(msg) utils.ensure_dir_exists(out_dir) zfile.extractall(path=out_dir) result = [utils.join_paths(out_dir, info.filename) for info in zfile.filelist] zfile.close() return result elif archive.endswith(".tar"): # plain tarball return _extract_tarball(archive, out_dir, ensure_has_files, None) elif archive.endswith(".tar.gz"): # gzipped tarball return _extract_tarball(archive, out_dir, ensure_has_files, "gz") elif archive.endswith(".tar.bz2"): # bzipped tarball return _extract_tarball(archive, out_dir, ensure_has_files, "bz2") elif archive.endswith(".rpm"): # RPM return _extract_rpm(archive, out_dir, ensure_has_files) # elif other types of archives else: raise ExtractionError("Unsuported archive type")
def ssg_available(root="/"): """ Tries to find the SCAP Security Guide under the given root. :return: True if SSG was found under the given root, False otherwise """ return os.path.exists(utils.join_paths(root, SSG_DIR + SSG_XCCDF))
def get_preinst_content_path(data): """Path to the pre-installation content file""" if data.content_type == "scap-security-guide": # SSG is not copied to the standard place return data.content_path if data.content_type == "datastream": return get_raw_preinst_content_path(data) return utils.join_paths(INSTALLATION_CONTENT_DIR, data.content_path)
def get_postinst_tailoring_path(data): """Path to the post-installation tailoring file (if any)""" if not data.tailoring_path: return "" if data.content_type == "rpm": # no path magic in case of RPM return data.tailoring_path return utils.join_paths(TARGET_CONTENT_DIR, data.tailoring_path)
def postinst_tailoring_path(self): """Path to the post-installation tailoring file (if any)""" if not self.tailoring_path: return "" if self.content_type == "rpm": # no path magic in case of RPM return self.tailoring_path return utils.join_paths(common.TARGET_CONTENT_DIR, self.tailoring_path)
def postinst_tailoring_path(self): """Path to the post-installation tailoring file (if any)""" if not self.tailoring_path: return None if self.content_type == "rpm": # no path magic in case of RPM return self.tailoring_path return utils.join_paths(common.TARGET_CONTENT_DIR, self.tailoring_path)
def _extract_tarball(archive, out_dir, ensure_has_files, alg): """ Extract the given TAR archive to the given output directory and make sure the given file exists in the archive. :see: extract_data :param alg: compression algorithm used for the tarball :type alg: str (one of "gz", "bz2") or None :return: a list of files and directories extracted from the archive :rtype: [str] """ if alg and alg not in ( "gz", "bz2", ): raise ExtractionError("Unsupported compression algorithm") mode = "r" if alg: mode += ":%s" % alg try: tfile = tarfile.TarFile.open(archive, mode) except tarfile.TarError as err: raise ExtractionError(err.message) # generator for the paths of the files found in the archive files = set(member.path for member in tfile.getmembers() if member.isfile()) for fpath in ensure_has_files or (): if fpath not in files: msg = "File '%s' not found in the archive '%s'" % (fpath, archive) raise ExtractionError(msg) utils.ensure_dir_exists(out_dir) tfile.extractall(path=out_dir) result = [ utils.join_paths(out_dir, member.path) for member in tfile.getmembers() ] tfile.close() return result
def _extract_tarball(archive, out_dir, ensure_has_files, alg): """ Extract the given TAR archive to the given output directory and make sure the given file exists in the archive. :see: extract_data :param alg: compression algorithm used for the tarball :type alg: str (one of "gz", "bz2") or None :return: a list of files and directories extracted from the archive :rtype: [str] """ if alg and alg not in ("gz", "bz2",): raise ExtractionError("Unsupported compression algorithm") mode = "r" if alg: mode += ":%s" % alg try: tfile = tarfile.TarFile.open(archive, mode) except tarfile.TarError as err: raise ExtractionError(str(err)) # generator for the paths of the files found in the archive files = set(member.path for member in tfile.getmembers() if member.isfile()) for fpath in ensure_has_files or (): if fpath not in files: msg = "File '%s' not found in the archive '%s'" % (fpath, archive) raise ExtractionError(msg) utils.ensure_dir_exists(out_dir) tfile.extractall(path=out_dir) result = [utils.join_paths(out_dir, member.path) for member in tfile.getmembers()] tfile.close() return result
def absolute_absolute_test(self): self.assertEqual(utils.join_paths("/foo", "/blah"), "/foo/blah")
def relative_relative_test(self): self.assertEqual(utils.join_paths("foo", "blah"), "foo/blah")
def get_preinst_tailoring_path(data): """Path to the pre-installation tailoring file (if any)""" if not data.tailoring_path: return "" return utils.join_paths(INSTALLATION_CONTENT_DIR, data.tailoring_path)
def extract_data(archive, out_dir, ensure_has_files=None): """ Fuction that extracts the given archive to the given output directory. It tries to find out the archive type by the file name. :param archive: path to the archive file that should be extracted :type archive: str :param out_dir: output directory the archive should be extracted to :type out_dir: str :param ensure_has_files: relative paths to the files that must exist in the archive :type ensure_has_files: iterable of strings or None :return: a list of files and directories extracted from the archive :rtype: [str] """ if not ensure_has_files: ensure_has_files = [] # get rid of empty file paths if not ensure_has_files: ensure_has_files = [] else: ensure_has_files = [fpath for fpath in ensure_has_files if fpath] msg = "OSCAP addon: Extracting {archive}".format(archive=archive) if ensure_has_files: msg += ", expecting to find {files} there.".format( files=tuple(ensure_has_files)) log.info(msg) result = [] if archive.endswith(".zip"): # ZIP file try: zfile = zipfile.ZipFile(archive, "r") except Exception as exc: msg = _(f"Error extracting archive as a zipfile: {exc}") raise ExtractionError(msg) # generator for the paths of the files found in the archive (dirs end # with "/") files = set(info.filename for info in zfile.filelist if not info.filename.endswith("/")) for fpath in ensure_has_files or (): if fpath not in files: msg = "File '%s' not found in the archive '%s'" % (fpath, archive) raise ExtractionError(msg) utils.ensure_dir_exists(out_dir) zfile.extractall(path=out_dir) result = [ utils.join_paths(out_dir, info.filename) for info in zfile.filelist ] zfile.close() elif archive.endswith(".tar"): # plain tarball result = _extract_tarball(archive, out_dir, ensure_has_files, None) elif archive.endswith(".tar.gz"): # gzipped tarball result = _extract_tarball(archive, out_dir, ensure_has_files, "gz") elif archive.endswith(".tar.bz2"): # bzipped tarball result = _extract_tarball(archive, out_dir, ensure_has_files, "bz2") elif archive.endswith(".rpm"): # RPM result = _extract_rpm(archive, out_dir, ensure_has_files) # elif other types of archives else: raise ExtractionError("Unsuported archive type") log.info("OSCAP addon: Extracted {files} from the supplied content".format( files=result)) return result
def raw_postinst_content_path(self): """Path to the raw (unextracted, ...) post-installation content file""" return utils.join_paths(common.TARGET_CONTENT_DIR, self.content_name)
from pyanaconda.threads import threadMgr, AnacondaThread from org_fedora_oscap import utils from org_fedora_oscap.data_fetch import fetch_data # everything else should be private __all__ = ["run_oscap_remediate", "get_fix_rules_pre", "wait_and_fetch_net_data", "extract_data", "strip_content_dir", "OSCAPaddonError"] INSTALLATION_CONTENT_DIR = "/tmp/openscap_data/" TARGET_CONTENT_DIR = "/root/openscap_data/" SSG_DIR = "/usr/share/xml/scap/ssg/fedora/" SSG_XCCDF = "ssg-fedora-xccdf.xml" RESULTS_PATH = utils.join_paths(TARGET_CONTENT_DIR, "eval_remediate_results.xml") PRE_INSTALL_FIX_SYSTEM_ATTR = "urn:redhat:anaconda:pre" THREAD_FETCH_DATA = "AnaOSCAPdataFetchThread" SUPPORTED_ARCHIVES = (".zip", ".tar", ".tar.gz", ".tar.bz2", ) # buffer size for reading and writing out data (in bytes) IO_BUF_SIZE = 2 * 1024 * 1024 class OSCAPaddonError(Exception): """Exception class for OSCAP addon related errors.""" pass
def test_absolute_relative(): assert utils.join_paths("/foo", "blah") == "/foo/blah"
def test_relative_relative(): assert utils.join_paths("foo", "blah") == "foo/blah"
def get_ssg_path(root="/"): return utils.join_paths(root, SSG_DIR + SSG_CONTENT)
"wait_and_fetch_net_data", "extract_data", "strip_content_dir", "OSCAPaddonError"] INSTALLATION_CONTENT_DIR = "/tmp/openscap_data/" TARGET_CONTENT_DIR = "/root/openscap_data/" SSG_DIR = "/usr/share/xml/scap/ssg/content/" SSG_CONTENT = "ssg-rhel7-ds.xml" if constants.shortProductName != 'anaconda': if constants.shortProductName == 'fedora': SSG_CONTENT = "ssg-fedora-ds.xml" else: SSG_CONTENT = "ssg-%s%s-ds.xml" % (constants.shortProductName, constants.productVersion.strip(".")[0]) RESULTS_PATH = utils.join_paths(TARGET_CONTENT_DIR, "eval_remediate_results.xml") REPORT_PATH = utils.join_paths(TARGET_CONTENT_DIR, "eval_remediate_report.html") PRE_INSTALL_FIX_SYSTEM_ATTR = "urn:redhat:anaconda:pre" THREAD_FETCH_DATA = "AnaOSCAPdataFetchThread" SUPPORTED_ARCHIVES = (".zip", ".tar", ".tar.gz", ".tar.bz2", ) # buffer size for reading and writing out data (in bytes) IO_BUF_SIZE = 2 * 1024 * 1024 class OSCAPaddonError(Exception): """Exception class for OSCAP addon related errors."""
def raw_preinst_content_path(self): """Path to the raw (unextracted, ...) pre-installation content file""" return utils.join_paths(common.INSTALLATION_CONTENT_DIR, self.content_name)
def test_relative_absolute(): assert utils.join_paths("foo", "/blah") == "foo/blah"
def test_absolute_absolute(): assert utils.join_paths("/foo", "/blah") == "/foo/blah"