adding XML/XSD support for hashtype attr
This commit is contained in:
parent
0c0f6ee81b
commit
af732a1d64
@ -15,14 +15,15 @@ from lxml import etree
|
|||||||
|
|
||||||
|
|
||||||
class BootSync(object):
|
class BootSync(object):
|
||||||
def __init__(self, cfg = None, *args, **kwargs):
|
def __init__(self, cfg = None, validate = True, *args, **kwargs):
|
||||||
if not cfg:
|
if not cfg:
|
||||||
self.cfgfile = '/etc/bootsync.xml'
|
self.cfgfile = '/etc/bootsync.xml'
|
||||||
else:
|
else:
|
||||||
self.cfgfile = os.path.abspath(os.path.expanduser(cfg))
|
self.cfgfile = os.path.abspath(os.path.expanduser(cfg))
|
||||||
self.ns = '{http://git.square-r00t.net/OpTools/tree/sys/BootSync/}'
|
self.ns = None
|
||||||
self.cfg = None
|
self.cfg = None
|
||||||
self.xml = None
|
self.xml = None
|
||||||
|
self.schema = None
|
||||||
# This is the current live kernel.
|
# This is the current live kernel.
|
||||||
self.currentKernVer = self._getRunningKernel()
|
self.currentKernVer = self._getRunningKernel()
|
||||||
# This is the installed kernel from the package manager.
|
# This is the installed kernel from the package manager.
|
||||||
@ -33,15 +34,13 @@ class BootSync(object):
|
|||||||
self.dummy_uuid = None
|
self.dummy_uuid = None
|
||||||
self.syncs = {}
|
self.syncs = {}
|
||||||
##
|
##
|
||||||
self.getCfg()
|
self.getCfg(validate = validate)
|
||||||
self.chkMounts()
|
self.chkMounts()
|
||||||
self.chkReboot()
|
self.chkReboot()
|
||||||
self.getHashes()
|
self.getHashes()
|
||||||
self.getBlkids()
|
self.getBlkids()
|
||||||
# self.sync()
|
|
||||||
# self.writeConfs()
|
|
||||||
|
|
||||||
def getCfg(self):
|
def getCfg(self, validate = True):
|
||||||
if not os.path.isfile(self.cfgfile):
|
if not os.path.isfile(self.cfgfile):
|
||||||
raise FileNotFoundError('Configuration file {0} does not exist!'.format(self.cfgfile))
|
raise FileNotFoundError('Configuration file {0} does not exist!'.format(self.cfgfile))
|
||||||
try:
|
try:
|
||||||
@ -53,6 +52,19 @@ class BootSync(object):
|
|||||||
# self.logger.error('{0} is invalid XML'.format(self.cfgfile))
|
# self.logger.error('{0} is invalid XML'.format(self.cfgfile))
|
||||||
raise ValueError(('{0} does not seem to be valid XML. '
|
raise ValueError(('{0} does not seem to be valid XML. '
|
||||||
'See sample.config.xml for an example configuration.').format(self.cfgfile))
|
'See sample.config.xml for an example configuration.').format(self.cfgfile))
|
||||||
|
self.ns = self.cfg.nsmap.get(None, 'http://git.square-r00t.net/OpTools/tree/sys/BootSync/')
|
||||||
|
self.ns = '{{{0}}}'.format(self.ns)
|
||||||
|
if validate:
|
||||||
|
if not self.schema:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
xsi = self.cfg.nsmap.get('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||||
|
schemaLocation = '{{{0}}}schemaLocation'.format(xsi)
|
||||||
|
schemaURL = self.cfg.attrib.get(schemaLocation,
|
||||||
|
('http://git.square-r00t.net/OpTools/plain/sys/BootSync/bootsync.xsd'))
|
||||||
|
with urlopen(schemaURL) as url:
|
||||||
|
self.schema = url.read()
|
||||||
|
self.schema = etree.XMLSchema(etree.XML(self.schema))
|
||||||
|
self.schema.assertValid(self.xml)
|
||||||
return()
|
return()
|
||||||
|
|
||||||
def chkMounts(self):
|
def chkMounts(self):
|
||||||
@ -278,6 +290,11 @@ class BootSync(object):
|
|||||||
|
|
||||||
def parseArgs():
|
def parseArgs():
|
||||||
args = argparse.ArgumentParser(description = ('Sync files to assist using mdadm RAID arrays with UEFI'))
|
args = argparse.ArgumentParser(description = ('Sync files to assist using mdadm RAID arrays with UEFI'))
|
||||||
|
args.add_argument('-V', '--no-validate',
|
||||||
|
dest = 'validate',
|
||||||
|
action = 'store_false',
|
||||||
|
help = ('If specified, do not attempt to validate the configuration file (-c/--cfg) against'
|
||||||
|
'its schema (otherwise it is fetched dynamically and requires network connection)'))
|
||||||
args.add_argument('-c', '--cfg',
|
args.add_argument('-c', '--cfg',
|
||||||
dest = 'cfg',
|
dest = 'cfg',
|
||||||
default = '/etc/bootsync.xml',
|
default = '/etc/bootsync.xml',
|
||||||
|
@ -24,6 +24,28 @@
|
|||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="hashtype_choice">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="false"/>
|
||||||
|
<!-- https://docs.python.org/3/library/hashlib.html#hash-algorithms -->
|
||||||
|
<xs:enumeration value="md5"/><!-- Not available on FIPS-compliant Python -->
|
||||||
|
<xs:enumeration value="sha1"/>
|
||||||
|
<xs:enumeration value="sha224"/>
|
||||||
|
<xs:enumeration value="sha256"/>
|
||||||
|
<xs:enumeration value="sha384"/>
|
||||||
|
<xs:enumeration value="sha512"/>
|
||||||
|
<xs:enumeration value="blake2b"/>
|
||||||
|
<xs:enumeration value="blake2s"/>
|
||||||
|
<!-- The below are only available for more recent versions of system's OpenSSL. -->
|
||||||
|
<xs:enumeration value="sha3_224"/>
|
||||||
|
<xs:enumeration value="sha3_256"/>
|
||||||
|
<xs:enumeration value="sha3_384"/>
|
||||||
|
<xs:enumeration value="sha3_512"/>
|
||||||
|
<xs:enumeration value="shake_128"/>
|
||||||
|
<xs:enumeration value="shake_256"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:element name="bootsync">
|
<xs:element name="bootsync">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
@ -56,11 +78,14 @@
|
|||||||
<xs:extension base="relpath">
|
<xs:extension base="relpath">
|
||||||
<xs:attribute name="isKernel" type="xs:boolean"
|
<xs:attribute name="isKernel" type="xs:boolean"
|
||||||
use="optional" default="false"/>
|
use="optional" default="false"/>
|
||||||
|
<xs:attribute name="hashtype" type="hashtype_choice"
|
||||||
|
use="optional" default="md5"/>
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:simpleContent>
|
</xs:simpleContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
<xs:attribute name="hashtype" type="hashtype_choice" use="optional" default="md5"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
<xs:unique name="filechk_unique">
|
<xs:unique name="filechk_unique">
|
||||||
<xs:selector xpath="bootsync:file"/>
|
<xs:selector xpath="bootsync:file"/>
|
||||||
@ -76,9 +101,12 @@
|
|||||||
<xs:attribute name="target" type="relpath" use="required"/>
|
<xs:attribute name="target" type="relpath" use="required"/>
|
||||||
<!-- TODO: make this optional? -->
|
<!-- TODO: make this optional? -->
|
||||||
<xs:attribute name="pattern" type="xs:string" use="required"/>
|
<xs:attribute name="pattern" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="hashtype" type="hashtype_choice"
|
||||||
|
use="optional" default="md5"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
<xs:attribute name="hashtype" type="hashtype_choice" use="optional" default="md5"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
<xs:unique name="syncpath_unique_source">
|
<xs:unique name="syncpath_unique_source">
|
||||||
<xs:selector xpath="bootsync:path"/>
|
<xs:selector xpath="bootsync:path"/>
|
||||||
|
@ -17,33 +17,72 @@ SEE prep.txt FOR WHAT MUST BE DONE BEFORE RUNNING BOOTSYNC.
|
|||||||
<part path="/dev/sdb1" mount="/mnt/boot1"/>
|
<part path="/dev/sdb1" mount="/mnt/boot1"/>
|
||||||
<part path="/dev/sdd1" mount="/mnt/boot2"/>
|
<part path="/dev/sdd1" mount="/mnt/boot2"/>
|
||||||
</partitions>
|
</partitions>
|
||||||
<!-- If specified, the files in this container are checksummed to determine if a sync is required.
|
<!--
|
||||||
If fileChecks isn't provided, we will always sync no matter what.
|
If fileChecks isn't provided, we will still sync syncPaths (which IS required).
|
||||||
These files will be evaluated to and synced to the ESP partitions with the same relative path.
|
These files will be evaluated to and synced to the ESP partitions with the same relative path.
|
||||||
i.e. (part[@mount])/(file)
|
i.e. (part[@mount])/(file)
|
||||||
|
|
||||||
|
fileChecks[@hashtype] attribute is used to checksum all <file> children,
|
||||||
|
unless they specify their own hashtype attribute (the default is hashtype="md5" for speed optimizations).
|
||||||
|
|
||||||
|
Guaranteed valid hashtype values are:
|
||||||
|
|
||||||
|
sha1
|
||||||
|
sha224
|
||||||
|
sha256
|
||||||
|
sha384
|
||||||
|
sha512
|
||||||
|
blake2b
|
||||||
|
blake2s
|
||||||
|
|
||||||
|
If you have a non-FIPS-compliant Python (you very most likely do), the following hashtype is also available:
|
||||||
|
|
||||||
|
md5
|
||||||
|
|
||||||
|
If you have a recent enough OpenSSL (and python3), you have the additional hashtype values available:
|
||||||
|
|
||||||
|
sha3_224
|
||||||
|
sha3_256
|
||||||
|
sha3_384
|
||||||
|
sha3_512
|
||||||
|
shake_128
|
||||||
|
shake_256
|
||||||
|
|
||||||
|
Additionally, the value "false" is always available to disable hashing for a specific <file> object or to set
|
||||||
|
the default. No checksumming will be done in this case and the file will always be overwritten on every run.
|
||||||
|
|
||||||
|
This is *highly not recommended* for solid-state disks or if you have large files you plan on syncing to
|
||||||
|
the alternate ESPs (e.g. loop-mounted ISO/IMG files).
|
||||||
|
|
||||||
"isKernel" is by default false, but if true it is treated specially to get a kernel version.
|
"isKernel" is by default false, but if true it is treated specially to get a kernel version.
|
||||||
This is to notify you if a reboot is required. If no <file> item is isKernel="true", no reboot requirement
|
This is to notify you if a reboot is required. If no <file> item is isKernel="true", no reboot requirement
|
||||||
detection will be done.
|
detection will be done.
|
||||||
Only *the last* <file> with isKernel="true" listed is used as the kernel identifier. -->
|
Only *the last* <file> with isKernel="true" listed is used as the kernel identifier.
|
||||||
<fileChecks>
|
-->
|
||||||
<!-- RELATIVE paths to /boot -->
|
<fileChecks hashtype="sha1">
|
||||||
|
<!-- RELATIVE paths to /boot on your / mount. -->
|
||||||
<file>initramfs-linux.img</file>
|
<file>initramfs-linux.img</file>
|
||||||
<file>intel-ucode.img</file>
|
<file>intel-ucode.img</file>
|
||||||
<file>memtest86+/memtest.bin</file>
|
<file>memtest86+/memtest.bin</file>
|
||||||
<file isKernel="true">vmlinuz-linux</file>
|
<file isKernel="true" hashtype="sha512">vmlinuz-linux</file>
|
||||||
</fileChecks>
|
</fileChecks>
|
||||||
<!-- These are system paths to sync to the ESPs. They are synced recursively.
|
<!--
|
||||||
|
These are system paths to sync to the ESPs. They are synced recursively.
|
||||||
|
|
||||||
|
"hashtype" is also supported for syncPaths and path objects just as the same with fileChecks
|
||||||
|
and file objects (see above).
|
||||||
|
|
||||||
"source" should be absolute.
|
"source" should be absolute.
|
||||||
"target" should be relative (to the ESP mount).
|
"target" should be relative (to the ESP mount).
|
||||||
"pattern" is a regex to match to restrict *filenames* to sync. Use ".*" for all files. -->
|
"pattern" is a regex to match to restrict *filenames* to sync. Use ".*" for all files.
|
||||||
<syncPaths>
|
-->
|
||||||
|
<syncPaths hashtype="sha1">
|
||||||
<!-- For example, these are grub theme files. -->
|
<!-- For example, these are grub theme files. -->
|
||||||
<path source="/usr/share/grub/themes" target="grub/themes" pattern=".*"/>
|
<path source="/usr/share/grub/themes" target="grub/themes" pattern=".*"/>
|
||||||
<!-- These are grub modules - specifically, UEFI. -->
|
<!-- These are grub modules - specifically, UEFI. -->
|
||||||
<path source="/usr/lib/grub/x86_64-efi" target="grub/x86_64-efi" pattern="^.*\.(mod|lst|sh)$"/>
|
<path source="/usr/lib/grub/x86_64-efi" target="grub/x86_64-efi" pattern="^.*\.(mod|lst|sh)$"/>
|
||||||
<!-- And these are ISO files, in case you're like me and do loop mounting in Grub for rescue situations.
|
<!-- And these are ISO files, in case you're like me and do loop mounting in Grub for rescue situations.
|
||||||
(e.g. https://wiki.archlinux.org/index.php/Multiboot_USB_drive#Using_GRUB_and_loopback_devices) -->
|
(e.g. https://wiki.archlinux.org/index.php/Multiboot_USB_drive#Using_GRUB_and_loopback_devices) -->
|
||||||
<path source="/boot/iso" target="iso" pattern="^.*\.(iso|img)$"/>
|
<path hashtype="false" source="/boot/iso" target="iso" pattern="^.*\.(iso|img)$"/>
|
||||||
</syncPaths>
|
</syncPaths>
|
||||||
</bootsync>
|
</bootsync>
|
Loading…
Reference in New Issue
Block a user