-
Notifications
You must be signed in to change notification settings - Fork 358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
edns: implement %certificate kickstart feature #6045
Changes from all commits
bb07209
2da7985
7354c6f
1e76e03
9d7ff2a
ad6d018
2109179
7fcd439
3fd4ebf
649c6bb
ff2a5ce
c29a13d
9646836
a10649c
844c561
a9b689b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[Unit] | ||
Description=Import of certificates added in initramfs stage of Anaconda via kickstart | ||
Before=NetworkManager.service | ||
Before=anaconda.target | ||
|
||
[Service] | ||
Type=oneshot | ||
ExecStart=/usr/libexec/anaconda/anaconda-import-initramfs-certs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
:Type: Kickstart | ||
:Summary: Support certificates import via kickstart file | ||
|
||
:Description: | ||
New kickstart section %certificate is supported. | ||
It allows users to securely embed certificates directly within | ||
the kickstart file. | ||
|
||
:Links: | ||
- https://issues.redhat.com/browse/RHELBU-2913 | ||
- https://issues.redhat.com/browse/INSTALLER-4027 | ||
- https://github.com/rhinstaller/anaconda/pull/6045 | ||
- https://github.com/pykickstart/pykickstart/pull/517 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,8 @@ TMPDIR = "/tmp" | |
ARPHRD_ETHER = "1" | ||
ARPHRD_INFINIBAND = "32" | ||
|
||
CERT_TRANSPORT_DIR = "/run/install/certificates" | ||
|
||
# Helper function for reading simple files in /sys | ||
def readsysfile(f): | ||
'''Return the contents of f, or "" if missing.''' | ||
|
@@ -403,6 +405,44 @@ def ksnet_to_dracut(args, lineno, net, bootdev=False): | |
|
||
return " ".join(line) | ||
|
||
|
||
def _dump_certificate(cert, root="/", dump_dir=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm missing a test for this code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, I'll add it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
"""Dump the certificate into specified file.""" | ||
dump_dir = dump_dir or cert.dir | ||
if not dump_dir: | ||
log.error("Certificate destination is missing for %s", cert.filename) | ||
return | ||
|
||
dst_dir = os.path.join(root, dump_dir.lstrip('/')) | ||
log.debug("Dumping certificate %s into %s.", cert.filename, dst_dir) | ||
if not os.path.exists(dst_dir): | ||
log.debug("Path %s for certificate does not exist, creating.", dst_dir) | ||
os.makedirs(dst_dir) | ||
|
||
dst = os.path.join(dst_dir, cert.filename) | ||
|
||
if os.path.exists(dst): | ||
log.warning("Certificate file %s already exists, replacing.", dst) | ||
|
||
with open(dst, 'w') as f: | ||
f.write(cert.cert) | ||
f.write('\n') | ||
|
||
|
||
def process_certificates(handler): | ||
"""Import certificates defined in %certificate sections.""" | ||
for cert in handler.certificates: | ||
log.info("Processing kickstart certificate %s", cert.filename) | ||
|
||
if not cert.filename: | ||
log.error("Missing certificate file name, skipping.") | ||
continue | ||
|
||
_dump_certificate(cert) | ||
# Dump for transport to switchroot | ||
_dump_certificate(cert, root=CERT_TRANSPORT_DIR+"/path/") | ||
|
||
|
||
def process_kickstart(ksfile): | ||
handler = DracutHandler() | ||
try: | ||
|
@@ -422,6 +462,7 @@ def process_kickstart(ksfile): | |
with open(TMPDIR+"/ks.info", "a") as f: | ||
f.write('parsed_kickstart="%s"\n' % processed_file) | ||
log.info("finished parsing kickstart") | ||
process_certificates(handler) | ||
return processed_file, handler.output | ||
|
||
if __name__ == '__main__': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# | ||
# DBus structures for the storage data. | ||
# | ||
# Copyright (C) 2024 Red Hat, Inc. All rights reserved. | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation; either version 2 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
# | ||
from dasbus.structure import DBusData | ||
from dasbus.typing import * # pylint: disable=wildcard-import | ||
|
||
__all__ = ["CertificateData"] | ||
|
||
|
||
class CertificateData(DBusData): | ||
"""Structure for the certificate data.""" | ||
|
||
def __init__(self): | ||
self._filename = "" | ||
self._cert = "" | ||
self._dir = "" | ||
|
||
@property | ||
def filename(self) -> Str: | ||
"""The certificate file name.""" | ||
return self._filename | ||
|
||
@filename.setter | ||
def filename(self, value: Str) -> None: | ||
self._filename = value | ||
|
||
@property | ||
def cert(self) -> Str: | ||
"""The certificate content.""" | ||
return self._cert | ||
|
||
@cert.setter | ||
def cert(self, value: Str) -> None: | ||
self._cert = value | ||
|
||
@property | ||
def dir(self) -> Str: | ||
"""The certificate directory.""" | ||
return self._dir | ||
|
||
@dir.setter | ||
def dir(self, value: Str) -> None: | ||
self._dir = value |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# | ||
# Copyright (C) 2024 Red Hat, Inc. | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU Lesser General Public License as published | ||
# by the Free Software Foundation; either version 2.1 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU Lesser General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME) | ||
certificatesdir = $(pkgpyexecdir)/modules/security/certificates | ||
dist_certificates_DATA = $(wildcard $(srcdir)/*.py) | ||
|
||
MAINTAINERCLEANFILES = Makefile.in |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# | ||
# Copyright (C) 2024 Red Hat, Inc. | ||
# | ||
# This copyrighted material is made available to anyone wishing to use, | ||
# modify, copy, or redistribute it subject to the terms and conditions of | ||
# the GNU General Public License v.2, or (at your option) any later version. | ||
# This program is distributed in the hope that it will be useful, but WITHOUT | ||
# ANY WARRANTY expressed or implied, including the implied warranties of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||
# Public License for more details. You should have received a copy of the | ||
# GNU General Public License along with this program; if not, write to the | ||
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the | ||
# source code or documentation are not subject to the GNU General Public | ||
# License and may only be used or replicated with the express permission of | ||
# Red Hat, Inc. | ||
# | ||
from pyanaconda.modules.security.certificates.certificates import CertificatesModule | ||
|
||
__all__ = ["CertificatesModule"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand it correctly, that there is a period of time, where certificates are not available in the installation environment - right after initramfs switchroot and before this import service is executed?
Is there an option to import the certificates to the stage2 environment even before switchroot to stage2 to ensure the provided certificates are available throughout the whole boot process?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting idea, I'll think about pushing from initramfs instead of pulling from root.
For just moving files I guess it should be fine, one possible problem is that for other potential actions, like running import tool as in rvykydal@51c67c5#diff-572b90e7fb275a5450a384189ddd4651c02f9ab6059576366cdc25e5cdbec5f9R9
this might be a bit more tricky (running in /sysroot chroot?).
But to be honest I don't know if it is usual / reasonable thing to do so I'll consult dracut people.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll create a follow-up issue for this. I think it would be better to handle it separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://issues.redhat.com/browse/INSTALLER-4089