|
Packit Service |
39273c |
#
|
|
Packit Service |
39273c |
# Copyright (C) 2013 Red Hat, Inc.
|
|
Packit Service |
39273c |
#
|
|
Packit Service |
39273c |
# This copyrighted material is made available to anyone wishing to use,
|
|
Packit Service |
39273c |
# modify, copy, or redistribute it subject to the terms and conditions of
|
|
Packit Service |
39273c |
# the GNU General Public License v.2, or (at your option) any later version.
|
|
Packit Service |
39273c |
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit Service |
39273c |
# ANY WARRANTY expressed or implied, including the implied warranties of
|
|
Packit Service |
39273c |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
Packit Service |
39273c |
# Public License for more details. You should have received a copy of the
|
|
Packit Service |
39273c |
# GNU General Public License along with this program; if not, write to the
|
|
Packit Service |
39273c |
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
39273c |
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
|
Packit Service |
39273c |
# source code or documentation are not subject to the GNU General Public
|
|
Packit Service |
39273c |
# License and may only be used or replicated with the express permission of
|
|
Packit Service |
39273c |
# Red Hat, Inc.
|
|
Packit Service |
39273c |
#
|
|
Packit Service |
39273c |
# Red Hat Author(s): Vratislav Podzimek <vpodzime@redhat.com>
|
|
Packit Service |
39273c |
#
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""Module with the OSCAPdata class."""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
import shutil
|
|
Packit Service |
39273c |
import re
|
|
Packit Service |
39273c |
import os
|
|
Packit Service |
39273c |
import time
|
|
Packit Service |
39273c |
import logging
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
from pyanaconda.addons import AddonData
|
|
Packit Service |
39273c |
from pyanaconda.core.configuration.anaconda import conf
|
|
Packit Service |
39273c |
from pyanaconda.progress import progressQ
|
|
Packit Service |
39273c |
from pyanaconda import errors
|
|
Packit Service |
39273c |
from pyanaconda.core import util
|
|
Packit Service |
39273c |
from pyanaconda import flags
|
|
Packit Service |
39273c |
from pykickstart.errors import KickstartParseError, KickstartValueError
|
|
Packit Service |
39273c |
from org_fedora_oscap import utils, common, rule_handling, data_fetch
|
|
Packit Service |
39273c |
from org_fedora_oscap.common import SUPPORTED_ARCHIVES, _
|
|
Packit Service |
39273c |
from org_fedora_oscap.content_handling import ContentCheckError
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
log = logging.getLogger("anaconda")
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# export OSCAPdata class to prevent Anaconda's collect method from taking
|
|
Packit Service |
39273c |
# AddonData class instead of the OSCAPdata class
|
|
Packit Service |
39273c |
# @see: pyanaconda.kickstart.AnacondaKSHandler.__init__
|
|
Packit Service |
39273c |
__all__ = ["OSCAPdata"]
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
SUPPORTED_CONTENT_TYPES = ("datastream", "rpm", "archive",
|
|
Packit Service |
39273c |
"scap-security-guide",
|
|
Packit Service |
39273c |
)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
SUPPORTED_URL_PREFIXES = ("http://", "https://", "ftp://"
|
|
Packit Service |
39273c |
# LABEL:?, hdaX:?,
|
|
Packit Service |
39273c |
)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
REQUIRED_PACKAGES = ("openscap", "openscap-scanner", )
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
FINGERPRINT_REGEX = re.compile(r'^[a-z0-9]+$')
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
class MisconfigurationError(common.OSCAPaddonError):
|
|
Packit Service |
39273c |
"""Exception for reporting misconfiguration."""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
pass
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
class OSCAPdata(AddonData):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
Class parsing and storing data for the OSCAP addon.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
:see: pyanaconda.addons.AddonData
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def __init__(self, name, just_clear=False):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
:param name: name of the addon
|
|
Packit Service |
39273c |
:type name: str
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if not just_clear:
|
|
Packit Service |
39273c |
# do not call the parent's __init__ more than once
|
|
Packit Service |
39273c |
AddonData.__init__(self, name)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# values specifying the content
|
|
Packit Service |
39273c |
self.content_type = ""
|
|
Packit Service |
39273c |
self.content_url = ""
|
|
Packit Service |
39273c |
self.datastream_id = ""
|
|
Packit Service |
39273c |
self.xccdf_id = ""
|
|
Packit Service |
39273c |
self.profile_id = ""
|
|
Packit Service |
39273c |
self.content_path = ""
|
|
Packit Service |
39273c |
self.cpe_path = ""
|
|
Packit Service |
39273c |
self.tailoring_path = ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# additional values
|
|
Packit Service |
39273c |
self.fingerprint = ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# certificate to verify HTTPS connection or signed data
|
|
Packit Service |
39273c |
self.certificates = ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# internal values
|
|
Packit Service |
39273c |
self.rule_data = rule_handling.RuleData()
|
|
Packit Service |
39273c |
self.dry_run = False
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def __str__(self):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
What should end up in the resulting kickstart file, i.e. string
|
|
Packit Service |
39273c |
representation of the stored data.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.dry_run or not self.profile_id:
|
|
Packit Service |
39273c |
# the addon was run in the dry run mode, omit it from the kickstart
|
|
Packit Service |
39273c |
return ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def key_value_pair(key, value, indent=4):
|
|
Packit Service |
39273c |
return "%s%s = %s" % (indent * " ", key, value)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
ret = "%%addon %s" % self.name
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("content-type", self.content_type)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_url:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("content-url", self.content_url)
|
|
Packit Service |
39273c |
if self.datastream_id:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("datastream-id", self.datastream_id)
|
|
Packit Service |
39273c |
if self.xccdf_id:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("xccdf-id", self.xccdf_id)
|
|
Packit Service |
39273c |
if self.content_path and self.content_type != "scap-security-guide":
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("content-path", self.content_path)
|
|
Packit Service |
39273c |
if self.cpe_path:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("cpe-path", self.cpe_path)
|
|
Packit Service |
39273c |
if self.tailoring_path:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("tailoring-path",
|
|
Packit Service |
39273c |
self.tailoring_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("profile", self.profile_id)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.fingerprint:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("fingerprint", self.fingerprint)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.certificates:
|
|
Packit Service |
39273c |
ret += "\n%s" % key_value_pair("certificates", self.certificates)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
ret += "\n%end\n\n"
|
|
Packit Service |
39273c |
return ret
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_content_type(self, value):
|
|
Packit Service |
39273c |
value_low = value.lower()
|
|
Packit Service |
39273c |
if value_low in SUPPORTED_CONTENT_TYPES:
|
|
Packit Service |
39273c |
self.content_type = value_low
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
msg = "Unsupported content type '%s' in the %s addon" % (value,
|
|
Packit Service |
39273c |
self.name)
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_content_url(self, value):
|
|
Packit Service |
39273c |
if any(value.startswith(prefix)
|
|
Packit Service |
39273c |
for prefix in SUPPORTED_URL_PREFIXES):
|
|
Packit Service |
39273c |
self.content_url = value
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
msg = "Unsupported url '%s' in the %s addon" % (value, self.name)
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_datastream_id(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.datastream_id = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_xccdf_id(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.xccdf_id = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_profile_id(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.profile_id = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_content_path(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.content_path = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_cpe_path(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.cpe_path = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_tailoring_path(self, value):
|
|
Packit Service |
39273c |
# need to be checked?
|
|
Packit Service |
39273c |
self.tailoring_path = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_fingerprint(self, value):
|
|
Packit Service |
39273c |
if FINGERPRINT_REGEX.match(value) is None:
|
|
Packit Service |
39273c |
msg = "Unsupported or invalid fingerprint"
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if utils.get_hashing_algorithm(value) is None:
|
|
Packit Service |
39273c |
msg = "Unsupported fingerprint"
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
self.fingerprint = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _parse_certificates(self, value):
|
|
Packit Service |
39273c |
self.certificates = value
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def handle_line(self, line):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
The handle_line method that is called with every line from this addon's
|
|
Packit Service |
39273c |
%addon section of the kickstart file.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
:param line: a single line from the %addon section
|
|
Packit Service |
39273c |
:type line: str
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
actions = {"content-type": self._parse_content_type,
|
|
Packit Service |
39273c |
"content-url": self._parse_content_url,
|
|
Packit Service |
39273c |
"content-path": self._parse_content_path,
|
|
Packit Service |
39273c |
"datastream-id": self._parse_datastream_id,
|
|
Packit Service |
39273c |
"profile": self._parse_profile_id,
|
|
Packit Service |
39273c |
"xccdf-id": self._parse_xccdf_id,
|
|
Packit Service |
39273c |
"xccdf-path": self._parse_content_path,
|
|
Packit Service |
39273c |
"cpe-path": self._parse_cpe_path,
|
|
Packit Service |
39273c |
"tailoring-path": self._parse_tailoring_path,
|
|
Packit Service |
39273c |
"fingerprint": self._parse_fingerprint,
|
|
Packit Service |
39273c |
"certificates": self._parse_certificates,
|
|
Packit Service |
39273c |
}
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
line = line.strip()
|
|
Packit Service |
39273c |
(pre, sep, post) = line.partition("=")
|
|
Packit Service |
39273c |
pre = pre.strip()
|
|
Packit Service |
39273c |
post = post.strip()
|
|
Packit Service |
39273c |
post = post.strip('"')
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
try:
|
|
Packit Service |
39273c |
actions[pre](post)
|
|
Packit Service |
39273c |
except KeyError:
|
|
Packit Service |
39273c |
msg = "Unknown item '%s' for %s addon" % (line, self.name)
|
|
Packit Service |
39273c |
raise KickstartParseError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def finalize(self):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
The finalize method that is called when the end of the %addon section
|
|
Packit Service |
39273c |
(the %end line) is reached. It means no more kickstart data will come.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
tmpl = "%s missing for the %s addon"
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# check provided data
|
|
Packit Service |
39273c |
if not self.content_type:
|
|
Packit Service |
39273c |
raise KickstartValueError(tmpl % ("content-type", self.name))
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type != "scap-security-guide" and not self.content_url:
|
|
Packit Service |
39273c |
raise KickstartValueError(tmpl % ("content-url", self.name))
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if not self.profile_id:
|
|
Packit Service |
39273c |
self.profile_id = "default"
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type in ("rpm", "archive") and not self.content_path:
|
|
Packit Service |
39273c |
msg = "Path to the XCCDF file has to be given if content in RPM "\
|
|
Packit Service |
39273c |
"or archive is used"
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "rpm" and not self.content_url.endswith(".rpm"):
|
|
Packit Service |
39273c |
msg = "Content type set to RPM, but the content URL doesn't end "\
|
|
Packit Service |
39273c |
"with '.rpm'"
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "archive":
|
|
Packit Service |
39273c |
supported_archive = any(self.content_url.endswith(arch_type)
|
|
Packit Service |
39273c |
for arch_type in SUPPORTED_ARCHIVES)
|
|
Packit Service |
39273c |
if not supported_archive:
|
|
Packit Service |
39273c |
msg = "Unsupported archive type of the content "\
|
|
Packit Service |
39273c |
"file '%s'" % self.content_url
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# do some initialization magic in case of SSG
|
|
Packit Service |
39273c |
if self.content_type == "scap-security-guide":
|
|
Packit Service |
39273c |
if not common.ssg_available():
|
|
Packit Service |
39273c |
msg = "SCAP Security Guide not found on the system"
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
self.content_path = common.SSG_DIR + common.SSG_CONTENT
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def content_defined(self):
|
|
Packit Service |
39273c |
return self.content_url or self.content_type == "scap-security-guide"
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def content_name(self):
|
|
Packit Service |
39273c |
if self.content_type == "scap-security-guide":
|
|
Packit Service |
39273c |
raise ValueError("Using scap-security-guide, no single content file")
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
rest = "/anonymous_content"
|
|
Packit Service |
39273c |
for prefix in SUPPORTED_URL_PREFIXES:
|
|
Packit Service |
39273c |
if self.content_url.startswith(prefix):
|
|
Packit Service |
39273c |
rest = self.content_url[len(prefix):]
|
|
Packit Service |
39273c |
break
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
parts = rest.rsplit("/", 1)
|
|
Packit Service |
39273c |
if len(parts) != 2:
|
|
Packit Service |
39273c |
msg = "Unsupported url '%s' in the %s addon" % (self.content_url,
|
|
Packit Service |
39273c |
self.name)
|
|
Packit Service |
39273c |
raise KickstartValueError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
return parts[1]
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def raw_preinst_content_path(self):
|
|
Packit Service |
39273c |
"""Path to the raw (unextracted, ...) pre-installation content file"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
return utils.join_paths(common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_name)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def raw_postinst_content_path(self):
|
|
Packit Service |
39273c |
"""Path to the raw (unextracted, ...) post-installation content file"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
return utils.join_paths(common.TARGET_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_name)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def preinst_content_path(self):
|
|
Packit Service |
39273c |
"""Path to the pre-installation content file"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "datastream":
|
|
Packit Service |
39273c |
return utils.join_paths(common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_name)
|
|
Packit Service |
39273c |
elif self.content_type == "scap-security-guide":
|
|
Packit Service |
39273c |
# SSG is not copied to the standard place
|
|
Packit Service |
39273c |
return self.content_path
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
return utils.join_paths(common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def postinst_content_path(self):
|
|
Packit Service |
39273c |
"""Path to the post-installation content file"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "datastream":
|
|
Packit Service |
39273c |
return utils.join_paths(common.TARGET_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_name)
|
|
Packit Service |
39273c |
elif self.content_type in ("rpm", "scap-security-guide"):
|
|
Packit Service |
39273c |
# no path magic in case of RPM (SSG is installed as an RPM)
|
|
Packit Service |
39273c |
return self.content_path
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
return utils.join_paths(common.TARGET_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.content_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def preinst_tailoring_path(self):
|
|
Packit Service |
39273c |
"""Path to the pre-installation tailoring file (if any)"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if not self.tailoring_path:
|
|
Packit Service |
39273c |
return ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
return utils.join_paths(common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.tailoring_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
@property
|
|
Packit Service |
39273c |
def postinst_tailoring_path(self):
|
|
Packit Service |
39273c |
"""Path to the post-installation tailoring file (if any)"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if not self.tailoring_path:
|
|
Packit Service |
39273c |
return ""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "rpm":
|
|
Packit Service |
39273c |
# no path magic in case of RPM
|
|
Packit Service |
39273c |
return self.tailoring_path
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
return utils.join_paths(common.TARGET_CONTENT_DIR,
|
|
Packit Service |
39273c |
self.tailoring_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def _fetch_content_and_initialize(self):
|
|
Packit Service |
39273c |
"""Fetch content and initialize from it"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
data_fetch.fetch_data(self.content_url, self.raw_preinst_content_path,
|
|
Packit Service |
39273c |
self.certificates)
|
|
Packit Service |
39273c |
# RPM is an archive at this phase
|
|
Packit Service |
39273c |
if self.content_type in ("archive", "rpm"):
|
|
Packit Service |
39273c |
# extract the content
|
|
Packit Service |
39273c |
common.extract_data(self.raw_preinst_content_path,
|
|
Packit Service |
39273c |
common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
[self.content_path])
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
rules = common.get_fix_rules_pre(self.profile_id,
|
|
Packit Service |
39273c |
self.preinst_content_path,
|
|
Packit Service |
39273c |
self.datastream_id, self.xccdf_id,
|
|
Packit Service |
39273c |
self.preinst_tailoring_path)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# parse and store rules with a clean RuleData instance
|
|
Packit Service |
39273c |
self.rule_data = rule_handling.RuleData()
|
|
Packit Service |
39273c |
for rule in rules.splitlines():
|
|
Packit Service |
39273c |
self.rule_data.new_rule(rule)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def setup(self, storage, ksdata, payload):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
The setup method that should make changes to the runtime environment
|
|
Packit Service |
39273c |
according to the data stored in this object.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
:param storage: object storing storage-related information
|
|
Packit Service |
39273c |
(disks, partitioning, bootloader, etc.)
|
|
Packit Service |
39273c |
:type storage: blivet.Blivet instance
|
|
Packit Service |
39273c |
:param ksdata: data parsed from the kickstart file and set in the
|
|
Packit Service |
39273c |
installation process
|
|
Packit Service |
39273c |
:type ksdata: pykickstart.base.BaseHandler instance
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.dry_run or not self.profile_id:
|
|
Packit Service |
39273c |
# nothing more to be done in the dry-run mode or if no profile is
|
|
Packit Service |
39273c |
# selected
|
|
Packit Service |
39273c |
return
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if not os.path.exists(self.preinst_content_path) and not os.path.exists(self.raw_preinst_content_path):
|
|
Packit Service |
39273c |
# content not available/fetched yet
|
|
Packit Service |
39273c |
try:
|
|
Packit Service |
39273c |
self._fetch_content_and_initialize()
|
|
Packit Service |
39273c |
except (common.OSCAPaddonError, data_fetch.DataFetchError) as e:
|
|
Packit Service |
39273c |
log.error("Failed to fetch and initialize SCAP content!")
|
|
Packit Service |
39273c |
msg = _("There was an error fetching and loading the security content:\n" +
|
|
Packit Service |
39273c |
"%s\n" +
|
|
Packit Service |
39273c |
"The installation should be aborted. Do you wish to continue anyway?") % e
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if flags.flags.automatedInstall and not flags.flags.ksprompt:
|
|
Packit Service |
39273c |
# cannot have ask in a non-interactive kickstart
|
|
Packit Service |
39273c |
# installation
|
|
Packit Service |
39273c |
raise errors.CmdlineError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
answ = errors.errorHandler.ui.showYesNoQuestion(msg)
|
|
Packit Service |
39273c |
if answ == errors.ERROR_CONTINUE:
|
|
Packit Service |
39273c |
# prevent any futher actions here by switching to the dry
|
|
Packit Service |
39273c |
# run mode and let things go on
|
|
Packit Service |
39273c |
self.dry_run = True
|
|
Packit Service |
39273c |
return
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
# Let's sleep forever to prevent any further actions and
|
|
Packit Service |
39273c |
# wait for the main thread to quit the process.
|
|
Packit Service |
39273c |
progressQ.send_quit(1)
|
|
Packit Service |
39273c |
while True:
|
|
Packit Service |
39273c |
time.sleep(100000)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# check fingerprint if given
|
|
Packit Service |
39273c |
if self.fingerprint:
|
|
Packit Service |
39273c |
hash_obj = utils.get_hashing_algorithm(self.fingerprint)
|
|
Packit Service |
39273c |
digest = utils.get_file_fingerprint(self.raw_preinst_content_path,
|
|
Packit Service |
39273c |
hash_obj)
|
|
Packit Service |
39273c |
if digest != self.fingerprint:
|
|
Packit Service |
39273c |
log.error("Failed to fetch and initialize SCAP content!")
|
|
Packit Service |
39273c |
msg = _("The integrity check of the security content failed.\n" +
|
|
Packit Service |
39273c |
"The installation should be aborted. Do you wish to continue anyway?")
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if flags.flags.automatedInstall and not flags.flags.ksprompt:
|
|
Packit Service |
39273c |
# cannot have ask in a non-interactive kickstart
|
|
Packit Service |
39273c |
# installation
|
|
Packit Service |
39273c |
raise errors.CmdlineError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
answ = errors.errorHandler.ui.showYesNoQuestion(msg)
|
|
Packit Service |
39273c |
if answ == errors.ERROR_CONTINUE:
|
|
Packit Service |
39273c |
# prevent any futher actions here by switching to the dry
|
|
Packit Service |
39273c |
# run mode and let things go on
|
|
Packit Service |
39273c |
self.dry_run = True
|
|
Packit Service |
39273c |
return
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
# Let's sleep forever to prevent any further actions and
|
|
Packit Service |
39273c |
# wait for the main thread to quit the process.
|
|
Packit Service |
39273c |
progressQ.send_quit(1)
|
|
Packit Service |
39273c |
while True:
|
|
Packit Service |
39273c |
time.sleep(100000)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# evaluate rules, do automatic fixes and stop if something that cannot
|
|
Packit Service |
39273c |
# be fixed automatically is wrong
|
|
Packit Service |
39273c |
fatal_messages = [message for message in self.rule_data.eval_rules(ksdata, storage)
|
|
Packit Service |
39273c |
if message.type == common.MESSAGE_TYPE_FATAL]
|
|
Packit Service |
39273c |
if any(fatal_messages):
|
|
Packit Service |
39273c |
msg = "Wrong configuration detected!\n"
|
|
Packit Service |
39273c |
msg += "\n".join(message.text for message in fatal_messages)
|
|
Packit Service |
39273c |
msg += "\nThe installation should be aborted. Do you wish to continue anyway?"
|
|
Packit Service |
39273c |
if flags.flags.automatedInstall and not flags.flags.ksprompt:
|
|
Packit Service |
39273c |
# cannot have ask in a non-interactive kickstart installation
|
|
Packit Service |
39273c |
raise errors.CmdlineError(msg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
answ = errors.errorHandler.ui.showYesNoQuestion(msg)
|
|
Packit Service |
39273c |
if answ == errors.ERROR_CONTINUE:
|
|
Packit Service |
39273c |
# prevent any futher actions here by switching to the dry
|
|
Packit Service |
39273c |
# run mode and let things go on
|
|
Packit Service |
39273c |
self.dry_run = True
|
|
Packit Service |
39273c |
return
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
# Let's sleep forever to prevent any further actions and wait
|
|
Packit Service |
39273c |
# for the main thread to quit the process.
|
|
Packit Service |
39273c |
progressQ.send_quit(1)
|
|
Packit Service |
39273c |
while True:
|
|
Packit Service |
39273c |
time.sleep(100000)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# add packages needed on the target system to the list of packages
|
|
Packit Service |
39273c |
# that are requested to be installed
|
|
Packit Service |
39273c |
pkgs_to_install = list(REQUIRED_PACKAGES)
|
|
Packit Service |
39273c |
if self.content_type == "scap-security-guide":
|
|
Packit Service |
39273c |
pkgs_to_install.append("scap-security-guide")
|
|
Packit Service |
39273c |
for pkg in pkgs_to_install:
|
|
Packit Service |
39273c |
if pkg not in ksdata.packages.packageList:
|
|
Packit Service |
39273c |
ksdata.packages.packageList.append(pkg)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def execute(self, storage, ksdata, users, payload):
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
The execute method that should make changes to the installed system. It
|
|
Packit Service |
39273c |
is called only once in the post-install setup phase.
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
:see: setup
|
|
Packit Service |
39273c |
:param users: information about created users
|
|
Packit Service |
39273c |
:type users: pyanaconda.users.Users instance
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
"""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.dry_run or not self.profile_id:
|
|
Packit Service |
39273c |
# nothing more to be done in the dry-run mode or if no profile is
|
|
Packit Service |
39273c |
# selected
|
|
Packit Service |
39273c |
return
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
target_content_dir = utils.join_paths(conf.target.system_root,
|
|
Packit Service |
39273c |
common.TARGET_CONTENT_DIR)
|
|
Packit Service |
39273c |
utils.ensure_dir_exists(target_content_dir)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
if self.content_type == "datastream":
|
|
Packit Service |
39273c |
shutil.copy2(self.preinst_content_path, target_content_dir)
|
|
Packit Service |
39273c |
elif self.content_type == "rpm":
|
|
Packit Service |
39273c |
# copy the RPM to the target system
|
|
Packit Service |
39273c |
shutil.copy2(self.raw_preinst_content_path, target_content_dir)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
# and install it with yum
|
|
Packit Service |
39273c |
ret = util.execInSysroot("yum", ["-y", "--nogpg", "install",
|
|
Packit Service |
39273c |
self.raw_postinst_content_path])
|
|
Packit Service |
39273c |
if ret != 0:
|
|
Packit Service |
39273c |
raise common.ExtractionError("Failed to install content "
|
|
Packit Service |
39273c |
"RPM to the target system")
|
|
Packit Service |
39273c |
elif self.content_type == "scap-security-guide":
|
|
Packit Service |
39273c |
# nothing needed
|
|
Packit Service |
39273c |
pass
|
|
Packit Service |
39273c |
else:
|
|
Packit Service |
39273c |
utils.universal_copy(utils.join_paths(common.INSTALLATION_CONTENT_DIR,
|
|
Packit Service |
39273c |
"*"),
|
|
Packit Service |
39273c |
target_content_dir)
|
|
Packit Service |
39273c |
if os.path.exists(self.preinst_tailoring_path):
|
|
Packit Service |
39273c |
shutil.copy2(self.preinst_tailoring_path, target_content_dir)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
common.run_oscap_remediate(self.profile_id, self.postinst_content_path,
|
|
Packit Service |
39273c |
self.datastream_id, self.xccdf_id,
|
|
Packit Service |
39273c |
self.postinst_tailoring_path,
|
|
Packit Service |
39273c |
chroot=conf.target.system_root)
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
def clear_all(self):
|
|
Packit Service |
39273c |
"""Clear all the stored values."""
|
|
Packit Service |
39273c |
|
|
Packit Service |
39273c |
self.__init__(self.name, just_clear=True)
|